removed activities by friends

This commit is contained in:
Mariotaku Lee 2016-10-05 21:12:33 +08:00
parent 327c4bc7a2
commit d4bb356f42
16 changed files with 408 additions and 101 deletions

View File

@ -8,7 +8,7 @@ buildscript {
}
dependencies {
classpath 'com.github.ben-manes:gradle-versions-plugin:0.13.0'
classpath 'com.android.tools.build:gradle:2.1.3'
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'com.google.gms:google-services:3.0.0'
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
classpath('fr.avianey.androidsvgdrawable:gradle-plugin:3.0.0') {

View File

@ -41,7 +41,7 @@ android {
buildConfigField 'boolean', 'LEAK_CANARY_ENABLED', 'Boolean.parseBoolean("false")'
buildConfigField 'boolean', 'SHOW_CUSTOM_TOKEN_DIALOG', 'Boolean.parseBoolean("false")'
buildConfigField 'boolean', 'HOTMOBI_LOG_ENABLED', 'Boolean.parseBoolean("false")'
buildConfigField 'boolean', 'HOTMOBI_LOG_ENABLED', 'Boolean.parseBoolean("true")'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}

View File

@ -27,8 +27,10 @@ import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.mariotaku.ktextension.LocaleExtensionKt;
import org.mariotaku.twidere.BuildConfig;
import java.util.Locale;
import java.util.TimeZone;
import edu.tsinghua.hotmobi.util.LocationUtils;
@ -59,6 +61,11 @@ public abstract class BaseEvent implements Parcelable, LogModel {
@ParcelableThisPlease
LatLng location;
@JsonField(name = "device_locale")
@ParcelableThisPlease
String deviceLocale;
public BaseEvent() {
}
@ -78,10 +85,19 @@ public abstract class BaseEvent implements Parcelable, LogModel {
this.location = location;
}
public String getDeviceLocale() {
return deviceLocale;
}
public void setDeviceLocale(String deviceLocale) {
this.deviceLocale = deviceLocale;
}
public void markStart(@NonNull Context context) {
setStartTime(System.currentTimeMillis());
setTimeOffset(TimeZone.getDefault().getOffset(startTime));
setLocation(LocationUtils.getCachedLatLng(context));
setDeviceLocale(LocaleExtensionKt.getBcp47Tag(Locale.getDefault()));
}
public void markEnd() {
@ -96,6 +112,7 @@ public abstract class BaseEvent implements Parcelable, LogModel {
", endTime=" + endTime +
", timeOffset=" + timeOffset +
", location=" + location +
", locale='" + deviceLocale + '\'' +
'}';
}

View File

@ -0,0 +1,97 @@
package edu.tsinghua.hotmobi.model;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import org.mariotaku.twidere.model.ParcelableMediaUpdate;
/**
* Created by mariotaku on 16/3/11.
*/
@JsonObject
@ParcelablePlease
public class MediaUploadEvent extends BaseEvent implements Parcelable {
@JsonField(name = "type")
int type;
@JsonField(name = "file_size")
long fileSize;
@JsonField(name = "width")
int width;
@JsonField(name = "height")
int height;
@JsonField(name = "network_type")
int networkType;
public void setMedia(ParcelableMediaUpdate media) {
this.type = media.type;
}
public void setFileSize(long fileSize) {
this.fileSize = fileSize;
}
public void setGeometry(int width, int height) {
this.width = width;
this.height = height;
}
public void setNetworkType(int networkType) {
this.networkType = networkType;
}
@NonNull
@Override
public String getLogFileName() {
return "media_upload";
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
MediaUploadEventParcelablePlease.writeToParcel(this, dest, flags);
}
@Override
public String toString() {
return "MediaUploadEvent{" +
"height=" + height +
", type=" + type +
", size=" + fileSize +
", width=" + width +
", networkType=" + networkType +
"} " + super.toString();
}
public static MediaUploadEvent create(@NonNull Context context, ParcelableMediaUpdate media) {
final MediaUploadEvent event = new MediaUploadEvent();
event.markStart(context);
event.setMedia(media);
event.setNetworkType(NetworkEvent.getActivateNetworkType(context));
return event;
}
public static final Creator<MediaUploadEvent> CREATOR = new Creator<MediaUploadEvent>() {
@Override
public MediaUploadEvent createFromParcel(Parcel source) {
MediaUploadEvent target = new MediaUploadEvent();
MediaUploadEventParcelablePlease.readFromParcel(target, source);
return target;
}
@Override
public MediaUploadEvent[] newArray(int size) {
return new MediaUploadEvent[size];
}
};
}

View File

@ -0,0 +1,117 @@
package edu.tsinghua.hotmobi.model;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
import com.hannesdorfmann.parcelableplease.annotation.ParcelableThisPlease;
import org.mariotaku.twidere.model.ParcelableStatus;
/**
* Created by mariotaku on 2016/10/3.
*/
@ParcelablePlease
@JsonObject
public class TranslateEvent extends BaseEvent implements Parcelable {
@ParcelableThisPlease
@JsonField(name = "id")
String id;
@ParcelableThisPlease
@JsonField(name = "account_id")
String accountId;
@ParcelableThisPlease
@JsonField(name = "account_host")
String accountHost;
@ParcelableThisPlease
@JsonField(name = "tweet_lang")
String tweetLang;
@ParcelableThisPlease
@JsonField(name = "translated_lang")
String translatedLang;
public static TranslateEvent create(Context context, ParcelableStatus status, String translatedLang) {
TranslateEvent event = new TranslateEvent();
event.markStart(context);
event.setId(status.id);
event.setAccountId(status.account_key.getId());
event.setAccountHost(status.account_key.getHost());
event.setTweetLang(status.lang);
event.setTranslatedLang(translatedLang);
return event;
}
public String getAccountHost() {
return accountHost;
}
public void setAccountHost(String accountHost) {
this.accountHost = accountHost;
}
public String getAccountId() {
return accountId;
}
public void setAccountId(String accountId) {
this.accountId = accountId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTweetLang() {
return tweetLang;
}
public void setTweetLang(String tweetLang) {
this.tweetLang = tweetLang;
}
public String getTranslatedLang() {
return translatedLang;
}
public void setTranslatedLang(String translatedLang) {
this.translatedLang = translatedLang;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
TranslateEventParcelablePlease.writeToParcel(this, dest, flags);
}
public static final Creator<TranslateEvent> CREATOR = new Creator<TranslateEvent>() {
public TranslateEvent createFromParcel(Parcel source) {
TranslateEvent target = new TranslateEvent();
TranslateEventParcelablePlease.readFromParcel(target, source);
return target;
}
public TranslateEvent[] newArray(int size) {
return new TranslateEvent[size];
}
};
@NonNull
@Override
public String getLogFileName() {
return "translate";
}
}

View File

@ -65,8 +65,19 @@ public class TweetEvent extends BaseEvent implements Parcelable {
@Action
String action;
@ParcelableThisPlease
@JsonField(name = "in_reply_to_id")
@Action
String inReplyToId;
@ParcelableThisPlease
@JsonField(name = "tweet_lang")
String tweetLang;
@ParcelableThisPlease
@JsonField(name = "following")
boolean following;
@ParcelableThisPlease
@JsonField(name = "has_translate_feature")
boolean hasTranslateFeature;
public static final Creator<TweetEvent> CREATOR = new Creator<TweetEvent>() {
public TweetEvent createFromParcel(Parcel source) {
TweetEvent target = new TweetEvent();
@ -88,6 +99,7 @@ public class TweetEvent extends BaseEvent implements Parcelable {
event.setUserId(status.user_key.getId());
event.setTimelineType(timelineType);
event.setTweetType(TwidereDataUtils.getTweetType(status));
event.setTweetLang(status.lang);
event.setFollowing(status.user_is_following);
return event;
}
@ -96,6 +108,10 @@ public class TweetEvent extends BaseEvent implements Parcelable {
this.following = following;
}
public String getAction() {
return action;
}
public void setAction(@Action String action) {
this.action = action;
}
@ -116,6 +132,14 @@ public class TweetEvent extends BaseEvent implements Parcelable {
this.timelineType = timelineType;
}
public String getTweetLang() {
return tweetLang;
}
public void setTweetLang(String tweetLang) {
this.tweetLang = tweetLang;
}
public String getAccountId() {
return accountId;
}
@ -132,15 +156,33 @@ public class TweetEvent extends BaseEvent implements Parcelable {
this.accountHost = accountHost;
}
public String getInReplyToId() {
return inReplyToId;
}
public void setInReplyToId(String inReplyToId) {
this.inReplyToId = inReplyToId;
}
public boolean isHasTranslateFeature() {
return hasTranslateFeature;
}
public void setHasTranslateFeature(boolean hasTranslateFeature) {
this.hasTranslateFeature = hasTranslateFeature;
}
@Override
public String toString() {
return "TweetEvent{" +
"id=" + id +
", accountKey=" + accountId +
", userId=" + userId +
"accountHost='" + accountHost + '\'' +
", id='" + id + '\'' +
", accountId='" + accountId + '\'' +
", userId='" + userId + '\'' +
", tweetType='" + tweetType + '\'' +
", timelineType='" + timelineType + '\'' +
", action='" + action + '\'' +
", inReplyToId='" + inReplyToId + '\'' +
", following=" + following +
"} " + super.toString();
}

View File

@ -15,7 +15,6 @@ import android.text.style.StyleSpan;
import org.mariotaku.microblog.library.twitter.model.Activity;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.model.util.ParcelableActivityExtensionsKt;
import org.mariotaku.twidere.model.util.ParcelableActivityUtils;
import org.mariotaku.twidere.util.UserColorNameManager;
import org.oshkimaadziig.george.androidutils.SpanFormatter;
@ -23,13 +22,13 @@ import org.oshkimaadziig.george.androidutils.SpanFormatter;
* Created by mariotaku on 16/1/1.
*/
public class ActivityTitleSummaryMessage {
final int icon;
final int color;
private final int icon;
private final int color;
@NonNull
final CharSequence title;
final CharSequence summary;
private final CharSequence title;
private final CharSequence summary;
ActivityTitleSummaryMessage(int icon, int color, @NonNull CharSequence title, @Nullable CharSequence summary) {
private ActivityTitleSummaryMessage(int icon, int color, @NonNull CharSequence title, @Nullable CharSequence summary) {
this.icon = icon;
this.color = color;
this.title = title;
@ -38,22 +37,18 @@ public class ActivityTitleSummaryMessage {
@Nullable
public static ActivityTitleSummaryMessage get(Context context, UserColorNameManager manager, ParcelableActivity activity,
ParcelableUser[] sources, int defaultColor, boolean byFriends,
ParcelableUser[] sources, int defaultColor,
boolean shouldUseStarsForLikes,
boolean nameFirst) {
final Resources resources = context.getResources();
boolean byFriends = false;
switch (activity.action) {
case Activity.Action.FOLLOW: {
int typeIcon = R.drawable.ic_activity_action_follow;
int color = ContextCompat.getColor(context, R.color.highlight_follow);
CharSequence title;
if (byFriends) {
title = getTitleStringByFriends(resources, manager, R.string.activity_by_friends_follow,
R.string.activity_by_friends_follow_multi, sources, activity.target_users, nameFirst);
} else {
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_follow,
R.string.activity_about_me_follow_multi, sources, nameFirst);
}
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_follow,
R.string.activity_about_me_follow_multi, sources, nameFirst);
return new ActivityTitleSummaryMessage(typeIcon, color, title, null);
}
case Activity.Action.FAVORITE: {
@ -63,24 +58,14 @@ public class ActivityTitleSummaryMessage {
if (shouldUseStarsForLikes) {
typeIcon = R.drawable.ic_activity_action_favorite;
color = ContextCompat.getColor(context, R.color.highlight_favorite);
if (byFriends) {
title = getTitleStringByFriends(resources, manager, R.string.activity_by_friends_favorite,
R.string.activity_by_friends_favorite_multi, sources, activity.target_statuses, nameFirst);
} else {
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorite,
R.string.activity_about_me_favorite_multi, sources, nameFirst);
}
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_favorite,
R.string.activity_about_me_favorite_multi, sources, nameFirst);
} else {
typeIcon = R.drawable.ic_activity_action_like;
color = ContextCompat.getColor(context, R.color.highlight_like);
if (byFriends) {
title = getTitleStringByFriends(resources, manager, R.string.activity_by_friends_like,
R.string.activity_by_friends_like_multi, sources, activity.target_statuses, nameFirst);
} else {
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_like,
R.string.activity_about_me_like_multi, sources, nameFirst);
}
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_like,
R.string.activity_about_me_like_multi, sources, nameFirst);
}
final CharSequence summary = generateTextOnlySummary(context, activity.target_statuses);
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
@ -89,19 +74,13 @@ public class ActivityTitleSummaryMessage {
int typeIcon = R.drawable.ic_activity_action_retweet;
int color = ContextCompat.getColor(context, R.color.highlight_retweet);
CharSequence title;
if (byFriends) {
title = getTitleStringByFriends(resources, manager, R.string.activity_by_friends_retweet,
R.string.activity_by_friends_retweet_multi, sources, activity.target_statuses, nameFirst);
} else {
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweet,
R.string.activity_about_me_retweet_multi, sources, nameFirst);
}
title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweet,
R.string.activity_about_me_retweet_multi, sources, nameFirst);
final CharSequence summary = generateTextOnlySummary(context,
activity.target_object_statuses);
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
}
case Activity.Action.FAVORITED_RETWEET: {
if (byFriends) return null;
int typeIcon;
int color;
CharSequence title;
@ -121,7 +100,6 @@ public class ActivityTitleSummaryMessage {
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
}
case Activity.Action.RETWEETED_RETWEET: {
if (byFriends) return null;
int typeIcon = R.drawable.ic_activity_action_retweet;
int color = ContextCompat.getColor(context, R.color.highlight_retweet);
CharSequence title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_retweet,
@ -131,7 +109,6 @@ public class ActivityTitleSummaryMessage {
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
}
case Activity.Action.RETWEETED_MENTION: {
if (byFriends) return null;
int typeIcon = R.drawable.ic_activity_action_retweet;
int color = ContextCompat.getColor(context, R.color.highlight_retweet);
CharSequence title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_mention,
@ -141,7 +118,6 @@ public class ActivityTitleSummaryMessage {
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
}
case Activity.Action.FAVORITED_MENTION: {
if (byFriends) return null;
int typeIcon;
int color;
CharSequence title;
@ -161,7 +137,6 @@ public class ActivityTitleSummaryMessage {
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
}
case Activity.Action.LIST_CREATED: {
if (!byFriends) return null;
int typeIcon = R.drawable.ic_activity_action_list_added;
CharSequence title = getTitleStringByFriends(resources, manager, R.string.activity_by_friends_list_created,
R.string.activity_by_friends_list_created_multi, sources,
@ -178,7 +153,6 @@ public class ActivityTitleSummaryMessage {
return new ActivityTitleSummaryMessage(typeIcon, defaultColor, title, sb);
}
case Activity.Action.LIST_MEMBER_ADDED: {
if (byFriends) return null;
CharSequence title;
int icon = R.drawable.ic_activity_action_list_added;
if ((sources.length == 1) && (activity.target_object_user_lists != null)
@ -218,7 +192,6 @@ public class ActivityTitleSummaryMessage {
return new ActivityTitleSummaryMessage(typeIcon, color, title, null);
}
case Activity.Action.MEDIA_TAGGED: {
if (byFriends) return null;
int typeIcon = R.drawable.ic_activity_action_media_tagged;
int color = ContextCompat.getColor(context, R.color.highlight_tagged);
CharSequence title;
@ -229,7 +202,6 @@ public class ActivityTitleSummaryMessage {
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
}
case Activity.Action.FAVORITED_MEDIA_TAGGED: {
if (byFriends) return null;
int typeIcon;
int color;
CharSequence title;
@ -249,7 +221,6 @@ public class ActivityTitleSummaryMessage {
return new ActivityTitleSummaryMessage(typeIcon, color, title, summary);
}
case Activity.Action.RETWEETED_MEDIA_TAGGED: {
if (byFriends) return null;
int typeIcon = R.drawable.ic_activity_action_retweet;
int color = ContextCompat.getColor(context, R.color.highlight_retweet);
CharSequence title = getTitleStringAboutMe(resources, manager, R.string.activity_about_me_retweeted_media_tagged,

View File

@ -1431,7 +1431,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
if (ArrayUtils.isEmpty(sources)) continue;
final ActivityTitleSummaryMessage message = ActivityTitleSummaryMessage.get(context,
mUserColorNameManager, activity, sources,
0, false, mUseStarForLikes, mNameFirst);
0, mUseStarForLikes, mNameFirst);
if (message != null) {
final CharSequence summary = message.getSummary();
if (TextUtils.isEmpty(summary)) {

View File

@ -0,0 +1,69 @@
package org.mariotaku.ktextension
import android.os.Build
import java.util.*
/**
* Created by mariotaku on 16/8/15.
*/
/**
* Modified from:
* https://github.com/apache/cordova-plugin-globalization/blob/master/src/android/Globalization.java
* Returns a well-formed ITEF BCP 47 language tag representing this locale string
* identifier for the client's current locale
* @return String: The BCP 47 language tag for the current locale
*/
val Locale.bcp47Tag: String
get() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return toLanguageTag()
}
// we will use a dash as per BCP 47
val SEP = '-'
var language = language
var country = country
var variant = variant
// special case for Norwegian Nynorsk since "NY" cannot be a variant as per BCP 47
// this goes before the string matching since "NY" wont pass the variant checks
if (language == "no" && country == "NO" && variant == "NY") {
language = "nn"
country = "NO"
variant = ""
}
if (language.isEmpty() || !language.matches("\\p{Alpha}{2,8}".toRegex())) {
language = "und" // Follow the Locale#toLanguageTag() implementation
// which says to return "und" for Undetermined
} else if (language == "iw") {
language = "he" // correct deprecated "Hebrew"
} else if (language == "in") {
language = "id" // correct deprecated "Indonesian"
} else if (language == "ji") {
language = "yi" // correct deprecated "Yiddish"
}
// ensure valid country code, if not well formed, it's omitted
if (!country.matches("\\p{Alpha}{2}|\\p{Digit}{3}".toRegex())) {
country = ""
}
// variant subtags that begin with a letter must be at least 5 characters long
if (!variant.matches("\\p{Alnum}{5,8}|\\p{Digit}\\p{Alnum}{3}".toRegex())) {
variant = ""
}
val bcp47Tag = StringBuilder(language)
if (!country.isEmpty()) {
bcp47Tag.append(SEP).append(country)
}
if (!variant.isEmpty()) {
bcp47Tag.append(SEP).append(variant)
}
return bcp47Tag.toString()
}

View File

@ -64,6 +64,7 @@ import com.squareup.otto.Subscribe
import edu.tsinghua.hotmobi.HotMobiLogger
import edu.tsinghua.hotmobi.model.MediaEvent
import edu.tsinghua.hotmobi.model.TimelineType
import edu.tsinghua.hotmobi.model.TranslateEvent
import edu.tsinghua.hotmobi.model.TweetEvent
import kotlinx.android.synthetic.main.adapter_item_status_count_label.view.*
import kotlinx.android.synthetic.main.fragment_status.*
@ -432,7 +433,8 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
}
val event = TweetEvent.create(activity, status, TimelineType.OTHER)
event.setAction(TweetEvent.Action.OPEN)
event.action = TweetEvent.Action.OPEN
event.isHasTranslateFeature = Utils.isOfficialCredentials(context, credentials)
mStatusEvent = event
} else if (readPosition != null) {
restoreReadPosition(readPosition)
@ -555,6 +557,11 @@ class StatusFragment : BaseSupportFragment(), LoaderCallbacks<SingleResponse<Par
private fun displayTranslation(translation: TranslationResult) {
adapter?.translationResult = translation
val status = this.status
if (status != null) {
val event = TranslateEvent.create(context, status, translation.translatedLang)
HotMobiLogger.getInstance(context).log(status.account_key, event);
}
}
private fun saveReadPosition(): ReadPosition? {

View File

@ -94,7 +94,7 @@ class ConversationLoader(
}
@Throws(MicroBlogException::class)
protected fun showConversationCompat(twitter: MicroBlog,
private fun showConversationCompat(twitter: MicroBlog,
credentials: ParcelableCredentials,
status: ParcelableStatus,
loadReplies: Boolean): List<Status> {

View File

@ -25,6 +25,7 @@ import android.app.Service
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.Point
import android.net.Uri
import android.os.Handler
import android.os.Looper
@ -39,6 +40,8 @@ import android.util.Pair
import android.widget.Toast
import com.twitter.Extractor
import edu.tsinghua.hotmobi.HotMobiLogger
import edu.tsinghua.hotmobi.model.MediaEvent
import edu.tsinghua.hotmobi.model.MediaUploadEvent
import edu.tsinghua.hotmobi.model.TimelineType
import edu.tsinghua.hotmobi.model.TweetEvent
import org.mariotaku.abstask.library.ManualTaskStarter
@ -326,7 +329,10 @@ class BackgroundOperationService : IntentService("background_operation"), Consta
for (status in result.statuses) {
if (status == null) continue
val event = TweetEvent.create(context, status, TimelineType.OTHER)
event.setAction(TweetEvent.Action.TWEET)
event.action = TweetEvent.Action.TWEET
if (item.in_reply_to_status != null && item.in_reply_to_status.user_is_protected) {
event.inReplyToId = item.in_reply_to_status.id
}
HotMobiLogger.getInstance(context).log(status.account_key, event)
}
}
@ -362,19 +368,19 @@ class BackgroundOperationService : IntentService("background_operation"), Consta
else -> {
if (imageUri != null) {
val mediaUri = Uri.parse(imageUri)
var body: FileBody? = null
var bodyAndSize: Pair<Body, Point>? = null
try {
body = UpdateStatusTask.getBodyFromMedia(this, mediaLoader,
bodyAndSize = UpdateStatusTask.getBodyFromMedia(this, mediaLoader,
mediaUri, null, ParcelableMedia.Type.IMAGE,
MessageMediaUploadListener(this, notificationManager,
builder, text))
val uploadResp = uploadMedia(twitterUpload, body)
val uploadResp = uploadMedia(twitterUpload, bodyAndSize.first)
val response = twitter.sendDirectMessage(recipientId,
text, uploadResp.id)
directMessage = ParcelableDirectMessageUtils.fromDirectMessage(response,
accountKey, true)
} finally {
Utils.closeSilently(body)
Utils.closeSilently(bodyAndSize?.first)
}
val path = Utils.getImagePathFromUri(this, mediaUri)
if (path != null) {

View File

@ -173,8 +173,7 @@ abstract class GetActivitiesTask(protected val context: Context) : AbstractTask<
val whereArgs = arrayOf(credentials.account_key.toString(), deleteBound[0].toString(), deleteBound[1].toString())
val rowsDeleted = cr.delete(writeUri, where.sql, whereArgs)
// Why loadItemLimit / 2? because it will not acting strange in most cases
val insertGap = valuesList.size >= loadItemLimit && !noItemsBefore && olderCount > 0
&& rowsDeleted <= 0 && activities.size > loadItemLimit / 2
val insertGap = !noItemsBefore && olderCount > 0 && rowsDeleted <= 0 && activities.size > loadItemLimit / 2
if (insertGap && !valuesList.isEmpty()) {
valuesList[valuesList.size - 1].put(Activities.IS_GAP, true)
}
@ -187,7 +186,7 @@ abstract class GetActivitiesTask(protected val context: Context) : AbstractTask<
val noGapWhere = Expression.and(Expression.equalsArgs(Activities.ACCOUNT_KEY),
Expression.equalsArgs(Activities.MIN_REQUEST_POSITION),
Expression.equalsArgs(Activities.MAX_REQUEST_POSITION)).sql
val noGapWhereArgs = arrayOf(credentials.toString(), maxId, maxId)
val noGapWhereArgs = arrayOf(credentials.account_key.toString(), maxId, maxId)
cr.update(writeUri, noGapValues, noGapWhere, noGapWhereArgs)
}
}

View File

@ -11,6 +11,8 @@ import android.support.annotation.WorkerThread
import android.text.TextUtils
import android.util.Pair
import com.nostra13.universalimageloader.core.assist.ImageSize
import edu.tsinghua.hotmobi.HotMobiLogger
import edu.tsinghua.hotmobi.model.MediaUploadEvent
import org.apache.commons.lang3.ArrayUtils
import org.apache.commons.lang3.math.NumberUtils
import org.mariotaku.abstask.library.AbstractTask
@ -221,7 +223,7 @@ class UpdateStatusTask(
for (i in 0 until pendingUpdate.length) {
val account = statusUpdate.accounts[i]
val microBlog = MicroBlogAPIFactory.getInstance(context, account.account_key, true)
var body: Body? = null
var bodyAndSize: Pair<Body, Point>? = null
try {
when (ParcelableAccountUtils.getAccountType(account)) {
ParcelableAccount.Type.FANFOU -> {
@ -233,13 +235,13 @@ class UpdateStatusTask(
context.getString(R.string.error_too_many_photos_fanfou))
} else {
val sizeLimit = Point(2048, 1536)
body = getBodyFromMedia(context, mediaLoader,
bodyAndSize = getBodyFromMedia(context, mediaLoader,
Uri.parse(statusUpdate.media[0].uri),
sizeLimit, statusUpdate.media[0].type,
ContentLengthInputStream.ReadListener { length, position ->
stateCallback.onUploadingProgressChanged(-1, position, length)
})
val photoUpdate = PhotoStatusUpdate(body,
val photoUpdate = PhotoStatusUpdate(bodyAndSize.first,
pendingUpdate.overrideTexts[i])
val requestResult = microBlog.uploadPhoto(photoUpdate)
@ -265,7 +267,7 @@ class UpdateStatusTask(
} catch (e: MicroBlogException) {
result.exceptions[i] = e
} finally {
Utils.closeSilently(body)
Utils.closeSilently(bodyAndSize?.first)
}
}
return result
@ -280,9 +282,7 @@ class UpdateStatusTask(
if (ArrayUtils.isEmpty(update.media)) return
val ownersList = update.accounts.filter {
ParcelableAccount.Type.TWITTER == ParcelableAccountUtils.getAccountType(it)
}.map {
it.account_key
}
}.map(ParcelableAccount::account_key)
val ownerIds = ownersList.map {
it.id
}.toTypedArray()
@ -418,25 +418,29 @@ class UpdateStatusTask(
val mediaIds = update.media.mapIndexed { index, media ->
val resp: MediaUploadResponse
//noinspection TryWithIdenticalCatches
var body: Body? = null
var bodyAndSize: Pair<Body, Point>? = null
try {
val sizeLimit = Point(2048, 1536)
body = getBodyFromMedia(context, mediaLoader, Uri.parse(media.uri), sizeLimit,
bodyAndSize = getBodyFromMedia(context, mediaLoader, Uri.parse(media.uri), sizeLimit,
media.type, ContentLengthInputStream.ReadListener { length, position ->
stateCallback.onUploadingProgressChanged(index, position, length)
})
val mediaUploadEvent = MediaUploadEvent.create(context, media)
mediaUploadEvent.setFileSize(bodyAndSize.first.length())
mediaUploadEvent.setGeometry(bodyAndSize.second.x, bodyAndSize.second.y)
if (chucked) {
resp = uploadMediaChucked(upload, body, ownerIds)
resp = uploadMediaChucked(upload, bodyAndSize.first, ownerIds)
} else {
resp = upload.uploadMedia(body, ownerIds)
resp = upload.uploadMedia(bodyAndSize.first, ownerIds)
}
mediaUploadEvent.markEnd()
HotMobiLogger.getInstance(context).log(mediaUploadEvent)
} catch (e: IOException) {
throw UploadException(e)
} catch (e: MicroBlogException) {
throw UploadException(e)
} finally {
Utils.closeSilently(body)
Utils.closeSilently(bodyAndSize?.first)
}
if (media.alt_text?.isNotEmpty() ?: false) {
try {
@ -663,9 +667,10 @@ class UpdateStatusTask(
fun getBodyFromMedia(context: Context, mediaLoader: MediaLoaderWrapper,
mediaUri: Uri, sizeLimit: Point? = null,
@ParcelableMedia.Type type: Int,
readListener: ContentLengthInputStream.ReadListener): FileBody {
readListener: ContentLengthInputStream.ReadListener): Pair<Body, Point> {
val resolver = context.contentResolver
var mediaType = resolver.getType(mediaUri)
val size = Point()
val cis = run {
if (type == ParcelableMedia.Type.IMAGE && sizeLimit != null) {
val length: Long
@ -675,6 +680,7 @@ class UpdateStatusTask(
if (o.outMimeType != null) {
mediaType = o.outMimeType
}
size.set(o.outWidth, o.outHeight)
o.inSampleSize = Utils.calculateInSampleSize(o.outWidth, o.outHeight,
sizeLimit.x, sizeLimit.y)
o.inJustDecodeBounds = false
@ -683,6 +689,7 @@ class UpdateStatusTask(
ImageSize(o.outWidth, o.outHeight).scaleDown(o.inSampleSize))
if (bitmap != null) {
size.set(bitmap.width, bitmap.height)
val os = DirectByteArrayOutputStream()
when (mediaType) {
"image/png", "image/x-png", "image/webp", "image-x-webp" -> {
@ -709,7 +716,7 @@ class UpdateStatusTask(
} else {
contentType = ContentType.parse(mediaType!!)
}
return FileBody(cis, "attachment", cis.length(), contentType)
return Pair(FileBody(cis, "attachment", cis.length(), contentType), size)
}
internal class DirectByteArrayOutputStream : ByteArrayOutputStream {

View File

@ -87,7 +87,7 @@ class ActivityTitleSummaryViewHolder(private val adapter: ParcelableActivitiesAd
val sources = ParcelableActivityUtils.getAfterFilteredSources(activity)
val message = ActivityTitleSummaryMessage.get(context,
adapter.userColorNameManager, activity, sources, activityTypeView.defaultColor,
byFriends, adapter.useStarsForLikes, adapter.isNameFirst)
adapter.useStarsForLikes, adapter.isNameFirst)
if (message == null) {
showNotSupported()
return

View File

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Twidere - Twitter client for Android
~
~ Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
~
~ This program is free software: you can redistribute it and/or modify
~ it under the terms of the GNU General Public License as published by
~ the Free Software Foundation, either version 3 of the License, or
~ (at your option) any later version.
~
~ This program is distributed in the hope that it will be useful,
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
~ GNU General Public License for more details.
~
~ You should have received a copy of the GNU General Public License
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
-->
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/list_details_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>