mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-02 17:56:56 +01:00
improved conversation loader
This commit is contained in:
parent
4a4defaa5d
commit
94788c7c3c
@ -86,19 +86,19 @@ public class ParcelableStatus implements Parcelable, Comparable<ParcelableStatus
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "user_id")
|
||||
@CursorField(Statuses.USER_ID)
|
||||
public long user_id;
|
||||
public long user_id = -1;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_id")
|
||||
@CursorField(Statuses.RETWEET_ID)
|
||||
public long retweet_id;
|
||||
public long retweet_id = -1;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweeted_by_user_id")
|
||||
@CursorField(Statuses.RETWEETED_BY_USER_ID)
|
||||
public long retweeted_by_user_id;
|
||||
public long retweeted_by_user_id = -1;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_timestamp")
|
||||
@CursorField(Statuses.RETWEET_TIMESTAMP)
|
||||
public long retweet_timestamp;
|
||||
public long retweet_timestamp = -1;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "retweet_count")
|
||||
@CursorField(Statuses.RETWEET_COUNT)
|
||||
|
@ -36,4 +36,9 @@ public class Nullables {
|
||||
return list;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static <T> T assertNonNull(@Nullable T object) {
|
||||
if (object == null) throw new NullPointerException();
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
@ -171,12 +171,18 @@ public class TwitterContentUtils {
|
||||
}
|
||||
|
||||
private static final CharSequenceTranslator UNESCAPE_TWITTER_RAW_TEXT = new LookupTranslator(EntityArrays.BASIC_UNESCAPE());
|
||||
private static final CharSequenceTranslator ESCAPE_TWITTER_RAW_TEXT = new LookupTranslator(EntityArrays.BASIC_ESCAPE());
|
||||
|
||||
public static String unescapeTwitterStatusText(final CharSequence text) {
|
||||
if (text == null) return null;
|
||||
return UNESCAPE_TWITTER_RAW_TEXT.translate(text);
|
||||
}
|
||||
|
||||
public static String escapeTwitterStatusText(final CharSequence text) {
|
||||
if (text == null) return null;
|
||||
return ESCAPE_TWITTER_RAW_TEXT.translate(text);
|
||||
}
|
||||
|
||||
public static <T extends List<Status>> T getStatusesWithQuoteData(Twitter twitter, @NonNull T list) throws TwitterException {
|
||||
LongSparseMap<Status> quotes = new LongSparseMap<>();
|
||||
// Phase 1: collect all statuses contains a status link, and put it in the map
|
||||
|
@ -27,7 +27,9 @@ import android.content.SharedPreferences;
|
||||
import android.location.Location;
|
||||
import android.os.BatteryManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mariotaku.twidere.BuildConfig;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.util.JsonSerializer;
|
||||
@ -58,6 +60,7 @@ import edu.tsinghua.hotmobi.model.ScreenEvent;
|
||||
import edu.tsinghua.hotmobi.model.ScrollRecord;
|
||||
import edu.tsinghua.hotmobi.model.SessionEvent;
|
||||
import edu.tsinghua.hotmobi.model.TweetEvent;
|
||||
import edu.tsinghua.hotmobi.model.UploadLogEvent;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/8/10.
|
||||
@ -107,6 +110,8 @@ public class HotMobiLogger {
|
||||
return "notification";
|
||||
} else if (event instanceof ScreenEvent) {
|
||||
return "screen";
|
||||
} else if (event instanceof UploadLogEvent) {
|
||||
return "upload_log";
|
||||
}
|
||||
throw new UnsupportedOperationException("Unknown event type " + event);
|
||||
}
|
||||
@ -187,6 +192,18 @@ public class HotMobiLogger {
|
||||
getInstance(context).log(record, null);
|
||||
}
|
||||
|
||||
public static boolean log(final String msg) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1];
|
||||
final String fullName = ste.getClassName();
|
||||
final String name = fullName.substring(fullName.lastIndexOf('.'));
|
||||
final String tag = name + "." + ste.getMethodName();
|
||||
Log.d(tag, msg);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
public <T> void log(long accountId, final T event, final PreProcessing<T> preProcessing) {
|
||||
mExecutor.execute(new WriteLogTask<>(mApplication, accountId, event, preProcessing));
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
import edu.tsinghua.hotmobi.model.UploadLogEvent;
|
||||
|
||||
/**
|
||||
* Upload logs to target server
|
||||
@ -67,7 +67,7 @@ public class UploadLogsTask implements Runnable {
|
||||
final double deltaDays = (System.currentTimeMillis() - lastUpload) /
|
||||
(double) HotMobiLogger.UPLOAD_INTERVAL_MILLIS;
|
||||
if (deltaDays < 1) {
|
||||
SpiceProfilingUtil.log("Last uploaded was conducted in 1 day ago.");
|
||||
HotMobiLogger.log("Last uploaded was conducted in 1 day ago.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -106,8 +106,13 @@ public class UploadLogsTask implements Runnable {
|
||||
builder.headers(headers);
|
||||
body = new FileTypedData(logFile);
|
||||
builder.body(body);
|
||||
final UploadLogEvent uploadLogEvent = UploadLogEvent.create(context, logFile);
|
||||
response = client.execute(builder.build());
|
||||
if (response.isSuccessful()) {
|
||||
uploadLogEvent.markEnd();
|
||||
if (!uploadLogEvent.shouldSkip()) {
|
||||
HotMobiLogger.getInstance(context).log(uploadLogEvent);
|
||||
}
|
||||
succeeded &= logFile.delete();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
@ -31,7 +31,7 @@ import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.hannesdorfmann.parcelableplease.annotation.ParcelablePlease;
|
||||
|
||||
import org.mariotaku.twidere.model.AccountPreferences;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
@ -92,7 +92,7 @@ public class SessionEvent extends BaseEvent implements Parcelable {
|
||||
|
||||
public void dumpPreferences(Context context) {
|
||||
final HashMap<String, String> preferences = new HashMap<>();
|
||||
for (AccountPreferences pref : AccountPreferences.getAccountPreferences(context, Utils.getAccountIds(context))) {
|
||||
for (AccountPreferences pref : AccountPreferences.getAccountPreferences(context, DataStoreUtils.getAccountIds(context))) {
|
||||
final long accountId = pref.getAccountId();
|
||||
preferences.put("notification_" + accountId + "_home", String.valueOf(pref.isHomeTimelineNotificationEnabled()));
|
||||
preferences.put("notification_" + accountId + "_interactions", String.valueOf(pref.isInteractionsNotificationEnabled()));
|
||||
|
@ -0,0 +1,77 @@
|
||||
package edu.tsinghua.hotmobi.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
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 java.io.File;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/1/2.
|
||||
*/
|
||||
@ParcelablePlease
|
||||
@JsonObject
|
||||
public class UploadLogEvent extends BaseEvent implements Parcelable {
|
||||
public static final Creator<UploadLogEvent> CREATOR = new Creator<UploadLogEvent>() {
|
||||
public UploadLogEvent createFromParcel(Parcel source) {
|
||||
UploadLogEvent target = new UploadLogEvent();
|
||||
UploadLogEventParcelablePlease.readFromParcel(target, source);
|
||||
return target;
|
||||
}
|
||||
|
||||
public UploadLogEvent[] newArray(int size) {
|
||||
return new UploadLogEvent[size];
|
||||
}
|
||||
};
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "file_name")
|
||||
String fileName;
|
||||
@ParcelableThisPlease
|
||||
@JsonField(name = "file_length")
|
||||
|
||||
long fileLength;
|
||||
|
||||
public long getFileLength() {
|
||||
|
||||
return fileLength;
|
||||
}
|
||||
|
||||
public void setFileLength(long fileLength) {
|
||||
this.fileLength = fileLength;
|
||||
}
|
||||
|
||||
public String getFileName() {
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public void setFileName(String fileName) {
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
UploadLogEventParcelablePlease.writeToParcel(this, dest, flags);
|
||||
}
|
||||
|
||||
public static UploadLogEvent create(Context context, File file) {
|
||||
UploadLogEvent event = new UploadLogEvent();
|
||||
event.markStart(context);
|
||||
event.setFileLength(file.length());
|
||||
event.setFileName(file.getName());
|
||||
return event;
|
||||
}
|
||||
|
||||
public boolean shouldSkip() {
|
||||
return fileName.contains("upload_log");
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package edu.tsinghua.spice.Task;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/21/15.
|
||||
*/
|
||||
|
||||
public final class SpiceFileFilter implements FileFilter {
|
||||
|
||||
@Override
|
||||
public boolean accept(final File file) {
|
||||
return file.isFile() && "spi".equalsIgnoreCase(getExtension(file));
|
||||
}
|
||||
|
||||
static String getExtension(final File file) {
|
||||
final String name = file.getName();
|
||||
final int pos = name.lastIndexOf('.');
|
||||
if (pos == -1) return null;
|
||||
return name.substring(pos + 1);
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package edu.tsinghua.spice.Utilies;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.BatteryManager;
|
||||
import android.util.Log;
|
||||
|
||||
import org.mariotaku.twidere.BuildConfig;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/20/15.
|
||||
*/
|
||||
|
||||
public class SpiceProfilingUtil {
|
||||
|
||||
public static final String FILE_NAME_PROFILE = "Profile_SPICE";
|
||||
public static final String FILE_NAME_LOCATION = "Location_SPICE";
|
||||
public static final String FILE_NAME_APP = "App_SPICE";
|
||||
public static final String FILE_NAME_NETWORK = "Network_SPICE";
|
||||
public static final String FILE_NAME_ONWIFI = "onWifi_SPICE";
|
||||
public static final String FILE_NAME_ONLAUNCH = "onLaunch_SPICE";
|
||||
public static final String FILE_NAME_SCREEN = "Screen_SPICE";
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
public static boolean isCharging(final Context context) {
|
||||
if (context == null) return false;
|
||||
final Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
if (intent == null) return false;
|
||||
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||
return plugged == BatteryManager.BATTERY_PLUGGED_AC
|
||||
|| plugged == BatteryManager.BATTERY_PLUGGED_USB
|
||||
|| plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||
}
|
||||
|
||||
public static boolean log(final String msg) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1];
|
||||
final String fullName = ste.getClassName();
|
||||
final String name = fullName.substring(fullName.lastIndexOf('.'));
|
||||
final String tag = name + "." + ste.getMethodName();
|
||||
Log.d(tag, msg);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
}
|
@ -474,7 +474,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
||||
intent.putExtra(EXTRA_ACCOUNT_IDS, accountIds);
|
||||
if (accountIds.length > 0) {
|
||||
final long account_id = accountIds[0];
|
||||
intent.putExtra(EXTRA_NAME, Utils.getAccountName(this, account_id));
|
||||
intent.putExtra(EXTRA_NAME, DataStoreUtils.getAccountName(this, account_id));
|
||||
intent.putExtra(EXTRA_SCREEN_NAME, DataStoreUtils.getAccountScreenName(this, account_id));
|
||||
}
|
||||
if (mInReplyToStatusId > 0) {
|
||||
@ -605,7 +605,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements OnMenuIte
|
||||
mValidator = new TwidereValidator(this);
|
||||
setContentView(R.layout.activity_compose);
|
||||
setFinishOnTouchOutside(false);
|
||||
final long[] defaultAccountIds = Utils.getAccountIds(this);
|
||||
final long[] defaultAccountIds = DataStoreUtils.getAccountIds(this);
|
||||
if (defaultAccountIds.length <= 0) {
|
||||
final Intent intent = new Intent(INTENT_ACTION_TWITTER_LOGIN);
|
||||
intent.setClass(this, SignInActivity.class);
|
||||
|
@ -347,7 +347,7 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
|
||||
}
|
||||
mMultiSelectHandler = new MultiSelectEventHandler(this);
|
||||
mMultiSelectHandler.dispatchOnCreate();
|
||||
if (!Utils.hasAccount(this)) {
|
||||
if (!DataStoreUtils.hasAccount(this)) {
|
||||
final Intent signInIntent = new Intent(INTENT_ACTION_TWITTER_LOGIN);
|
||||
signInIntent.setClass(this, SignInActivity.class);
|
||||
startActivity(signInIntent);
|
||||
|
@ -33,6 +33,7 @@ import org.mariotaku.twidere.model.DraftItemCursorIndices;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableMediaUpdate;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
import org.mariotaku.twidere.util.SharedPreferencesWrapper;
|
||||
@ -43,8 +44,6 @@ import org.mariotaku.twidere.view.holder.DraftViewHolder;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.getAccountColors;
|
||||
|
||||
public class DraftsAdapter extends SimpleCursorAdapter implements Constants {
|
||||
|
||||
@Inject
|
||||
@ -81,7 +80,7 @@ public class DraftsAdapter extends SimpleCursorAdapter implements Constants {
|
||||
} else {
|
||||
holder.media_preview_container.setVisibility(View.GONE);
|
||||
}
|
||||
holder.content.drawEnd(getAccountColors(context, accountIds));
|
||||
holder.content.drawEnd(DataStoreUtils.getAccountColors(context, accountIds));
|
||||
holder.setTextSize(mTextSize);
|
||||
final boolean emptyContent = TextUtils.isEmpty(text);
|
||||
if (emptyContent) {
|
||||
|
@ -0,0 +1,65 @@
|
||||
package org.mariotaku.twidere.api.twitter.model;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/1/3.
|
||||
*/
|
||||
public class StatusUtils {
|
||||
|
||||
public static Status fromParcelableStatus(@NonNull ParcelableStatus parcelable) {
|
||||
Status status = new Status();
|
||||
status.id = parcelable.id;
|
||||
status.text = TwitterContentUtils.escapeTwitterStatusText(parcelable.text_plain);
|
||||
status.createdAt = new Date(parcelable.timestamp);
|
||||
status.inReplyToStatusId = parcelable.in_reply_to_status_id;
|
||||
status.inReplyToUserId = parcelable.in_reply_to_user_id;
|
||||
status.inReplyToScreenName = parcelable.in_reply_to_screen_name;
|
||||
if (parcelable.is_retweet) {
|
||||
Status retweet = status.retweetedStatus = new Status();
|
||||
retweet.id = parcelable.retweet_id;
|
||||
retweet.text = TwitterContentUtils.escapeTwitterStatusText(parcelable.text_plain);
|
||||
retweet.createdAt = new Date(parcelable.retweet_timestamp);
|
||||
User retweetUser = retweet.user = new User();
|
||||
retweetUser.id = parcelable.user_id;
|
||||
retweetUser.screenName = parcelable.user_screen_name;
|
||||
retweetUser.name = parcelable.user_name;
|
||||
retweetUser.profileBackgroundImageUrl = parcelable.user_profile_image_url;
|
||||
|
||||
User user = status.user = new User();
|
||||
user.id = parcelable.retweeted_by_user_id;
|
||||
user.name = parcelable.retweeted_by_user_name;
|
||||
user.screenName = parcelable.retweeted_by_user_screen_name;
|
||||
user.profileImageUrl = parcelable.retweeted_by_user_profile_image;
|
||||
} else if (parcelable.is_quote) {
|
||||
Status quote = status.quotedStatus = new Status();
|
||||
quote.id = parcelable.quoted_id;
|
||||
quote.text = TwitterContentUtils.escapeTwitterStatusText(parcelable.quoted_text_plain);
|
||||
quote.createdAt = new Date(parcelable.quoted_timestamp);
|
||||
User quotedUser = quote.user = new User();
|
||||
quotedUser.id = parcelable.quoted_user_id;
|
||||
quotedUser.name = parcelable.quoted_user_name;
|
||||
quotedUser.screenName = parcelable.quoted_user_screen_name;
|
||||
quotedUser.profileImageUrl = parcelable.quoted_user_profile_image;
|
||||
|
||||
User user = status.user = new User();
|
||||
user.id = parcelable.user_id;
|
||||
user.screenName = parcelable.user_screen_name;
|
||||
user.name = parcelable.user_name;
|
||||
user.profileBackgroundImageUrl = parcelable.user_profile_image_url;
|
||||
} else {
|
||||
User user = status.user = new User();
|
||||
user.id = parcelable.user_id;
|
||||
user.screenName = parcelable.user_screen_name;
|
||||
user.name = parcelable.user_name;
|
||||
user.profileBackgroundImageUrl = parcelable.user_profile_image_url;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
}
|
@ -64,6 +64,7 @@ import org.mariotaku.twidere.activity.support.CustomTabEditorActivity;
|
||||
import org.mariotaku.twidere.model.CustomTabConfiguration;
|
||||
import org.mariotaku.twidere.model.CustomTabConfiguration.CustomTabConfigurationComparator;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.holder.TwoLineWithIconViewHolder;
|
||||
@ -80,7 +81,6 @@ import static org.mariotaku.twidere.util.CustomTabUtils.getTabIconObject;
|
||||
import static org.mariotaku.twidere.util.CustomTabUtils.getTabTypeName;
|
||||
import static org.mariotaku.twidere.util.CustomTabUtils.isTabAdded;
|
||||
import static org.mariotaku.twidere.util.CustomTabUtils.isTabTypeValid;
|
||||
import static org.mariotaku.twidere.util.Utils.getAccountIds;
|
||||
|
||||
public class CustomTabsFragment extends BaseFragment implements LoaderCallbacks<Cursor>,
|
||||
MultiChoiceModeListener, OnItemClickListener {
|
||||
@ -221,7 +221,7 @@ public class CustomTabsFragment extends BaseFragment implements LoaderCallbacks<
|
||||
final Resources res = getResources();
|
||||
final boolean hasOfficialKeyAccounts = Utils.hasAccountSignedWithOfficialKeys(getActivity());
|
||||
final boolean forcePrivateAPI = mPreferences.getBoolean(KEY_FORCE_USING_PRIVATE_APIS, false);
|
||||
final long[] accountIds = getAccountIds(getActivity());
|
||||
final long[] accountIds = DataStoreUtils.getAccountIds(getActivity());
|
||||
final MenuItem itemAdd = menu.findItem(R.id.add_submenu);
|
||||
if (itemAdd != null && itemAdd.hasSubMenu()) {
|
||||
final SubMenu subMenu = itemAdd.getSubMenu();
|
||||
|
@ -111,6 +111,7 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Statuses;
|
||||
import org.mariotaku.twidere.util.AsyncTaskUtils;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.CompareUtils;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.HtmlSpanBuilder;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutCallback;
|
||||
@ -197,14 +198,13 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
mStatusAdapter.setRepliesLoading(true);
|
||||
mStatusAdapter.setConversationsLoading(true);
|
||||
mStatusAdapter.updateItemDecoration();
|
||||
final long accountId = args.getLong(EXTRA_ACCOUNT_ID, -1);
|
||||
final String screenName = args.getString(EXTRA_SCREEN_NAME);
|
||||
final long statusId = args.getLong(EXTRA_STATUS_ID, -1);
|
||||
final ParcelableStatus status = args.getParcelable(EXTRA_STATUS);
|
||||
final long maxId = args.getLong(EXTRA_MAX_ID, -1);
|
||||
final long sinceId = args.getLong(EXTRA_SINCE_ID, -1);
|
||||
final boolean twitterOptimizedSearches = mPreferences.getBoolean(KEY_TWITTER_OPTIMIZED_SEARCHES);
|
||||
final ConversationLoader loader = new ConversationLoader(getActivity(), accountId,
|
||||
statusId, screenName, sinceId, maxId, null, true);
|
||||
assert status != null;
|
||||
final ConversationLoader loader = new ConversationLoader(getActivity(), status, sinceId,
|
||||
maxId, null, true, twitterOptimizedSearches);
|
||||
loader.setComparator(ParcelableStatus.REVERSE_ID_COMPARATOR);
|
||||
return loader;
|
||||
}
|
||||
@ -618,7 +618,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
final Bundle args = new Bundle();
|
||||
args.putLong(EXTRA_ACCOUNT_ID, status.account_id);
|
||||
args.putLong(EXTRA_STATUS_ID, status.is_retweet ? status.retweet_id : status.id);
|
||||
args.putString(EXTRA_SCREEN_NAME, status.is_retweet ? status.retweeted_by_user_screen_name : status.user_screen_name);
|
||||
args.putParcelable(EXTRA_STATUS, status);
|
||||
if (mConversationLoaderInitialized) {
|
||||
getLoaderManager().restartLoader(LOADER_ID_STATUS_CONVERSATIONS, args, mConversationsLoaderCallback);
|
||||
return;
|
||||
@ -917,7 +917,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
retweetedByView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
profileContainer.drawEnd(Utils.getAccountColor(context, status.account_id));
|
||||
profileContainer.drawEnd(DataStoreUtils.getAccountColor(context, status.account_id));
|
||||
|
||||
final int layoutPosition = getLayoutPosition();
|
||||
if (status.is_quote && ArrayUtils.isEmpty(status.media)) {
|
||||
@ -1542,16 +1542,17 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
||||
final ParcelableStatus status = mStatus;
|
||||
if (status == null) return;
|
||||
mData = data;
|
||||
if (data == null) {
|
||||
if (data == null || data.isEmpty()) {
|
||||
setCount(ITEM_IDX_CONVERSATION, 0);
|
||||
setCount(ITEM_IDX_REPLY, 0);
|
||||
} else {
|
||||
int conversationCount = 0, replyCount = 0;
|
||||
boolean containsStatus = false;
|
||||
final long statusId = status.is_retweet ? status.retweet_id : status.id;
|
||||
for (ParcelableStatus item : data) {
|
||||
if (item.id < status.id) {
|
||||
if (item.id < statusId) {
|
||||
conversationCount++;
|
||||
} else if (item.id > status.id) {
|
||||
} else if (item.id > statusId) {
|
||||
replyCount++;
|
||||
} else {
|
||||
containsStatus = true;
|
||||
|
@ -493,7 +493,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
||||
mUser = user;
|
||||
final int userColor = mUserColorNameManager.getUserColor(user.id, true);
|
||||
mProfileImageView.setBorderColor(userColor != 0 ? userColor : Color.WHITE);
|
||||
mProfileNameContainer.drawEnd(Utils.getAccountColor(activity, user.account_id));
|
||||
mProfileNameContainer.drawEnd(DataStoreUtils.getAccountColor(activity, user.account_id));
|
||||
final String nick = mUserColorNameManager.getUserNickname(user.id, true);
|
||||
mNameView.setText(TextUtils.isEmpty(nick) ? user.name : getString(R.string.name_with_nickname, user.name, nick));
|
||||
final int typeIconRes = Utils.getUserTypeIconRes(user.is_verified, user.is_protected);
|
||||
@ -840,7 +840,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
||||
MenuUtils.setMenuItemAvailability(menu, R.id.incoming_friendships, isMyself);
|
||||
MenuUtils.setMenuItemAvailability(menu, R.id.saved_searches, isMyself);
|
||||
MenuUtils.setMenuItemAvailability(menu, R.id.scheduled_statuses, isMyself
|
||||
&& Utils.getOfficialKeyType(getActivity(), user.account_id) == ConsumerKeyType.TWEETDECK);
|
||||
&& TwitterAPIFactory.getOfficialKeyType(getActivity(), user.account_id) == ConsumerKeyType.TWEETDECK);
|
||||
// final MenuItem followItem = menu.findItem(MENU_FOLLOW);
|
||||
// followItem.setVisible(!isMyself);
|
||||
// final boolean shouldShowFollowItem = !creatingFriendship && !destroyingFriendship && !isMyself
|
||||
@ -1448,7 +1448,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
||||
}
|
||||
mPagerAdapter.addTab(UserTimelineFragment.class, tabArgs, getString(R.string.statuses),
|
||||
R.drawable.ic_action_quote, TAB_TYPE_STATUSES, TAB_POSITION_STATUSES, null);
|
||||
if (Utils.isOfficialKeyAccount(context, accountId)) {
|
||||
if (TwitterAPIFactory.isOfficialKeyAccount(context, accountId)) {
|
||||
mPagerAdapter.addTab(UserMediaTimelineFragment.class, tabArgs, getString(R.string.media),
|
||||
R.drawable.ic_action_gallery, TAB_TYPE_MEDIA, TAB_POSITION_MEDIA, null);
|
||||
}
|
||||
|
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.loader.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.Activity;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
|
||||
public class ActivitiesAboutMeLoader extends TwitterAPIActivitiesLoader {
|
||||
|
||||
public ActivitiesAboutMeLoader(final Context context, final long accountId, long sinceId,
|
||||
long maxId, final List<ParcelableActivity> data,
|
||||
final String[] saveFileArgs, final int position) {
|
||||
super(context, accountId, sinceId, maxId, data, saveFileArgs, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Activity> getActivities(final Twitter twitter, final Paging paging) throws TwitterException {
|
||||
if (twitter == null) return null;
|
||||
return twitter.getActivitiesAboutMe(paging);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldFilterActivity(SQLiteDatabase database, ParcelableActivity activity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.loader.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.Activity;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
|
||||
public class ActivitiesByFriendsLoader extends TwitterAPIActivitiesLoader {
|
||||
|
||||
|
||||
public ActivitiesByFriendsLoader(final Context context, final long accountId, long sinceId,
|
||||
long maxId, final List<ParcelableActivity> data,
|
||||
final String[] saveFileArgs, final int position) {
|
||||
super(context, accountId, sinceId, maxId, data, saveFileArgs, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Activity> getActivities(final Twitter twitter, final Paging paging) throws TwitterException {
|
||||
if (twitter == null) return null;
|
||||
return twitter.getActivitiesByFriends(paging);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldFilterActivity(SQLiteDatabase database, ParcelableActivity activity) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -26,27 +26,74 @@ import android.support.annotation.NonNull;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.SearchQuery;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.model.StatusUtils;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.util.ParcelableStatusUtils;
|
||||
import org.mariotaku.twidere.util.Nullables;
|
||||
import org.mariotaku.twidere.util.ParcelUtils;
|
||||
import org.mariotaku.twidere.util.TwitterAPIFactory;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ConversationLoader extends TwitterAPIStatusesLoader {
|
||||
|
||||
private final long mInReplyToStatusId;
|
||||
private final boolean mTwitterOptimizedSearches;
|
||||
|
||||
public ConversationLoader(final Context context, final long accountId, final long statusId,
|
||||
final String screenName, final long sinceId, final long maxId,
|
||||
final List<ParcelableStatus> data, final boolean fromUser) {
|
||||
super(context, accountId, sinceId, maxId, data, null, -1, fromUser);
|
||||
mInReplyToStatusId = statusId;
|
||||
@NonNull
|
||||
private final ParcelableStatus mStatus;
|
||||
|
||||
public ConversationLoader(final Context context, @NonNull final ParcelableStatus status,
|
||||
final long sinceId, final long maxId, final List<ParcelableStatus> data,
|
||||
final boolean fromUser, final boolean twitterOptimizedSearches) {
|
||||
super(context, status.account_id, sinceId, maxId, data, null, -1, fromUser);
|
||||
mStatus = Nullables.assertNonNull(ParcelUtils.clone(status));
|
||||
ParcelableStatusUtils.makeOriginalStatus(mStatus);
|
||||
mTwitterOptimizedSearches = twitterOptimizedSearches;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public List<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
|
||||
return twitter.showConversation(mInReplyToStatusId, paging);
|
||||
final ParcelableStatus status = mStatus;
|
||||
if (Utils.shouldForceUsingPrivateAPIs(getContext()) || TwitterAPIFactory.isOfficialTwitterInstance(getContext(), twitter)) {
|
||||
return twitter.showConversation(status.id, paging);
|
||||
}
|
||||
final List<Status> statuses = new ArrayList<>();
|
||||
final long maxId = getMaxId(), sinceId = getSinceId();
|
||||
boolean getConversations = maxId < status.id || (maxId <= 0 && sinceId <= 0);
|
||||
boolean getReplies = sinceId > status.id || (maxId <= 0 && sinceId <= 0);
|
||||
if (getConversations) {
|
||||
long inReplyToId = status.in_reply_to_status_id;
|
||||
int count = 0;
|
||||
while (inReplyToId > 0 && count < 10) {
|
||||
final Status item = twitter.showStatus(inReplyToId);
|
||||
inReplyToId = item.getInReplyToStatusId();
|
||||
statuses.add(item);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if ((sinceId <= 0 && maxId <= 0) || (sinceId > 0 && sinceId < status.id) || (maxId > 0 && maxId >= status.id)) {
|
||||
statuses.add(StatusUtils.fromParcelableStatus(status));
|
||||
}
|
||||
if (getReplies) {
|
||||
SearchQuery query = new SearchQuery();
|
||||
if (mTwitterOptimizedSearches) {
|
||||
query.query("to:" + status.user_screen_name);
|
||||
} else {
|
||||
query.query("@" + status.user_screen_name);
|
||||
}
|
||||
query.sinceId(status.id);
|
||||
for (Status item : twitter.search(query)) {
|
||||
if (item.getInReplyToStatusId() == status.id) {
|
||||
statuses.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return statuses;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -23,17 +23,16 @@ import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.getAccountId;
|
||||
import static org.mariotaku.twidere.util.Utils.isFiltered;
|
||||
|
||||
public class MediaTimelineLoader extends TwitterAPIStatusesLoader {
|
||||
@ -48,7 +47,7 @@ public class MediaTimelineLoader extends TwitterAPIStatusesLoader {
|
||||
super(context, accountId, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
|
||||
mUserId = userId;
|
||||
mUserScreenName = screenName;
|
||||
mIsMyTimeline = userId > 0 ? accountId == userId : accountId == getAccountId(context, screenName);
|
||||
mIsMyTimeline = userId > 0 ? accountId == userId : accountId == DataStoreUtils.getAccountId(context, screenName);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 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/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.loader.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.model.ParcelableActivity;
|
||||
import org.mariotaku.twidere.util.collection.NoDuplicatesArrayList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ParcelableActivitiesLoader extends AsyncTaskLoader<List<ParcelableActivity>> implements Constants {
|
||||
|
||||
private final List<ParcelableActivity> mData = new NoDuplicatesArrayList<>();
|
||||
private final boolean mFirstLoad;
|
||||
private final int mTabPosition;
|
||||
|
||||
private Long mLastViewedId;
|
||||
|
||||
public ParcelableActivitiesLoader(final Context context, final List<ParcelableActivity> data, final int tab_position) {
|
||||
super(context);
|
||||
mFirstLoad = data == null;
|
||||
if (data != null) {
|
||||
mData.addAll(data);
|
||||
}
|
||||
mTabPosition = tab_position;
|
||||
}
|
||||
|
||||
public Long getLastViewedId() {
|
||||
return mLastViewedId;
|
||||
}
|
||||
|
||||
protected boolean containsStatus(final long id) {
|
||||
for (final ParcelableActivity activity : mData) {
|
||||
if (activity.max_position <= id && activity.min_position >= id) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean deleteActivity(final List<ParcelableActivity> activities, final long id) {
|
||||
if (activities == null || activities.isEmpty()) return false;
|
||||
boolean result = false;
|
||||
for (final ParcelableActivity activity : activities.toArray(new ParcelableActivity[activities.size()])) {
|
||||
if (id <= activity.max_position && id >= activity.min_position) {
|
||||
result |= activities.remove(activity);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected List<ParcelableActivity> getData() {
|
||||
return mData;
|
||||
}
|
||||
|
||||
protected int getTabPosition() {
|
||||
return mTabPosition;
|
||||
}
|
||||
|
||||
protected boolean isFirstLoad() {
|
||||
return mFirstLoad;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
forceLoad();
|
||||
}
|
||||
|
||||
}
|
@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 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/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.loader.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
|
||||
import org.mariotaku.twidere.BuildConfig;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Activity;
|
||||
import org.mariotaku.twidere.api.twitter.model.Paging;
|
||||
import org.mariotaku.twidere.model.ParcelableActivity;
|
||||
import org.mariotaku.twidere.util.JsonSerializer;
|
||||
import org.mariotaku.twidere.util.TwitterAPIFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.truncateActivities;
|
||||
|
||||
public abstract class TwitterAPIActivitiesLoader extends ParcelableActivitiesLoader {
|
||||
|
||||
private final Context mContext;
|
||||
private final long mAccountIds;
|
||||
private final long mMaxId, mSinceId;
|
||||
private final Object[] mSavedStatusesFileArgs;
|
||||
private Comparator<ParcelableActivity> mComparator;
|
||||
|
||||
public TwitterAPIActivitiesLoader(final Context context, final long accountId, final long sinceId,
|
||||
final long maxId, final List<ParcelableActivity> data, final String[] savedStatusesArgs,
|
||||
final int tabPosition) {
|
||||
super(context, data, tabPosition);
|
||||
mContext = context;
|
||||
mAccountIds = accountId;
|
||||
mSinceId = sinceId;
|
||||
mMaxId = maxId;
|
||||
mSavedStatusesFileArgs = savedStatusesArgs;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public final List<ParcelableActivity> loadInBackground() {
|
||||
final File serializationFile = getSerializationFile();
|
||||
final List<ParcelableActivity> data = getData();
|
||||
if (isFirstLoad() && getTabPosition() >= 0 && serializationFile != null) {
|
||||
final List<ParcelableActivity> cached = getCachedData(serializationFile);
|
||||
if (cached != null) {
|
||||
data.addAll(cached);
|
||||
if (mComparator != null) {
|
||||
Collections.sort(data, mComparator);
|
||||
} else {
|
||||
Collections.sort(data);
|
||||
}
|
||||
return new CopyOnWriteArrayList<>(data);
|
||||
}
|
||||
}
|
||||
final List<Activity> activities;
|
||||
final boolean truncated;
|
||||
final Context context = getContext();
|
||||
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final int loadItemLimit = prefs.getInt(KEY_LOAD_ITEM_LIMIT, DEFAULT_LOAD_ITEM_LIMIT);
|
||||
try {
|
||||
final Paging paging = new Paging();
|
||||
paging.setCount(loadItemLimit);
|
||||
if (mMaxId > 0) {
|
||||
paging.setMaxId(mMaxId);
|
||||
}
|
||||
if (mSinceId > 0) {
|
||||
paging.setSinceId(mSinceId);
|
||||
}
|
||||
activities = new ArrayList<>();
|
||||
truncated = truncateActivities(getActivities(getTwitter(), paging), activities, mSinceId);
|
||||
} catch (final TwitterException e) {
|
||||
// mHandler.post(new ShowErrorRunnable(e));
|
||||
Log.w(LOGTAG, e);
|
||||
return new CopyOnWriteArrayList<>(data);
|
||||
}
|
||||
final Pair<Long, Long> position;
|
||||
if (activities.isEmpty()) {
|
||||
position = new Pair<>(-1L, -1L);
|
||||
} else {
|
||||
final Activity minActivity = Collections.min(activities);
|
||||
position = new Pair<>(minActivity.getMinPosition(), minActivity.getMaxPosition());
|
||||
}
|
||||
final boolean insertGap = position.first > 0 && position.second > 0 && activities.size() > 1
|
||||
&& !data.isEmpty() && !truncated;
|
||||
// mHandler.post(CacheUsersStatusesTask.getRunnable(context, new StatusListResponse(mAccountIds, activities)));
|
||||
for (final Activity activity : activities) {
|
||||
final long min = activity.getMinPosition(), max = activity.getMaxPosition();
|
||||
final boolean deleted = deleteActivity(data, max);
|
||||
final boolean isGap = position.first == min && position.second == max && insertGap && !deleted;
|
||||
data.add(new ParcelableActivity(activity, mAccountIds, isGap));
|
||||
}
|
||||
// final ParcelableActivity[] array = data.toArray(new ParcelableActivity[data.size()]);
|
||||
// for (int i = 0, size = array.length; i < size; i++) {
|
||||
// final ParcelableActivity status = array[i];
|
||||
// if (shouldFilterActivity(mDatabase, status) && !status.is_gap && i != size - 1) {
|
||||
// deleteActivity(data, status.max_position);
|
||||
// }
|
||||
// }
|
||||
if (mComparator != null) {
|
||||
Collections.sort(data, mComparator);
|
||||
} else {
|
||||
Collections.sort(data);
|
||||
}
|
||||
saveCachedData(serializationFile, data);
|
||||
return new CopyOnWriteArrayList<>(data);
|
||||
}
|
||||
|
||||
public final void setComparator(Comparator<ParcelableActivity> comparator) {
|
||||
mComparator = comparator;
|
||||
}
|
||||
|
||||
protected abstract List<Activity> getActivities(Twitter twitter, Paging paging) throws TwitterException;
|
||||
|
||||
protected final Twitter getTwitter() {
|
||||
return TwitterAPIFactory.getTwitterInstance(mContext, mAccountIds, true, true);
|
||||
}
|
||||
|
||||
protected abstract boolean shouldFilterActivity(final SQLiteDatabase database, final ParcelableActivity activity);
|
||||
|
||||
private List<ParcelableActivity> getCachedData(final File file) {
|
||||
if (file == null) return null;
|
||||
try {
|
||||
return JsonSerializer.parseList(file, ParcelableActivity.class);
|
||||
} catch (final IOException e) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.w(LOGTAG, e);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
throw e;
|
||||
}
|
||||
Log.e(LOGTAG, "Error unserializing data", e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private File getSerializationFile() {
|
||||
if (mSavedStatusesFileArgs == null) return null;
|
||||
try {
|
||||
return JsonSerializer.getSerializationFile(mContext, mSavedStatusesFileArgs);
|
||||
} catch (final IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void saveCachedData(final File file, final List<ParcelableActivity> data) {
|
||||
if (file == null || data == null) return;
|
||||
final SharedPreferences prefs = mContext.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final int databaseItemLimit = prefs.getInt(KEY_DATABASE_ITEM_LIMIT, DEFAULT_DATABASE_ITEM_LIMIT);
|
||||
try {
|
||||
final List<ParcelableActivity> activities = data.subList(0, Math.min(databaseItemLimit, data.size()));
|
||||
LoganSquare.serialize(activities, new FileOutputStream(file), ParcelableActivity.class);
|
||||
} catch (final IOException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -55,12 +55,13 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
|
||||
private final Context mContext;
|
||||
private final long mAccountId;
|
||||
private final long mMaxId, mSinceId;
|
||||
@Nullable
|
||||
private final Object[] mSavedStatusesFileArgs;
|
||||
private Comparator<ParcelableStatus> mComparator;
|
||||
|
||||
public TwitterAPIStatusesLoader(final Context context, final long accountId, final long sinceId,
|
||||
final long maxId, final List<ParcelableStatus> data,
|
||||
final String[] savedStatusesArgs, final int tabPosition, boolean fromUser) {
|
||||
@Nullable final String[] savedStatusesArgs, final int tabPosition, boolean fromUser) {
|
||||
super(context, data, tabPosition, fromUser);
|
||||
mContext = context;
|
||||
mAccountId = accountId;
|
||||
@ -105,11 +106,14 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
|
||||
paging.setMaxId(mMaxId);
|
||||
}
|
||||
if (mSinceId > 0) {
|
||||
paging.setSinceId(mSinceId - 1);
|
||||
paging.setSinceId(mSinceId);
|
||||
if (mMaxId <= 0) {
|
||||
paging.setLatestResults(true);
|
||||
}
|
||||
}
|
||||
statuses = new ArrayList<>();
|
||||
truncated = Utils.truncateStatuses(getStatuses(twitter, paging), statuses, mSinceId);
|
||||
if (!Utils.isOfficialTwitterInstance(context, twitter)) {
|
||||
if (!TwitterAPIFactory.isOfficialTwitterInstance(context, twitter)) {
|
||||
TwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
|
||||
}
|
||||
} catch (final TwitterException e) {
|
||||
@ -167,6 +171,17 @@ public abstract class TwitterAPIStatusesLoader extends ParcelableStatusesLoader
|
||||
mComparator = comparator;
|
||||
}
|
||||
|
||||
public long getSinceId() {
|
||||
return mSinceId;
|
||||
}
|
||||
|
||||
public long getMaxId() {
|
||||
return mMaxId;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return mAccountId;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected abstract List<Status> getStatuses(@NonNull Twitter twitter, Paging paging) throws TwitterException;
|
||||
|
@ -32,8 +32,9 @@ import org.mariotaku.twidere.api.twitter.model.ResponseList;
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.getAccountId;
|
||||
import static org.mariotaku.twidere.util.Utils.isFiltered;
|
||||
|
||||
public class UserTimelineLoader extends TwitterAPIStatusesLoader {
|
||||
@ -49,7 +50,7 @@ public class UserTimelineLoader extends TwitterAPIStatusesLoader {
|
||||
super(context, accountId, sinceId, maxId, data, savedStatusesArgs, tabPosition, fromUser);
|
||||
mUserId = userId;
|
||||
mUserScreenName = screenName;
|
||||
mIsMyTimeline = userId > 0 ? accountId == userId : accountId == getAccountId(context, screenName);
|
||||
mIsMyTimeline = userId > 0 ? accountId == userId : accountId == DataStoreUtils.getAccountId(context, screenName);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
@ -0,0 +1,24 @@
|
||||
package org.mariotaku.twidere.model.util;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.api.twitter.model.Status;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/1/3.
|
||||
*/
|
||||
public class ParcelableStatusUtils {
|
||||
|
||||
public static void makeOriginalStatus(@NonNull ParcelableStatus status) {
|
||||
if (!status.is_retweet) return;
|
||||
status.id = status.retweet_id;
|
||||
status.retweeted_by_user_id = -1;
|
||||
status.retweeted_by_user_name = null;
|
||||
status.retweeted_by_user_screen_name = null;
|
||||
status.retweeted_by_user_profile_image = null;
|
||||
status.retweet_timestamp = -1;
|
||||
status.retweet_id = -1;
|
||||
}
|
||||
|
||||
}
|
@ -86,7 +86,6 @@ import org.mariotaku.twidere.model.AccountPreferences;
|
||||
import org.mariotaku.twidere.model.DraftItem;
|
||||
import org.mariotaku.twidere.model.DraftItemCursorIndices;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.ParcelableStatusCursorIndices;
|
||||
import org.mariotaku.twidere.model.StringLongPair;
|
||||
import org.mariotaku.twidere.model.UnreadItem;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
|
||||
@ -96,7 +95,6 @@ import org.mariotaku.twidere.provider.TwidereDataStore.CachedStatuses;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Drafts;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Mentions;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.NetworkUsages;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Preferences;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.SavedSearches;
|
||||
@ -108,7 +106,6 @@ import org.mariotaku.twidere.receiver.NotificationReceiver;
|
||||
import org.mariotaku.twidere.service.BackgroundOperationService;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.DatabaseQueryUtils;
|
||||
import org.mariotaku.twidere.util.ImagePreloader;
|
||||
import org.mariotaku.twidere.util.NotificationManagerWrapper;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
@ -146,7 +143,6 @@ import static org.mariotaku.twidere.util.DataStoreUtils.getTableId;
|
||||
import static org.mariotaku.twidere.util.DataStoreUtils.getTableNameById;
|
||||
import static org.mariotaku.twidere.util.Utils.clearAccountColor;
|
||||
import static org.mariotaku.twidere.util.Utils.clearAccountName;
|
||||
import static org.mariotaku.twidere.util.Utils.getAccountIds;
|
||||
import static org.mariotaku.twidere.util.Utils.getNotificationUri;
|
||||
import static org.mariotaku.twidere.util.Utils.isNotificationsSilent;
|
||||
|
||||
@ -1215,7 +1211,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
switch (tableId) {
|
||||
case TABLE_ID_STATUSES: {
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(context,
|
||||
getAccountIds(context));
|
||||
DataStoreUtils.getAccountIds(context));
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
if (!pref.isHomeTimelineNotificationEnabled()) continue;
|
||||
showTimelineNotification(pref, getPositionTag(TAB_TYPE_HOME_TIMELINE, pref.getAccountId()));
|
||||
@ -1225,7 +1221,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
}
|
||||
case TABLE_ID_ACTIVITIES_ABOUT_ME: {
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(context,
|
||||
getAccountIds(context));
|
||||
DataStoreUtils.getAccountIds(context));
|
||||
final boolean combined = mPreferences.getBoolean(KEY_COMBINED_NOTIFICATIONS);
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
if (!pref.isInteractionsNotificationEnabled()) continue;
|
||||
@ -1236,7 +1232,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
}
|
||||
case TABLE_ID_DIRECT_MESSAGES_INBOX: {
|
||||
final AccountPreferences[] prefs = AccountPreferences.getNotificationEnabledPreferences(context,
|
||||
getAccountIds(context));
|
||||
DataStoreUtils.getAccountIds(context));
|
||||
for (final AccountPreferences pref : prefs) {
|
||||
if (!pref.isDirectMessagesNotificationEnabled()) continue;
|
||||
final StringLongPair[] pairs = mReadStateManager.getPositionPairs(TAB_TYPE_DIRECT_MESSAGES);
|
||||
@ -1443,7 +1439,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
|
||||
final int usersCount = userCursor.getCount();
|
||||
final int messagesCount = messageCursor.getCount();
|
||||
if (messagesCount == 0 || usersCount == 0) return;
|
||||
final String accountName = Utils.getAccountName(context, accountId);
|
||||
final String accountName = DataStoreUtils.getAccountName(context, accountId);
|
||||
final String accountScreenName = DataStoreUtils.getAccountScreenName(context, accountId);
|
||||
final int idxMessageText = messageCursor.getColumnIndex(DirectMessages.TEXT_UNESCAPED),
|
||||
idxMessageTimestamp = messageCursor.getColumnIndex(DirectMessages.MESSAGE_TIMESTAMP),
|
||||
|
@ -31,12 +31,12 @@ import org.mariotaku.twidere.BuildConfig;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.util.ConnectivityUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.net.NetworkUsageUtils;
|
||||
|
||||
import edu.tsinghua.hotmobi.HotMobiLogger;
|
||||
import edu.tsinghua.hotmobi.UploadLogsTask;
|
||||
import edu.tsinghua.hotmobi.model.NetworkEvent;
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.startRefreshServiceIfNeeded;
|
||||
|
||||
@ -64,7 +64,7 @@ public class ConnectivityStateReceiver extends BroadcastReceiver implements Cons
|
||||
final int networkType = ConnectivityUtils.getActiveNetworkType(context.getApplicationContext());
|
||||
NetworkUsageUtils.setNetworkType(networkType);
|
||||
final boolean isWifi = networkType == ConnectivityManager.TYPE_WIFI;
|
||||
final boolean isCharging = SpiceProfilingUtil.isCharging(context.getApplicationContext());
|
||||
final boolean isCharging = Utils.isCharging(context.getApplicationContext());
|
||||
if (isWifi && isCharging) {
|
||||
final long currentTime = System.currentTimeMillis();
|
||||
final long lastSuccessfulTime = HotMobiLogger.getLastUploadTime(context);
|
||||
|
@ -49,7 +49,6 @@ import javax.inject.Inject;
|
||||
import edu.tsinghua.hotmobi.HotMobiLogger;
|
||||
import edu.tsinghua.hotmobi.model.ScreenEvent;
|
||||
|
||||
import static org.mariotaku.twidere.util.Utils.getAccountIds;
|
||||
import static org.mariotaku.twidere.util.Utils.getDefaultAccountId;
|
||||
import static org.mariotaku.twidere.util.Utils.hasAutoRefreshAccounts;
|
||||
import static org.mariotaku.twidere.util.Utils.isBatteryOkay;
|
||||
@ -84,7 +83,7 @@ public class RefreshService extends Service implements Constants {
|
||||
} else if (BROADCAST_RESCHEDULE_TRENDS_REFRESHING.equals(action)) {
|
||||
rescheduleTrendsRefreshing();
|
||||
} else if (isAutoRefreshAllowed()) {
|
||||
final long[] accountIds = getAccountIds(context);
|
||||
final long[] accountIds = DataStoreUtils.getAccountIds(context);
|
||||
final AccountPreferences[] accountPrefs = AccountPreferences.getAccountPreferences(context, accountIds);
|
||||
if (BROADCAST_REFRESH_HOME_TIMELINE.equals(action)) {
|
||||
final long[] refreshIds = getRefreshableIds(accountPrefs, new HomeRefreshableFilter());
|
||||
|
@ -72,7 +72,8 @@ public abstract class GetStatusesTask extends ManagedAsyncTask<Object, TwitterWr
|
||||
return sinceIds != null && sinceIds.length == accountIds.length;
|
||||
}
|
||||
|
||||
private void storeStatus(long accountId, List<org.mariotaku.twidere.api.twitter.model.Status> statuses, long maxId, boolean truncated, boolean notify) {
|
||||
private void storeStatus(long accountId, List<org.mariotaku.twidere.api.twitter.model.Status> statuses,
|
||||
long maxId, boolean notify, int loadItemLimit) {
|
||||
if (statuses == null || statuses.isEmpty() || accountId <= 0) {
|
||||
return;
|
||||
}
|
||||
@ -96,7 +97,8 @@ public abstract class GetStatusesTask extends ManagedAsyncTask<Object, TwitterWr
|
||||
}
|
||||
// Delete all rows conflicting before new data inserted.
|
||||
final Expression accountWhere = Expression.equals(TwidereDataStore.Statuses.ACCOUNT_ID, accountId);
|
||||
final Expression statusWhere = Expression.in(new Columns.Column(TwidereDataStore.Statuses.STATUS_ID), new RawItemArray(statusIds));
|
||||
final Expression statusWhere = Expression.in(new Columns.Column(TwidereDataStore.Statuses.STATUS_ID),
|
||||
new RawItemArray(statusIds));
|
||||
final String countWhere = Expression.and(accountWhere, statusWhere).getSQL();
|
||||
final String[] projection = {SQLFunctions.COUNT()};
|
||||
final int rowsDeleted;
|
||||
@ -119,8 +121,8 @@ public abstract class GetStatusesTask extends ManagedAsyncTask<Object, TwitterWr
|
||||
// Insert a gap.
|
||||
final boolean deletedOldGap = rowsDeleted > 0 && ArrayUtils.contains(statusIds, maxId);
|
||||
final boolean noRowsDeleted = rowsDeleted == 0;
|
||||
final boolean insertGap = minId > 0 && (noRowsDeleted || deletedOldGap) && !truncated
|
||||
&& !noItemsBefore && statuses.size() > 1;
|
||||
final boolean insertGap = minId > 0 && (noRowsDeleted || deletedOldGap) && !noItemsBefore
|
||||
&& statuses.size() >= loadItemLimit;
|
||||
if (insertGap && minIdx != -1) {
|
||||
values[minIdx].put(TwidereDataStore.Statuses.IS_GAP, true);
|
||||
}
|
||||
@ -181,10 +183,9 @@ public abstract class GetStatusesTask extends ManagedAsyncTask<Object, TwitterWr
|
||||
} else {
|
||||
sinceId = -1;
|
||||
}
|
||||
final List<org.mariotaku.twidere.api.twitter.model.Status> statuses = new ArrayList<>();
|
||||
final boolean truncated = Utils.truncateStatuses(getStatuses(twitter, paging), statuses, sinceId);
|
||||
final List<org.mariotaku.twidere.api.twitter.model.Status> statuses = getStatuses(twitter, paging);
|
||||
TwitterContentUtils.getStatusesWithQuoteData(twitter, statuses);
|
||||
storeStatus(accountId, statuses, maxId, truncated, true);
|
||||
storeStatus(accountId, statuses, maxId, true, loadItemLimit);
|
||||
publishProgress(new TwitterWrapper.StatusListResponse(accountId, statuses));
|
||||
} catch (final TwitterException e) {
|
||||
Log.w(LOGTAG, e);
|
||||
|
@ -116,7 +116,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
private final UserColorNameManager mUserColorNameManager;
|
||||
private final ReadStateManager mReadStateManager;
|
||||
|
||||
private int mGetHomeTimelineTaskId, mGetMentionsTaskId;
|
||||
private int mGetReceivedDirectMessagesTaskId, mGetSentDirectMessagesTaskId;
|
||||
private int mGetLocalTrendsTaskId;
|
||||
|
||||
@ -282,9 +281,8 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
}
|
||||
|
||||
public boolean getHomeTimelineAsync(final long[] accountIds, final long[] max_ids, final long[] since_ids) {
|
||||
mAsyncTaskManager.cancel(mGetHomeTimelineTaskId);
|
||||
final GetHomeTimelineTask task = new GetHomeTimelineTask(accountIds, max_ids, since_ids);
|
||||
mGetHomeTimelineTaskId = mAsyncTaskManager.add(task, true);
|
||||
final GetHomeTimelineTask task = new GetHomeTimelineTask(this, accountIds, max_ids, since_ids);
|
||||
mAsyncTaskManager.add(task, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -544,7 +542,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
|
||||
@Override
|
||||
protected ResponseList<Activity> getActivities(long accountId, Twitter twitter, Paging paging) throws TwitterException {
|
||||
if (Utils.isOfficialKeyAccount(getContext(), accountId)) {
|
||||
if (TwitterAPIFactory.isOfficialKeyAccount(getContext(), accountId)) {
|
||||
return twitter.getActivitiesAboutMe(paging);
|
||||
}
|
||||
final ResponseList<Activity> activities = new ResponseList<>();
|
||||
@ -588,7 +586,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
public Object doLongOperation(Object o) throws InterruptedException {
|
||||
for (long accountId : accountIds) {
|
||||
Twitter twitter = TwitterAPIFactory.getTwitterInstance(mContext, accountId, false);
|
||||
if (Utils.isOfficialTwitterInstance(mContext, twitter)) continue;
|
||||
if (TwitterAPIFactory.isOfficialTwitterInstance(mContext, twitter)) continue;
|
||||
try {
|
||||
twitter.setActivitiesAboutMeUnread(cursor);
|
||||
} catch (TwitterException e) {
|
||||
@ -2125,10 +2123,13 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
|
||||
}
|
||||
|
||||
class GetHomeTimelineTask extends GetStatusesTask {
|
||||
static class GetHomeTimelineTask extends GetStatusesTask {
|
||||
|
||||
public GetHomeTimelineTask(final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
|
||||
super(AsyncTwitterWrapper.this, accountIds, maxIds, sinceIds, TASK_TAG_GET_HOME_TIMELINE);
|
||||
private AsyncTwitterWrapper twitterWrapper;
|
||||
|
||||
public GetHomeTimelineTask(AsyncTwitterWrapper asyncTwitterWrapper, final long[] accountIds, final long[] maxIds, final long[] sinceIds) {
|
||||
super(asyncTwitterWrapper, accountIds, maxIds, sinceIds, TASK_TAG_GET_HOME_TIMELINE);
|
||||
this.twitterWrapper = asyncTwitterWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -2152,13 +2153,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
@Override
|
||||
protected void onPostExecute(final List<StatusListResponse> result) {
|
||||
super.onPostExecute(result);
|
||||
mGetHomeTimelineTaskId = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
final Intent intent = new Intent(BROADCAST_RESCHEDULE_HOME_TIMELINE_REFRESHING);
|
||||
mContext.sendBroadcast(intent);
|
||||
twitterWrapper.getContext().sendBroadcast(intent);
|
||||
super.onPreExecute();
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,12 @@ import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.UriMatcher;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.mariotaku.sqliteqb.library.Columns;
|
||||
import org.mariotaku.sqliteqb.library.Expression;
|
||||
import org.mariotaku.sqliteqb.library.RawItemArray;
|
||||
@ -70,6 +72,7 @@ import static android.text.TextUtils.isEmpty;
|
||||
*/
|
||||
public class DataStoreUtils implements Constants {
|
||||
static final UriMatcher CONTENT_PROVIDER_URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
|
||||
static LongSparseArray<Integer> sAccountColors = new LongSparseArray<>();
|
||||
|
||||
static {
|
||||
CONTENT_PROVIDER_URI_MATCHER.addURI(TwidereDataStore.AUTHORITY, Accounts.CONTENT_PATH,
|
||||
@ -714,4 +717,122 @@ public class DataStoreUtils implements Constants {
|
||||
}
|
||||
return filterExpression;
|
||||
}
|
||||
|
||||
public static int getAccountColor(final Context context, final long accountId) {
|
||||
if (context == null) return Color.TRANSPARENT;
|
||||
final Integer cached = sAccountColors.get(accountId);
|
||||
if (cached != null) return cached;
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||
new String[]{Accounts.COLOR}, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(),
|
||||
null, null);
|
||||
if (cur == null) return Color.TRANSPARENT;
|
||||
try {
|
||||
if (cur.getCount() > 0 && cur.moveToFirst()) {
|
||||
final int color = cur.getInt(0);
|
||||
sAccountColors.put(accountId, color);
|
||||
return color;
|
||||
}
|
||||
return Color.TRANSPARENT;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static int[] getAccountColors(final Context context, final long[] accountIds) {
|
||||
if (context == null || accountIds == null) return new int[0];
|
||||
final String[] cols = new String[]{Accounts.ACCOUNT_ID, Accounts.COLOR};
|
||||
final String where = Expression.in(new Columns.Column(Accounts.ACCOUNT_ID), new RawItemArray(accountIds)).getSQL();
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI, cols, where,
|
||||
null, null);
|
||||
if (cur == null) return new int[0];
|
||||
try {
|
||||
final int[] colors = new int[cur.getCount()];
|
||||
for (int i = 0, j = cur.getCount(); i < j; i++) {
|
||||
cur.moveToPosition(i);
|
||||
colors[ArrayUtils.indexOf(accountIds, cur.getLong(0))] = cur.getInt(1);
|
||||
}
|
||||
return colors;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAccountDisplayName(final Context context, final long accountId, final boolean nameFirst) {
|
||||
final String name;
|
||||
if (nameFirst) {
|
||||
name = getAccountName(context, accountId);
|
||||
} else {
|
||||
name = String.format("@%s", getAccountScreenName(context, accountId));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static long getAccountId(final Context context, final String screenName) {
|
||||
if (context == null || isEmpty(screenName)) return -1;
|
||||
final Cursor cur = ContentResolverUtils
|
||||
.query(context.getContentResolver(), Accounts.CONTENT_URI, new String[]{Accounts.ACCOUNT_ID},
|
||||
Expression.equalsArgs(Accounts.SCREEN_NAME).getSQL(), new String[]{screenName}, null);
|
||||
if (cur == null) return -1;
|
||||
try {
|
||||
if (cur.getCount() > 0 && cur.moveToFirst()) return cur.getLong(0);
|
||||
return -1;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static long[] getAccountIds(final Context context) {
|
||||
if (context == null) return new long[0];
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||
new String[]{Accounts.ACCOUNT_ID}, null, null, null);
|
||||
if (cur == null) return new long[0];
|
||||
try {
|
||||
cur.moveToFirst();
|
||||
final long[] ids = new long[cur.getCount()];
|
||||
int i = 0;
|
||||
while (!cur.isAfterLast()) {
|
||||
ids[i++] = cur.getLong(0);
|
||||
cur.moveToNext();
|
||||
}
|
||||
return ids;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasAccount(final Context context) {
|
||||
if (context == null) return false;
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||
new String[]{SQLFunctions.COUNT()}, null, null, null);
|
||||
try {
|
||||
cur.moveToFirst();
|
||||
return cur.getInt(0) > 0;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAccountName(final Context context, final long accountId) {
|
||||
if (context == null) return null;
|
||||
final String cached = sAccountNames.get(accountId);
|
||||
if (!isEmpty(cached)) return cached;
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||
new String[]{Accounts.NAME}, Accounts.ACCOUNT_ID + " = " + accountId, null, null);
|
||||
if (cur == null) return null;
|
||||
try {
|
||||
if (cur.getCount() > 0 && cur.moveToFirst()) {
|
||||
final String name = cur.getString(0);
|
||||
sAccountNames.put(accountId, name);
|
||||
return name;
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getAccountNames(final Context context) {
|
||||
return getAccountScreenNames(context, null);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,33 @@
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/1/3.
|
||||
*/
|
||||
public class ParcelUtils {
|
||||
|
||||
@Nullable
|
||||
public static <T extends Parcelable> T clone(@Nullable T object) {
|
||||
if (object == null) return null;
|
||||
final Parcel parcel = Parcel.obtain();
|
||||
try {
|
||||
object.writeToParcel(parcel, 0);
|
||||
parcel.setDataPosition(0);
|
||||
final Field creatorField = object.getClass().getDeclaredField("CREATOR");
|
||||
//noinspection unchecked
|
||||
final Parcelable.Creator<T> creator = (Parcelable.Creator<T>) creatorField.get(null);
|
||||
return creator.createFromParcel(parcel);
|
||||
} catch (NoSuchFieldException e) {
|
||||
throw new NoSuchFieldError("Missing CREATOR field");
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new IllegalAccessError("Can't access CREATOR field");
|
||||
} finally {
|
||||
parcel.recycle();
|
||||
}
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.SSLCertificateSocketFactory;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
@ -25,6 +26,7 @@ import org.mariotaku.restfu.HttpRequestFactory;
|
||||
import org.mariotaku.restfu.Pair;
|
||||
import org.mariotaku.restfu.RequestInfoFactory;
|
||||
import org.mariotaku.restfu.RestAPIFactory;
|
||||
import org.mariotaku.restfu.RestClient;
|
||||
import org.mariotaku.restfu.RestMethodInfo;
|
||||
import org.mariotaku.restfu.RestRequestInfo;
|
||||
import org.mariotaku.restfu.annotation.RestMethod;
|
||||
@ -38,6 +40,7 @@ import org.mariotaku.restfu.http.RestHttpResponse;
|
||||
import org.mariotaku.restfu.http.mime.StringTypedData;
|
||||
import org.mariotaku.restfu.http.mime.TypedData;
|
||||
import org.mariotaku.restfu.okhttp.OkHttpRestClient;
|
||||
import org.mariotaku.sqliteqb.library.Expression;
|
||||
import org.mariotaku.twidere.BuildConfig;
|
||||
import org.mariotaku.twidere.TwidereConstants;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
@ -50,11 +53,13 @@ import org.mariotaku.twidere.api.twitter.auth.BasicAuthorization;
|
||||
import org.mariotaku.twidere.api.twitter.auth.EmptyAuthorization;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthAuthorization;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthEndpoint;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthSupport;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthToken;
|
||||
import org.mariotaku.twidere.api.twitter.util.TwitterConverter;
|
||||
import org.mariotaku.twidere.model.ConsumerKeyType;
|
||||
import org.mariotaku.twidere.model.ParcelableCredentials;
|
||||
import org.mariotaku.twidere.model.RequestType;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||
import org.mariotaku.twidere.util.dagger.DependencyHolder;
|
||||
import org.mariotaku.twidere.util.net.InetAddressUtils;
|
||||
import org.mariotaku.twidere.util.net.NetworkUsageUtils;
|
||||
@ -483,6 +488,36 @@ public class TwitterAPIFactory implements TwidereConstants {
|
||||
return ('A' <= codePoint && codePoint <= 'Z') || ('a' <= codePoint && codePoint <= 'z') || '0' <= codePoint && codePoint <= '9';
|
||||
}
|
||||
|
||||
public static boolean isOfficialKeyAccount(final Context context, final long accountId) {
|
||||
return getOfficialKeyType(context, accountId) != ConsumerKeyType.UNKNOWN;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ConsumerKeyType getOfficialKeyType(final Context context, final long accountId) {
|
||||
if (context == null) return ConsumerKeyType.UNKNOWN;
|
||||
final String[] projection = {TwidereDataStore.Accounts.CONSUMER_KEY, TwidereDataStore.Accounts.CONSUMER_SECRET};
|
||||
final String selection = Expression.equals(TwidereDataStore.Accounts.ACCOUNT_ID, accountId).getSQL();
|
||||
final Cursor c = context.getContentResolver().query(TwidereDataStore.Accounts.CONTENT_URI, projection, selection, null, null);
|
||||
//noinspection TryFinallyCanBeTryWithResources
|
||||
try {
|
||||
if (c.moveToPosition(0))
|
||||
return TwitterContentUtils.getOfficialKeyType(context, c.getString(0), c.getString(1));
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
return ConsumerKeyType.UNKNOWN;
|
||||
}
|
||||
|
||||
public static boolean isOfficialTwitterInstance(final Context context, final Twitter twitter) {
|
||||
if (context == null || twitter == null) return false;
|
||||
final RestClient restClient = RestAPIFactory.getRestClient(twitter);
|
||||
final Authorization auth = restClient.getAuthorization();
|
||||
if (!(auth instanceof OAuthSupport)) return false;
|
||||
final String consumerKey = ((OAuthSupport) auth).getConsumerKey();
|
||||
final String consumerSecret = ((OAuthSupport) auth).getConsumerSecret();
|
||||
return TwitterContentUtils.isOfficialKey(context, consumerKey, consumerSecret);
|
||||
}
|
||||
|
||||
public static class Options {
|
||||
|
||||
final HashMap<String, String> extras = new HashMap<>();
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActionBar;
|
||||
import android.app.Activity;
|
||||
@ -74,7 +75,6 @@ import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.util.LongSparseArray;
|
||||
import android.support.v4.util.Pair;
|
||||
import android.support.v4.view.ActionProvider;
|
||||
import android.support.v4.view.GravityCompat;
|
||||
@ -116,16 +116,12 @@ import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.json.JSONException;
|
||||
import org.mariotaku.restfu.RestAPIFactory;
|
||||
import org.mariotaku.restfu.RestClient;
|
||||
import org.mariotaku.restfu.http.Authorization;
|
||||
import org.mariotaku.sqliteqb.library.AllColumns;
|
||||
import org.mariotaku.sqliteqb.library.Columns;
|
||||
import org.mariotaku.sqliteqb.library.Columns.Column;
|
||||
import org.mariotaku.sqliteqb.library.Expression;
|
||||
import org.mariotaku.sqliteqb.library.OrderBy;
|
||||
import org.mariotaku.sqliteqb.library.RawItemArray;
|
||||
import org.mariotaku.sqliteqb.library.SQLFunctions;
|
||||
import org.mariotaku.sqliteqb.library.Selectable;
|
||||
import org.mariotaku.sqliteqb.library.Tables;
|
||||
import org.mariotaku.sqliteqb.library.query.SQLSelectQuery;
|
||||
@ -140,7 +136,6 @@ import org.mariotaku.twidere.adapter.iface.IBaseAdapter;
|
||||
import org.mariotaku.twidere.adapter.iface.IBaseCardAdapter;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.auth.OAuthSupport;
|
||||
import org.mariotaku.twidere.api.twitter.model.DirectMessage;
|
||||
import org.mariotaku.twidere.api.twitter.model.GeoLocation;
|
||||
import org.mariotaku.twidere.api.twitter.model.RateLimitStatus;
|
||||
@ -186,7 +181,6 @@ import org.mariotaku.twidere.graphic.ActionIconDrawable;
|
||||
import org.mariotaku.twidere.graphic.PaddingDrawable;
|
||||
import org.mariotaku.twidere.menu.SupportStatusShareProvider;
|
||||
import org.mariotaku.twidere.model.AccountPreferences;
|
||||
import org.mariotaku.twidere.model.ConsumerKeyType;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.model.ParcelableCredentials;
|
||||
import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices;
|
||||
@ -303,8 +297,6 @@ public final class Utils implements Constants {
|
||||
}
|
||||
|
||||
|
||||
private static LongSparseArray<Integer> sAccountColors = new LongSparseArray<>();
|
||||
|
||||
private Utils() {
|
||||
throw new AssertionError("You are trying to create an instance for this utility class!");
|
||||
}
|
||||
@ -457,7 +449,7 @@ public final class Utils implements Constants {
|
||||
final int itemLimit = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE).getInt(
|
||||
KEY_DATABASE_ITEM_LIMIT, DEFAULT_DATABASE_ITEM_LIMIT);
|
||||
|
||||
for (final long accountId : getAccountIds(context)) {
|
||||
for (final long accountId : DataStoreUtils.getAccountIds(context)) {
|
||||
// Clean statuses.
|
||||
for (final Uri uri : STATUSES_URIS) {
|
||||
if (CachedStatuses.CONTENT_URI.equals(uri)) {
|
||||
@ -500,7 +492,7 @@ public final class Utils implements Constants {
|
||||
}
|
||||
|
||||
public static void clearAccountColor() {
|
||||
sAccountColors.clear();
|
||||
DataStoreUtils.sAccountColors.clear();
|
||||
}
|
||||
|
||||
public static void clearAccountName() {
|
||||
@ -909,7 +901,7 @@ public final class Utils implements Constants {
|
||||
} else {
|
||||
final String paramAccountName = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_NAME);
|
||||
if (paramAccountName != null) {
|
||||
args.putLong(EXTRA_ACCOUNT_ID, getAccountId(context, paramAccountName));
|
||||
args.putLong(EXTRA_ACCOUNT_ID, DataStoreUtils.getAccountId(context, paramAccountName));
|
||||
} else {
|
||||
final long accountId = getDefaultAccountId(context);
|
||||
if (isMyAccount(context, accountId)) {
|
||||
@ -1100,124 +1092,6 @@ public final class Utils implements Constants {
|
||||
return DateUtils.formatDateTime(context, timestamp, format_flags);
|
||||
}
|
||||
|
||||
public static int getAccountColor(final Context context, final long accountId) {
|
||||
if (context == null) return Color.TRANSPARENT;
|
||||
final Integer cached = sAccountColors.get(accountId);
|
||||
if (cached != null) return cached;
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||
new String[]{Accounts.COLOR}, Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL(),
|
||||
null, null);
|
||||
if (cur == null) return Color.TRANSPARENT;
|
||||
try {
|
||||
if (cur.getCount() > 0 && cur.moveToFirst()) {
|
||||
final int color = cur.getInt(0);
|
||||
sAccountColors.put(accountId, color);
|
||||
return color;
|
||||
}
|
||||
return Color.TRANSPARENT;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static int[] getAccountColors(final Context context, final long[] accountIds) {
|
||||
if (context == null || accountIds == null) return new int[0];
|
||||
final String[] cols = new String[]{Accounts.ACCOUNT_ID, Accounts.COLOR};
|
||||
final String where = Expression.in(new Column(Accounts.ACCOUNT_ID), new RawItemArray(accountIds)).getSQL();
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI, cols, where,
|
||||
null, null);
|
||||
if (cur == null) return new int[0];
|
||||
try {
|
||||
final int[] colors = new int[cur.getCount()];
|
||||
for (int i = 0, j = cur.getCount(); i < j; i++) {
|
||||
cur.moveToPosition(i);
|
||||
colors[ArrayUtils.indexOf(accountIds, cur.getLong(0))] = cur.getInt(1);
|
||||
}
|
||||
return colors;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAccountDisplayName(final Context context, final long accountId, final boolean nameFirst) {
|
||||
final String name;
|
||||
if (nameFirst) {
|
||||
name = getAccountName(context, accountId);
|
||||
} else {
|
||||
name = String.format("@%s", DataStoreUtils.getAccountScreenName(context, accountId));
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static long getAccountId(final Context context, final String screenName) {
|
||||
if (context == null || isEmpty(screenName)) return -1;
|
||||
final Cursor cur = ContentResolverUtils
|
||||
.query(context.getContentResolver(), Accounts.CONTENT_URI, new String[]{Accounts.ACCOUNT_ID},
|
||||
Expression.equalsArgs(Accounts.SCREEN_NAME).getSQL(), new String[]{screenName}, null);
|
||||
if (cur == null) return -1;
|
||||
try {
|
||||
if (cur.getCount() > 0 && cur.moveToFirst()) return cur.getLong(0);
|
||||
return -1;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static long[] getAccountIds(final Context context) {
|
||||
if (context == null) return new long[0];
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||
new String[]{Accounts.ACCOUNT_ID}, null, null, null);
|
||||
if (cur == null) return new long[0];
|
||||
try {
|
||||
cur.moveToFirst();
|
||||
final long[] ids = new long[cur.getCount()];
|
||||
int i = 0;
|
||||
while (!cur.isAfterLast()) {
|
||||
ids[i++] = cur.getLong(0);
|
||||
cur.moveToNext();
|
||||
}
|
||||
return ids;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean hasAccount(final Context context) {
|
||||
if (context == null) return false;
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||
new String[]{SQLFunctions.COUNT()}, null, null, null);
|
||||
try {
|
||||
cur.moveToFirst();
|
||||
return cur.getInt(0) > 0;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getAccountName(final Context context, final long accountId) {
|
||||
if (context == null) return null;
|
||||
final String cached = DataStoreUtils.sAccountNames.get(accountId);
|
||||
if (!isEmpty(cached)) return cached;
|
||||
final Cursor cur = ContentResolverUtils.query(context.getContentResolver(), Accounts.CONTENT_URI,
|
||||
new String[]{Accounts.NAME}, Accounts.ACCOUNT_ID + " = " + accountId, null, null);
|
||||
if (cur == null) return null;
|
||||
try {
|
||||
if (cur.getCount() > 0 && cur.moveToFirst()) {
|
||||
final String name = cur.getString(0);
|
||||
DataStoreUtils.sAccountNames.put(accountId, name);
|
||||
return name;
|
||||
}
|
||||
return null;
|
||||
} finally {
|
||||
cur.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static String[] getAccountNames(final Context context) {
|
||||
return DataStoreUtils.getAccountScreenNames(context, null);
|
||||
}
|
||||
|
||||
public static int getAccountNotificationId(final int notificationType, final long accountId) {
|
||||
return Arrays.hashCode(new long[]{notificationType, accountId});
|
||||
}
|
||||
@ -1385,7 +1259,7 @@ public final class Utils implements Constants {
|
||||
if (context == null) return -1;
|
||||
final SharedPreferences prefs = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
final long accountId = prefs.getLong(KEY_DEFAULT_ACCOUNT_ID, -1);
|
||||
final long[] accountIds = Utils.getAccountIds(context);
|
||||
final long[] accountIds = DataStoreUtils.getAccountIds(context);
|
||||
if (accountIds.length > 0 && !ArrayUtils.contains(accountIds, accountId) && accountIds.length > 0) {
|
||||
/* TODO: this is just a quick fix */
|
||||
return accountIds[0];
|
||||
@ -1816,7 +1690,7 @@ public final class Utils implements Constants {
|
||||
}
|
||||
|
||||
public static boolean hasAutoRefreshAccounts(final Context context) {
|
||||
final long[] accountIds = getAccountIds(context);
|
||||
final long[] accountIds = DataStoreUtils.getAccountIds(context);
|
||||
return !ArrayUtils.isEmpty(AccountPreferences.getAutoRefreshEnabledAccountIds(context, accountIds));
|
||||
}
|
||||
|
||||
@ -1832,7 +1706,7 @@ public final class Utils implements Constants {
|
||||
final int id_idx = cur.getColumnIndex(Accounts.ACCOUNT_ID), color_idx = cur.getColumnIndex(Accounts.COLOR);
|
||||
cur.moveToFirst();
|
||||
while (!cur.isAfterLast()) {
|
||||
sAccountColors.put(cur.getLong(id_idx), cur.getInt(color_idx));
|
||||
DataStoreUtils.sAccountColors.put(cur.getLong(id_idx), cur.getInt(color_idx));
|
||||
cur.moveToNext();
|
||||
}
|
||||
cur.close();
|
||||
@ -1980,36 +1854,6 @@ public final class Utils implements Constants {
|
||||
return prefs.getBoolean("silent_notifications_at_" + now.get(Calendar.HOUR_OF_DAY), false);
|
||||
}
|
||||
|
||||
public static boolean isOfficialKeyAccount(final Context context, final long accountId) {
|
||||
return getOfficialKeyType(context, accountId) != ConsumerKeyType.UNKNOWN;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ConsumerKeyType getOfficialKeyType(final Context context, final long accountId) {
|
||||
if (context == null) return ConsumerKeyType.UNKNOWN;
|
||||
final String[] projection = {Accounts.CONSUMER_KEY, Accounts.CONSUMER_SECRET};
|
||||
final String selection = Expression.equals(Accounts.ACCOUNT_ID, accountId).getSQL();
|
||||
final Cursor c = context.getContentResolver().query(Accounts.CONTENT_URI, projection, selection, null, null);
|
||||
//noinspection TryFinallyCanBeTryWithResources
|
||||
try {
|
||||
if (c.moveToPosition(0))
|
||||
return TwitterContentUtils.getOfficialKeyType(context, c.getString(0), c.getString(1));
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
return ConsumerKeyType.UNKNOWN;
|
||||
}
|
||||
|
||||
public static boolean isOfficialTwitterInstance(final Context context, final Twitter twitter) {
|
||||
if (context == null || twitter == null) return false;
|
||||
final RestClient restClient = RestAPIFactory.getRestClient(twitter);
|
||||
final Authorization auth = restClient.getAuthorization();
|
||||
if (!(auth instanceof OAuthSupport)) return false;
|
||||
final String consumerKey = ((OAuthSupport) auth).getConsumerKey();
|
||||
final String consumerSecret = ((OAuthSupport) auth).getConsumerSecret();
|
||||
return TwitterContentUtils.isOfficialKey(context, consumerKey, consumerSecret);
|
||||
}
|
||||
|
||||
public static boolean isRedirected(final int code) {
|
||||
return code == 301 || code == 302 || code == 307;
|
||||
}
|
||||
@ -2025,7 +1869,7 @@ public final class Utils implements Constants {
|
||||
|
||||
public static boolean isUserLoggedIn(final Context context, final long accountId) {
|
||||
if (context == null) return false;
|
||||
final long[] ids = getAccountIds(context);
|
||||
final long[] ids = DataStoreUtils.getAccountIds(context);
|
||||
if (ids == null) return false;
|
||||
for (final long id : ids) {
|
||||
if (id == accountId) return true;
|
||||
@ -3056,18 +2900,6 @@ public final class Utils implements Constants {
|
||||
return in.size() != out.size();
|
||||
}
|
||||
|
||||
public static boolean truncateActivities(final List<org.mariotaku.twidere.api.twitter.model.Activity> in, final List<org.mariotaku.twidere.api.twitter.model.Activity> out,
|
||||
final long sinceId) {
|
||||
if (in == null) return false;
|
||||
for (final org.mariotaku.twidere.api.twitter.model.Activity status : in) {
|
||||
if (sinceId > 0 && status.getMaxPosition() <= sinceId) {
|
||||
continue;
|
||||
}
|
||||
out.add(status);
|
||||
}
|
||||
return in.size() != out.size();
|
||||
}
|
||||
|
||||
public static void updateRelationship(Context context, Relationship relationship, long accountId) {
|
||||
final ContentResolver resolver = context.getContentResolver();
|
||||
final ContentValues values = ContentValuesCreator.createCachedRelationship(relationship, accountId);
|
||||
@ -3403,6 +3235,17 @@ public final class Utils implements Constants {
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
public static boolean isCharging(final Context context) {
|
||||
if (context == null) return false;
|
||||
final Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
if (intent == null) return false;
|
||||
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||
return plugged == BatteryManager.BATTERY_PLUGGED_AC
|
||||
|| plugged == BatteryManager.BATTERY_PLUGGED_USB
|
||||
|| plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||
}
|
||||
|
||||
static class UtilsL {
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
|
@ -31,9 +31,9 @@ import android.widget.TextView;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.MessageEntriesAdapter;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages.ConversationEntries;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.UserColorNameManager;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.view.ShortTimeView;
|
||||
import org.mariotaku.twidere.view.iface.IColorLabelView;
|
||||
|
||||
@ -88,7 +88,7 @@ public class MessageEntryViewHolder extends ViewHolder implements OnClickListene
|
||||
screenNameView.setTypeface(null, isUnread && !isOutgoing ? Typeface.BOLD : Typeface.NORMAL);
|
||||
textView.setTypeface(null, isUnread && !isOutgoing ? Typeface.BOLD : Typeface.NORMAL);
|
||||
if (adapter.shouldShowAccountsColor()) {
|
||||
content.drawEnd(Utils.getAccountColor(context, accountId));
|
||||
content.drawEnd(DataStoreUtils.getAccountColor(context, accountId));
|
||||
} else {
|
||||
content.drawEnd();
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import org.mariotaku.twidere.model.ParcelableLocation;
|
||||
import org.mariotaku.twidere.model.ParcelableMedia;
|
||||
import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.DataStoreUtils;
|
||||
import org.mariotaku.twidere.util.HtmlSpanBuilder;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MediaLoadingHandler;
|
||||
@ -236,7 +237,7 @@ public class StatusViewHolder extends ViewHolder implements Constants, OnClickLi
|
||||
}
|
||||
|
||||
if (adapter.shouldShowAccountsColor()) {
|
||||
itemContent.drawEnd(Utils.getAccountColor(context, status.account_id));
|
||||
itemContent.drawEnd(DataStoreUtils.getAccountColor(context, status.account_id));
|
||||
} else {
|
||||
itemContent.drawEnd();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user