added workaround for blackberry devices when setting hotkey.
added quote user to reply dialog for quoted tweet trying to make mock user-agent work for some consumer keys.
This commit is contained in:
parent
d7b934a3e0
commit
738fc2468b
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.model;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/20.
|
||||
*/
|
||||
public enum ConsumerKeyType {
|
||||
TWITTER_FOR_ANDROID, TWITTER_FOR_IPHONE, TWITTER_FOR_IPAD, TWITTER_FOR_MAC,
|
||||
TWITTER_FOR_WINDOWS_PHONE, TWITTER_FOR_GOOGLE_TV, UNKNOWN;
|
||||
|
||||
@NonNull
|
||||
public static ConsumerKeyType parse(String type) {
|
||||
try {
|
||||
return ConsumerKeyType.valueOf(type);
|
||||
} catch (Exception e) {
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -495,10 +495,12 @@ public class ParcelableMedia implements Parcelable, JSONParcelable, SimpleValueS
|
|||
}
|
||||
|
||||
public static final Parcelable.Creator<Variant> CREATOR = new Parcelable.Creator<Variant>() {
|
||||
@Override
|
||||
public Variant createFromParcel(Parcel source) {
|
||||
return new Variant(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Variant[] newArray(int size) {
|
||||
return new Variant[size];
|
||||
}
|
||||
|
@ -526,10 +528,12 @@ public class ParcelableMedia implements Parcelable, JSONParcelable, SimpleValueS
|
|||
}
|
||||
|
||||
public static final Parcelable.Creator<VideoInfo> CREATOR = new Parcelable.Creator<VideoInfo>() {
|
||||
@Override
|
||||
public VideoInfo createFromParcel(Parcel source) {
|
||||
return new VideoInfo(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VideoInfo[] newArray(int size) {
|
||||
return new VideoInfo[size];
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import android.content.Context;
|
|||
import android.support.annotation.NonNull;
|
||||
|
||||
import org.mariotaku.twidere.common.R;
|
||||
import org.mariotaku.twidere.model.ConsumerKeyType;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.zip.CRC32;
|
||||
|
@ -120,6 +121,43 @@ public class TwitterContentUtils {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static String getOfficialKeyName(final Context context, final String consumerKey,
|
||||
final String consumerSecret) {
|
||||
if (context == null || consumerKey == null || consumerSecret == null) return null;
|
||||
final String[] keySecrets = context.getResources().getStringArray(R.array.values_official_consumer_secret_crc32);
|
||||
final String[] keyNames = context.getResources().getStringArray(R.array.names_official_consumer_secret);
|
||||
final CRC32 crc32 = new CRC32();
|
||||
final byte[] consumerSecretBytes = consumerSecret.getBytes(Charset.forName("UTF-8"));
|
||||
crc32.update(consumerSecretBytes, 0, consumerSecretBytes.length);
|
||||
final long value = crc32.getValue();
|
||||
crc32.reset();
|
||||
for (int i = 0, j = keySecrets.length; i < j; i++) {
|
||||
if (Long.parseLong(keySecrets[i], 16) == value) return keyNames[i];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ConsumerKeyType getOfficialKeyType(final Context context, final String consumerKey,
|
||||
final String consumerSecret) {
|
||||
if (context == null || consumerKey == null || consumerSecret == null) {
|
||||
return ConsumerKeyType.UNKNOWN;
|
||||
}
|
||||
final String[] keySecrets = context.getResources().getStringArray(R.array.values_official_consumer_secret_crc32);
|
||||
final String[] keyNames = context.getResources().getStringArray(R.array.types_official_consumer_secret);
|
||||
final CRC32 crc32 = new CRC32();
|
||||
final byte[] consumerSecretBytes = consumerSecret.getBytes(Charset.forName("UTF-8"));
|
||||
crc32.update(consumerSecretBytes, 0, consumerSecretBytes.length);
|
||||
final long value = crc32.getValue();
|
||||
crc32.reset();
|
||||
for (int i = 0, j = keySecrets.length; i < j; i++) {
|
||||
if (Long.parseLong(keySecrets[i], 16) == value) {
|
||||
return ConsumerKeyType.parse(keyNames[i]);
|
||||
}
|
||||
}
|
||||
return ConsumerKeyType.UNKNOWN;
|
||||
}
|
||||
|
||||
private static void parseEntities(final HtmlBuilder builder, final EntitySupport entities) {
|
||||
// Format media.
|
||||
final MediaEntity[] mediaEntities = entities.getMediaEntities();
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<!--Twitter for Google TV-->
|
||||
<item>56d8f9ff</item>
|
||||
</string-array>
|
||||
<string-array name="names_official_consumer_secret_crc32">
|
||||
<string-array name="names_official_consumer_secret">
|
||||
<!--Twitter for Android-->
|
||||
<item>Twitter for Android</item>
|
||||
<!--Twitter for iPhone-->
|
||||
|
@ -48,4 +48,18 @@
|
|||
<!--Twitter for Google TV-->
|
||||
<item>Twitter for Google TV</item>
|
||||
</string-array>
|
||||
<string-array name="types_official_consumer_secret">
|
||||
<!--Twitter for Android-->
|
||||
<item>TWITTER_FOR_ANDROID</item>
|
||||
<!--Twitter for iPhone-->
|
||||
<item>TWITTER_FOR_IPHONE</item>
|
||||
<!--Twitter for iPad-->
|
||||
<item>TWITTER_FOR_IPAD</item>
|
||||
<!--Twitter for Mac-->
|
||||
<item>TWITTER_FOR_MAC</item>
|
||||
<!--Twitter for Windows Phone-->
|
||||
<item>TWITTER_FOR_WINDOWS_PHONE</item>
|
||||
<!--Twitter for Google TV-->
|
||||
<item>TWITTER_FOR_GOOGLE_TV</item>
|
||||
</string-array>
|
||||
</resources>
|
|
@ -584,6 +584,9 @@
|
|||
android:name="com.android.systemui.action_assist_icon"
|
||||
android:resource="@drawable/ic_assist_twidere"/>
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".activity.KeyboardShortcutPreferenceCompatActivity"
|
||||
android:theme="@style/Theme.Blank.Dialog"/>
|
||||
<activity
|
||||
android:name=".activity.TestActivity"
|
||||
android:enabled="false"
|
||||
|
|
|
@ -31,7 +31,7 @@ public class SpiceService extends Service {
|
|||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
SpiceProfilingUtil.log(this, "onCreate");
|
||||
SpiceProfilingUtil.log("onCreate");
|
||||
mAlarmManager = (AlarmManager) getSystemService(Service.ALARM_SERVICE);
|
||||
|
||||
IntentFilter screenFilter = new IntentFilter();
|
||||
|
@ -58,10 +58,10 @@ public class SpiceService extends Service {
|
|||
String action = intent.getAction();
|
||||
if (action.equals(Intent.ACTION_SCREEN_ON)) {
|
||||
SpiceProfilingUtil.profile(context, SpiceProfilingUtil.FILE_NAME_SCREEN, "SCREEN ON" + "," + NetworkStateUtil.getConnectedType(context));
|
||||
SpiceProfilingUtil.log(context, "SCREEN ON" + "," + NetworkStateUtil.getConnectedType(context));
|
||||
SpiceProfilingUtil.log("SCREEN ON" + "," + NetworkStateUtil.getConnectedType(context));
|
||||
} else if (action.equals(Intent.ACTION_SCREEN_OFF)) {
|
||||
SpiceProfilingUtil.profile(context, SpiceProfilingUtil.FILE_NAME_SCREEN, "SCREEN OFF" + "," + NetworkStateUtil.getConnectedType(context));
|
||||
SpiceProfilingUtil.log(context, "SCREEN OFF" + "," + NetworkStateUtil.getConnectedType(context));
|
||||
SpiceProfilingUtil.log("SCREEN OFF" + "," + NetworkStateUtil.getConnectedType(context));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ public class SpiceAsyUploadTask extends AsyncTask<Object, Object, Object> {
|
|||
final File tmp_dir = new File(app_root + "/spice");
|
||||
if (!tmp_dir.exists()) {
|
||||
if (!tmp_dir.mkdirs()) {
|
||||
SpiceProfilingUtil.log(context, "cannot create folder spice, do nothing.");
|
||||
SpiceProfilingUtil.log("cannot create folder spice, do nothing.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -58,12 +58,12 @@ public class SpiceAsyUploadTask extends AsyncTask<Object, Object, Object> {
|
|||
final String url = PROFILE_SERVER_URL;
|
||||
final HttpParameter[] parameters = {new HttpParameter("file", tmp)};
|
||||
client.post(url, url, parameters);
|
||||
SpiceProfilingUtil.log(context, "server has already received file " + tmp.getName());
|
||||
SpiceProfilingUtil.log("server has already received file " + tmp.getName());
|
||||
tmp.delete();
|
||||
} catch (Exception e) {
|
||||
if (Utils.isDebugBuild()) {
|
||||
Log.w(LOGTAG, e);
|
||||
SpiceProfilingUtil.log(context, "server does not receive file " + tmp.getName());
|
||||
SpiceProfilingUtil.log("server does not receive file " + tmp.getName());
|
||||
}
|
||||
putBackProfile(context, tmp, file);
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class SpiceAsyUploadTask extends AsyncTask<Object, Object, Object> {
|
|||
final long lastUpload = prefs.getLong(LAST_UPLOAD_DATE, System.currentTimeMillis());
|
||||
final double deltaDays = (System.currentTimeMillis() - lastUpload) / (MILLSECS_HALF_DAY * 2);
|
||||
if (deltaDays < 1) {
|
||||
SpiceProfilingUtil.log(context, "Last uploaded was conducted in 1 day ago.");
|
||||
SpiceProfilingUtil.log("Last uploaded was conducted in 1 day ago.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ public class SpiceAsyUploadTask extends AsyncTask<Object, Object, Object> {
|
|||
continue;
|
||||
}
|
||||
final String url = PROFILE_SERVER_URL;
|
||||
SpiceProfilingUtil.log(context, url);
|
||||
SpiceProfilingUtil.log(url);
|
||||
uploadMultipart(file);
|
||||
}
|
||||
return false;
|
||||
|
@ -121,15 +121,15 @@ public class SpiceAsyUploadTask extends AsyncTask<Object, Object, Object> {
|
|||
}
|
||||
|
||||
if (success && tmp.renameTo(profile) && tmp.delete()) {
|
||||
SpiceProfilingUtil.log(context, "put profile back success");
|
||||
SpiceProfilingUtil.log("put profile back success");
|
||||
} else {
|
||||
SpiceProfilingUtil.log(context, "put profile back failed");
|
||||
SpiceProfilingUtil.log("put profile back failed");
|
||||
}
|
||||
} else {
|
||||
if (tmp.renameTo(profile)) {
|
||||
SpiceProfilingUtil.log(context, "put profile back success");
|
||||
SpiceProfilingUtil.log("put profile back success");
|
||||
} else {
|
||||
SpiceProfilingUtil.log(context, "put profile back failed");
|
||||
SpiceProfilingUtil.log("put profile back failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,11 +43,11 @@ public class SpiceProfilingUtil {
|
|||
|| plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||
}
|
||||
|
||||
public static boolean log(final Context context, final String msg) {
|
||||
if (Utils.isDebuggable(context)) {
|
||||
public static boolean log(final String msg) {
|
||||
if (Utils.isDebugBuild()) {
|
||||
final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1];
|
||||
final String fullname = ste.getClassName();
|
||||
final String name = fullname.substring(fullname.lastIndexOf('.'));
|
||||
final String fullName = ste.getClassName();
|
||||
final String name = fullName.substring(fullName.lastIndexOf('.'));
|
||||
final String tag = name + "." + ste.getMethodName();
|
||||
Log.d(tag, msg);
|
||||
return true;
|
||||
|
|
|
@ -30,7 +30,7 @@ public class ProfilingUtil {
|
|||
}
|
||||
|
||||
public static boolean log(final Context context, final String msg) {
|
||||
if (Utils.isDebuggable(context)) {
|
||||
if (Utils.isDebugBuild()) {
|
||||
final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1];
|
||||
final String fullname = ste.getClassName();
|
||||
final String name = fullname.substring(fullname.lastIndexOf('.'));
|
||||
|
|
|
@ -38,6 +38,11 @@ public abstract class BaseThemedActivity extends Activity implements IThemedActi
|
|||
private String mCurrentThemeFontFamily;
|
||||
private String mCurrentThemeBackgroundOption;
|
||||
|
||||
@Override
|
||||
public String getCurrentThemeBackgroundOption() {
|
||||
return mCurrentThemeBackgroundOption;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCurrentThemeBackgroundAlpha() {
|
||||
return mCurrentThemeBackgroundAlpha;
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.activity;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutSpec;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/20.
|
||||
*/
|
||||
public class KeyboardShortcutPreferenceCompatActivity extends BaseThemedActivity implements Constants, OnClickListener {
|
||||
|
||||
public static final String EXTRA_CONTEXT_TAG = "context_tag";
|
||||
public static final String EXTRA_KEY_ACTION = "key_action";
|
||||
|
||||
private KeyboardShortcutsHandler mKeyboardShortcutHandler;
|
||||
private TextView mKeysLabel, mConflictLabel;
|
||||
|
||||
private KeyboardShortcutSpec mKeySpec;
|
||||
private Button mButtonPositive, mButtonNegative, mButtonNeutral;
|
||||
|
||||
@Override
|
||||
public String getThemeBackgroundOption() {
|
||||
return VALUE_THEME_BACKGROUND_DEFAULT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getThemeColor() {
|
||||
return ThemeUtils.getThemeColor(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getThemeResourceId() {
|
||||
return ThemeUtils.getDialogThemeResource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mKeyboardShortcutHandler = TwidereApplication.getInstance(this).getKeyboardShortcutsHandler();
|
||||
setContentView(R.layout.activity_keyboard_shortcut_input);
|
||||
setTitle(KeyboardShortcutsHandler.getActionLabel(this, getKeyAction()));
|
||||
|
||||
mButtonPositive.setOnClickListener(this);
|
||||
mButtonNegative.setOnClickListener(this);
|
||||
mButtonNeutral.setOnClickListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switch (v.getId()) {
|
||||
case R.id.button_positive: {
|
||||
if (mKeySpec == null) return;
|
||||
mKeyboardShortcutHandler.register(mKeySpec, getKeyAction());
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
case R.id.button_neutral: {
|
||||
mKeyboardShortcutHandler.unregister(getKeyAction());
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
case R.id.button_negative: {
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
|
||||
final String keyAction = getKeyAction();
|
||||
if (keyAction == null) return false;
|
||||
final KeyboardShortcutSpec spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(getContextTag(), keyCode, event);
|
||||
if (spec == null || !spec.isValid()) {
|
||||
return super.onKeyUp(keyCode, event);
|
||||
}
|
||||
mKeySpec = spec;
|
||||
mKeysLabel.setText(spec.toKeyString());
|
||||
final String oldAction = mKeyboardShortcutHandler.findAction(spec);
|
||||
final KeyboardShortcutSpec copyOfSpec = spec.copy();
|
||||
copyOfSpec.setContextTag(null);
|
||||
final String oldGeneralAction = mKeyboardShortcutHandler.findAction(copyOfSpec);
|
||||
if (!TextUtils.isEmpty(oldAction) && !keyAction.equals(oldAction)) {
|
||||
// Conflicts with keys in same context tag
|
||||
mConflictLabel.setVisibility(View.VISIBLE);
|
||||
final String label = KeyboardShortcutsHandler.getActionLabel(this, oldAction);
|
||||
mConflictLabel.setText(getString(R.string.conflicts_with_name, label));
|
||||
mButtonPositive.setText((R.string.overwrite));
|
||||
} else if (!TextUtils.isEmpty(oldGeneralAction) && !keyAction.equals(oldGeneralAction)) {
|
||||
// Conflicts with keys in root context
|
||||
mConflictLabel.setVisibility(View.VISIBLE);
|
||||
final String label = KeyboardShortcutsHandler.getActionLabel(this, oldGeneralAction);
|
||||
mConflictLabel.setText(getString(R.string.conflicts_with_name, label));
|
||||
mButtonPositive.setText((R.string.overwrite));
|
||||
} else {
|
||||
mConflictLabel.setVisibility(View.GONE);
|
||||
mButtonPositive.setText((android.R.string.ok));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
mKeysLabel = (TextView) findViewById(R.id.keys_label);
|
||||
mConflictLabel = (TextView) findViewById(R.id.conflict_label);
|
||||
mButtonPositive = (Button) findViewById(R.id.button_positive);
|
||||
mButtonNegative = (Button) findViewById(R.id.button_negative);
|
||||
mButtonNeutral = (Button) findViewById(R.id.button_neutral);
|
||||
}
|
||||
|
||||
private String getContextTag() {
|
||||
return getIntent().getStringExtra(EXTRA_CONTEXT_TAG);
|
||||
}
|
||||
|
||||
private String getKeyAction() {
|
||||
return getIntent().getStringExtra(EXTRA_KEY_ACTION);
|
||||
}
|
||||
}
|
|
@ -240,11 +240,7 @@ public class BrowserSignInActivity extends BaseSupportDialogActivity implements
|
|||
TWITTER_CONSUMER_SECRET_3);
|
||||
cb.setHostAddressResolverFactory(new TwidereHostResolverFactory(mApplication));
|
||||
cb.setHttpClientFactory(new OkHttpClientFactory(mApplication));
|
||||
if (TwitterContentUtils.isOfficialKey(mActivity, consumerKey, consumerSecret)) {
|
||||
Utils.setMockOfficialUserAgent(mActivity, cb);
|
||||
} else {
|
||||
Utils.setUserAgent(mActivity, cb);
|
||||
}
|
||||
Utils.setClientUserAgent(mActivity, consumerKey, consumerSecret, cb);
|
||||
cb.setRestBaseURL(DEFAULT_REST_BASE_URL);
|
||||
cb.setOAuthBaseURL(DEFAULT_OAUTH_BASE_URL);
|
||||
cb.setSigningRestBaseURL(DEFAULT_SIGNING_REST_BASE_URL);
|
||||
|
|
|
@ -914,6 +914,9 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
|||
if (status == null || status.id <= 0) return false;
|
||||
final String myScreenName = Utils.getAccountScreenName(this, status.account_id);
|
||||
if (TextUtils.isEmpty(myScreenName)) return false;
|
||||
if (!TextUtils.isEmpty(status.quoted_by_user_name)) {
|
||||
mEditText.append("@" + status.quoted_by_user_name + " ");
|
||||
}
|
||||
mEditText.append("@" + status.user_screen_name + " ");
|
||||
final int selectionStart = mEditText.length();
|
||||
if (!TextUtils.isEmpty(status.retweeted_by_screen_name)) {
|
||||
|
|
|
@ -44,6 +44,7 @@ import android.support.v4.app.NotificationCompat;
|
|||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v4.view.ViewPager.OnPageChangeListener;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.view.Gravity;
|
||||
import android.view.KeyEvent;
|
||||
|
@ -279,6 +280,19 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
|||
@Override
|
||||
public boolean handleKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||
if (handleFragmentKeyboardShortcutSingle(keyCode, event)) return true;
|
||||
final String action = mKeyboardShortcutsHandler.getKeyAction("home", keyCode, event);
|
||||
if (action != null) {
|
||||
switch (action) {
|
||||
case "home.accounts_dashboard": {
|
||||
if (mSlidingMenu.isMenuShowing()) {
|
||||
mSlidingMenu.showContent(true);
|
||||
} else {
|
||||
mSlidingMenu.showMenu(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mKeyboardShortcutsHandler.handleKey(this, null, keyCode, event);
|
||||
}
|
||||
|
||||
|
@ -645,7 +659,7 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
|||
public long[] getActivatedAccountIds() {
|
||||
final Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.left_drawer);
|
||||
if (fragment instanceof AccountsDashboardFragment) {
|
||||
((AccountsDashboardFragment) fragment).getActivatedAccountIds();
|
||||
return ((AccountsDashboardFragment) fragment).getActivatedAccountIds();
|
||||
}
|
||||
return Utils.getActivatedAccountIds(this);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,6 @@ import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.AuthenticityTokenEx
|
|||
import org.mariotaku.twidere.util.OAuthPasswordAuthenticator.WrongUserPassException;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.TwitterContentUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.ViewUtils;
|
||||
import org.mariotaku.twidere.util.net.OkHttpClientFactory;
|
||||
|
@ -369,19 +368,13 @@ public class SignInActivity extends BaseActionBarActivity implements TwitterCons
|
|||
final boolean enable_proxy = mPreferences.getBoolean(KEY_ENABLE_PROXY, false);
|
||||
cb.setHostAddressResolverFactory(new TwidereHostResolverFactory(mApplication));
|
||||
cb.setHttpClientFactory(new OkHttpClientFactory(mApplication));
|
||||
if (TwitterContentUtils.isOfficialKey(this, mConsumerKey, mConsumerSecret)) {
|
||||
Utils.setMockOfficialUserAgent(this, cb);
|
||||
} else {
|
||||
Utils.setUserAgent(this, cb);
|
||||
}
|
||||
Utils.setClientUserAgent(this, mConsumerKey, mConsumerSecret, cb);
|
||||
final String apiUrlFormat = TextUtils.isEmpty(mAPIUrlFormat) ? DEFAULT_TWITTER_API_URL_FORMAT : mAPIUrlFormat;
|
||||
final String versionSuffix = mNoVersionSuffix ? null : "/1.1/";
|
||||
cb.setRestBaseURL(Utils.getApiUrl(apiUrlFormat, "api", versionSuffix));
|
||||
cb.setOAuthBaseURL(Utils.getApiUrl(apiUrlFormat, "api", "/oauth/"));
|
||||
cb.setUploadBaseURL(Utils.getApiUrl(apiUrlFormat, "upload", versionSuffix));
|
||||
cb.setOAuthAuthorizationURL(Utils.getApiUrl(apiUrlFormat, null, "/oauth/authorize"));
|
||||
final String userAgent = TwidereApplication.getInstance(this).getDefaultUserAgent();
|
||||
cb.setHttpUserAgent(userAgent);
|
||||
if (!mSameOAuthSigningUrl) {
|
||||
cb.setSigningRestBaseURL(DEFAULT_SIGNING_REST_BASE_URL);
|
||||
cb.setSigningOAuthBaseURL(DEFAULT_SIGNING_OAUTH_BASE_URL);
|
||||
|
|
|
@ -28,10 +28,13 @@ import android.content.Context;
|
|||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.DialogInterface.OnKeyListener;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.preference.DialogPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceCategory;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.support.annotation.NonNull;
|
||||
|
@ -46,6 +49,7 @@ import android.view.View;
|
|||
import android.widget.TextView;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.KeyboardShortcutPreferenceCompatActivity;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.KeyboardShortcutSpec;
|
||||
|
@ -57,18 +61,6 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment {
|
|||
|
||||
private KeyboardShortcutsHandler mKeyboardShortcutHandler;
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_RESET: {
|
||||
final DialogFragment f = new ResetKeyboardShortcutConfirmDialogFragment();
|
||||
f.show(getFragmentManager().beginTransaction(), "reset_keyboard_shortcut_confirm");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
@ -92,11 +84,25 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment {
|
|||
inflater.inflate(R.menu.menu_keyboard_shortcuts, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case MENU_RESET: {
|
||||
final DialogFragment f = new ResetKeyboardShortcutConfirmDialogFragment();
|
||||
f.show(getFragmentManager().beginTransaction(), "reset_keyboard_shortcut_confirm");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void addPreferences() {
|
||||
final PreferenceCategory general = makeAndAddCategory(getString(R.string.general));
|
||||
general.addPreference(makePreferences(null, "compose"));
|
||||
general.addPreference(makePreferences(null, "search"));
|
||||
general.addPreference(makePreferences(null, "message"));
|
||||
final PreferenceCategory home = makeAndAddCategory(getString(R.string.home));
|
||||
home.addPreference(makePreferences("home", "home.accounts_dashboard"));
|
||||
final PreferenceCategory navigation = makeAndAddCategory(getString(R.string.navigation));
|
||||
navigation.addPreference(makePreferences("navigation", "navigation.next"));
|
||||
navigation.addPreference(makePreferences("navigation", "navigation.previous"));
|
||||
|
@ -117,13 +123,17 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment {
|
|||
return category;
|
||||
}
|
||||
|
||||
private KeyboardShortcutPreferences makePreferences(String contextTag, String action) {
|
||||
private Preference makePreferences(String contextTag, String action) {
|
||||
final PreferenceScreen preferenceScreen = getPreferenceScreen();
|
||||
final Context context = preferenceScreen.getContext();
|
||||
return new KeyboardShortcutPreferences(context, mKeyboardShortcutHandler, contextTag, action);
|
||||
final KeyboardShortcutsHandler shortcutHandler = mKeyboardShortcutHandler;
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||
return new KeyboardShortcutPreferenceCompat(context, shortcutHandler, contextTag, action);
|
||||
}
|
||||
return new KeyboardShortcutPreference(context, shortcutHandler, contextTag, action);
|
||||
}
|
||||
|
||||
private static class KeyboardShortcutPreferences extends DialogPreference implements OnKeyListener {
|
||||
private static class KeyboardShortcutPreference extends DialogPreference implements OnKeyListener {
|
||||
|
||||
private final KeyboardShortcutsHandler mKeyboardShortcutHandler;
|
||||
private final String mContextTag, mAction;
|
||||
|
@ -131,8 +141,8 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment {
|
|||
private TextView mKeysLabel, mConflictLabel;
|
||||
private KeyboardShortcutSpec mKeySpec;
|
||||
|
||||
public KeyboardShortcutPreferences(final Context context, final KeyboardShortcutsHandler handler,
|
||||
@Nullable final String contextTag, @NonNull final String action) {
|
||||
public KeyboardShortcutPreference(final Context context, final KeyboardShortcutsHandler handler,
|
||||
@Nullable final String contextTag, @NonNull final String action) {
|
||||
//noinspection ConstantConditions
|
||||
super(context, null);
|
||||
mKeyboardShortcutHandler = handler;
|
||||
|
@ -151,61 +161,12 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment {
|
|||
updateSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToActivity() {
|
||||
super.onAttachedToActivity();
|
||||
mKeyboardShortcutHandler.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareForRemoval() {
|
||||
mKeyboardShortcutHandler.unregisterOnSharedPreferenceChangeListener(mPreferencesChangeListener);
|
||||
super.onPrepareForRemoval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE: {
|
||||
if (mKeySpec == null) return;
|
||||
mKeyboardShortcutHandler.register(mKeySpec, mAction);
|
||||
break;
|
||||
}
|
||||
case DialogInterface.BUTTON_NEUTRAL: {
|
||||
mKeyboardShortcutHandler.unregister(mAction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(Builder builder) {
|
||||
builder.setPositiveButton(getContext().getString(android.R.string.ok), this);
|
||||
builder.setNegativeButton(getContext().getString(android.R.string.cancel), this);
|
||||
builder.setNeutralButton(getContext().getString(R.string.clear), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showDialog(Bundle state) {
|
||||
super.showDialog(state);
|
||||
final Dialog dialog = getDialog();
|
||||
dialog.setOnKeyListener(this);
|
||||
mKeysLabel = (TextView) dialog.findViewById(R.id.keys_label);
|
||||
mConflictLabel = (TextView) dialog.findViewById(R.id.conflict_label);
|
||||
|
||||
mConflictLabel.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
|
||||
if (event.getAction() != KeyEvent.ACTION_UP) return false;
|
||||
if (event.hasNoModifiers() && keyCode == KeyEvent.KEYCODE_DEL || keyCode == KeyEvent.KEYCODE_FORWARD_DEL) {
|
||||
mKeyboardShortcutHandler.unregister(mAction);
|
||||
return true;
|
||||
}
|
||||
final KeyboardShortcutSpec spec = KeyboardShortcutsHandler.getKeyboardShortcutSpec(mContextTag, keyCode, event);
|
||||
if (spec == null || !spec.isValid()) {
|
||||
Log.d(LOGTAG, String.format("Invalid key %s", spec));
|
||||
Log.d(LOGTAG, String.format("Invalid key %s", event), new Exception());
|
||||
return false;
|
||||
}
|
||||
mKeySpec = spec;
|
||||
|
@ -228,10 +189,108 @@ public class KeyboardShortcutsFragment extends BasePreferenceFragment {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToActivity() {
|
||||
super.onAttachedToActivity();
|
||||
mKeyboardShortcutHandler.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(Builder builder) {
|
||||
builder.setPositiveButton(getContext().getString(android.R.string.ok), this);
|
||||
builder.setNegativeButton(getContext().getString(android.R.string.cancel), this);
|
||||
builder.setNeutralButton(getContext().getString(R.string.clear), this);
|
||||
builder.setOnKeyListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareForRemoval() {
|
||||
mKeyboardShortcutHandler.unregisterOnSharedPreferenceChangeListener(mPreferencesChangeListener);
|
||||
super.onPrepareForRemoval();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected View onCreateDialogView() {
|
||||
final View view = super.onCreateDialogView();
|
||||
mKeysLabel = (TextView) view.findViewById(R.id.keys_label);
|
||||
mConflictLabel = (TextView) view.findViewById(R.id.conflict_label);
|
||||
mConflictLabel.setVisibility(View.GONE);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE: {
|
||||
if (mKeySpec == null) return;
|
||||
mKeyboardShortcutHandler.register(mKeySpec, mAction);
|
||||
break;
|
||||
}
|
||||
case DialogInterface.BUTTON_NEUTRAL: {
|
||||
mKeyboardShortcutHandler.unregister(mAction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSummary() {
|
||||
final KeyboardShortcutSpec spec = mKeyboardShortcutHandler.findKey(mAction);
|
||||
setSummary(spec != null ? spec.toKeyString() : null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class KeyboardShortcutPreferenceCompat extends Preference {
|
||||
|
||||
private final KeyboardShortcutsHandler mKeyboardShortcutHandler;
|
||||
private final String mContextTag, mAction;
|
||||
private final OnSharedPreferenceChangeListener mPreferencesChangeListener;
|
||||
|
||||
public KeyboardShortcutPreferenceCompat(final Context context, final KeyboardShortcutsHandler handler,
|
||||
@Nullable final String contextTag, @NonNull final String action) {
|
||||
//noinspection ConstantConditions
|
||||
super(context, null);
|
||||
mKeyboardShortcutHandler = handler;
|
||||
mContextTag = contextTag;
|
||||
mAction = action;
|
||||
setPersistent(false);
|
||||
setTitle(KeyboardShortcutsHandler.getActionLabel(context, action));
|
||||
mPreferencesChangeListener = new OnSharedPreferenceChangeListener() {
|
||||
@Override
|
||||
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
|
||||
updateSummary();
|
||||
}
|
||||
};
|
||||
updateSummary();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
final Context context = getContext();
|
||||
final Intent intent = new Intent(context, KeyboardShortcutPreferenceCompatActivity.class);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_CONTEXT_TAG, mContextTag);
|
||||
intent.putExtra(KeyboardShortcutPreferenceCompatActivity.EXTRA_KEY_ACTION, mAction);
|
||||
context.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToActivity() {
|
||||
super.onAttachedToActivity();
|
||||
mKeyboardShortcutHandler.registerOnSharedPreferenceChangeListener(mPreferencesChangeListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareForRemoval() {
|
||||
mKeyboardShortcutHandler.unregisterOnSharedPreferenceChangeListener(mPreferencesChangeListener);
|
||||
super.onPrepareForRemoval();
|
||||
}
|
||||
|
||||
private void updateSummary() {
|
||||
final KeyboardShortcutSpec spec = mKeyboardShortcutHandler.findKey(mAction);
|
||||
setSummary(spec != null ? spec.toKeyString() : null);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static class ResetKeyboardShortcutConfirmDialogFragment extends DialogFragment implements OnClickListener {
|
||||
|
|
|
@ -249,7 +249,7 @@ public abstract class AbsStatusesFragment<Data> extends AbsContentListFragment<A
|
|||
final Bundle options = Utils.createMediaViewerActivityOption(view);
|
||||
Utils.openMedia(getActivity(), status, media, options);
|
||||
//spice
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
SpiceProfilingUtil.log(
|
||||
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
||||
+ "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + adapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
||||
|
|
|
@ -298,7 +298,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
if (status == null) return;
|
||||
final Bundle options = Utils.createMediaViewerActivityOption(view);
|
||||
Utils.openMedia(getActivity(), status, media, options);
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
SpiceProfilingUtil.log(
|
||||
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
||||
+ "," + media.preview_url + "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + mStatusAdapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
||||
|
@ -383,7 +383,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
final Bundle options = Utils.createMediaViewerActivityOption(view);
|
||||
Utils.openMediaDirectly(getActivity(), accountId, status, media, status.media, options);
|
||||
//spice
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
SpiceProfilingUtil.log(
|
||||
status.id + ",Clicked," + status.account_id + "," + status.user_id + "," + status.text_plain.length()
|
||||
+ "," + media.preview_url + "," + media.media_url + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + mStatusAdapter.isMediaPreviewEnabled() + "," + status.timestamp);
|
||||
|
@ -444,7 +444,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
status.id + ",Words," + status.account_id + "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.text_plain.length() + "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(getActivity(), status.id + ",Words," + status.account_id + "," + status.user_id
|
||||
SpiceProfilingUtil.log(status.id + ",Words," + status.account_id + "," + status.user_id
|
||||
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.text_plain.length() + "," + status.timestamp);
|
||||
} else {
|
||||
|
@ -456,7 +456,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
+ "," + status.text_plain.length() + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + media.media_url + "," + media.width + "x" + media.height
|
||||
+ "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
SpiceProfilingUtil.log(
|
||||
status.id + ",PreviewM," + status.account_id + "," + status.user_id
|
||||
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.text_plain.length() + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
|
@ -468,7 +468,7 @@ public class StatusFragment extends BaseSupportFragment implements LoaderCallbac
|
|||
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.text_plain.length() + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
+ "," + media.preview_url + "," + media.media_url + "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(getActivity(),
|
||||
SpiceProfilingUtil.log(
|
||||
status.id + ",PreviewO," + status.account_id + "," + status.user_id
|
||||
+ "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.text_plain.length() + "," + TypeMappingUtil.getMediaType(media.type)
|
||||
|
|
|
@ -321,13 +321,13 @@ public class BackgroundOperationService extends IntentService implements Constan
|
|||
failedAccountIds.remove(response.getData().account_id);
|
||||
//spice
|
||||
if (response.getData().media == null) {
|
||||
SpiceProfilingUtil.log(this.getBaseContext(), response.getData().id + ",Tweet," + response.getData().account_id + ","
|
||||
SpiceProfilingUtil.log(response.getData().id + ",Tweet," + response.getData().account_id + ","
|
||||
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id);
|
||||
SpiceProfilingUtil.profile(this.getBaseContext(), response.getData().account_id, response.getData().id + ",Tweet," + response.getData().account_id + ","
|
||||
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id);
|
||||
} else
|
||||
for (final ParcelableMedia spiceMedia : response.getData().media) {
|
||||
SpiceProfilingUtil.log(this.getBaseContext(), response.getData().id + ",Media," + response.getData().account_id + ","
|
||||
SpiceProfilingUtil.log(response.getData().id + ",Media," + response.getData().account_id + ","
|
||||
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id + "," + spiceMedia.media_url + "," + TypeMappingUtil.getMediaType(spiceMedia.type));
|
||||
SpiceProfilingUtil.profile(this.getBaseContext(), response.getData().account_id, response.getData().id + ",Media," + response.getData().account_id + ","
|
||||
+ response.getData().in_reply_to_user_id + "," + response.getData().in_reply_to_status_id + "," + spiceMedia.media_url + "," + TypeMappingUtil.getMediaType(spiceMedia.type));
|
||||
|
|
|
@ -913,7 +913,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
+ status.account_id + "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(context, status.id + ",Favor,"
|
||||
SpiceProfilingUtil.log(status.id + ",Favor,"
|
||||
+ status.account_id + "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count + "," + status.timestamp);
|
||||
//end
|
||||
|
@ -1468,7 +1468,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
+ "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
SpiceProfilingUtil.log(context, status.id + ",Unfavor," + status.account_id
|
||||
SpiceProfilingUtil.log(status.id + ",Unfavor," + status.account_id
|
||||
+ "," + status.user_id + "," + status.reply_count
|
||||
+ "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + status.timestamp);
|
||||
|
@ -2377,21 +2377,21 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
|||
}
|
||||
//spice
|
||||
if (status.media == null) {
|
||||
SpiceProfilingUtil.log(getContext(), status.id + ",Retweet," + account_id + ","
|
||||
SpiceProfilingUtil.log(status.id + ",Retweet," + account_id + ","
|
||||
+ status.user_id + "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count);
|
||||
SpiceProfilingUtil.profile(getContext(), account_id, status.id + ",Retweet," + account_id + ","
|
||||
+ status.user_id + "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count);
|
||||
} else {
|
||||
for (final ParcelableMedia spiceMedia : status.media) {
|
||||
if (spiceMedia.type == ParcelableMedia.TYPE_IMAGE) {
|
||||
SpiceProfilingUtil.log(getContext(), status.id + ",RetweetM," + account_id + ","
|
||||
SpiceProfilingUtil.log(status.id + ",RetweetM," + account_id + ","
|
||||
+ status.user_id + "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + spiceMedia.media_url + "," + TypeMappingUtil.getMediaType(spiceMedia.type) + "," + spiceMedia.width + "x" + spiceMedia.height);
|
||||
SpiceProfilingUtil.profile(getContext(), account_id, status.id + ",RetweetM," + account_id + ","
|
||||
+ status.user_id + "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + spiceMedia.preview_url + "," + spiceMedia.media_url + "," + TypeMappingUtil.getMediaType(spiceMedia.type) + "," + spiceMedia.width + "x" + spiceMedia.height);
|
||||
} else {
|
||||
SpiceProfilingUtil.log(getContext(), status.id + ",RetweetO," + account_id + ","
|
||||
SpiceProfilingUtil.log(status.id + ",RetweetO," + account_id + ","
|
||||
+ status.user_id + "," + status.reply_count + "," + status.retweet_count + "," + status.favorite_count
|
||||
+ "," + spiceMedia.media_url + "," + TypeMappingUtil.getMediaType(spiceMedia.type));
|
||||
SpiceProfilingUtil.profile(getContext(), account_id, status.id + ",RetweetO," + account_id + ","
|
||||
|
|
|
@ -42,6 +42,7 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
sActionLabelMap.put("compose", R.string.compose);
|
||||
sActionLabelMap.put("search", R.string.search);
|
||||
sActionLabelMap.put("message", R.string.new_direct_message);
|
||||
sActionLabelMap.put("home.accounts_dashboard", R.string.open_accounts_dashboard);
|
||||
sActionLabelMap.put("status.reply", R.string.reply);
|
||||
sActionLabelMap.put("status.retweet", R.string.retweet);
|
||||
sActionLabelMap.put("status.favorite", R.string.favorite);
|
||||
|
@ -216,6 +217,7 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
editor.putString("n", "compose");
|
||||
editor.putString("m", "message");
|
||||
editor.putString("slash", "search");
|
||||
editor.putString("home.q", "home.accounts_dashboard");
|
||||
editor.putString("navigation.period", "navigation.refresh");
|
||||
editor.putString("navigation.j", "navigation.next");
|
||||
editor.putString("navigation.k", "navigation.previous");
|
||||
|
@ -280,6 +282,10 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
this.action = action;
|
||||
}
|
||||
|
||||
public KeyboardShortcutSpec copy() {
|
||||
return new KeyboardShortcutSpec(contextTag, keyMeta, keyName, action);
|
||||
}
|
||||
|
||||
public String getContextTag() {
|
||||
return contextTag;
|
||||
}
|
||||
|
@ -308,6 +314,10 @@ public class KeyboardShortcutsHandler implements Constants {
|
|||
return keyName != null;
|
||||
}
|
||||
|
||||
public void setContextTag(String contextTag) {
|
||||
this.contextTag = contextTag;
|
||||
}
|
||||
|
||||
public String toKeyString() {
|
||||
return metaToFriendlyString(keyMeta) + keyToFriendlyString(keyName);
|
||||
}
|
||||
|
|
|
@ -35,7 +35,6 @@ import android.content.pm.ActivityInfo;
|
|||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
|
@ -56,6 +55,7 @@ import android.net.NetworkInfo;
|
|||
import android.net.Uri;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.BatteryManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
|
@ -172,6 +172,7 @@ import org.mariotaku.twidere.graphic.ActionIconDrawable;
|
|||
import org.mariotaku.twidere.graphic.PaddingDrawable;
|
||||
import org.mariotaku.twidere.menu.SupportStatusShareProvider;
|
||||
import org.mariotaku.twidere.model.AccountPreferences;
|
||||
import org.mariotaku.twidere.model.ConsumerKeyType;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount;
|
||||
import org.mariotaku.twidere.model.ParcelableAccount.ParcelableCredentials;
|
||||
import org.mariotaku.twidere.model.ParcelableDirectMessage;
|
||||
|
@ -2511,11 +2512,7 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
cb.setSigningUploadBaseURL(DEFAULT_SIGNING_UPLOAD_BASE_URL);
|
||||
}
|
||||
}
|
||||
if (TwitterContentUtils.isOfficialKey(context, consumerKey, consumerSecret)) {
|
||||
setMockOfficialUserAgent(context, cb);
|
||||
} else {
|
||||
setUserAgent(context, cb);
|
||||
}
|
||||
setClientUserAgent(context, consumerKey, consumerSecret, cb);
|
||||
|
||||
cb.setIncludeEntitiesEnabled(includeEntities);
|
||||
cb.setIncludeRTsEnabled(includeRetweets);
|
||||
|
@ -2685,17 +2682,6 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
return BuildConfig.DEBUG;
|
||||
}
|
||||
|
||||
public static boolean isDebuggable(final Context context) {
|
||||
if (context == null) return false;
|
||||
final ApplicationInfo info;
|
||||
try {
|
||||
info = context.getPackageManager().getApplicationInfo(context.getPackageName(), 0);
|
||||
} catch (final NameNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
|
||||
}
|
||||
|
||||
public static boolean isFiltered(final SQLiteDatabase database, final long user_id, final String text_plain,
|
||||
final String text_html, final String source, final long retweeted_by_id) {
|
||||
return isFiltered(database, user_id, text_plain, text_html, source, retweeted_by_id, true);
|
||||
|
@ -3600,28 +3586,58 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
* TwitterAndroid/[versionName] ([versionCode]-[buildName]-[r|d)]-[buildNumber]) [deviceInfo]
|
||||
*
|
||||
* @param context
|
||||
* @param consumerKey
|
||||
* @param consumerSecret
|
||||
* @param cb
|
||||
*/
|
||||
public static void setMockOfficialUserAgent(final Context context, final ConfigurationBuilder cb) {
|
||||
final PackageManager pm = context.getPackageManager();
|
||||
cb.setClientName("TwitterAndroid");
|
||||
cb.setClientURL(null);
|
||||
String versionName;
|
||||
int versionCode;
|
||||
try {
|
||||
final PackageInfo packageInfo = pm.getPackageInfo("com.twitter.android", 0);
|
||||
versionName = packageInfo.versionName;
|
||||
versionCode = packageInfo.versionCode;
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
versionName = "5.53.0";
|
||||
versionCode = 4030814;
|
||||
public static void setClientUserAgent(final Context context, String consumerKey, String consumerSecret, final ConfigurationBuilder cb) {
|
||||
final ConsumerKeyType officialKeyType = TwitterContentUtils.getOfficialKeyType(context, consumerKey, consumerSecret);
|
||||
if (officialKeyType == ConsumerKeyType.UNKNOWN) {
|
||||
setUserAgent(context, cb);
|
||||
return;
|
||||
}
|
||||
cb.setClientVersion(versionName);
|
||||
final String deviceInfo = String.format(Locale.ROOT, "%s/%s (%s;%s;%s;%s;)",
|
||||
Build.MODEL, Build.VERSION.RELEASE, Build.MANUFACTURER, Build.MODEL, Build.BRAND,
|
||||
Build.PRODUCT);
|
||||
cb.setHttpUserAgent(String.format(Locale.ROOT, "TwitterAndroid/%s (%d-%c-%d) %s",
|
||||
versionName, versionCode, 'r', versionCode / 4200, deviceInfo));
|
||||
final String userAgentName = getUserAgentName(officialKeyType);
|
||||
cb.setClientName(userAgentName);
|
||||
cb.setClientURL(null);
|
||||
cb.setClientVersion(null);
|
||||
cb.setHttpUserAgent(userAgentName);
|
||||
// final PackageManager pm = context.getPackageManager();
|
||||
// final String clientName = "TwitterAndroid";
|
||||
// cb.setClientName(clientName);
|
||||
// cb.setClientURL(null);
|
||||
// String versionName;
|
||||
// int versionCode;
|
||||
// try {
|
||||
// final PackageInfo packageInfo = pm.getPackageInfo("com.twitter.android", 0);
|
||||
// versionName = packageInfo.versionName;
|
||||
// versionCode = packageInfo.versionCode;
|
||||
// } catch (PackageManager.NameNotFoundException e) {
|
||||
// versionName = "5.53.0";
|
||||
// versionCode = 4030814;
|
||||
// }
|
||||
// cb.setClientVersion(versionName);
|
||||
// final String deviceInfo = String.format(Locale.ROOT, "%s/%s (%s;%s;%s;%s;)", Build.MODEL,
|
||||
// Build.VERSION.RELEASE, Build.MANUFACTURER, Build.MODEL, Build.BRAND, Build.PRODUCT);
|
||||
// cb.setHttpUserAgent(String.format(Locale.ROOT, "%s/%s (%d-%c-%d) %s", clientName,
|
||||
// versionName, versionCode, 'r', versionCode / 4200, deviceInfo));
|
||||
}
|
||||
|
||||
private static String getUserAgentName(ConsumerKeyType type) {
|
||||
switch (type) {
|
||||
case TWITTER_FOR_ANDROID: {
|
||||
return "TwitterAndroid";
|
||||
}
|
||||
case TWITTER_FOR_IPHONE: {
|
||||
return "Twitter-iPhone";
|
||||
}
|
||||
case TWITTER_FOR_IPAD: {
|
||||
return "Twitter-iPad";
|
||||
}
|
||||
case TWITTER_FOR_MAC: {
|
||||
return "Twitter-Mac";
|
||||
}
|
||||
}
|
||||
return "Twitter";
|
||||
}
|
||||
|
||||
public static boolean shouldForceUsingPrivateAPIs(final Context context) {
|
||||
|
@ -3793,14 +3809,19 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
|
||||
public static void startRefreshServiceIfNeeded(final Context context) {
|
||||
final Intent refreshServiceIntent = new Intent(context, RefreshService.class);
|
||||
if (isNetworkAvailable(context) && hasAutoRefreshAccounts(context)) {
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, "Start background refresh service");
|
||||
AsyncTask.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (isNetworkAvailable(context) && hasAutoRefreshAccounts(context)) {
|
||||
if (isDebugBuild()) {
|
||||
Log.d(LOGTAG, "Start background refresh service");
|
||||
}
|
||||
context.startService(refreshServiceIntent);
|
||||
} else {
|
||||
context.stopService(refreshServiceIntent);
|
||||
}
|
||||
}
|
||||
context.startService(refreshServiceIntent);
|
||||
} else {
|
||||
context.stopService(refreshServiceIntent);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static void startStatusShareChooser(final Context context, final ParcelableStatus status) {
|
||||
|
@ -3838,10 +3859,10 @@ public final class Utils implements Constants, TwitterConstants {
|
|||
}
|
||||
|
||||
public static boolean truncateMessages(final List<DirectMessage> in, final List<DirectMessage> out,
|
||||
final long since_id) {
|
||||
final long sinceId) {
|
||||
if (in == null) return false;
|
||||
for (final DirectMessage message : in) {
|
||||
if (since_id > 0 && message.getId() <= since_id) {
|
||||
if (sinceId > 0 && message.getId() <= sinceId) {
|
||||
continue;
|
||||
}
|
||||
out.add(message);
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
~ Twidere - Twitter client for Android
|
||||
~
|
||||
~ Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
~
|
||||
~ This program is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ This program is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/keyboard_shortcut_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_xlarge">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/keys_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/keyboard_shortcut_hint"
|
||||
android:textAppearance="?android:textAppearanceMedium"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conflict_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/buttonPanel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:divider="?android:attr/dividerHorizontal"
|
||||
android:dividerPadding="0dip"
|
||||
android:minHeight="@dimen/element_size_normal"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="beginning">
|
||||
|
||||
<LinearLayout
|
||||
style="?android:attr/buttonBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layoutDirection="locale"
|
||||
android:measureWithLargestChild="true"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_negative"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="2"
|
||||
android:minHeight="@dimen/element_size_normal"
|
||||
android:text="@android:string/cancel"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_neutral"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="2"
|
||||
android:minHeight="@dimen/element_size_normal"
|
||||
android:text="@string/clear"
|
||||
android:textSize="14sp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/button_positive"
|
||||
style="?android:attr/buttonBarButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_weight="1"
|
||||
android:maxLines="2"
|
||||
android:minHeight="@dimen/element_size_normal"
|
||||
android:text="@android:string/ok"
|
||||
android:textSize="14sp"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
|
@ -24,20 +24,21 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/element_spacing_xlarge">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/keys_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:textAppearanceMedium"
|
||||
android:text="@string/keyboard_shortcut_hint"/>
|
||||
android:text="@string/keyboard_shortcut_hint"
|
||||
android:textAppearance="?android:textAppearanceMedium"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/conflict_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</org.mariotaku.twidere.view.ExtendedLinearLayout>
|
|
@ -0,0 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Twidere - Twitter client for Android
|
||||
~
|
||||
~ Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
~
|
||||
~ This program is free software: you can redistribute it and/or modify
|
||||
~ it under the terms of the GNU General Public License as published by
|
||||
~ the Free Software Foundation, either version 3 of the License, or
|
||||
~ (at your option) any later version.
|
||||
~
|
||||
~ This program is distributed in the hope that it will be useful,
|
||||
~ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
~ GNU General Public License for more details.
|
||||
~
|
||||
~ You should have received a copy of the GNU General Public License
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<dimen name="drawer_offset_home">128dp</dimen>
|
||||
</resources>
|
|
@ -730,5 +730,6 @@
|
|||
<string name="navigation">Navigation</string>
|
||||
<string name="reset_to_default">Reset to default</string>
|
||||
<string name="reset_keyboard_shortcuts_confirm">Reset keyboard shortcuts to default?</string>
|
||||
<string name="open_accounts_dashboard">Open accounts dashboard</string>
|
||||
|
||||
</resources>
|
Loading…
Reference in New Issue