bug fixes

This commit is contained in:
Mariotaku Lee 2015-10-19 17:28:16 +08:00
parent ed80e534cc
commit b22fdcfe72
31 changed files with 291 additions and 255 deletions

View File

@ -45,6 +45,6 @@ dependencies {
compile 'org.apache.commons:commons-lang3:3.4'
compile 'com.github.mariotaku:RestFu:0.9.2'
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.1'
compile 'com.github.mariotaku:SQLiteQB:ef3f596199'
compile 'com.github.mariotaku:SQLiteQB:901dd5e72f'
compile fileTree(dir: 'libs', include: ['*.jar'])
}

View File

@ -19,10 +19,13 @@
package org.mariotaku.twidere.api.twitter.model;
import org.mariotaku.twidere.util.AbsLogger;
import java.util.Date;
public interface Activity extends TwitterResponse, Comparable<Activity> {
int ACTION_UNKNOWN = 0x00;
int ACTION_FAVORITE = 0x01;
int ACTION_FOLLOW = 0x02;
int ACTION_MENTION = 0x03;
@ -36,6 +39,9 @@ public interface Activity extends TwitterResponse, Comparable<Activity> {
int ACTION_RETWEETED_MENTION = 0x0B;
int ACTION_FAVORITED_MENTION = 0x0C;
int ACTION_JOINED_TWITTER = 0x0D;
int ACTION_MEDIA_TAGGED = 0x0E;
int ACTION_FAVORITED_MEDIA_TAGGED = 0x0F;
int ACTION_RETWEETED_MEDIA_TAGGED = 0x10;
Action getAction();
@ -71,7 +77,9 @@ public interface Activity extends TwitterResponse, Comparable<Activity> {
RETWEET(ACTION_RETWEET), LIST_MEMBER_ADDED(ACTION_LIST_MEMBER_ADDED), LIST_CREATED(ACTION_LIST_CREATED),
FAVORITED_RETWEET(ACTION_FAVORITED_RETWEET), RETWEETED_RETWEET(ACTION_RETWEETED_RETWEET),
QUOTE(ACTION_QUOTE), RETWEETED_MENTION(ACTION_RETWEETED_MENTION),
FAVORITED_MENTION(ACTION_FAVORITED_MENTION), JOINED_TWITTER(ACTION_JOINED_TWITTER);
FAVORITED_MENTION(ACTION_FAVORITED_MENTION), JOINED_TWITTER(ACTION_JOINED_TWITTER),
MEDIA_TAGGED(ACTION_MEDIA_TAGGED), FAVORITED_MEDIA_TAGGED(ACTION_FAVORITED_MEDIA_TAGGED),
RETWEETED_MEDIA_TAGGED(ACTION_RETWEETED_MEDIA_TAGGED), UNKNOWN(ACTION_UNKNOWN);
private final int actionId;
@ -93,7 +101,11 @@ public interface Activity extends TwitterResponse, Comparable<Activity> {
if ("retweeted_mention".equalsIgnoreCase(string)) return RETWEETED_MENTION;
if ("favorited_mention".equalsIgnoreCase(string)) return FAVORITED_MENTION;
if ("joined_twitter".equalsIgnoreCase(string)) return JOINED_TWITTER;
throw new IllegalArgumentException("Unknown action " + string);
if ("media_tagged".equalsIgnoreCase(string)) return MEDIA_TAGGED;
if ("favorited_media_tagged".equalsIgnoreCase(string)) return FAVORITED_MEDIA_TAGGED;
if ("retweeted_media_tagged".equalsIgnoreCase(string)) return RETWEETED_MEDIA_TAGGED;
AbsLogger.error("Unknown Twitter activity action " + string);
return UNKNOWN;
}
public int getActionId() {

View File

@ -110,7 +110,10 @@ public class ActivityImpl extends TwitterResponseImpl implements Activity {
case FAVORITED_RETWEET:
case RETWEETED_RETWEET:
case RETWEETED_MENTION:
case FAVORITED_MENTION: {
case FAVORITED_MENTION:
case MEDIA_TAGGED:
case FAVORITED_MEDIA_TAGGED:
case RETWEETED_MEDIA_TAGGED: {
instance.targetStatuses = LoganSquare.mapperFor(Status.class).parseList(jsonParser).toArray(new Status[instance.targetsSize]);
break;
}
@ -145,7 +148,10 @@ public class ActivityImpl extends TwitterResponseImpl implements Activity {
case FAVORITED_RETWEET:
case RETWEETED_RETWEET:
case RETWEETED_MENTION:
case FAVORITED_MENTION: {
case FAVORITED_MENTION:
case MEDIA_TAGGED:
case FAVORITED_MEDIA_TAGGED:
case RETWEETED_MEDIA_TAGGED: {
instance.targetObjectUsers = LoganSquare.mapperFor(User.class).parseList(jsonParser).toArray(new User[instance.targetObjectsSize]);
break;
}

View File

@ -213,9 +213,15 @@ public final class TwidereArrayUtils {
return string_array;
}
public static String[] toStringArray(final String s) {
if (s == null) return null;
return s.split("(?!^)");
public static String[] toStringArray(final List<?> list) {
if (list == null) return null;
final int length = list.size();
final String[] stringArray = new String[length];
for (int i = 0; i < length; i++) {
stringArray[i] = ParseUtils.parseString(list.get(i));
}
return stringArray;
}
public static String toStringForSQL(final String[] array) {

View File

@ -14,7 +14,7 @@ android {
applicationId "org.mariotaku.twidere"
minSdkVersion 14
targetSdkVersion 23
versionCode 128
versionCode 129
versionName "0.3.0"
multiDexEnabled true
}
@ -91,7 +91,7 @@ dependencies {
compile 'com.makeramen:roundedimageview:2.1.1'
compile 'com.soundcloud.android:android-crop:1.0.1@aar'
compile 'com.hannesdorfmann.parcelableplease:annotation:1.0.1'
compile 'com.github.mariotaku:PickNCrop:44b09cbc69'
compile 'com.github.mariotaku:PickNCrop:1dff3ed574'
compile 'com.diogobernardino:williamchart:2.0.1'
compile 'com.lnikkila:extendedtouchview:0.1.0'
compile 'com.google.dagger:dagger:2.0.1'

View File

@ -29,6 +29,7 @@ import android.os.BatteryManager;
import android.text.TextUtils;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.util.Utils;
import org.mariotaku.twidere.util.dagger.ApplicationModule;
@ -151,7 +152,8 @@ public class HotMobiLogger {
}
public static void logPowerBroadcast(Context context) {
logPowerBroadcast(context, context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
final TwidereApplication app = TwidereApplication.getInstance(context);
logPowerBroadcast(context, app.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)));
}
public static void logPowerBroadcast(Context context, Intent intent) {

View File

@ -70,18 +70,6 @@ public abstract class BasePreferenceActivity extends AppCompatPreferenceActivity
protected ActivityTracker mActivityTracker;
private int mMetaState;
@Override
protected void onStart() {
super.onStart();
mActivityTracker.dispatchStart(this);
}
@Override
protected void onStop() {
mActivityTracker.dispatchStop(this);
super.onStop();
}
@Override
public String getCurrentThemeFontFamily() {
return mCurrentThemeFontFamily;

View File

@ -50,18 +50,6 @@ public abstract class BaseThemedActivity extends Activity implements IThemedActi
@Inject
protected KeyboardShortcutsHandler mKeyboardShortcutHandler;
@Override
protected void onStart() {
super.onStart();
mActivityTracker.dispatchStart(this);
}
@Override
protected void onStop() {
mActivityTracker.dispatchStop(this);
super.onStop();
}
@Override
public String getCurrentThemeFontFamily() {
return mCurrentThemeFontFamily;

View File

@ -25,13 +25,11 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.KeyEvent;
import android.view.MenuItem;
import android.view.MotionEvent;
import com.squareup.otto.Bus;
import org.mariotaku.twidere.Constants;
import org.mariotaku.twidere.R;
import org.mariotaku.twidere.activity.iface.IControlBarActivity;
import org.mariotaku.twidere.app.TwidereApplication;
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
@ -138,17 +136,6 @@ public class BaseAppCompatActivity extends ThemedAppCompatActivity implements Co
return isKeyboardShortcutHandled(mKeyboardShortcutsHandler, keyCode, event, mKeyMetaState) || super.onKeyDown(keyCode, event);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
switch (item.getItemId()) {
case R.id.back: {
onBackPressed();
return true;
}
}
return super.onOptionsItemSelected(item);
}
@Override
public void startActivity(final Intent intent) {
super.startActivity(intent);
@ -179,7 +166,6 @@ public class BaseAppCompatActivity extends ThemedAppCompatActivity implements Co
@Override
protected void onStart() {
super.onStart();
mActivityTracker.dispatchStart(this);
mIsVisible = true;
}
@ -208,7 +194,6 @@ public class BaseAppCompatActivity extends ThemedAppCompatActivity implements Co
@Override
protected void onStop() {
mIsVisible = false;
mActivityTracker.dispatchStop(this);
super.onStop();
}

View File

@ -983,7 +983,10 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
if (TextUtils.isEmpty(myScreenName)) return false;
int selectionStart = 0;
mEditText.append("@" + status.user_screen_name + " ");
selectionStart = mEditText.length();
// If status is not sent by our self, just include our screen name into selection.
if (status.account_id != status.user_id) {
selectionStart = mEditText.length();
}
if (status.is_retweet) {
mEditText.append("@" + status.retweeted_by_user_screen_name + " ");
}
@ -1164,7 +1167,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements LocationL
PermissionUtils.getPermission(permissions, grantResults, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
startLocationUpdateIfEnabled();
} else {
//TODO show permission denied message
Toast.makeText(this, R.string.cannot_get_location, Toast.LENGTH_SHORT).show();
}
}

View File

@ -320,10 +320,8 @@ public class HomeActivity extends BaseAppCompatActivity implements OnClickListen
final DrawerLayout drawer = mDrawerLayout;
if (isDrawerOpen()) {
drawer.closeDrawers();
} else {
onBackPressed();
return true;
}
return true;
}
}
return super.onKeyUp(keyCode, event);

View File

@ -128,6 +128,8 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
private ContentResolver mResolver;
private AbstractSignInTask mTask;
private TintedStatusLayout mMainContent;
private Runnable mResumeFragmentRunnable;
private boolean mFragmentsResumed;
@Override
public void afterTextChanged(final Editable s) {
@ -433,11 +435,7 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
}
void onSignInResult(final SignInResponse result) {
final FragmentManager fm = getSupportFragmentManager();
final Fragment f = fm.findFragmentByTag(FRAGMENT_TAG_SIGN_IN_PROGRESS);
if (f instanceof DialogFragment) {
((DialogFragment) f).dismiss();
}
dismissDialogFragment(FRAGMENT_TAG_SIGN_IN_PROGRESS);
if (result != null) {
if (result.alreadyLoggedIn) {
final ContentValues values = result.toContentValues();
@ -472,8 +470,40 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
setSignInButton();
}
@Override
protected void onResumeFragments() {
super.onResumeFragments();
if (!mFragmentsResumed && mResumeFragmentRunnable != null) {
mResumeFragmentRunnable.run();
}
mFragmentsResumed = true;
}
@Override
protected void onPause() {
mFragmentsResumed = false;
super.onPause();
}
private void dismissDialogFragment(final String tag) {
mResumeFragmentRunnable = new Runnable() {
@Override
public void run() {
final FragmentManager fm = getSupportFragmentManager();
final Fragment f = fm.findFragmentByTag(tag);
if (f instanceof DialogFragment) {
((DialogFragment) f).dismiss();
}
mResumeFragmentRunnable = null;
}
};
if (mFragmentsResumed) {
mResumeFragmentRunnable.run();
}
}
void onSignInStart() {
mHandler.post(new Runnable() {
mResumeFragmentRunnable = new Runnable() {
@Override
public void run() {
if (isFinishing()) return;
@ -482,8 +512,12 @@ public class SignInActivity extends BaseAppCompatActivity implements OnClickList
final SupportProgressDialogFragment fragment = new SupportProgressDialogFragment();
fragment.setCancelable(false);
fragment.show(ft, FRAGMENT_TAG_SIGN_IN_PROGRESS);
mResumeFragmentRunnable = null;
}
});
};
if (mFragmentsResumed) {
mResumeFragmentRunnable.run();
}
}
protected boolean isActionBarOutlineEnabled() {

View File

@ -214,15 +214,4 @@ public abstract class ThemedFragmentActivity extends FragmentActivity implements
return true;
}
@Override
protected void onStart() {
super.onStart();
mActivityTracker.dispatchStart(this);
}
@Override
protected void onStop() {
mActivityTracker.dispatchStop(this);
super.onStop();
}
}

View File

@ -162,6 +162,8 @@ public class TwidereApplication extends MultiDexApplication implements Constants
startRefreshServiceIfNeeded(this);
reloadConnectivitySettings();
registerActivityLifecycleCallbacks(getApplicationModule().getActivityTracker());
}
private void initDebugMode() {

View File

@ -325,14 +325,6 @@ public class MessagesConversationFragment extends BaseSupportFragment implements
}
}
mEditText.setSelection(mEditText.length());
// mEditText.setMaxCharacters(mValidator.getMaxTweetLength());
// mEditText.setLengthChecker(new METLengthChecker() {
// @Override
// public int getLength(CharSequence text) {
// return mValidator.getTweetLength(String.valueOf(text));
// }
// });
// TODO show text length
final boolean isValid = mAccount != null && mRecipient != null;
mConversationContainer.setVisibility(isValid ? View.VISIBLE : View.GONE);
mRecipientSelectorContainer.setVisibility(isValid ? View.GONE : View.VISIBLE);

View File

@ -1222,8 +1222,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
case R.id.profile_image: {
final String url = Utils.getOriginalTwitterProfileImage(user.profile_image_url);
final ParcelableMedia[] media = {ParcelableMedia.newImage(url, url)};
//TODO open media animation
Bundle options = null;
Bundle options = Utils.createMediaViewerActivityOption(view);
Utils.openMedia(activity, user.account_id, false, null, media, options);
break;
}
@ -1231,8 +1230,7 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
if (user.profile_banner_url == null) return;
final String url = user.profile_banner_url + "/ipad_retina";
final ParcelableMedia[] media = {ParcelableMedia.newImage(url, url)};
//TODO open media animation
Bundle options = null;
Bundle options = Utils.createMediaViewerActivityOption(view);
Utils.openMedia(activity, user.account_id, false, null, media, options);
break;
}

View File

@ -105,6 +105,8 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
private ParcelableUser mUser;
private boolean mUserInfoLoaderInitialized;
private boolean mGetUserInfoCalled;
private boolean mFragmentsResumed;
private Runnable mResumeFragmentRunnable;
@Override
public void beforeTextChanged(final CharSequence s, final int length, final int start, final int end) {
@ -205,13 +207,6 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
return super.onOptionsItemSelected(item);
}
@Override
public void onResume() {
super.onResume();
if (mTask != null && mTask.getStatus() == Status.PENDING) {
AsyncTaskUtils.executeTask(mTask);
}
}
@Override
public void onActivityCreated(final Bundle savedInstanceState) {
@ -364,15 +359,58 @@ public class UserProfileEditorFragment extends BaseSupportFragment implements On
}
}
@Override
public void onResume() {
super.onResume();
if (mTask != null && mTask.getStatus() == Status.PENDING) {
AsyncTaskUtils.executeTask(mTask);
}
if (!mFragmentsResumed && mResumeFragmentRunnable != null) {
mResumeFragmentRunnable.run();
}
mFragmentsResumed = true;
}
@Override
public void onPause() {
mFragmentsResumed = false;
super.onPause();
}
private void dismissDialogFragment(final String tag) {
mResumeFragmentRunnable = new Runnable() {
@Override
public void run() {
final FragmentManager fm = getChildFragmentManager();
final Fragment f = fm.findFragmentByTag(tag);
if (f instanceof DialogFragment) {
((DialogFragment) f).dismiss();
}
mResumeFragmentRunnable = null;
}
};
if (mFragmentsResumed) {
mResumeFragmentRunnable.run();
}
}
private void setUpdateState(final boolean start) {
final FragmentManager fm = getChildFragmentManager();
final Fragment f = fm.findFragmentByTag(UPDATE_PROFILE_DIALOG_FRAGMENT_TAG);
if (!start && f instanceof DialogFragment) {
((DialogFragment) f).dismiss();
} else if (start) {
SupportProgressDialogFragment df = new SupportProgressDialogFragment();
df.show(fm, UPDATE_PROFILE_DIALOG_FRAGMENT_TAG);
df.setCancelable(false);
if (!start) {
dismissDialogFragment(UPDATE_PROFILE_DIALOG_FRAGMENT_TAG);
return;
}
mResumeFragmentRunnable = new Runnable() {
@Override
public void run() {
final FragmentManager fm = getChildFragmentManager();
SupportProgressDialogFragment df = new SupportProgressDialogFragment();
df.show(fm, UPDATE_PROFILE_DIALOG_FRAGMENT_TAG);
df.setCancelable(false);
mResumeFragmentRunnable = null;
}
};
if (mFragmentsResumed) {
mResumeFragmentRunnable.run();
}
}

View File

@ -320,7 +320,7 @@ public final class TwidereDataProvider extends ContentProvider implements Consta
}
int result = 0;
final long[] newIds = new long[valuesArray.length];
if (table != null) {
if (table != null && valuesArray.length > 0) {
mDatabaseWrapper.beginTransaction();
if (tableId == TABLE_ID_CACHED_USERS) {
for (final ContentValues values : valuesArray) {

View File

@ -32,6 +32,7 @@ import org.mariotaku.twidere.util.message.TaskStateChangedEvent;
import javax.inject.Inject;
@Deprecated
public abstract class ManagedAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> implements
Constants {

View File

@ -21,6 +21,8 @@ package org.mariotaku.twidere.util;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import org.apache.commons.collections.primitives.ArrayIntList;
import org.apache.commons.collections.primitives.IntList;
@ -31,12 +33,30 @@ import edu.tsinghua.hotmobi.model.SessionEvent;
/**
* Created by mariotaku on 15/10/5.
*/
public class ActivityTracker {
public class ActivityTracker implements Application.ActivityLifecycleCallbacks {
private final IntList mInternalStack = new ArrayIntList();
private SessionEvent mSessionEvent;
public void dispatchStart(Activity activity) {
private boolean isSwitchingInSameTask(int hashCode) {
return mInternalStack.lastIndexOf(hashCode) < mInternalStack.size() - 1;
}
public int size() {
return mInternalStack.size();
}
public boolean isEmpty() {
return mInternalStack.isEmpty();
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(Activity activity) {
mInternalStack.add(System.identityHashCode(activity));
// BEGIN HotMobi
if (mSessionEvent == null) {
@ -45,8 +65,18 @@ public class ActivityTracker {
// END HotMobi
}
public void dispatchStop(Activity activity) {
@Override
public void onActivityResumed(Activity activity) {
}
@Override
public void onActivityPaused(Activity activity) {
}
@Override
public void onActivityStopped(Activity activity) {
final int hashCode = System.identityHashCode(activity);
// BEGIN HotMobi
@ -62,16 +92,13 @@ public class ActivityTracker {
mInternalStack.removeElement(hashCode);
}
private boolean isSwitchingInSameTask(int hashCode) {
return mInternalStack.lastIndexOf(hashCode) < mInternalStack.size() - 1;
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
public int size() {
return mInternalStack.size();
}
@Override
public void onActivityDestroyed(Activity activity) {
public boolean isEmpty() {
return mInternalStack.isEmpty();
}
}

View File

@ -31,6 +31,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Deprecated
public final class AsyncTaskManager {
private final CopyOnWriteArrayList<ManagedAsyncTask<?, ?, ?>> mTasks = new CopyOnWriteArrayList<>();
@ -84,7 +85,7 @@ public final class AsyncTaskManager {
@SuppressWarnings("unchecked")
public final <T> boolean execute(final int hashCode, final T... params) {
final ManagedAsyncTask<T, ?, ?> task = (ManagedAsyncTask<T, ?, ?>) findTask(hashCode);
if (task != null) {
if (task != null && task.getStatus() == AsyncTask.Status.PENDING) {
task.executeOnExecutor(mExecutor, params);
return true;
}
@ -99,13 +100,6 @@ public final class AsyncTaskManager {
return new ArrayList<>(mTasks);
}
public boolean hasRunningTask() {
for (final ManagedAsyncTask<?, ?, ?> task : getTaskSpecList()) {
if (task.getStatus() == ManagedAsyncTask.Status.RUNNING) return true;
}
return false;
}
public boolean hasRunningTasksForTag(final String tag) {
if (tag == null) return false;
for (final ManagedAsyncTask<?, ?, ?> task : getTaskSpecList()) {

View File

@ -1010,7 +1010,13 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
}
// I bet you don't want to see these users in your auto complete list.
//TODO insert to blocked users data
// bulkDelete(mResolver, CachedUsers.CONTENT_URI, CachedUsers.USER_ID, list, null, false);
final ContentValues values = new ContentValues();
values.put(CachedRelationships.BLOCKING, true);
values.put(CachedRelationships.FOLLOWING, false);
values.put(CachedRelationships.FOLLOWED_BY, false);
mResolver.update(CachedRelationships.CONTENT_URI, values,
Expression.inArgs(CachedRelationships.USER_ID, list.size()).getSQL(),
TwidereArrayUtils.toStringArray(list));
}
@Override

View File

@ -19,70 +19,66 @@
package org.mariotaku.twidere.util;
import android.support.v4.util.SimpleArrayMap;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class HostsFileParser {
private final Map<String, String> mHosts = new HashMap<>();
private final String mPath;
private final SimpleArrayMap<String, String> mHosts = new SimpleArrayMap<>();
private final String mPath;
public HostsFileParser() {
this("/etc/hosts");
}
public HostsFileParser() {
this("/etc/hosts");
}
public HostsFileParser(final String path) {
mPath = path;
}
public HostsFileParser(final String path) {
mPath = path;
}
public boolean contains(final String host) {
return mHosts.containsKey(host);
}
public boolean contains(final String host) {
return mHosts.containsKey(host);
}
public String getAddress(final String host) {
return mHosts.get(host);
}
public String getAddress(final String host) {
return mHosts.get(host);
}
public Map<String, String> getAll() {
return new HashMap<>(mHosts);
}
public boolean reload() {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(mPath));
mHosts.clear();
String line;
while ((line = reader.readLine()) != null) {
final String trimmed = line.trim();
// Skip if this line is empty or commented out
if (trimmed.length() == 0 || trimmed.startsWith("#")) {
continue;
}
final String[] segments = trimmed.replaceAll("(\\s|\t)+", " ").split("\\s");
if (segments.length < 2) {
continue;
}
final String host = segments[1];
if (!contains(host)) {
mHosts.put(host, segments[0]);
}
}
return true;
} catch (final IOException e) {
return false;
} finally {
if (reader != null) {
Utils.closeSilently(reader);
}
}
}
public boolean reload() {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(mPath));
mHosts.clear();
String line = null;
while ((line = reader.readLine()) != null) {
final String trimmed = line.trim();
// Skip if this line is empty or commented out
if (trimmed.length() == 0 || trimmed.startsWith("#")) {
continue;
}
final String[] segments = trimmed.replaceAll("(\\s|\t)+", " ").split("\\s");
if (segments.length < 2) {
continue;
}
final String host = segments[1];
if (!contains(host)) {
mHosts.put(host, segments[0]);
}
}
return true;
} catch (final IOException e) {
return false;
} finally {
if (reader != null) {
Utils.closeSilently(reader);
}
}
}
public void reloadIfNeeded() {
if (!mHosts.isEmpty()) return;
reload();
}
public void reloadIfNeeded() {
if (!mHosts.isEmpty()) return;
reload();
}
}

View File

@ -57,7 +57,7 @@ public class LoganSquareWrapper extends LoganSquare {
if (context == null || args == null || args.length == 0) return null;
final File cacheDir = Utils.getBestCacheDir(context, JSON_CACHE_DIR);
if (!cacheDir.exists()) {
AbsLogger.logIfFalse(cacheDir.mkdirs(), "Unable to create cache dir");
AbsLogger.logIfFalse(cacheDir.mkdirs(), "Unable to create cache dir " + cacheDir);
}
final String filename = Utils.encodeQueryParams(TwidereArrayUtils.toString(args, '.', false));
return new File(cacheDir, filename + ".json");

View File

@ -776,13 +776,15 @@ public final class Utils implements Constants {
}
}
public static Bundle createMediaViewerActivityOption(View view) {
public static Bundle createMediaViewerActivityOption(@NonNull View view) {
view.buildDrawingCache();
try {
final Bitmap viewDrawingCache = view.getDrawingCache();
if (viewDrawingCache == null) return null;
final Bitmap drawingCache = Bitmap.createBitmap(viewDrawingCache);
return ActivityOptionsCompat.makeThumbnailScaleUpAnimation(view, drawingCache, 0, 0).toBundle();
} catch (NullPointerException e) {
return null;
} finally {
view.destroyDrawingCache();
}
@ -1600,7 +1602,7 @@ public final class Utils implements Constants {
}
public static boolean isComposeNowSupported(Context context) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return false;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN || context == null) return false;
return hasNavBar(context);
}
@ -1624,11 +1626,15 @@ public final class Utils implements Constants {
public static boolean removeLineBreaks(Editable s) {
boolean deleted = false;
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '\n') {
s.delete(i, i + 1);
deleted |= true;
try {
for (int i = s.length() - 1; i >= 0; i--) {
if (s.charAt(i) == '\n') {
s.delete(i, i + 1);
deleted |= true;
}
}
} catch (IndexOutOfBoundsException e) {
throw new IndexOutOfBoundsException("Error processing " + s + ", original message: " + e.getMessage());
}
return deleted;
}
@ -2277,24 +2283,14 @@ public final class Utils implements Constants {
return getTableNameById(getTableId(uri));
}
public static int getTextCount(final String string) {
if (string == null) return 0;
return TwidereArrayUtils.toStringArray(string).length;
}
public static int getTextCount(final TextView view) {
if (view == null) return 0;
final String string = ParseUtils.parseString(view.getText());
return getTextCount(string);
}
public static long getTimestampFromDate(final Date date) {
if (date == null) return -1;
return date.getTime();
}
public static boolean hasNavBar(Context context) {
public static boolean hasNavBar(@NonNull Context context) {
final Resources resources = context.getResources();
if (resources == null) return false;
int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
if (id > 0) {
return resources.getBoolean(id);

View File

@ -26,7 +26,9 @@
*/
package org.mariotaku.twidere.util.net;
import java.util.regex.Pattern;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.UnknownHostException;
/**
* A collection of utilities relating to InetAddresses.
@ -37,28 +39,6 @@ public class InetAddressUtils {
private InetAddressUtils() {
}
private static final String IPV4_BASIC_PATTERN_STRING =
"(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}" + // initial 3 fields, 0-255 followed by .
"([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])"; // final field, 0-255
private static final Pattern IPV4_PATTERN =
Pattern.compile("^" + IPV4_BASIC_PATTERN_STRING + "$");
private static final Pattern IPV4_MAPPED_IPV6_PATTERN = // TODO does not allow for redundant leading zeros
Pattern.compile("^::[fF]{4}:" + IPV4_BASIC_PATTERN_STRING + "$");
private static final Pattern IPV6_STD_PATTERN =
Pattern.compile(
"^[0-9a-fA-F]{1,4}(:[0-9a-fA-F]{1,4}){7}$");
private static final Pattern IPV6_HEX_COMPRESSED_PATTERN =
Pattern.compile(
"^(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)" + // 0-6 hex fields
"::" +
"(([0-9A-Fa-f]{1,4}(:[0-9A-Fa-f]{1,4}){0,5})?)$"); // 0-6 hex fields
/*
* The above pattern is not totally rigorous as it allows for more than 7 hex fields in total
*/
private static final char COLON_CHAR = ':';
// Must not have more than 7 colons (i.e. 8 fields)
private static final int MAX_COLON_COUNT = 7;
/**
* Checks whether the parameter is a valid IPv4 address
*
@ -66,37 +46,11 @@ public class InetAddressUtils {
* @return true if the input parameter is a valid IPv4 address
*/
public static boolean isIPv4Address(final String input) {
return IPV4_PATTERN.matcher(input).matches();
}
public static boolean isIPv4MappedIPv64Address(final String input) {
return IPV4_MAPPED_IPV6_PATTERN.matcher(input).matches();
}
/**
* Checks whether the parameter is a valid standard (non-compressed) IPv6 address
*
* @param input the address string to check for validity
* @return true if the input parameter is a valid standard (non-compressed) IPv6 address
*/
public static boolean isIPv6StdAddress(final String input) {
return IPV6_STD_PATTERN.matcher(input).matches();
}
/**
* Checks whether the parameter is a valid compressed IPv6 address
*
* @param input the address string to check for validity
* @return true if the input parameter is a valid compressed IPv6 address
*/
public static boolean isIPv6HexCompressedAddress(final String input) {
int colonCount = 0;
for (int i = 0; i < input.length(); i++) {
if (input.charAt(i) == COLON_CHAR) {
colonCount++;
}
try {
return Inet4Address.getByName(input) != null;
} catch (UnknownHostException ex) {
return false;
}
return colonCount <= MAX_COLON_COUNT && IPV6_HEX_COMPRESSED_PATTERN.matcher(input).matches();
}
/**
@ -106,6 +60,10 @@ public class InetAddressUtils {
* @return true if the input parameter is a valid standard or compressed IPv6 address
*/
public static boolean isIPv6Address(final String input) {
return isIPv6StdAddress(input) || isIPv6HexCompressedAddress(input);
try {
return Inet6Address.getByName(input) != null;
} catch (UnknownHostException ex) {
return false;
}
}
}

View File

@ -34,15 +34,26 @@ public class ExtendedViewPager extends ViewPager {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(final MotionEvent event) {
public boolean onTouchEvent(MotionEvent ev) {
if (!isEnabled()) return false;
return super.onInterceptTouchEvent(event);
try {
return super.onTouchEvent(ev);
} catch (IllegalArgumentException ex) {
// Ignore
}
return false;
}
@Override
public boolean onTouchEvent(final MotionEvent event) {
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (!isEnabled()) return false;
return super.onTouchEvent(event);
try {
return super.onInterceptTouchEvent(ev);
} catch (IllegalArgumentException ex) {
// Ignore
}
return false;
}
}

View File

@ -62,7 +62,13 @@ public class HandleSpanClickTextView extends ThemedTextView {
final Layout layout = getLayout();
final int line = layout.getLineForVertical(y);
final int off = layout.getOffsetForHorizontal(line, x);
final int off;
try {
off = layout.getOffsetForHorizontal(line, x);
} catch (IndexOutOfBoundsException e) {
throw new IndexOutOfBoundsException("Line count " + layout.getLineCount() +
", line for y " + y + " is " + line + ", x is " + x);
}
final float lineWidth = layout.getLineWidth(line);
final ClickableSpan[] links = buffer.getSpans(off, off, ClickableSpan.class);

View File

@ -475,6 +475,7 @@ public class ShapedImageView extends ImageView {
final float radius = mShadowRadius, dy = radius * 1.5f / 2;
final int size = Math.round(Math.min(contentWidth, contentHeight) + radius * 2);
mShadowBitmap = Bitmap.createBitmap(size, Math.round(size + dy), Config.ARGB_8888);
if (mShadowBitmap == null) return;
Canvas canvas = new Canvas(mShadowBitmap);
final Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(0xFF000000 | mBackgroundPaint.getColor());

View File

@ -30,7 +30,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
<org.mariotaku.twidere.view.ExtendedViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@ -66,7 +66,6 @@
<item name="add_to_filter" type="id"/>
<item name="follow" type="id"/>
<item name="unfollow" type="id"/>
<item name="back" type="id"/>
<item name="translate" type="id"/>
<item name="accept" type="id"/>
<item name="deny" type="id"/>