1
0
mirror of https://github.com/TwidereProject/Twidere-Android synced 2025-02-17 04:00:48 +01:00

bug fixes

This commit is contained in:
Mariotaku Lee 2016-03-08 14:40:23 +08:00
parent 06812df71a
commit 5e6fbc12c2
42 changed files with 589 additions and 389 deletions

View File

@ -21,6 +21,7 @@ package org.mariotaku.twidere;
import android.content.ContentResolver;
import org.mariotaku.twidere.constant.CompatibilityConstants;
import org.mariotaku.twidere.constant.IntentConstants;
import org.mariotaku.twidere.constant.SharedPreferenceConstants;
@ -29,7 +30,7 @@ import org.mariotaku.twidere.constant.SharedPreferenceConstants;
*
* @author mariotaku
*/
public interface TwidereConstants extends SharedPreferenceConstants, IntentConstants {
public interface TwidereConstants extends SharedPreferenceConstants, IntentConstants, CompatibilityConstants {
String TWIDERE_APP_NAME = "Twidere";
String TWIDERE_PROJECT_URL = "https://github.com/mariotaku/twidere";
@ -109,8 +110,6 @@ public interface TwidereConstants extends SharedPreferenceConstants, IntentConst
String AUTHORITY_PROFILE_EDITOR = "profile_editor";
String QUERY_PARAM_ACCOUNT_KEY = "account_key";
String QUERY_PARAM_ACCOUNT_ID = "account_id";
String QUERY_PARAM_ACCOUNT_IDS = "account_ids";
String QUERY_PARAM_ACCOUNT_NAME = "account_name";
String QUERY_PARAM_STATUS_ID = "status_id";
String QUERY_PARAM_USER_ID = "user_id";

View File

@ -0,0 +1,15 @@
package org.mariotaku.twidere.constant;
/**
* Created by mariotaku on 16/3/8.
*/
public interface CompatibilityConstants {
String QUERY_PARAM_ACCOUNT_ID = "account_id";
String QUERY_PARAM_ACCOUNT_IDS = "account_ids";
String EXTRA_ACCOUNT_ID = "account_id";
String EXTRA_ACCOUNT_IDS = "account_ids";
}

View File

@ -100,8 +100,6 @@ public interface IntentConstants {
String EXTRA_MENTIONS = "mentions";
String EXTRA_ACCOUNT_KEY = "account_key";
String EXTRA_ACCOUNT_KEYS = "account_keys";
String EXTRA_ACCOUNT_ID = "account_id";
String EXTRA_ACCOUNT_IDS = "account_ids";
String EXTRA_PAGE = "page";
String EXTRA_DATA = "data";
String EXTRA_QUERY = "query";

View File

@ -20,100 +20,14 @@
package org.mariotaku.twidere.util;
import android.graphics.Color;
import android.os.Bundle;
import android.util.JsonWriter;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import org.mariotaku.restfu.RestFuUtils;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.constant.IntentConstants;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import static android.text.TextUtils.isEmpty;
public final class ParseUtils {
public static String bundleToJSON(final Bundle args) {
final Set<String> keys = args.keySet();
final StringWriter sw = new StringWriter();
final JsonWriter json = new JsonWriter(sw);
try {
json.beginObject();
for (final String key : keys) {
json.name(key);
final Object value = args.get(key);
if (value == null) {
json.nullValue();
} else if (value instanceof Boolean) {
json.value((Boolean) value);
} else if (value instanceof Integer) {
json.value((Integer) value);
} else if (value instanceof Long) {
json.value((Long) value);
} else if (value instanceof String) {
json.value((String) value);
} else if (value instanceof Float) {
json.value((Float) value);
} else if (value instanceof Double) {
json.value((Double) value);
} else {
Log.w(TwidereConstants.LOGTAG, "Unknown type " + value.getClass().getSimpleName() + " in arguments key " + key);
}
}
json.endObject();
json.flush();
sw.flush();
return sw.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
RestFuUtils.closeSilently(json);
}
}
public static Bundle jsonToBundle(final String string) {
final Bundle bundle = new Bundle();
if (string == null) return bundle;
try {
final JSONObject json = new JSONObject(string);
final Iterator<?> it = json.keys();
while (it.hasNext()) {
final Object key_obj = it.next();
if (key_obj == null) {
continue;
}
final String key = key_obj.toString();
final Object value = json.get(key);
if (value instanceof Boolean) {
bundle.putBoolean(key, json.optBoolean(key));
} else if (value instanceof Integer) {
// Simple workaround for account_id
if (shouldPutLong(key)) {
bundle.putLong(key, json.optLong(key));
} else {
bundle.putInt(key, json.optInt(key));
}
} else if (value instanceof Long) {
bundle.putLong(key, json.optLong(key));
} else if (value instanceof String) {
bundle.putString(key, json.optString(key));
} else {
Log.w(TwidereConstants.LOGTAG, "Unknown type " + value.getClass().getSimpleName() + " in arguments key " + key);
}
}
} catch (final JSONException | ClassCastException e) {
e.printStackTrace();
}
return bundle;
}
public final class ParseUtils implements TwidereConstants {
public static String parseString(final String object) {
return object;
@ -136,11 +50,6 @@ public final class ParseUtils {
return String.valueOf(object);
}
private static boolean shouldPutLong(final String key) {
return IntentConstants.EXTRA_ACCOUNT_ID.equals(key) || IntentConstants.EXTRA_USER_ID.equals(key) || IntentConstants.EXTRA_STATUS_ID.equals(key)
|| IntentConstants.EXTRA_LIST_ID.equals(key);
}
public static String parsePrettyDecimal(double num, int decimalDigits) {
String result = String.format(Locale.US, "%." + decimalDigits + "f", num);
int dotIdx = result.lastIndexOf('.');

View File

@ -69,6 +69,7 @@ import org.mariotaku.twidere.preference.WizardPageNavPreference;
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
import org.mariotaku.twidere.util.AsyncTaskUtils;
import org.mariotaku.twidere.util.CustomTabUtils;
import org.mariotaku.twidere.util.InternalParseUtils;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.ThemeUtils;
import org.mariotaku.twidere.util.ThemedLayoutInflaterFactory;
@ -627,7 +628,7 @@ public class SettingsWizardActivity extends BaseThemedActivity implements Consta
if (type != null) {
final ContentValues values = new ContentValues();
values.put(Tabs.TYPE, type);
values.put(Tabs.ARGUMENTS, ParseUtils.bundleToJSON(spec.args));
values.put(Tabs.ARGUMENTS, InternalParseUtils.bundleToJSON(spec.args));
values.put(Tabs.NAME, ParseUtils.parseString(spec.name));
if (spec.icon instanceof Integer) {
values.put(Tabs.ICON, CustomTabUtils.findTabIconKey((Integer) spec.icon));

View File

@ -58,6 +58,7 @@ import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableUser;
import org.mariotaku.twidere.model.ParcelableUserList;
import org.mariotaku.twidere.util.DataStoreUtils;
import org.mariotaku.twidere.util.InternalParseUtils;
import org.mariotaku.twidere.util.ParseUtils;
import org.mariotaku.twidere.util.ThemeUtils;
@ -170,8 +171,8 @@ public class CustomTabEditorActivity extends BaseSupportDialogActivity implement
data.putExtra(EXTRA_TYPE, mTabType);
data.putExtra(EXTRA_NAME, ParseUtils.parseString(mEditTabName.getText()));
data.putExtra(EXTRA_ICON, getIconKey());
data.putExtra(EXTRA_ARGUMENTS, ParseUtils.bundleToJSON(args));
data.putExtra(EXTRA_EXTRAS, ParseUtils.bundleToJSON(mExtrasBundle));
data.putExtra(EXTRA_ARGUMENTS, InternalParseUtils.bundleToJSON(args));
data.putExtra(EXTRA_EXTRAS, InternalParseUtils.bundleToJSON(mExtrasBundle));
setResult(RESULT_OK, data);
finish();
} else {
@ -180,7 +181,7 @@ public class CustomTabEditorActivity extends BaseSupportDialogActivity implement
data.putExtra(EXTRA_NAME, ParseUtils.parseString(mEditTabName.getText()));
data.putExtra(EXTRA_ICON, getIconKey());
data.putExtra(EXTRA_ID, mTabId);
data.putExtra(EXTRA_EXTRAS, ParseUtils.bundleToJSON(mExtrasBundle));
data.putExtra(EXTRA_EXTRAS, InternalParseUtils.bundleToJSON(mExtrasBundle));
setResult(RESULT_OK, data);
finish();
}
@ -224,7 +225,7 @@ public class CustomTabEditorActivity extends BaseSupportDialogActivity implement
if (value instanceof ParcelableUser) {
final ParcelableUser user = (ParcelableUser) value;
text1.setText(mUserColorNameManager.getUserNickname(user.key, user.name, false));
text2.setText("@" + user.screen_name);
text2.setText(String.format("@%s", user.screen_name));
if (displayProfileImage) {
mImageLoader.displayProfileImage(icon, user);
}
@ -333,7 +334,7 @@ public class CustomTabEditorActivity extends BaseSupportDialogActivity implement
iconKey = intent.getStringExtra(EXTRA_ICON);
mEditTabName.setText(intent.getStringExtra(EXTRA_NAME));
if (savedInstanceState == null && intent.hasExtra(EXTRA_EXTRAS)) {
mExtrasBundle.putAll(ParseUtils.jsonToBundle(intent.getStringExtra(EXTRA_EXTRAS)));
mExtrasBundle.putAll(InternalParseUtils.jsonToBundle(intent.getStringExtra(EXTRA_EXTRAS)));
}
}
final int selection = mTabIconsAdapter.getIconPosition(iconKey);
@ -480,7 +481,8 @@ public class CustomTabEditorActivity extends BaseSupportDialogActivity implement
final int value = item.getValue();
if (value > 0) {
final String key = item.getKey();
text1.setText(key.substring(0, 1).toUpperCase(Locale.US) + key.substring(1, key.length()));
final String name = key.substring(0, 1).toUpperCase(Locale.US) + key.substring(1, key.length());
text1.setText(name);
} else {
text1.setText(R.string.customize);
}

View File

@ -224,7 +224,7 @@ public class LinkHandlerActivity extends BaseAppCompatActivity implements System
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
setActionBarTheme(actionBar, linkId, data);
setActionBarTheme(linkId);
}
mMainContent.setOnFitSystemWindowsListener(this);
setStatusBarColor(linkId, data);
@ -332,10 +332,9 @@ public class LinkHandlerActivity extends BaseAppCompatActivity implements System
}
@SuppressLint("AppCompatMethod")
private void setActionBarTheme(ActionBar actionBar, int linkId, Uri data) {
private void setActionBarTheme(int linkId) {
final int themeColor = getCurrentThemeColor();
final String option = getThemeBackgroundOption();
int actionBarItemsColor = ThemeUtils.getContrastForegroundColor(this, themeColor);
final ActionBarContainer actionBarContainer = (ActionBarContainer) findViewById(R.id.twidere_action_bar_container);
switch (linkId) {
case LINK_ID_SEARCH:

View File

@ -144,7 +144,7 @@ public class ComposeAutoCompleteAdapter extends SimpleCursorAdapter implements C
return null;
}
}
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(mAccountKey.getId()));
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, String.valueOf(mAccountKey));
return mContext.getContentResolver().query(builder.build(), Suggestions.AutoComplete.COLUMNS,
null, null, null);
}

View File

@ -31,6 +31,7 @@ import org.mariotaku.twidere.adapter.ParcelableActivitiesAdapter;
import org.mariotaku.twidere.annotation.ReadPositionTag;
import org.mariotaku.twidere.api.twitter.model.Activity;
import org.mariotaku.twidere.model.RefreshTaskParam;
import org.mariotaku.twidere.model.tab.extra.InteractionsTabExtras;
import org.mariotaku.twidere.provider.TwidereDataStore.Activities;
import org.mariotaku.twidere.util.ErrorInfoStore;
@ -81,8 +82,8 @@ public class InteractionsTimelineFragment extends CursorActivitiesFragment {
protected Where processWhere(@NonNull Expression where, @NonNull String[] whereArgs) {
final Bundle arguments = getArguments();
if (arguments != null) {
final Bundle extras = arguments.getBundle(EXTRA_EXTRAS);
if (extras != null && extras.getBoolean(EXTRA_MENTIONS_ONLY)) {
final InteractionsTabExtras extras = arguments.getParcelable(EXTRA_EXTRAS);
if (extras != null && extras.isMentionsOnly()) {
final Expression expression = Expression.and(where, Expression.inArgs(Activities.ACTION, 3));
return new Where(expression, ArrayUtils.addAll(whereArgs, Activity.Action.MENTION,
Activity.Action.REPLY, Activity.Action.QUOTE));
@ -97,10 +98,10 @@ public class InteractionsTimelineFragment extends CursorActivitiesFragment {
final ParcelableActivitiesAdapter adapter = new ParcelableActivitiesAdapter(context, compact, false);
final Bundle arguments = getArguments();
if (arguments != null) {
final Bundle extras = arguments.getBundle(EXTRA_EXTRAS);
final InteractionsTabExtras extras = arguments.getParcelable(EXTRA_EXTRAS);
if (extras != null) {
adapter.setFollowingOnly(extras.getBoolean(EXTRA_MY_FOLLOWING_ONLY));
adapter.setMentionsOnly(extras.getBoolean(EXTRA_MENTIONS_ONLY));
adapter.setFollowingOnly(extras.isMyFollowingOnly());
adapter.setMentionsOnly(extras.isMentionsOnly());
}
}
return adapter;

View File

@ -20,7 +20,6 @@
package org.mariotaku.twidere.fragment.support;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
@ -52,11 +51,6 @@ public abstract class ParcelableUsersFragment extends AbsUsersFragment<List<Parc
return (ParcelableUsersAdapter) super.getAdapter();
}
protected long getAccountId() {
final Bundle args = getArguments();
return args != null ? args.getLong(EXTRA_ACCOUNT_ID, -1) : -1;
}
@Override
protected boolean hasMoreData(List<ParcelableUser> data) {
return data == null || !data.isEmpty();

View File

@ -78,7 +78,7 @@ public class ScheduledStatusesFragment extends AbsContentListRecyclerViewFragmen
super.onActivityCreated(savedInstanceState);
final Bundle args = getArguments();
final Bundle loaderArgs = new Bundle();
loaderArgs.putLong(EXTRA_ACCOUNT_ID, args.getLong(EXTRA_ACCOUNT_ID));
loaderArgs.putParcelable(EXTRA_ACCOUNT_KEY, args.getParcelable(EXTRA_ACCOUNT_KEY));
getLoaderManager().initLoader(0, loaderArgs, this);
showProgress();
}

View File

@ -47,7 +47,7 @@ public class SetUserNicknameDialogFragment extends BaseSupportDialogFragment imp
final Bundle args = getArguments();
assert args != null;
final String text = ParseUtils.parseString(mEditText.getText());
final UserKey userId = args.getParcelable(EXTRA_USER_ID);
final UserKey userId = args.getParcelable(EXTRA_USER_KEY);
assert userId != null;
switch (which) {
case DialogInterface.BUTTON_POSITIVE: {

View File

@ -26,8 +26,8 @@ import android.support.annotation.NonNull;
import android.support.v4.content.Loader;
import org.mariotaku.twidere.loader.support.TweetSearchLoader;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
@ -58,7 +58,6 @@ public class StatusesSearchFragment extends ParcelableStatusesFragment {
final String query = args.getString(EXTRA_QUERY);
final int tabPosition = args.getInt(EXTRA_TAB_POSITION, -1);
final boolean makeGap = args.getBoolean(EXTRA_MAKE_GAP, true);
if (query == null) throw new NullPointerException();
return new TweetSearchLoader(getActivity(), accountKey, query, sinceId, maxId, getAdapterData(),
getSavedStatusesFileArgs(), tabPosition, fromUser, makeGap);
}
@ -72,9 +71,9 @@ public class StatusesSearchFragment extends ParcelableStatusesFragment {
protected String[] getSavedStatusesFileArgs() {
final Bundle args = getArguments();
if (args == null) return null;
final long account_id = args.getLong(EXTRA_ACCOUNT_ID, -1);
final UserKey accountKey = args.getParcelable(EXTRA_ACCOUNT_KEY);
final String query = args.getString(EXTRA_QUERY);
return new String[]{AUTHORITY_SEARCH_TWEETS, "account" + account_id, "query" + query};
return new String[]{AUTHORITY_SEARCH_TWEETS, "account" + accountKey, "query" + query};
}

View File

@ -1022,7 +1022,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
final Uri.Builder builder = new Uri.Builder();
builder.scheme(SCHEME_TWIDERE);
builder.authority(AUTHORITY_DIRECT_MESSAGES_CONVERSATION);
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(user.account_key));
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, String.valueOf(user.account_key));
builder.appendQueryParameter(QUERY_PARAM_USER_ID, String.valueOf(user.key));
final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
intent.putExtra(EXTRA_ACCOUNT, ParcelableCredentialsUtils.getCredentials(getActivity(), user.account_key));

View File

@ -71,6 +71,8 @@ public class MediaTimelineLoader extends TwitterAPIStatusesLoader {
return twitter.getMediaTimeline(mUserId, paging);
if (mUserScreenName != null)
return twitter.getMediaTimeline(mUserScreenName, paging);
} else if (TwitterAPIFactory.isStatusNetCredentials(credentials)) {
throw new TwitterException("Not implemented");
} else {
final String screenName;
if (mUserScreenName != null) {

View File

@ -22,6 +22,7 @@ package org.mariotaku.twidere.loader.support;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.WorkerThread;
import org.mariotaku.twidere.api.twitter.Twitter;
@ -29,8 +30,8 @@ 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.model.UserKey;
import org.mariotaku.twidere.model.ParcelableStatus;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.util.InternalTwitterContentUtils;
import org.mariotaku.twidere.util.TwitterAPIFactory;
@ -38,11 +39,11 @@ import java.util.List;
public class TweetSearchLoader extends TwitterAPIStatusesLoader {
@NonNull
@Nullable
private final String mQuery;
private final boolean mGapEnabled;
public TweetSearchLoader(final Context context, final UserKey accountKey, @NonNull final String query,
public TweetSearchLoader(final Context context, final UserKey accountKey, @Nullable final String query,
final long sinceId, final long maxId, final List<ParcelableStatus> data,
final String[] savedStatusesArgs, final int tabPosition, boolean fromUser,
boolean makeGap) {
@ -54,6 +55,7 @@ public class TweetSearchLoader extends TwitterAPIStatusesLoader {
@NonNull
@Override
public List<Status> getStatuses(@NonNull final Twitter twitter, final Paging paging) throws TwitterException {
if (mQuery == null) throw new TwitterException("Empty query");
final String processedQuery = processQuery(mQuery);
if (TwitterAPIFactory.isTwitterCredentials(getContext(), getAccountKey())) {
final SearchQuery query = new SearchQuery(processedQuery);

View File

@ -62,7 +62,7 @@ public class ListResponse<Data> extends AbstractList<Data> implements Response<L
@Override
public int size() {
if (list == null) throw new NullPointerException();
if (list == null) return 0;
return list.size();
}
@ -73,25 +73,25 @@ public class ListResponse<Data> extends AbstractList<Data> implements Response<L
@Override
public Data remove(int location) {
if (list == null) throw new NullPointerException();
if (list == null) return null;
return list.remove(location);
}
@Override
public Data set(int location, Data object) {
if (list == null) throw new NullPointerException();
if (list == null) return null;
return list.set(location, object);
}
@Override
public void add(int location, Data object) {
if (list == null) throw new NullPointerException();
if (list == null) return;
list.add(location, object);
}
@Override
public Data get(int location) {
if (list == null) throw new NullPointerException();
if (list == null) return null;
return list.get(location);
}

View File

@ -3,8 +3,8 @@ package org.mariotaku.twidere.model;
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.Arguments;
import org.mariotaku.twidere.model.tab.Extras;
import org.mariotaku.twidere.model.tab.argument.TabArguments;
import org.mariotaku.twidere.model.tab.extra.TabExtras;
import org.mariotaku.twidere.model.util.TabArgumentsFieldConverter;
import org.mariotaku.twidere.model.util.TabExtrasFieldConverter;
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
@ -28,10 +28,10 @@ public class Tab {
int position;
@CursorField(value = Tabs.ARGUMENTS, converter = TabArgumentsFieldConverter.class)
Arguments arguments;
TabArguments arguments;
@CursorField(value = Tabs.EXTRAS, converter = TabExtrasFieldConverter.class)
Extras extras;
TabExtras extras;
public String getName() {
return name;
@ -66,19 +66,19 @@ public class Tab {
this.position = position;
}
public Arguments getArguments() {
public TabArguments getArguments() {
return arguments;
}
public void setArguments(Arguments arguments) {
public void setArguments(TabArguments arguments) {
this.arguments = arguments;
}
public Extras getExtras() {
public TabExtras getExtras() {
return extras;
}
public void setExtras(Extras extras) {
public void setExtras(TabExtras extras) {
this.extras = extras;
}
}

View File

@ -1,34 +0,0 @@
package org.mariotaku.twidere.model.tab;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import org.mariotaku.twidere.model.UserKey;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class Arguments {
@JsonField(name = "account_id")
long accountId;
@JsonField(name = "account_key")
UserKey accountKey;
public long getAccountId() {
return accountId;
}
public void setAccountId(long accountId) {
this.accountId = accountId;
}
public UserKey getAccountKey() {
return accountKey;
}
public void setAccountKey(UserKey accountKey) {
this.accountKey = accountKey;
}
}

View File

@ -1,10 +0,0 @@
package org.mariotaku.twidere.model.tab;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class Extras {
}

View File

@ -1,13 +0,0 @@
package org.mariotaku.twidere.model.tab;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class TextArguments extends Arguments {
@JsonField(name = "text")
String text;
}

View File

@ -1,13 +0,0 @@
package org.mariotaku.twidere.model.tab;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class UserArguments extends Arguments {
@JsonField(name = "user_id")
long userId;
}

View File

@ -1,13 +0,0 @@
package org.mariotaku.twidere.model.tab;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class UserListArguments extends Arguments {
@JsonField(name = "list_id")
long listId;
}

View File

@ -1,33 +0,0 @@
package org.mariotaku.twidere.model.tab;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class UserMentionTabExtras extends Extras {
@JsonField(name = "my_following_only")
boolean myFollowingOnly;
@JsonField(name = "mentions_only")
boolean mentionsOnly;
public boolean isMyFollowingOnly() {
return myFollowingOnly;
}
public void setMyFollowingOnly(boolean myFollowingOnly) {
this.myFollowingOnly = myFollowingOnly;
}
public boolean isMentionsOnly() {
return mentionsOnly;
}
public void setMentionsOnly(boolean mentionsOnly) {
this.mentionsOnly = mentionsOnly;
}
}

View File

@ -0,0 +1,56 @@
package org.mariotaku.twidere.model.tab.argument;
import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
import org.mariotaku.twidere.constant.IntentConstants;
import org.mariotaku.twidere.model.UserKey;
import java.util.Arrays;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class TabArguments implements IntentConstants {
@JsonField(name = "account_id")
long accountId = -1;
@JsonField(name = "account_keys")
UserKey[] accountKeys;
public long getAccountId() {
return accountId;
}
public void setAccountId(long accountId) {
this.accountId = accountId;
}
public UserKey[] getAccountKeys() {
return accountKeys;
}
public void setAccountKeys(UserKey[] accountKeys) {
this.accountKeys = accountKeys;
}
@CallSuper
public void copyToBundle(@NonNull Bundle bundle) {
if (accountId > 0) {
bundle.putLong(EXTRA_ACCOUNT_ID, accountId);
}
}
@Override
public String toString() {
return "TabArguments{" +
"accountId=" + accountId +
", accountKeys=" + Arrays.toString(accountKeys) +
'}';
}
}

View File

@ -0,0 +1,29 @@
package org.mariotaku.twidere.model.tab.argument;
import android.os.Bundle;
import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class TextQueryArguments extends TabArguments {
@JsonField(name = "query")
String query;
@Override
public void copyToBundle(@NonNull Bundle bundle) {
super.copyToBundle(bundle);
bundle.putString(EXTRA_QUERY, query);
}
@Override
public String toString() {
return "TextQueryArguments{" +
"query='" + query + '\'' +
"} " + super.toString();
}
}

View File

@ -0,0 +1,29 @@
package org.mariotaku.twidere.model.tab.argument;
import android.os.Bundle;
import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class UserArguments extends TabArguments {
@JsonField(name = "user_id")
long userId;
@Override
public void copyToBundle(@NonNull Bundle bundle) {
super.copyToBundle(bundle);
bundle.putLong(EXTRA_USER_ID, userId);
}
@Override
public String toString() {
return "UserArguments{" +
"userId=" + userId +
"} " + super.toString();
}
}

View File

@ -0,0 +1,29 @@
package org.mariotaku.twidere.model.tab.argument;
import android.os.Bundle;
import android.support.annotation.NonNull;
import com.bluelinelabs.logansquare.annotation.JsonField;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public class UserListArguments extends TabArguments {
@JsonField(name = "list_id")
long listId;
@Override
public void copyToBundle(@NonNull Bundle bundle) {
super.copyToBundle(bundle);
bundle.putLong(EXTRA_LIST_ID, listId);
}
@Override
public String toString() {
return "UserListArguments{" +
"listId=" + listId +
"} " + super.toString();
}
}

View File

@ -0,0 +1,63 @@
package org.mariotaku.twidere.model.tab.extra;
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;
/**
* Created by mariotaku on 16/3/6.
*/
@ParcelablePlease
@JsonObject
public class InteractionsTabExtras extends TabExtras implements Parcelable {
@ParcelableThisPlease
@JsonField(name = "my_following_only")
boolean myFollowingOnly;
@ParcelableThisPlease
@JsonField(name = "mentions_only")
boolean mentionsOnly;
public boolean isMyFollowingOnly() {
return myFollowingOnly;
}
public void setMyFollowingOnly(boolean myFollowingOnly) {
this.myFollowingOnly = myFollowingOnly;
}
public boolean isMentionsOnly() {
return mentionsOnly;
}
public void setMentionsOnly(boolean mentionsOnly) {
this.mentionsOnly = mentionsOnly;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
InteractionsTabExtrasParcelablePlease.writeToParcel(this, dest, flags);
}
public static final Creator<InteractionsTabExtras> CREATOR = new Creator<InteractionsTabExtras>() {
public InteractionsTabExtras createFromParcel(Parcel source) {
InteractionsTabExtras target = new InteractionsTabExtras();
InteractionsTabExtrasParcelablePlease.readFromParcel(target, source);
return target;
}
public InteractionsTabExtras[] newArray(int size) {
return new InteractionsTabExtras[size];
}
};
}

View File

@ -0,0 +1,12 @@
package org.mariotaku.twidere.model.tab.extra;
import android.os.Parcelable;
import com.bluelinelabs.logansquare.annotation.JsonObject;
/**
* Created by mariotaku on 16/3/6.
*/
@JsonObject
public abstract class TabExtras implements Parcelable {
}

View File

@ -5,10 +5,9 @@ import android.database.Cursor;
import android.text.TextUtils;
import org.mariotaku.library.objectcursor.converter.CursorFieldConverter;
import org.mariotaku.twidere.annotation.CustomTabType;
import org.mariotaku.twidere.model.tab.Arguments;
import org.mariotaku.twidere.model.tab.UserArguments;
import org.mariotaku.twidere.model.tab.argument.TabArguments;
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
import org.mariotaku.twidere.util.CustomTabUtils;
import org.mariotaku.twidere.util.JsonSerializer;
import java.lang.reflect.ParameterizedType;
@ -16,21 +15,17 @@ import java.lang.reflect.ParameterizedType;
/**
* Created by mariotaku on 16/3/6.
*/
public class TabArgumentsFieldConverter implements CursorFieldConverter<Arguments> {
public class TabArgumentsFieldConverter implements CursorFieldConverter<TabArguments> {
@Override
public Arguments parseField(Cursor cursor, int columnIndex, ParameterizedType fieldType) {
final String tabType = cursor.getString(cursor.getColumnIndex(Tabs.TYPE));
public TabArguments parseField(Cursor cursor, int columnIndex, ParameterizedType fieldType) {
final String tabType = CustomTabUtils.getTabTypeAlias(cursor.getString(cursor.getColumnIndex(Tabs.TYPE)));
if (TextUtils.isEmpty(tabType)) return null;
switch (tabType) {
case CustomTabType.FAVORITES:
case CustomTabType.USER_TIMELINE:
return JsonSerializer.parse(cursor.getString(columnIndex), UserArguments.class);
}
return JsonSerializer.parse(cursor.getString(columnIndex), Arguments.class);
return CustomTabUtils.parseTabArguments(tabType, cursor.getString(columnIndex));
}
@Override
public void writeField(ContentValues values, Arguments object, String columnName, ParameterizedType fieldType) {
public void writeField(ContentValues values, TabArguments object, String columnName, ParameterizedType fieldType) {
if (object == null) return;
values.put(columnName, JsonSerializer.serialize(object));
}

View File

@ -5,12 +5,9 @@ import android.database.Cursor;
import android.text.TextUtils;
import org.mariotaku.library.objectcursor.converter.CursorFieldConverter;
import org.mariotaku.twidere.annotation.CustomTabType;
import org.mariotaku.twidere.model.tab.Arguments;
import org.mariotaku.twidere.model.tab.Extras;
import org.mariotaku.twidere.model.tab.UserArguments;
import org.mariotaku.twidere.model.tab.UserMentionTabExtras;
import org.mariotaku.twidere.model.tab.extra.TabExtras;
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
import org.mariotaku.twidere.util.CustomTabUtils;
import org.mariotaku.twidere.util.JsonSerializer;
import java.lang.reflect.ParameterizedType;
@ -18,20 +15,16 @@ import java.lang.reflect.ParameterizedType;
/**
* Created by mariotaku on 16/3/6.
*/
public class TabExtrasFieldConverter implements CursorFieldConverter<Extras> {
public class TabExtrasFieldConverter implements CursorFieldConverter<TabExtras> {
@Override
public Extras parseField(Cursor cursor, int columnIndex, ParameterizedType fieldType) {
final String tabType = cursor.getString(cursor.getColumnIndex(Tabs.TYPE));
public TabExtras parseField(Cursor cursor, int columnIndex, ParameterizedType fieldType) {
final String tabType = CustomTabUtils.getTabTypeAlias(cursor.getString(cursor.getColumnIndex(Tabs.TYPE)));
if (TextUtils.isEmpty(tabType)) return null;
switch (tabType) {
case CustomTabType.NOTIFICATIONS_TIMELINE:
return JsonSerializer.parse(cursor.getString(columnIndex), UserMentionTabExtras.class);
}
return null;
return CustomTabUtils.parseTabExtras(tabType, cursor.getString(columnIndex));
}
@Override
public void writeField(ContentValues values, Extras object, String columnName, ParameterizedType fieldType) {
public void writeField(ContentValues values, TabExtras object, String columnName, ParameterizedType fieldType) {
if (object == null) return;
values.put(columnName, JsonSerializer.serialize(object));
}

View File

@ -59,6 +59,7 @@ import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.util.Log;
import android.util.Pair;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.squareup.otto.Bus;
@ -225,15 +226,15 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
}
private static PendingIntent getMarkReadDeleteIntent(Context context, @NotificationType String notificationType,
@Nullable UserKey accountId, StringLongPair[] positions) {
@Nullable UserKey accountKey, StringLongPair[] positions) {
// Setup delete intent
final Intent intent = new Intent(context, NotificationReceiver.class);
final Uri.Builder linkBuilder = new Uri.Builder();
linkBuilder.scheme(SCHEME_TWIDERE);
linkBuilder.authority(AUTHORITY_INTERACTIONS);
linkBuilder.appendPath(notificationType);
if (accountId != null) {
linkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, accountId.toString());
if (accountKey != null) {
linkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, accountKey.toString());
}
linkBuilder.appendQueryParameter(QUERY_PARAM_READ_POSITIONS, StringLongPair.toString(positions));
linkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
@ -715,29 +716,27 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
case TABLE_ID_DIRECT_MESSAGES_CONVERSATION_SCREEN_NAME: {
final List<String> segments = uri.getPathSegments();
if (segments.size() != 4) return null;
final long accountId = NumberUtils.toLong(segments.get(2), -1);
final UserKey accountKey = UserKey.valueOf(segments.get(2));
final String screenName = segments.get(3);
final SQLSelectQuery query = ConversationQueryBuilder.buildByScreenName(projection,
accountId, screenName, selection, sortOrder);
final Cursor c = mDatabaseWrapper.rawQuery(query.getSQL(), selectionArgs);
final Pair<SQLSelectQuery, String[]> query = ConversationQueryBuilder.byScreenName(
projection, accountKey, screenName, selection, sortOrder);
final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second);
setNotificationUri(c, DirectMessages.CONTENT_URI);
return c;
}
case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_RELATIONSHIP: {
final long def = -1;
final long accountId = NumberUtils.toLong(uri.getLastPathSegment(), def);
final SQLSelectQuery query = CachedUsersQueryBuilder.withRelationship(projection,
selection, sortOrder, accountId);
final Cursor c = mDatabaseWrapper.rawQuery(query.getSQL(), selectionArgs);
final UserKey accountKey = UserKey.valueOf(uri.getLastPathSegment());
final Pair<SQLSelectQuery, String[]> query = CachedUsersQueryBuilder.withRelationship(projection,
selection, sortOrder, accountKey);
final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second);
setNotificationUri(c, CachedUsers.CONTENT_URI);
return c;
}
case VIRTUAL_TABLE_ID_CACHED_USERS_WITH_SCORE: {
final long def = -1;
final long accountId = NumberUtils.toLong(uri.getLastPathSegment(), def);
final SQLSelectQuery query = CachedUsersQueryBuilder.withScore(projection,
selection, sortOrder, accountId, 0);
final Cursor c = mDatabaseWrapper.rawQuery(query.getSQL(), selectionArgs);
final UserKey accountKey = UserKey.valueOf(uri.getLastPathSegment());
final Pair<SQLSelectQuery, String[]> query = CachedUsersQueryBuilder.withScore(projection,
selection, sortOrder, accountKey, 0);
final Cursor c = mDatabaseWrapper.rawQuery(query.first.getSQL(), query.second);
setNotificationUri(c, CachedUsers.CONTENT_URI);
return c;
}
@ -783,9 +782,8 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
private Cursor getSearchSuggestionCursor(Uri uri) {
final String query = uri.getQueryParameter(QUERY_PARAM_QUERY);
final long def = -1;
final long accountId = NumberUtils.toLong(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID), def);
if (query == null || accountId <= 0) return null;
final UserKey accountKey = UserKey.valueOf(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_KEY));
if (query == null || accountKey == null) return null;
final boolean emptyQuery = TextUtils.isEmpty(query);
final String queryEscaped = query.replace("_", "^_");
final Cursor[] cursors;
@ -815,10 +813,11 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
new Column(SQLConstants.NULL, Suggestions.Search.EXTRA).getSQL(),
new Column(SavedSearches.QUERY, Suggestions.Search.VALUE).getSQL()
};
final Expression savedSearchesWhere = Expression.equals(SavedSearches.ACCOUNT_KEY, accountId);
final Expression savedSearchesWhere = Expression.equalsArgs(SavedSearches.ACCOUNT_KEY);
final String[] whereArgs = {accountKey.toString()};
@SuppressLint("Recycle") final Cursor savedSearchesCursor = mDatabaseWrapper.query(true,
SavedSearches.TABLE_NAME, savedSearchesProjection, savedSearchesWhere.getSQL(),
null, null, null, SavedSearches.DEFAULT_SORT_ORDER, null);
whereArgs, null, null, SavedSearches.DEFAULT_SORT_ORDER, null);
cursors = new Cursor[2];
cursors[1] = savedSearchesCursor;
} else {
@ -844,9 +843,9 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
final boolean[] ascending = {false, false, true, true};
final OrderBy orderBy = new OrderBy(order, ascending);
final SQLSelectQuery usersQuery = CachedUsersQueryBuilder.withScore(usersProjection,
usersSelection.getSQL(), orderBy.getSQL(), accountId, 0);
@SuppressLint("Recycle") final Cursor usersCursor = mDatabaseWrapper.rawQuery(usersQuery.getSQL(), selectionArgs);
final Pair<SQLSelectQuery, String[]> usersQuery = CachedUsersQueryBuilder.withScore(usersProjection,
usersSelection.getSQL(), orderBy.getSQL(), accountKey, 0);
@SuppressLint("Recycle") final Cursor usersCursor = mDatabaseWrapper.rawQuery(usersQuery.first.getSQL(), usersQuery.second);
final Expression exactUserSelection = Expression.or(Expression.likeRaw(new Column(CachedUsers.SCREEN_NAME), "?", "^"));
final Cursor exactUserCursor = mDatabaseWrapper.query(CachedUsers.TABLE_NAME,
new String[]{SQLFunctions.COUNT()}, exactUserSelection.getSQL(),
@ -873,7 +872,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
private Cursor getAutoCompleteSuggestionsCursor(@NonNull Uri uri) {
final String query = uri.getQueryParameter(QUERY_PARAM_QUERY);
final String type = uri.getQueryParameter(QUERY_PARAM_TYPE);
final String accountId = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID);
final String accountKey = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_KEY);
if (query == null || type == null) return null;
final String queryEscaped = query.replace("_", "^_");
if (Suggestions.AutoComplete.TYPE_USERS.equals(type)) {
@ -894,7 +893,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
final String[] orderBy = {CachedUsers.SCORE, CachedUsers.LAST_SEEN, CachedUsers.SCREEN_NAME,
CachedUsers.NAME};
final boolean[] ascending = {false, false, true, true};
return query(Uri.withAppendedPath(CachedUsers.CONTENT_URI_WITH_SCORE, accountId),
return query(Uri.withAppendedPath(CachedUsers.CONTENT_URI_WITH_SCORE, accountKey),
mappedProjection, where.getSQL(), whereArgs, new OrderBy(orderBy, ascending).getSQL());
} else if (Suggestions.AutoComplete.TYPE_HASHTAGS.equals(type)) {
final Expression where = Expression.likeRaw(new Column(CachedHashtags.NAME), "?||'%'", "^");
@ -1454,28 +1453,6 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
return PendingIntent.getActivity(context, 0, homeIntent, 0);
}
private PendingIntent getStatusContentIntent(final Context context, @CustomTabType final String type,
@NotificationType final String notificationType,
long accountId, long statusId,
long userId, boolean userFollowing) {
// Setup click intent
final Intent homeIntent = new Intent(Intent.ACTION_VIEW);
homeIntent.setPackage(BuildConfig.APPLICATION_ID);
final Uri.Builder homeLinkBuilder = new Uri.Builder();
homeLinkBuilder.scheme(SCHEME_TWIDERE);
homeLinkBuilder.authority(AUTHORITY_STATUS);
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(accountId));
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_STATUS_ID, String.valueOf(statusId));
UriExtraUtils.addExtra(homeLinkBuilder, "item_id", statusId);
UriExtraUtils.addExtra(homeLinkBuilder, "item_user_id", userId);
UriExtraUtils.addExtra(homeLinkBuilder, "item_user_following", userFollowing);
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_FROM_NOTIFICATION, String.valueOf(true));
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_TIMESTAMP, String.valueOf(System.currentTimeMillis()));
homeLinkBuilder.appendQueryParameter(QUERY_PARAM_NOTIFICATION_TYPE, notificationType);
homeIntent.setData(homeLinkBuilder.build());
return PendingIntent.getActivity(context, 0, homeIntent, 0);
}
private void applyNotificationPreferences(NotificationCompat.Builder builder, AccountPreferences pref, int defaultFlags) {
int notificationDefaults = 0;
if (AccountPreferences.isNotificationHasLight(defaultFlags)) {

View File

@ -49,11 +49,17 @@ import org.mariotaku.twidere.fragment.support.TrendsSuggestionsFragment;
import org.mariotaku.twidere.fragment.support.UserFavoritesFragment;
import org.mariotaku.twidere.fragment.support.UserListTimelineFragment;
import org.mariotaku.twidere.fragment.support.UserTimelineFragment;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.CustomTabConfiguration;
import org.mariotaku.twidere.model.CustomTabConfiguration.ExtraConfiguration;
import org.mariotaku.twidere.model.SupportTabSpec;
import org.mariotaku.twidere.model.TabCursorIndices;
import org.mariotaku.twidere.model.UserKey;
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.provider.TwidereDataStore.Tabs;
import java.io.File;
@ -158,11 +164,18 @@ public class CustomTabUtils implements Constants {
final int position = cur.getInt(indices.position);
final String iconType = cur.getString(indices.icon);
final String name = cur.getString(indices.name);
final Bundle args = ParseUtils.jsonToBundle(cur.getString(idxArguments));
final Bundle args = new Bundle();
final TabArguments tabArguments = parseTabArguments(type, cur.getString(idxArguments));
if (tabArguments != null) {
tabArguments.copyToBundle(args);
}
@ReadPositionTag
final String tag = getTagByType(type);
args.putInt(EXTRA_TAB_POSITION, position);
args.putBundle(EXTRA_EXTRAS, ParseUtils.jsonToBundle(cur.getString(idxExtras)));
final TabExtras tabExtras = parseTabExtras(type, cur.getString(idxExtras));
if (tabExtras != null) {
args.putParcelable(EXTRA_EXTRAS, tabExtras);
}
final CustomTabConfiguration conf = getTabConfiguration(type);
final Class<? extends Fragment> cls = conf != null ? conf.getFragmentClass() : InvalidTabFragment.class;
final String tabTypeName = getTabTypeName(context, type);
@ -176,10 +189,43 @@ public class CustomTabUtils implements Constants {
return tabs;
}
@Nullable
public static TabArguments parseTabArguments(@NonNull @CustomTabType String type, String json) {
switch (type) {
case CustomTabType.HOME_TIMELINE:
case CustomTabType.NOTIFICATIONS_TIMELINE:
case CustomTabType.DIRECT_MESSAGES:
case CustomTabType.RETWEETS_OF_ME: {
return JsonSerializer.parse(json, TabArguments.class);
}
case CustomTabType.USER_TIMELINE:
case CustomTabType.FAVORITES: {
return JsonSerializer.parse(json, UserArguments.class);
}
case CustomTabType.LIST_TIMELINE: {
return JsonSerializer.parse(json, UserListArguments.class);
}
case CustomTabType.SEARCH_STATUSES: {
return JsonSerializer.parse(json, TextQueryArguments.class);
}
}
return null;
}
@Nullable
public static TabExtras parseTabExtras(@NonNull @CustomTabType String type, String json) {
switch (type) {
case CustomTabType.NOTIFICATIONS_TIMELINE: {
return JsonSerializer.parse(json, InteractionsTabExtras.class);
}
}
return null;
}
@Nullable
@ReadPositionTag
private static String getTagByType(@NonNull @CustomTabType String tabType) {
switch (getTabTypeAlias(tabType)) {
public static String getTagByType(@NonNull @CustomTabType String tabType) {
switch (tabType) {
case CustomTabType.HOME_TIMELINE:
return ReadPositionTag.HOME_TIMELINE;
case "activities_about_me":

View File

@ -49,11 +49,13 @@ import org.mariotaku.sqliteqb.library.query.SQLSelectQuery;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.api.twitter.model.Activity;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.ParcelableAccount;
import org.mariotaku.twidere.model.ParcelableCredentials;
import org.mariotaku.twidere.model.ParcelableCredentialsCursorIndices;
import org.mariotaku.twidere.model.UserFollowState;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.model.tab.extra.InteractionsTabExtras;
import org.mariotaku.twidere.model.tab.extra.TabExtras;
import org.mariotaku.twidere.provider.TwidereDataStore;
import org.mariotaku.twidere.provider.TwidereDataStore.AccountSupportColumns;
import org.mariotaku.twidere.provider.TwidereDataStore.Accounts;
@ -654,8 +656,7 @@ public class DataStoreUtils implements Constants {
}
}
public static UserKey getAccountKey(final Context context, final String screenName) {
if (context == null || isEmpty(screenName)) return null;
public static UserKey findAccountKey(@NonNull final Context context, @NonNull final String screenName) {
final String[] projection = {Accounts.ACCOUNT_KEY};
final String where = Expression.equalsArgs(Accounts.SCREEN_NAME).getSQL();
final String[] whereArgs = {screenName};
@ -672,6 +673,20 @@ public class DataStoreUtils implements Constants {
}
}
public static UserKey findAccountKey(@NonNull final Context context, final long accountId) {
final String[] projection = {Accounts.ACCOUNT_KEY};
final Cursor cur = findAccountCursorsById(context, projection, accountId);
if (cur == null) return null;
try {
if (cur.moveToFirst()) {
return UserKey.valueOf(cur.getString(0));
}
return null;
} finally {
cur.close();
}
}
@NonNull
public static UserKey[] getAccountKeys(final Context context) {
if (context == null) return new UserKey[0];
@ -965,14 +980,15 @@ public class DataStoreUtils implements Constants {
String[] extraWhereArgs = null;
boolean followingOnly = false;
if (extraArgs != null) {
Bundle extras = extraArgs.getBundle(EXTRA_EXTRAS);
if (extras != null) {
if (extras.getBoolean(EXTRA_MENTIONS_ONLY)) {
final TabExtras extras = extraArgs.getParcelable(EXTRA_EXTRAS);
if (extras instanceof InteractionsTabExtras) {
InteractionsTabExtras ite = ((InteractionsTabExtras) extras);
if (ite.isMentionsOnly()) {
extraWhere = Expression.inArgs(Activities.ACTION, 3);
extraWhereArgs = new String[]{Activity.Action.MENTION,
Activity.Action.REPLY, Activity.Action.QUOTE};
}
if (extras.getBoolean(EXTRA_MY_FOLLOWING_ONLY)) {
if (ite.isMyFollowingOnly()) {
followingOnly = true;
}
}

View File

@ -0,0 +1,102 @@
package org.mariotaku.twidere.util;
import android.os.Bundle;
import android.util.JsonWriter;
import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import org.mariotaku.restfu.RestFuUtils;
import org.mariotaku.twidere.TwidereConstants;
import org.mariotaku.twidere.constant.CompatibilityConstants;
import org.mariotaku.twidere.constant.IntentConstants;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.Set;
/**
* Created by mariotaku on 16/3/8.
*/
public class InternalParseUtils {
public static String bundleToJSON(final Bundle args) {
final Set<String> keys = args.keySet();
final StringWriter sw = new StringWriter();
final JsonWriter json = new JsonWriter(sw);
try {
json.beginObject();
for (final String key : keys) {
json.name(key);
final Object value = args.get(key);
if (value == null) {
json.nullValue();
} else if (value instanceof Boolean) {
json.value((Boolean) value);
} else if (value instanceof Integer) {
json.value((Integer) value);
} else if (value instanceof Long) {
json.value((Long) value);
} else if (value instanceof String) {
json.value((String) value);
} else if (value instanceof Float) {
json.value((Float) value);
} else if (value instanceof Double) {
json.value((Double) value);
} else {
Log.w(TwidereConstants.LOGTAG, "Unknown type " + value.getClass().getSimpleName() + " in arguments key " + key);
}
}
json.endObject();
json.flush();
sw.flush();
return sw.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
RestFuUtils.closeSilently(json);
}
}
public static Bundle jsonToBundle(final String string) {
final Bundle bundle = new Bundle();
if (string == null) return bundle;
try {
final JSONObject json = new JSONObject(string);
final Iterator<?> it = json.keys();
while (it.hasNext()) {
final Object key_obj = it.next();
if (key_obj == null) {
continue;
}
final String key = key_obj.toString();
final Object value = json.get(key);
if (value instanceof Boolean) {
bundle.putBoolean(key, json.optBoolean(key));
} else if (value instanceof Integer) {
// Simple workaround for account_id
if (shouldPutLong(key)) {
bundle.putLong(key, json.optLong(key));
} else {
bundle.putInt(key, json.optInt(key));
}
} else if (value instanceof Long) {
bundle.putLong(key, json.optLong(key));
} else if (value instanceof String) {
bundle.putString(key, json.optString(key));
} else {
Log.w(TwidereConstants.LOGTAG, "Unknown type " + value.getClass().getSimpleName() + " in arguments key " + key);
}
}
} catch (final JSONException | ClassCastException e) {
e.printStackTrace();
}
return bundle;
}
private static boolean shouldPutLong(final String key) {
return CompatibilityConstants.EXTRA_ACCOUNT_ID.equals(key) || IntentConstants.EXTRA_USER_ID.equals(key) || IntentConstants.EXTRA_STATUS_ID.equals(key)
|| IntentConstants.EXTRA_LIST_ID.equals(key);
}
}

View File

@ -20,9 +20,13 @@
package org.mariotaku.twidere.util;
import android.support.annotation.Nullable;
import android.util.Log;
import com.bluelinelabs.logansquare.JsonMapper;
import org.mariotaku.twidere.BuildConfig;
import org.mariotaku.twidere.Constants;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@ -42,6 +46,9 @@ public class JsonSerializer {
try {
return LoganSquareMapperFinder.mapperFor(cls).serialize(list);
} catch (IOException e) {
if (BuildConfig.DEBUG) {
Log.w(Constants.LOGTAG, e);
}
return null;
}
}
@ -52,6 +59,9 @@ public class JsonSerializer {
try {
return LoganSquareMapperFinder.mapperFor(cls).serialize(list);
} catch (IOException e) {
if (BuildConfig.DEBUG) {
Log.w(Constants.LOGTAG, e);
}
return null;
}
}
@ -62,6 +72,9 @@ public class JsonSerializer {
try {
return LoganSquareMapperFinder.mapperFor(cls).serialize(Arrays.asList(array));
} catch (IOException e) {
if (BuildConfig.DEBUG) {
Log.w(Constants.LOGTAG, e);
}
return null;
}
}
@ -72,6 +85,9 @@ public class JsonSerializer {
try {
return LoganSquareMapperFinder.mapperFor(cls).serialize(object);
} catch (IOException e) {
if (BuildConfig.DEBUG) {
Log.w(Constants.LOGTAG, e);
}
return null;
}
}
@ -85,6 +101,9 @@ public class JsonSerializer {
LoganSquareMapperFinder.mapperFor(object.getClass());
return mapper.serialize(object);
} catch (IOException e) {
if (BuildConfig.DEBUG) {
Log.w(Constants.LOGTAG, e);
}
return null;
}
}
@ -97,6 +116,9 @@ public class JsonSerializer {
//noinspection unchecked
return list.toArray((T[]) Array.newInstance(cls, list.size()));
} catch (IOException e) {
if (BuildConfig.DEBUG) {
Log.w(Constants.LOGTAG, e);
}
return null;
}
}
@ -107,6 +129,9 @@ public class JsonSerializer {
try {
return LoganSquareMapperFinder.mapperFor(cls).parse(string);
} catch (IOException e) {
if (BuildConfig.DEBUG) {
Log.w(Constants.LOGTAG, e);
}
return null;
}
}
@ -118,6 +143,9 @@ public class JsonSerializer {
is = new FileInputStream(file);
return LoganSquareMapperFinder.mapperFor(cls).parseList(is);
} catch (IOException e) {
if (BuildConfig.DEBUG) {
Log.w(Constants.LOGTAG, e);
}
return null;
} finally {
Utils.closeSilently(is);

View File

@ -19,6 +19,8 @@
package org.mariotaku.twidere.util;
import android.util.Pair;
import org.mariotaku.sqliteqb.library.Columns;
import org.mariotaku.sqliteqb.library.Columns.Column;
import org.mariotaku.sqliteqb.library.Expression;
@ -30,6 +32,7 @@ import org.mariotaku.sqliteqb.library.Selectable;
import org.mariotaku.sqliteqb.library.Table;
import org.mariotaku.sqliteqb.library.Tables;
import org.mariotaku.sqliteqb.library.query.SQLSelectQuery;
import org.mariotaku.twidere.model.UserKey;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedRelationships;
import org.mariotaku.twidere.provider.TwidereDataStore.CachedUsers;
import org.mariotaku.twidere.provider.TwidereDataStore.DirectMessages;
@ -44,18 +47,18 @@ public class TwidereQueryBuilder {
public static final class CachedUsersQueryBuilder {
public static SQLSelectQuery withRelationship(final String[] projection,
final String selection,
final String sortOrder,
final long accountId) {
public static Pair<SQLSelectQuery, String[]> withRelationship(final String[] projection,
final String selection,
final String sortOrder,
final UserKey accountKey) {
return withRelationship(Utils.getColumnsFromProjection(projection), selection,
sortOrder, accountId);
sortOrder, accountKey);
}
public static SQLSelectQuery withRelationship(final Selectable select,
public static Pair<SQLSelectQuery, String[]> withRelationship(final Selectable select,
final String selection,
final String sortOrder,
final long accountId) {
final UserKey accountKey) {
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
qb.select(select).from(new Tables(CachedUsers.TABLE_NAME));
final Column relationshipsUserId = new Column(new Table(CachedRelationships.TABLE_NAME),
@ -66,7 +69,7 @@ public class TwidereQueryBuilder {
CachedRelationships.ACCOUNT_KEY);
final Expression on = Expression.and(
Expression.equals(relationshipsUserId, usersUserId),
Expression.equals(relationshipsAccountId, accountId)
Expression.equalsArgs(relationshipsAccountId.getSQL())
);
qb.join(new Join(false, Operation.LEFT, new Table(CachedRelationships.TABLE_NAME), on));
if (selection != null) {
@ -75,11 +78,12 @@ public class TwidereQueryBuilder {
if (sortOrder != null) {
qb.orderBy(new OrderBy(sortOrder));
}
return qb.build();
return Pair.create(qb.build(), new String[]{accountKey.toString()});
}
public static SQLSelectQuery withScore(final String[] projection, final String selection,
final String sortOrder, final long accountId, final int limit) {
public static Pair<SQLSelectQuery, String[]> withScore(final String[] projection, final String selection,
final String sortOrder, final UserKey accountKey,
final int limit) {
final SQLSelectQuery.Builder qb = new SQLSelectQuery.Builder();
final Selectable select = Utils.getColumnsFromProjection(projection);
final Column[] columns = new Column[CachedUsers.COLUMNS.length + 1];
@ -97,7 +101,8 @@ public class TwidereQueryBuilder {
CachedRelationships.MUTING));
columns[columns.length - 1] = new Column(expr, "score");
qb.select(select);
qb.from(withRelationship(new Columns(columns), null, null, accountId));
final Pair<SQLSelectQuery, String[]> pair = withRelationship(new Columns(columns), null, null, accountKey);
qb.from(pair.first);
if (selection != null) {
qb.where(new Expression(selection));
}
@ -107,7 +112,7 @@ public class TwidereQueryBuilder {
if (limit > 0) {
qb.limit(limit);
}
return qb.build();
return Pair.create(qb.build(), pair.second);
}
private static Object[] valueOrZero(String... columns) {
@ -143,13 +148,13 @@ public class TwidereQueryBuilder {
return qb.build();
}
public static SQLSelectQuery buildByScreenName(final String[] projection, final long account_id,
final String screen_name, final String selection, final String sortOrder) {
public static Pair<SQLSelectQuery, String[]> byScreenName(final String[] projection, final UserKey accountKey,
final String screen_name, final String selection, final String sortOrder) {
final Selectable select = Utils.getColumnsFromProjection(projection);
final SQLSelectQuery.Builder qb = SQLQueryBuilder.select(select);
qb.select(select);
qb.from(new Tables(DirectMessages.TABLE_NAME));
final Expression accountIdWhere = Expression.equals(DirectMessages.ACCOUNT_KEY, account_id);
final Expression accountIdWhere = Expression.equalsArgs(DirectMessages.ACCOUNT_KEY);
final Expression incomingWhere = Expression.and(Expression.notEquals(DirectMessages.IS_OUTGOING, 1),
Expression.equals(new Column(DirectMessages.SENDER_SCREEN_NAME), screen_name));
final Expression outgoingWhere = Expression.and(Expression.equals(DirectMessages.IS_OUTGOING, 1),
@ -160,7 +165,7 @@ public class TwidereQueryBuilder {
qb.where(Expression.and(accountIdWhere, incomingWhere, outgoingWhere));
}
qb.orderBy(new OrderBy(sortOrder != null ? sortOrder : Conversation.DEFAULT_SORT_ORDER));
return qb.build();
return Pair.create(qb.build(), new String[]{accountKey.toString()});
}
}

View File

@ -466,9 +466,6 @@ public final class Utils implements Constants {
break;
}
case LINK_ID_PROFILE_EDITOR: {
if (noAccount(uri, args)) {
return null;
}
fragment = new UserProfileEditorFragment();
break;
}
@ -745,30 +742,28 @@ public final class Utils implements Constants {
}
}
if (isAccountIdRequired) {
final String paramAccountKey = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_KEY);
if (paramAccountKey != null) {
args.putParcelable(EXTRA_ACCOUNT_KEY, UserKey.valueOf(paramAccountKey));
} else {
UserKey accountKey = UserKey.valueOf(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_KEY));
if (accountKey == null) {
final long accountId = NumberUtils.toLong(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID), -1);
final String paramAccountName = uri.getQueryParameter(QUERY_PARAM_ACCOUNT_NAME);
if (paramAccountName != null) {
args.putParcelable(EXTRA_ACCOUNT_KEY, DataStoreUtils.getAccountKey(context,
paramAccountName));
if (accountId != -1) {
accountKey = DataStoreUtils.findAccountKey(context,
accountId);
args.putParcelable(EXTRA_ACCOUNT_KEY, accountKey);
} else if (paramAccountName != null) {
accountKey = DataStoreUtils.findAccountKey(context,
paramAccountName);
} else {
final UserKey accountKey = getDefaultAccountKey(context);
if (isMyAccount(context, accountKey)) {
args.putParcelable(EXTRA_ACCOUNT_KEY, accountKey);
}
accountKey = getDefaultAccountKey(context);
}
}
if (accountKey == null) return null;
args.putParcelable(EXTRA_ACCOUNT_KEY, accountKey);
}
fragment.setArguments(args);
return fragment;
}
protected static boolean noAccount(Uri uri, Bundle args) {
return TextUtils.isEmpty(uri.getQueryParameter(QUERY_PARAM_ACCOUNT_ID)) && !args.containsKey(EXTRA_ACCOUNT_ID);
}
public static Intent createStatusShareIntent(@NonNull final Context context, @NonNull final ParcelableStatus status) {
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
@ -1704,18 +1699,20 @@ public final class Utils implements Constants {
return top - actionBarHeight;
}
public static void openUserMediaTimeline(final Activity activity, final long account_id, final long user_id,
final String screen_name) {
public static void openUserMediaTimeline(final Activity activity, final UserKey accountKey,
final long userId, final String screenName) {
if (activity == null) return;
final Uri.Builder builder = new Uri.Builder();
builder.scheme(SCHEME_TWIDERE);
builder.authority(AUTHORITY_USER_MEDIA_TIMELINE);
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_ID, String.valueOf(account_id));
if (user_id > 0) {
builder.appendQueryParameter(QUERY_PARAM_USER_ID, String.valueOf(user_id));
if (accountKey != null) {
builder.appendQueryParameter(QUERY_PARAM_ACCOUNT_KEY, String.valueOf(accountKey));
}
if (screen_name != null) {
builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screen_name);
if (userId > 0) {
builder.appendQueryParameter(QUERY_PARAM_USER_ID, String.valueOf(userId));
}
if (screenName != null) {
builder.appendQueryParameter(QUERY_PARAM_SCREEN_NAME, screenName);
}
final Intent intent = new Intent(Intent.ACTION_VIEW, builder.build());
activity.startActivity(intent);

View File

@ -160,4 +160,13 @@ public class NameView extends ThemedTextView {
setSingleLine(true);
}
}
@Override
public int getBaseline() {
try {
return super.getBaseline();
} catch (IndexOutOfBoundsException e) {
return -1;
}
}
}

View File

@ -45,4 +45,4 @@ public class StatusTextView extends ThemedTextView {
return LinkMovementMethod.getInstance();
}
}
}

View File

@ -88,4 +88,13 @@ public class TimelineContentTextView extends ThemedTextView {
return super.onTouchEvent(event);
}
}
@Override
public int getBaseline() {
try {
return super.getBaseline();
} catch (IndexOutOfBoundsException e) {
return -1;
}
}
}