mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-01 17:26:46 +01:00
supports tab and filters import/export
fixed some crashes
This commit is contained in:
parent
ebf3deb1d8
commit
1eada0f072
@ -231,7 +231,6 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
|
||||
String TASK_TAG_GET_SENT_DIRECT_MESSAGES = "get_sent_direct_messages";
|
||||
String TASK_TAG_GET_RECEIVED_DIRECT_MESSAGES = "get_received_direct_messages";
|
||||
String TASK_TAG_GET_TRENDS = "get_trends";
|
||||
String TASK_TAG_STORE_TRENDS = "store_trends";
|
||||
|
||||
String METADATA_KEY_EXTENSION = "org.mariotaku.twidere.extension";
|
||||
String METADATA_KEY_EXTENSION_PERMISSIONS = "org.mariotaku.twidere.extension.permissions";
|
||||
|
@ -208,14 +208,6 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
|
||||
}
|
||||
|
||||
|
||||
public static int calculateHashCode(long accountId, long userId) {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (int) (accountId ^ accountId >>> 32);
|
||||
result = prime * result + (int) (userId ^ userId >>> 32);
|
||||
return result;
|
||||
}
|
||||
|
||||
@AfterCursorObjectCreated
|
||||
void afterCursorObjectCreated() {
|
||||
is_cache = true;
|
||||
@ -240,7 +232,8 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
|
||||
|
||||
ParcelableUser user = (ParcelableUser) o;
|
||||
|
||||
if (!account_key.equals(user.account_key)) return false;
|
||||
if (account_key != null ? !account_key.equals(user.account_key) : user.account_key != null)
|
||||
return false;
|
||||
return key.equals(user.key);
|
||||
|
||||
}
|
||||
@ -250,9 +243,9 @@ public class ParcelableUser implements Parcelable, Comparable<ParcelableUser> {
|
||||
return calculateHashCode(account_key, key);
|
||||
}
|
||||
|
||||
public static int calculateHashCode(UserKey accountKey, UserKey userKey) {
|
||||
int result = accountKey.hashCode();
|
||||
result = 31 * result + userKey.hashCode();
|
||||
public static int calculateHashCode(UserKey accountKey, UserKey key) {
|
||||
int result = accountKey != null ? key.hashCode() : 0;
|
||||
result = 31 * result + key.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,6 @@ import android.view.View.OnClickListener;
|
||||
import android.view.View.OnLongClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
@ -1582,7 +1581,7 @@ public class ComposeActivity extends BaseActivity implements OnMenuItemClickList
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
((CheckableLinearLayout) itemView).toggle();
|
||||
adapter.toggleSelection(getAdapterPosition());
|
||||
adapter.toggleSelection(getLayoutPosition());
|
||||
}
|
||||
|
||||
|
||||
@ -1683,7 +1682,7 @@ public class ComposeActivity extends BaseActivity implements OnMenuItemClickList
|
||||
}
|
||||
|
||||
private void toggleSelection(int position) {
|
||||
if (mAccounts == null) return;
|
||||
if (mAccounts == null || position < 0) return;
|
||||
final ParcelableCredentials account = mAccounts[position];
|
||||
mSelection.put(account.account_key, !Boolean.TRUE.equals(mSelection.get(account.account_key)));
|
||||
mActivity.notifyAccountSelectionChanged();
|
||||
|
@ -41,6 +41,8 @@ import android.view.View;
|
||||
|
||||
import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.mariotaku.abstask.library.AbstractTask;
|
||||
import org.mariotaku.abstask.library.TaskStarter;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.adapter.ParcelableStatusesAdapter;
|
||||
import org.mariotaku.twidere.adapter.iface.ILoadMoreSupportAdapter.IndicatorPosition;
|
||||
@ -53,8 +55,6 @@ import org.mariotaku.twidere.model.ParcelableStatus;
|
||||
import org.mariotaku.twidere.model.RefreshTaskParam;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.model.message.StatusListChangedEvent;
|
||||
import org.mariotaku.abstask.library.AbstractTask;
|
||||
import org.mariotaku.abstask.library.TaskStarter;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.IntentUtils;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
@ -549,10 +549,13 @@ public abstract class AbsStatusesFragment extends AbsContentListRecyclerViewFrag
|
||||
if (status == null) return;
|
||||
final long positionKey = status.position_key > 0 ? status.position_key : status.timestamp;
|
||||
mReadStateManager.setPosition(readPositionTag, positionKey);
|
||||
for (UserKey accountKey : getAccountKeys()) {
|
||||
final String tag = Utils.getReadPositionTagWithAccounts(getReadPositionTagWithArguments(),
|
||||
accountKey);
|
||||
mReadStateManager.setPosition(tag, positionKey);
|
||||
final UserKey[] accountKeys = getAccountKeys();
|
||||
if (accountKeys.length > 1) {
|
||||
for (UserKey accountKey : accountKeys) {
|
||||
final String tag = Utils.getReadPositionTagWithAccounts(getReadPositionTagWithArguments(),
|
||||
accountKey);
|
||||
mReadStateManager.setPosition(tag, positionKey);
|
||||
}
|
||||
}
|
||||
mReadStateManager.setPosition(getCurrentReadPositionTag(), positionKey, true);
|
||||
}
|
||||
|
@ -86,6 +86,8 @@ public final class DataExportImportTypeSelectorDialogFragment extends BaseSuppor
|
||||
mAdapter.add(new Type(R.string.user_colors, DataImportExportUtils.FLAG_USER_COLORS));
|
||||
mAdapter.add(new Type(R.string.custom_host_mapping, DataImportExportUtils.FLAG_HOST_MAPPING));
|
||||
mAdapter.add(new Type(R.string.keyboard_shortcuts, DataImportExportUtils.FLAG_KEYBOARD_SHORTCUTS));
|
||||
mAdapter.add(new Type(R.string.filters, DataImportExportUtils.FLAG_FILTERS));
|
||||
mAdapter.add(new Type(R.string.tabs, DataImportExportUtils.FLAG_TABS));
|
||||
mListView.setAdapter(mAdapter);
|
||||
mListView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
|
||||
mListView.setOnItemClickListener(this);
|
||||
|
@ -35,7 +35,7 @@ import com.squareup.otto.Subscribe;
|
||||
|
||||
import org.mariotaku.twidere.adapter.TrendsAdapter;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.model.message.TaskStateChangedEvent;
|
||||
import org.mariotaku.twidere.model.message.TrendsRefreshedEvent;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
|
||||
@ -124,14 +124,8 @@ public class TrendsSuggestionsFragment extends AbsContentListViewFragment<Trends
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
public void notifyTaskStateChanged(TaskStateChangedEvent event) {
|
||||
updateRefreshState();
|
||||
}
|
||||
|
||||
protected void updateRefreshState() {
|
||||
final AsyncTwitterWrapper twitter = mTwitterWrapper;
|
||||
if (twitter == null || !getUserVisibleHint()) return;
|
||||
setRefreshing(twitter.isLocalTrendsRefreshing());
|
||||
public void onTrendsRefreshedEvent(TrendsRefreshedEvent event) {
|
||||
setRefreshing(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -101,6 +101,8 @@ public class UserListTimelineFragment extends ParcelableStatusesFragment {
|
||||
}
|
||||
sb.append('_');
|
||||
sb.append(listName);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
@ -0,0 +1,122 @@
|
||||
package org.mariotaku.twidere.model;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.mariotaku.library.objectcursor.annotation.CursorField;
|
||||
import org.mariotaku.library.objectcursor.annotation.CursorObject;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/3/28.
|
||||
*/
|
||||
@JsonObject
|
||||
public class FiltersData {
|
||||
|
||||
@JsonField(name = "users")
|
||||
List<UserItem> users;
|
||||
@JsonField(name = "keywords")
|
||||
List<BaseItem> keywords;
|
||||
@JsonField(name = "sources")
|
||||
List<BaseItem> sources;
|
||||
@JsonField(name = "links")
|
||||
List<BaseItem> links;
|
||||
|
||||
public List<UserItem> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
public List<BaseItem> getKeywords() {
|
||||
return keywords;
|
||||
}
|
||||
|
||||
public List<BaseItem> getSources() {
|
||||
return sources;
|
||||
}
|
||||
|
||||
public List<BaseItem> getLinks() {
|
||||
return links;
|
||||
}
|
||||
|
||||
public void setUsers(List<UserItem> users) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
public void setKeywords(List<BaseItem> keywords) {
|
||||
this.keywords = keywords;
|
||||
}
|
||||
|
||||
public void setSources(List<BaseItem> sources) {
|
||||
this.sources = sources;
|
||||
}
|
||||
|
||||
public void setLinks(List<BaseItem> links) {
|
||||
this.links = links;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FiltersData{" +
|
||||
"users=" + users +
|
||||
", keywords=" + keywords +
|
||||
", sources=" + sources +
|
||||
", links=" + links +
|
||||
'}';
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
@CursorObject(valuesCreator = true)
|
||||
public static class UserItem {
|
||||
@CursorField(Filters.Users.USER_KEY)
|
||||
@JsonField(name = "user_key")
|
||||
String userKey;
|
||||
@CursorField(Filters.Users.NAME)
|
||||
@JsonField(name = "name")
|
||||
String name;
|
||||
@CursorField(Filters.Users.SCREEN_NAME)
|
||||
@JsonField(name = "screen_name")
|
||||
String screenName;
|
||||
|
||||
public String getUserKey() {
|
||||
return userKey;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getScreenName() {
|
||||
return screenName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserItem{" +
|
||||
"userKey='" + userKey + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", screenName='" + screenName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
@CursorObject(valuesCreator = true)
|
||||
public static class BaseItem {
|
||||
@CursorField(Filters.VALUE)
|
||||
@JsonField(name = "value")
|
||||
String value;
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "BaseItem{" +
|
||||
"value='" + value + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,20 @@
|
||||
package org.mariotaku.twidere.model;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.bluelinelabs.logansquare.annotation.OnJsonParseComplete;
|
||||
import com.bluelinelabs.logansquare.annotation.OnPreJsonSerialize;
|
||||
|
||||
import org.mariotaku.library.objectcursor.annotation.CursorField;
|
||||
import org.mariotaku.library.objectcursor.annotation.CursorObject;
|
||||
import org.mariotaku.twidere.annotation.CustomTabType;
|
||||
import org.mariotaku.twidere.model.tab.argument.TabArguments;
|
||||
import org.mariotaku.twidere.model.tab.argument.TextQueryArguments;
|
||||
import org.mariotaku.twidere.model.tab.argument.UserArguments;
|
||||
import org.mariotaku.twidere.model.tab.argument.UserListArguments;
|
||||
import org.mariotaku.twidere.model.tab.extra.InteractionsTabExtras;
|
||||
import org.mariotaku.twidere.model.tab.extra.TabExtras;
|
||||
import org.mariotaku.twidere.model.util.TabArgumentsFieldConverter;
|
||||
import org.mariotaku.twidere.model.util.TabExtrasFieldConverter;
|
||||
@ -13,29 +24,45 @@ import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
|
||||
* Created by mariotaku on 16/3/6.
|
||||
*/
|
||||
@CursorObject(valuesCreator = true)
|
||||
@JsonObject
|
||||
public class Tab {
|
||||
@CursorField(value = Tabs._ID, excludeWrite = true)
|
||||
@JsonField(name = "id")
|
||||
long id;
|
||||
|
||||
@CursorField(Tabs.NAME)
|
||||
@JsonField(name = "name")
|
||||
String name;
|
||||
|
||||
@CursorField(Tabs.ICON)
|
||||
@JsonField(name = "icon")
|
||||
String icon;
|
||||
|
||||
@CursorField(Tabs.TYPE)
|
||||
@JsonField(name = "type")
|
||||
@CustomTabType
|
||||
String type;
|
||||
|
||||
@CursorField(Tabs.POSITION)
|
||||
@JsonField(name = "position")
|
||||
int position;
|
||||
|
||||
@Nullable
|
||||
@CursorField(value = Tabs.ARGUMENTS, converter = TabArgumentsFieldConverter.class)
|
||||
TabArguments arguments;
|
||||
|
||||
@Nullable
|
||||
@CursorField(value = Tabs.EXTRAS, converter = TabExtrasFieldConverter.class)
|
||||
TabExtras extras;
|
||||
|
||||
@Nullable
|
||||
@JsonField(name = "arguments")
|
||||
InternalArguments internalArguments;
|
||||
|
||||
@Nullable
|
||||
@JsonField(name = "extras")
|
||||
InternalExtras internalExtras;
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
@ -73,22 +100,41 @@ public class Tab {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TabArguments getArguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
public void setArguments(TabArguments arguments) {
|
||||
public void setArguments(@Nullable TabArguments arguments) {
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TabExtras getExtras() {
|
||||
return extras;
|
||||
}
|
||||
|
||||
public void setExtras(TabExtras extras) {
|
||||
public void setExtras(@Nullable TabExtras extras) {
|
||||
this.extras = extras;
|
||||
}
|
||||
|
||||
|
||||
@OnPreJsonSerialize
|
||||
void beforeJsonSerialize() {
|
||||
internalArguments = InternalArguments.from(arguments);
|
||||
internalExtras = InternalExtras.from(extras);
|
||||
}
|
||||
|
||||
@OnJsonParseComplete
|
||||
void onJsonParseComplete() {
|
||||
if (internalArguments != null) {
|
||||
arguments = internalArguments.getArguments();
|
||||
}
|
||||
if (internalExtras != null) {
|
||||
extras = internalExtras.getExtras();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Tab{" +
|
||||
@ -101,4 +147,71 @@ public class Tab {
|
||||
", extras=" + extras +
|
||||
'}';
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
static class InternalArguments {
|
||||
@JsonField(name = "base")
|
||||
TabArguments base;
|
||||
@JsonField(name = "text_query")
|
||||
TextQueryArguments textQuery;
|
||||
@JsonField(name = "user")
|
||||
UserArguments user;
|
||||
@JsonField(name = "user_list")
|
||||
UserListArguments userList;
|
||||
|
||||
public static InternalArguments from(TabArguments arguments) {
|
||||
if (arguments == null) return null;
|
||||
InternalArguments result = new InternalArguments();
|
||||
if (arguments instanceof TextQueryArguments) {
|
||||
result.textQuery = (TextQueryArguments) arguments;
|
||||
} else if (arguments instanceof UserArguments) {
|
||||
result.user = (UserArguments) arguments;
|
||||
} else if (arguments instanceof UserListArguments) {
|
||||
result.userList = (UserListArguments) arguments;
|
||||
} else {
|
||||
result.base = arguments;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public TabArguments getArguments() {
|
||||
if (userList != null) {
|
||||
return userList;
|
||||
} else if (user != null) {
|
||||
return user;
|
||||
} else if (textQuery != null) {
|
||||
return textQuery;
|
||||
} else {
|
||||
return base;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JsonObject
|
||||
static class InternalExtras {
|
||||
|
||||
@JsonField(name = "base")
|
||||
TabExtras base;
|
||||
@JsonField(name = "interactions")
|
||||
InteractionsTabExtras interactions;
|
||||
|
||||
public static InternalExtras from(TabExtras extras) {
|
||||
if (extras == null) return null;
|
||||
InternalExtras result = new InternalExtras();
|
||||
if (extras instanceof InteractionsTabExtras) {
|
||||
result.interactions = (InteractionsTabExtras) extras;
|
||||
} else {
|
||||
result.base = extras;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public TabExtras getExtras() {
|
||||
if (interactions != null) {
|
||||
return interactions;
|
||||
} else {
|
||||
return base;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package org.mariotaku.twidere.model.message;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/3/28.
|
||||
*/
|
||||
public class TrendsRefreshedEvent {
|
||||
}
|
@ -45,6 +45,10 @@ import org.mariotaku.sqliteqb.library.Expression;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.preference.iface.IDialogPreference;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
|
||||
public class RingtonePreference extends DialogPreference implements IDialogPreference {
|
||||
@ -52,7 +56,6 @@ public class RingtonePreference extends DialogPreference implements IDialogPrefe
|
||||
private final int mRingtoneType;
|
||||
private final boolean mShowDefault;
|
||||
private final boolean mShowSilent;
|
||||
private int mSelectedItem;
|
||||
|
||||
public RingtonePreference(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
@ -64,12 +67,16 @@ public class RingtonePreference extends DialogPreference implements IDialogPrefe
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public int getItem() {
|
||||
return mSelectedItem;
|
||||
public int getRingtoneType() {
|
||||
return mRingtoneType;
|
||||
}
|
||||
|
||||
public void setItem(final int selected) {
|
||||
mSelectedItem = selected;
|
||||
public boolean isShowDefault() {
|
||||
return mShowDefault;
|
||||
}
|
||||
|
||||
public boolean isShowSilent() {
|
||||
return mShowSilent;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -83,6 +90,7 @@ public class RingtonePreference extends DialogPreference implements IDialogPrefe
|
||||
implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||
private MediaPlayer mMediaPlayer;
|
||||
private SimpleCursorAdapter mAdapter;
|
||||
private Uri mCurrentUri;
|
||||
|
||||
public static RingtonePreferenceDialogFragment newInstance(String key) {
|
||||
final RingtonePreferenceDialogFragment df = new RingtonePreferenceDialogFragment();
|
||||
@ -94,6 +102,12 @@ public class RingtonePreference extends DialogPreference implements IDialogPrefe
|
||||
|
||||
@Override
|
||||
public void onDialogClosed(boolean positive) {
|
||||
if (positive && mCurrentUri != null) {
|
||||
final RingtonePreference preference = (RingtonePreference) getPreference();
|
||||
if (preference.isPersistent()) {
|
||||
preference.persistString(mCurrentUri.toString());
|
||||
}
|
||||
}
|
||||
if (mMediaPlayer != null) {
|
||||
if (mMediaPlayer.isPlaying()) {
|
||||
mMediaPlayer.stop();
|
||||
@ -151,8 +165,9 @@ public class RingtonePreference extends DialogPreference implements IDialogPrefe
|
||||
mMediaPlayer = new MediaPlayer();
|
||||
mMediaPlayer.setLooping(false);
|
||||
final String ringtone = cursor.getString(cursor.getColumnIndex(Audio.Media.DATA));
|
||||
final Uri def_uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||
final Uri uri = isEmpty(ringtone) ? def_uri : Uri.parse(ringtone);
|
||||
final Uri defUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
|
||||
final Uri uri = isEmpty(ringtone) ? defUri : Uri.parse(ringtone);
|
||||
mCurrentUri = uri;
|
||||
try {
|
||||
mMediaPlayer.setDataSource(getContext(), uri);
|
||||
mMediaPlayer.prepare();
|
||||
@ -169,8 +184,29 @@ public class RingtonePreference extends DialogPreference implements IDialogPrefe
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
final String[] cols = new String[]{Audio.Media._ID, Audio.Media.DATA, Audio.Media.TITLE};
|
||||
final String selection = Expression.equalsArgs(Audio.Media.IS_NOTIFICATION).getSQL();
|
||||
final String[] selectionArgs = {"1"};
|
||||
RingtonePreference preference = (RingtonePreference) getPreference();
|
||||
int ringtoneType = preference.getRingtoneType();
|
||||
List<Expression> expressions = new ArrayList<>();
|
||||
if ((ringtoneType & RingtoneManager.TYPE_NOTIFICATION) != 0) {
|
||||
expressions.add(Expression.equalsArgs(Audio.Media.IS_NOTIFICATION));
|
||||
}
|
||||
if ((ringtoneType & RingtoneManager.TYPE_RINGTONE) != 0) {
|
||||
expressions.add(Expression.equalsArgs(Audio.Media.IS_RINGTONE));
|
||||
}
|
||||
if ((ringtoneType & RingtoneManager.TYPE_ALARM) != 0) {
|
||||
expressions.add(Expression.equalsArgs(Audio.Media.IS_ALARM));
|
||||
}
|
||||
final String selection;
|
||||
final String[] selectionArgs;
|
||||
if (expressions.isEmpty()) {
|
||||
selection = null;
|
||||
selectionArgs = null;
|
||||
} else {
|
||||
final int size = expressions.size();
|
||||
selection = Expression.or(expressions.toArray(new Expression[size])).getSQL();
|
||||
selectionArgs = new String[size];
|
||||
Arrays.fill(selectionArgs, "1");
|
||||
}
|
||||
return new CursorLoader(getContext(), Audio.Media.INTERNAL_CONTENT_URI, cols, selection,
|
||||
selectionArgs, Audio.Media.DEFAULT_SORT_ORDER);
|
||||
}
|
||||
|
@ -176,9 +176,7 @@ public class RefreshService extends Service implements Constants {
|
||||
if (BuildConfig.DEBUG) {
|
||||
Log.d(LOGTAG, String.format("Auto refreshing trends for %s", Arrays.toString(refreshIds)));
|
||||
}
|
||||
if (!isLocalTrendsRefreshing()) {
|
||||
getLocalTrends(refreshIds);
|
||||
}
|
||||
getLocalTrends(refreshIds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -324,10 +322,6 @@ public class RefreshService extends Service implements Constants {
|
||||
return mTwitterWrapper.isHomeTimelineRefreshing();
|
||||
}
|
||||
|
||||
private boolean isLocalTrendsRefreshing() {
|
||||
return mTwitterWrapper.isLocalTrendsRefreshing();
|
||||
}
|
||||
|
||||
private boolean isReceivedDirectMessagesRefreshing() {
|
||||
return mTwitterWrapper.isReceivedDirectMessagesRefreshing();
|
||||
}
|
||||
|
@ -6,19 +6,25 @@ import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.squareup.otto.Bus;
|
||||
|
||||
import org.mariotaku.abstask.library.AbstractTask;
|
||||
import org.mariotaku.twidere.api.twitter.Twitter;
|
||||
import org.mariotaku.twidere.api.twitter.TwitterException;
|
||||
import org.mariotaku.twidere.api.twitter.model.Trends;
|
||||
import org.mariotaku.twidere.model.UserKey;
|
||||
import org.mariotaku.twidere.model.message.TrendsRefreshedEvent;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore;
|
||||
import org.mariotaku.twidere.util.ContentValuesCreator;
|
||||
import org.mariotaku.twidere.util.TwitterAPIFactory;
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
||||
import org.mariotaku.twidere.util.dagger.GeneralComponentHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 16/2/24.
|
||||
*/
|
||||
@ -27,7 +33,11 @@ public abstract class GetTrendsTask extends AbstractTask<Object, Object, Object>
|
||||
private final Context mContext;
|
||||
private final UserKey mAccountId;
|
||||
|
||||
@Inject
|
||||
protected Bus mBus;
|
||||
|
||||
public GetTrendsTask(Context context, final UserKey accountKey) {
|
||||
GeneralComponentHelper.build(context).inject(this);
|
||||
this.mContext = context;
|
||||
this.mAccountId = accountKey;
|
||||
}
|
||||
@ -47,6 +57,11 @@ public abstract class GetTrendsTask extends AbstractTask<Object, Object, Object>
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterExecute(Object o) {
|
||||
mBus.post(new TrendsRefreshedEvent());
|
||||
}
|
||||
|
||||
protected abstract Uri getContentUri();
|
||||
|
||||
private static void storeTrends(ContentResolver cr, Uri uri, List<Trends> trendsList) {
|
||||
|
@ -357,11 +357,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
return mAsyncTaskManager.hasRunningTasksForTag(TASK_TAG_GET_HOME_TIMELINE);
|
||||
}
|
||||
|
||||
public boolean isLocalTrendsRefreshing() {
|
||||
return mAsyncTaskManager.hasRunningTasksForTag(TASK_TAG_GET_TRENDS)
|
||||
|| mAsyncTaskManager.hasRunningTasksForTag(TASK_TAG_STORE_TRENDS);
|
||||
}
|
||||
|
||||
public boolean isReceivedDirectMessagesRefreshing() {
|
||||
return mAsyncTaskManager.hasRunningTasksForTag(TASK_TAG_GET_RECEIVED_DIRECT_MESSAGES);
|
||||
}
|
||||
|
@ -19,20 +19,38 @@
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.WorkerThread;
|
||||
import android.util.Log;
|
||||
|
||||
import com.bluelinelabs.logansquare.JsonMapper;
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
import org.mariotaku.library.objectcursor.ObjectCursor;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.annotation.Preference;
|
||||
import org.mariotaku.twidere.annotation.PreferenceType;
|
||||
import org.mariotaku.twidere.constant.SharedPreferenceConstants;
|
||||
import org.mariotaku.twidere.model.FiltersData;
|
||||
import org.mariotaku.twidere.model.FiltersData$BaseItemCursorIndices;
|
||||
import org.mariotaku.twidere.model.FiltersData$BaseItemValuesCreator;
|
||||
import org.mariotaku.twidere.model.FiltersData$UserItemCursorIndices;
|
||||
import org.mariotaku.twidere.model.FiltersData$UserItemValuesCreator;
|
||||
import org.mariotaku.twidere.model.Tab;
|
||||
import org.mariotaku.twidere.model.TabCursorIndices;
|
||||
import org.mariotaku.twidere.model.TabValuesCreator;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
@ -40,7 +58,9 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
@ -54,16 +74,19 @@ public class DataImportExportUtils implements Constants {
|
||||
public static final String ENTRY_HOST_MAPPING = "host_mapping.json";
|
||||
public static final String ENTRY_KEYBOARD_SHORTCUTS = "keyboard_shortcuts.json";
|
||||
public static final String ENTRY_FILTERS = "filters.json";
|
||||
public static final String ENTRY_TABS = "tabs.json";
|
||||
|
||||
public static final int FLAG_PREFERENCES = 0x1;
|
||||
public static final int FLAG_NICKNAMES = 0x2;
|
||||
public static final int FLAG_USER_COLORS = 0x4;
|
||||
public static final int FLAG_HOST_MAPPING = 0x8;
|
||||
public static final int FLAG_KEYBOARD_SHORTCUTS = 0x10;
|
||||
public static final int FLAG_FILTERS = 0x20;
|
||||
public static final int FLAG_PREFERENCES = 0b1;
|
||||
public static final int FLAG_NICKNAMES = 0b10;
|
||||
public static final int FLAG_USER_COLORS = 0b100;
|
||||
public static final int FLAG_HOST_MAPPING = 0b1000;
|
||||
public static final int FLAG_KEYBOARD_SHORTCUTS = 0b10000;
|
||||
public static final int FLAG_FILTERS = 0b100000;
|
||||
public static final int FLAG_TABS = 0b1000000;
|
||||
public static final int FLAG_ALL = FLAG_PREFERENCES | FLAG_NICKNAMES | FLAG_USER_COLORS
|
||||
| FLAG_HOST_MAPPING | FLAG_KEYBOARD_SHORTCUTS | FLAG_FILTERS;
|
||||
| FLAG_HOST_MAPPING | FLAG_KEYBOARD_SHORTCUTS | FLAG_FILTERS | FLAG_TABS;
|
||||
|
||||
@WorkerThread
|
||||
public static void exportData(final Context context, @NonNull final File dst, final int flags) throws IOException {
|
||||
dst.delete();
|
||||
final FileOutputStream fos = new FileOutputStream(dst);
|
||||
@ -84,6 +107,40 @@ public class DataImportExportUtils implements Constants {
|
||||
if (hasFlag(flags, FLAG_KEYBOARD_SHORTCUTS)) {
|
||||
exportSharedPreferencesData(zos, context, KEYBOARD_SHORTCUTS_PREFERENCES_NAME, ENTRY_KEYBOARD_SHORTCUTS, ConvertToStringProcessStrategy.SINGLETON);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_FILTERS)) {
|
||||
// TODO export filters
|
||||
FiltersData data = new FiltersData();
|
||||
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
data.setUsers(queryAll(cr, Filters.Users.CONTENT_URI, Filters.Users.COLUMNS,
|
||||
FiltersData$UserItemCursorIndices.class));
|
||||
data.setKeywords(queryAll(cr, Filters.Keywords.CONTENT_URI, Filters.Keywords.COLUMNS,
|
||||
FiltersData$BaseItemCursorIndices.class));
|
||||
data.setSources(queryAll(cr, Filters.Sources.CONTENT_URI, Filters.Sources.COLUMNS,
|
||||
FiltersData$BaseItemCursorIndices.class));
|
||||
data.setLinks(queryAll(cr, Filters.Links.CONTENT_URI, Filters.Links.COLUMNS,
|
||||
FiltersData$BaseItemCursorIndices.class));
|
||||
exportItem(zos, ENTRY_FILTERS, FiltersData.class, data);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_TABS)) {
|
||||
// TODO export tabs
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
final Cursor c = cr.query(Tabs.CONTENT_URI, Tabs.COLUMNS, null, null, null);
|
||||
if (c != null) {
|
||||
final List<Tab> tabs = new ArrayList<>(c.getCount());
|
||||
try {
|
||||
TabCursorIndices ci = new TabCursorIndices(c);
|
||||
c.moveToFirst();
|
||||
while (!c.isAfterLast()) {
|
||||
tabs.add(ci.newObject(c));
|
||||
c.moveToNext();
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
exportItemsList(zos, ENTRY_TABS, Tab.class, tabs);
|
||||
}
|
||||
}
|
||||
zos.finish();
|
||||
zos.flush();
|
||||
} finally {
|
||||
@ -92,6 +149,30 @@ public class DataImportExportUtils implements Constants {
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> List<T> queryAll(ContentResolver cr, Uri uri, String[] projection,
|
||||
Class<? extends ObjectCursor.CursorIndices<T>> cls) {
|
||||
Cursor c = cr.query(uri, projection, null, null, null);
|
||||
if (c == null) return null;
|
||||
try {
|
||||
final ObjectCursor.CursorIndices<T> ci;
|
||||
try {
|
||||
ci = cls.getConstructor(Cursor.class).newInstance(c);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
List<T> items = new ArrayList<>(c.getCount());
|
||||
c.moveToFirst();
|
||||
while (!c.isAfterLast()) {
|
||||
items.add(ci.newObject(c));
|
||||
c.moveToNext();
|
||||
}
|
||||
return items;
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public static int getImportedSettingsFlags(@NonNull final File src) throws IOException {
|
||||
final ZipFile zipFile = new ZipFile(src);
|
||||
int flags = 0;
|
||||
@ -113,6 +194,9 @@ public class DataImportExportUtils implements Constants {
|
||||
if (zipFile.getEntry(ENTRY_FILTERS) != null) {
|
||||
flags |= FLAG_FILTERS;
|
||||
}
|
||||
if (zipFile.getEntry(ENTRY_TABS) != null) {
|
||||
flags |= FLAG_TABS;
|
||||
}
|
||||
zipFile.close();
|
||||
return flags;
|
||||
}
|
||||
@ -153,7 +237,50 @@ public class DataImportExportUtils implements Constants {
|
||||
importSharedPreferencesData(zipFile, context, KEYBOARD_SHORTCUTS_PREFERENCES_NAME, ENTRY_KEYBOARD_SHORTCUTS, ConvertToStringProcessStrategy.SINGLETON);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_FILTERS)) {
|
||||
importItem(context, zipFile, ENTRY_FILTERS, FiltersData.class, new ContentResolverProcessStrategy<FiltersData>() {
|
||||
@Override
|
||||
public boolean importItem(ContentResolver cr, FiltersData filtersData) {
|
||||
if (filtersData == null) return false;
|
||||
insertBase(cr, Filters.Keywords.CONTENT_URI, filtersData.getKeywords());
|
||||
insertBase(cr, Filters.Sources.CONTENT_URI, filtersData.getSources());
|
||||
insertBase(cr, Filters.Links.CONTENT_URI, filtersData.getLinks());
|
||||
insertUser(cr, Filters.Users.CONTENT_URI, filtersData.getUsers());
|
||||
return true;
|
||||
}
|
||||
|
||||
void insertBase(ContentResolver cr, Uri uri, List<FiltersData.BaseItem> items) {
|
||||
if (items == null) return;
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (FiltersData.BaseItem item : items) {
|
||||
values.add(FiltersData$BaseItemValuesCreator.create(item));
|
||||
}
|
||||
ContentResolverUtils.bulkInsert(cr, uri, values);
|
||||
}
|
||||
|
||||
void insertUser(ContentResolver cr, Uri uri, List<FiltersData.UserItem> items) {
|
||||
if (items == null) return;
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (FiltersData.UserItem item : items) {
|
||||
values.add(FiltersData$UserItemValuesCreator.create(item));
|
||||
}
|
||||
ContentResolverUtils.bulkInsert(cr, uri, values);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (hasFlag(flags, FLAG_TABS)) {
|
||||
importItemsList(context, zipFile, ENTRY_TABS, Tab.class, new ContentResolverProcessStrategy<List<Tab>>() {
|
||||
@Override
|
||||
public boolean importItem(ContentResolver cr, List<Tab> items) {
|
||||
if (items == null) return false;
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (Tab item : items) {
|
||||
values.add(TabValuesCreator.create(item));
|
||||
}
|
||||
cr.delete(Tabs.CONTENT_URI, null, null);
|
||||
ContentResolverUtils.bulkInsert(cr, Tabs.CONTENT_URI, values);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
zipFile.close();
|
||||
}
|
||||
@ -164,7 +291,7 @@ public class DataImportExportUtils implements Constants {
|
||||
|
||||
private static void importSharedPreferencesData(@NonNull final ZipFile zipFile, @NonNull final Context context,
|
||||
@NonNull final String preferencesName, @NonNull final String entryName,
|
||||
@NonNull final ProcessStrategy strategy) throws IOException {
|
||||
@NonNull final SharedPreferencesProcessStrategy strategy) throws IOException {
|
||||
final ZipEntry entry = zipFile.getEntry(entryName);
|
||||
if (entry == null) return;
|
||||
final JsonParser jsonParser = LoganSquare.JSON_FACTORY.createParser(zipFile.getInputStream(entry));
|
||||
@ -186,7 +313,7 @@ public class DataImportExportUtils implements Constants {
|
||||
|
||||
private static void exportSharedPreferencesData(@NonNull final ZipOutputStream zos, final Context context,
|
||||
@NonNull final String preferencesName, @NonNull final String entryName,
|
||||
@NonNull final ProcessStrategy strategy) throws IOException {
|
||||
@NonNull final SharedPreferencesProcessStrategy strategy) throws IOException {
|
||||
final SharedPreferences preferences = context.getSharedPreferences(preferencesName, Context.MODE_PRIVATE);
|
||||
final Map<String, ?> map = preferences.getAll();
|
||||
zos.putNextEntry(new ZipEntry(entryName));
|
||||
@ -200,15 +327,69 @@ public class DataImportExportUtils implements Constants {
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
private interface ProcessStrategy {
|
||||
private static <T> void importItemsList(@NonNull final Context context,
|
||||
@NonNull final ZipFile zipFile,
|
||||
@NonNull final String entryName,
|
||||
@NonNull final Class<T> itemCls,
|
||||
@NonNull final ContentResolverProcessStrategy<List<T>> strategy)
|
||||
throws IOException {
|
||||
final ZipEntry entry = zipFile.getEntry(entryName);
|
||||
if (entry == null) return;
|
||||
final JsonMapper<T> mapper = LoganSquareMapperFinder.mapperFor(itemCls);
|
||||
List<T> itemsList = mapper.parseList(zipFile.getInputStream(entry));
|
||||
strategy.importItem(context.getContentResolver(), itemsList);
|
||||
}
|
||||
|
||||
|
||||
private static <T> void exportItemsList(@NonNull final ZipOutputStream zos,
|
||||
@NonNull final String entryName,
|
||||
@NonNull final Class<T> itemCls,
|
||||
@NonNull final List<T> itemList) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(entryName));
|
||||
final JsonGenerator jsonGenerator = LoganSquare.JSON_FACTORY.createGenerator(zos);
|
||||
LoganSquareMapperFinder.mapperFor(itemCls).serialize(itemList, jsonGenerator);
|
||||
jsonGenerator.flush();
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
private static <T> void importItem(@NonNull final Context context,
|
||||
@NonNull final ZipFile zipFile,
|
||||
@NonNull final String entryName,
|
||||
@NonNull final Class<T> itemCls,
|
||||
@NonNull final ContentResolverProcessStrategy<T> strategy)
|
||||
throws IOException {
|
||||
final ZipEntry entry = zipFile.getEntry(entryName);
|
||||
if (entry == null) return;
|
||||
final JsonMapper<T> mapper = LoganSquareMapperFinder.mapperFor(itemCls);
|
||||
T item = mapper.parse(zipFile.getInputStream(entry));
|
||||
strategy.importItem(context.getContentResolver(), item);
|
||||
}
|
||||
|
||||
|
||||
private static <T> void exportItem(@NonNull final ZipOutputStream zos,
|
||||
@NonNull final String entryName,
|
||||
@NonNull final Class<T> itemCls,
|
||||
@NonNull final T item) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(entryName));
|
||||
final JsonGenerator jsonGenerator = LoganSquare.JSON_FACTORY.createGenerator(zos);
|
||||
LoganSquareMapperFinder.mapperFor(itemCls).serialize(item, jsonGenerator, true);
|
||||
jsonGenerator.flush();
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
private interface ContentResolverProcessStrategy<T> {
|
||||
boolean importItem(ContentResolver cr, T item);
|
||||
}
|
||||
|
||||
private interface SharedPreferencesProcessStrategy {
|
||||
boolean importValue(JsonParser jsonParser, String key, SharedPreferences.Editor editor) throws IOException;
|
||||
|
||||
boolean exportValue(JsonGenerator jsonGenerator, String key, SharedPreferences preferences) throws IOException;
|
||||
}
|
||||
|
||||
private static final class ConvertToStringProcessStrategy implements ProcessStrategy {
|
||||
private static final class ConvertToStringProcessStrategy implements SharedPreferencesProcessStrategy {
|
||||
|
||||
private static final ProcessStrategy SINGLETON = new ConvertToStringProcessStrategy();
|
||||
private static final SharedPreferencesProcessStrategy SINGLETON = new ConvertToStringProcessStrategy();
|
||||
|
||||
@Override
|
||||
public boolean importValue(JsonParser jsonParser, String key, SharedPreferences.Editor editor) throws IOException {
|
||||
@ -230,9 +411,9 @@ public class DataImportExportUtils implements Constants {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ConvertToIntProcessStrategy implements ProcessStrategy {
|
||||
private static final class ConvertToIntProcessStrategy implements SharedPreferencesProcessStrategy {
|
||||
|
||||
private static final ProcessStrategy SINGLETON = new ConvertToIntProcessStrategy();
|
||||
private static final SharedPreferencesProcessStrategy SINGLETON = new ConvertToIntProcessStrategy();
|
||||
|
||||
@Override
|
||||
public boolean importValue(JsonParser jsonParser, String key, SharedPreferences.Editor editor) throws IOException {
|
||||
@ -254,7 +435,7 @@ public class DataImportExportUtils implements Constants {
|
||||
}
|
||||
}
|
||||
|
||||
private static final class AnnotationProcessStrategy implements ProcessStrategy {
|
||||
private static final class AnnotationProcessStrategy implements SharedPreferencesProcessStrategy {
|
||||
|
||||
private final HashMap<String, Preference> supportedMap;
|
||||
|
||||
|
@ -316,7 +316,8 @@ public class TwitterAPIFactory implements TwidereConstants {
|
||||
}
|
||||
|
||||
public static boolean verifyApiFormat(@NonNull String format) {
|
||||
return URLUtil.isValidUrl(getApiBaseUrl(format, "test"));
|
||||
final String url = getApiBaseUrl(format, "test");
|
||||
return URLUtil.isHttpsUrl(url) || URLUtil.isHttpUrl(url);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@ -339,7 +340,10 @@ public class TwitterAPIFactory implements TwidereConstants {
|
||||
|
||||
@NonNull
|
||||
static String substituteLegacyApiBaseUrl(@NonNull String format, String domain) {
|
||||
final int startOfHost = format.indexOf("://") + 3;
|
||||
final int idxOfSlash = format.indexOf("://");
|
||||
// Not an url
|
||||
if (idxOfSlash < 0) return format;
|
||||
final int startOfHost = idxOfSlash + 3;
|
||||
if (startOfHost < 0) return getApiBaseUrl("https://[DOMAIN.]twitter.com/", domain);
|
||||
final int endOfHost = format.indexOf('/', startOfHost);
|
||||
final String host = endOfHost != -1 ? format.substring(startOfHost, endOfHost) : format.substring(startOfHost);
|
||||
|
@ -49,6 +49,7 @@ import org.mariotaku.twidere.service.BackgroundOperationService;
|
||||
import org.mariotaku.twidere.service.RefreshService;
|
||||
import org.mariotaku.twidere.task.AbsFriendshipOperationTask;
|
||||
import org.mariotaku.twidere.task.GetDirectMessagesTask;
|
||||
import org.mariotaku.twidere.task.GetTrendsTask;
|
||||
import org.mariotaku.twidere.task.ManagedAsyncTask;
|
||||
import org.mariotaku.twidere.task.twitter.GetActivitiesTask;
|
||||
import org.mariotaku.twidere.task.twitter.GetStatusesTask;
|
||||
@ -135,4 +136,6 @@ public interface GeneralComponent {
|
||||
void inject(ParcelableUserLoader loader);
|
||||
|
||||
void inject(ParcelableStatusLoader loader);
|
||||
|
||||
void inject(GetTrendsTask task);
|
||||
}
|
||||
|
@ -43,7 +43,7 @@
|
||||
android:title="@string/read_from_bottom"/>
|
||||
|
||||
<org.mariotaku.twidere.preference.TrendsLocationPreference
|
||||
android:key="trends_location"
|
||||
android:key="local_trends_woeid"
|
||||
android:summary="@string/trends_location_summary"
|
||||
android:title="@string/trends_location"/>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user