mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-02-12 01:30:43 +01:00
optimized code (fixed some lint problems)
This commit is contained in:
parent
9641290502
commit
162ac1af42
@ -84,7 +84,7 @@ dependencies {
|
||||
compile 'com.github.mariotaku:MessageBubbleView:1.0'
|
||||
compile 'com.github.mariotaku:DragSortListView:0.6.1'
|
||||
compile 'com.github.mariotaku:SlidingMenu:1.3'
|
||||
compile 'com.github.uucky:ColorPicker-Android:0.9.1'
|
||||
compile 'com.github.uucky:ColorPicker-Android:0.9.3'
|
||||
compile 'com.sprylab.android.texturevideoview:texturevideoview:1.0.0'
|
||||
compile 'com.squareup:pollexor:2.0.2'
|
||||
compile 'org.apache.commons:commons-lang3:3.4'
|
||||
|
@ -627,7 +627,8 @@
|
||||
android:exported="true"
|
||||
android:icon="@drawable/nyan_sakamoto_thumbnail"
|
||||
android:label="@string/nyan_sakamoto"
|
||||
android:process=":daydream">
|
||||
android:process=":daydream"
|
||||
tools:ignore="ExportedService">
|
||||
<intent-filter android:priority="1">
|
||||
<action android:name="android.service.dreams.DreamService"/>
|
||||
</intent-filter>
|
||||
|
@ -3,8 +3,6 @@ package edu.tsinghua.spice;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
|
@ -22,8 +22,6 @@ package edu.tsinghua.spice.Utilies;
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.NetworkInfo;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
|
||||
/**
|
||||
* Created by Denny C. Ng on 2/28/15.
|
||||
|
@ -1,5 +1,6 @@
|
||||
package edu.tsinghua.spice.Utilies;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
@ -31,12 +32,15 @@ public class SpiceProfilingUtil {
|
||||
public static final String FILE_NAME_ONLAUNCH = "onLaunch_SPICE";
|
||||
public static final String FILE_NAME_SCREEN = "Screen_SPICE";
|
||||
|
||||
@SuppressLint("InlinedApi")
|
||||
public static boolean isCharging(final Context context) {
|
||||
if (context == null) return false;
|
||||
final Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
if (intent == null) return false;
|
||||
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||
return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB || plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||
return plugged == BatteryManager.BATTERY_PLUGGED_AC
|
||||
|| plugged == BatteryManager.BATTERY_PLUGGED_USB
|
||||
|| plugged == BatteryManager.BATTERY_PLUGGED_WIRELESS;
|
||||
}
|
||||
|
||||
public static boolean log(final Context context, final String msg) {
|
||||
@ -87,8 +91,6 @@ public class SpiceProfilingUtil {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
;
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
@ -16,55 +16,55 @@ import java.io.OutputStreamWriter;
|
||||
|
||||
public class ProfilingUtil {
|
||||
|
||||
public static final String FILE_NAME_PROFILE = "Profile";
|
||||
public static final String FILE_NAME_LOCATION = "Location";
|
||||
public static final String FILE_NAME_APP = "App";
|
||||
public static final String FILE_NAME_WIFI = "Wifi";
|
||||
public static final String FILE_NAME_PROFILE = "Profile";
|
||||
public static final String FILE_NAME_LOCATION = "Location";
|
||||
public static final String FILE_NAME_APP = "App";
|
||||
public static final String FILE_NAME_WIFI = "Wifi";
|
||||
|
||||
public static boolean isCharging(final Context context) {
|
||||
if (context == null) return false;
|
||||
final Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
if (intent == null) return false;
|
||||
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||
return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB;
|
||||
}
|
||||
public static boolean isCharging(final Context context) {
|
||||
if (context == null) return false;
|
||||
final Intent intent = context.registerReceiver(null, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
|
||||
if (intent == null) return false;
|
||||
final int plugged = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
|
||||
return plugged == BatteryManager.BATTERY_PLUGGED_AC || plugged == BatteryManager.BATTERY_PLUGGED_USB;
|
||||
}
|
||||
|
||||
public static boolean log(final Context context, final String msg) {
|
||||
if (Utils.isDebuggable(context)) {
|
||||
final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1];
|
||||
final String fullname = ste.getClassName();
|
||||
final String name = fullname.substring(fullname.lastIndexOf('.'));
|
||||
final String tag = name + "." + ste.getMethodName();
|
||||
Log.d(tag, msg);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
public static boolean log(final Context context, final String msg) {
|
||||
if (Utils.isDebuggable(context)) {
|
||||
final StackTraceElement ste = new Throwable().fillInStackTrace().getStackTrace()[1];
|
||||
final String fullname = ste.getClassName();
|
||||
final String name = fullname.substring(fullname.lastIndexOf('.'));
|
||||
final String tag = name + "." + ste.getMethodName();
|
||||
Log.d(tag, msg);
|
||||
return true;
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void profile(final Context context, final long accountID, final String text) {
|
||||
profile(context, accountID + "_" + FILE_NAME_PROFILE, text);
|
||||
}
|
||||
public static void profile(final Context context, final long accountID, final String text) {
|
||||
profile(context, accountID + "_" + FILE_NAME_PROFILE, text);
|
||||
}
|
||||
|
||||
public static void profile(final Context context, final String name, final String text) {
|
||||
if (context == null) return;
|
||||
final SharedPreferences prefs = context.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME,
|
||||
Context.MODE_PRIVATE);
|
||||
if (!prefs.getBoolean(Constants.KEY_USAGE_STATISTICS, false)) return;
|
||||
final String filename = name + ".csv";
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final FileOutputStream fos = context.openFileOutput(filename, Context.MODE_APPEND);
|
||||
if (fos == null) return;
|
||||
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
|
||||
bw.write("[" + System.currentTimeMillis() + "], " + text + "\n");
|
||||
bw.flush();
|
||||
fos.close();
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
};
|
||||
}.start();
|
||||
}
|
||||
public static void profile(final Context context, final String name, final String text) {
|
||||
if (context == null) return;
|
||||
final SharedPreferences prefs = context.getSharedPreferences(Constants.SHARED_PREFERENCES_NAME,
|
||||
Context.MODE_PRIVATE);
|
||||
if (!prefs.getBoolean(Constants.KEY_USAGE_STATISTICS, false)) return;
|
||||
final String filename = name + ".csv";
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final FileOutputStream fos = context.openFileOutput(filename, Context.MODE_APPEND);
|
||||
if (fos == null) return;
|
||||
final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
|
||||
bw.write("[" + System.currentTimeMillis() + "], " + text + "\n");
|
||||
bw.flush();
|
||||
fos.close();
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ public class DraggableArrayAdapter<T> extends ArrayAdapter<T> implements Draggab
|
||||
|
||||
final int INVALID_ID = -1;
|
||||
|
||||
private final HashMap<T, Integer> mIdMap = new HashMap<T, Integer>();
|
||||
private final HashMap<T, Integer> mIdMap = new HashMap<>();
|
||||
|
||||
public DraggableArrayAdapter(final Context context, final int layoutRes) {
|
||||
this(context, layoutRes, null);
|
||||
|
@ -30,6 +30,7 @@ import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
@ -119,9 +120,9 @@ public class DynamicGridView extends GridView {
|
||||
}
|
||||
};
|
||||
|
||||
private final HashMap<Long, Integer> mItemIdTops = new HashMap<Long, Integer>();
|
||||
private final HashMap<Long, Integer> mItemIdTops = new HashMap<>();
|
||||
|
||||
private final HashMap<Long, Integer> mItemIdLefts = new HashMap<Long, Integer>();
|
||||
private final HashMap<Long, Integer> mItemIdLefts = new HashMap<>();
|
||||
|
||||
/**
|
||||
* This TypeEvaluator is used to animate the BitmapDrawable back to its
|
||||
@ -264,7 +265,7 @@ public class DynamicGridView extends GridView {
|
||||
if (id == itemID) return v;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
public View getViewForPosition(final int position) {
|
||||
if (position < 0) return null;
|
||||
@ -309,7 +310,7 @@ public class DynamicGridView extends GridView {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
public boolean onTouchEvent(@NonNull final MotionEvent event) {
|
||||
|
||||
switch (event.getAction() & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
@ -383,7 +384,7 @@ public class DynamicGridView extends GridView {
|
||||
* over the gridview's items whenever the gridview is redrawn.
|
||||
*/
|
||||
@Override
|
||||
protected void dispatchDraw(final Canvas canvas) {
|
||||
protected void dispatchDraw(@NonNull final Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
if (mHoverCell != null) {
|
||||
mHoverCell.draw(canvas);
|
||||
|
@ -1,588 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2013 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.mariotaku.dynamicgridview;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.TypeEvaluator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.BitmapDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.widget.AbsListView;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
|
||||
/**
|
||||
* The dynamic listview is an extension of listview that supports cell dragging
|
||||
* and swapping.
|
||||
*
|
||||
* This layout is in charge of positioning the hover cell in the correct
|
||||
* location on the screen in response to user touch events. It uses the position
|
||||
* of the hover cell to determine when two cells should be swapped. If two cells
|
||||
* should be swapped, all the corresponding data set and layout changes are
|
||||
* handled here.
|
||||
*
|
||||
* If no cell is selected, all the touch events are passed down to the listview
|
||||
* and behave normally. If one of the items in the listview experiences a long
|
||||
* press event, the contents of its current visible state are captured as a
|
||||
* bitmap and its visibility is set to INVISIBLE. A hover cell is then created
|
||||
* and added to this layout as an overlaying BitmapDrawable above the listview.
|
||||
* Once the hover cell is translated some distance to signify an item swap, a
|
||||
* data set change accompanied by animation takes place. When the user releases
|
||||
* the hover cell, it animates into its corresponding position in the listview.
|
||||
*
|
||||
* When the hover cell is either above or below the bounds of the listview, this
|
||||
* listview also scrolls on its own so as to reveal additional content.
|
||||
*/
|
||||
public class DynamicListView extends ListView {
|
||||
|
||||
private final int SMOOTH_SCROLL_AMOUNT_AT_EDGE = 15;
|
||||
private final int MOVE_DURATION = 150;
|
||||
private final int LINE_THICKNESS = 15;
|
||||
|
||||
private int mLastEventY = -1;
|
||||
|
||||
private int mDownY = -1;
|
||||
private int mDownX = -1;
|
||||
|
||||
private int mTotalOffset = 0;
|
||||
|
||||
private boolean mCellIsMobile = false;
|
||||
private boolean mIsMobileScrolling = false;
|
||||
private int mSmoothScrollAmountAtEdge = 0;
|
||||
|
||||
private final int INVALID_ID = -1;
|
||||
private long mAboveItemId = INVALID_ID;
|
||||
private long mMobileItemId = INVALID_ID;
|
||||
private long mBelowItemId = INVALID_ID;
|
||||
|
||||
private BitmapDrawable mHoverCell;
|
||||
private Rect mHoverCellCurrentBounds;
|
||||
private Rect mHoverCellOriginalBounds;
|
||||
|
||||
private final int INVALID_POINTER_ID = -1;
|
||||
private int mActivePointerId = INVALID_POINTER_ID;
|
||||
|
||||
private boolean mIsWaitingForScrollFinish = false;
|
||||
private int mScrollState = OnScrollListener.SCROLL_STATE_IDLE;
|
||||
|
||||
/**
|
||||
* Listens for long clicks on any items in the listview. When a cell has
|
||||
* been selected, the hover cell is created and set up.
|
||||
*/
|
||||
private final AdapterView.OnItemLongClickListener mOnItemLongClickListener = new AdapterView.OnItemLongClickListener() {
|
||||
@Override
|
||||
public boolean onItemLongClick(final AdapterView<?> arg0, final View arg1, final int pos, final long id) {
|
||||
mTotalOffset = 0;
|
||||
|
||||
final int position = pointToPosition(mDownX, mDownY);
|
||||
final int itemNum = position - getFirstVisiblePosition();
|
||||
|
||||
final View selectedView = getChildAt(itemNum);
|
||||
mMobileItemId = getAdapter().getItemId(position);
|
||||
mHoverCell = getAndAddHoverView(selectedView);
|
||||
selectedView.setVisibility(INVISIBLE);
|
||||
|
||||
mCellIsMobile = true;
|
||||
|
||||
updateNeighborViewsForID(mMobileItemId);
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This TypeEvaluator is used to animate the BitmapDrawable back to its
|
||||
* final location when the user lifts his finger by modifying the
|
||||
* BitmapDrawable's bounds.
|
||||
*/
|
||||
private final static TypeEvaluator<Rect> sBoundEvaluator = new TypeEvaluator<Rect>() {
|
||||
@Override
|
||||
public Rect evaluate(final float fraction, final Rect startValue, final Rect endValue) {
|
||||
return new Rect(interpolate(startValue.left, endValue.left, fraction), interpolate(startValue.top,
|
||||
endValue.top, fraction), interpolate(startValue.right, endValue.right, fraction), interpolate(
|
||||
startValue.bottom, endValue.bottom, fraction));
|
||||
}
|
||||
|
||||
public int interpolate(final int start, final int end, final float fraction) {
|
||||
return (int) (start + fraction * (end - start));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This scroll listener is added to the listview in order to handle cell
|
||||
* swapping when the cell is either at the top or bottom edge of the
|
||||
* listview. If the hover cell is at either edge of the listview, the
|
||||
* listview will begin scrolling. As scrolling takes place, the listview
|
||||
* continuously checks if new cells became visible and determines whether
|
||||
* they are potential candidates for a cell swap.
|
||||
*/
|
||||
private final AbsListView.OnScrollListener mScrollListener = new AbsListView.OnScrollListener() {
|
||||
|
||||
private int mPreviousFirstVisibleItem = -1;
|
||||
private int mPreviousVisibleItemCount = -1;
|
||||
private int mCurrentFirstVisibleItem;
|
||||
private int mCurrentVisibleItemCount;
|
||||
private int mCurrentScrollState;
|
||||
|
||||
/**
|
||||
* Determines if the listview scrolled up enough to reveal a new cell at
|
||||
* the top of the list. If so, then the appropriate parameters are
|
||||
* updated.
|
||||
*/
|
||||
public void checkAndHandleFirstVisibleCellChange() {
|
||||
if (mCurrentFirstVisibleItem != mPreviousFirstVisibleItem) {
|
||||
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
|
||||
updateNeighborViewsForID(mMobileItemId);
|
||||
handleCellSwitch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the listview scrolled down enough to reveal a new cell
|
||||
* at the bottom of the list. If so, then the appropriate parameters are
|
||||
* updated.
|
||||
*/
|
||||
public void checkAndHandleLastVisibleCellChange() {
|
||||
final int currentLastVisibleItem = mCurrentFirstVisibleItem + mCurrentVisibleItemCount;
|
||||
final int previousLastVisibleItem = mPreviousFirstVisibleItem + mPreviousVisibleItemCount;
|
||||
if (currentLastVisibleItem != previousLastVisibleItem) {
|
||||
if (mCellIsMobile && mMobileItemId != INVALID_ID) {
|
||||
updateNeighborViewsForID(mMobileItemId);
|
||||
handleCellSwitch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScroll(final AbsListView view, final int firstVisibleItem, final int visibleItemCount,
|
||||
final int totalItemCount) {
|
||||
mCurrentFirstVisibleItem = firstVisibleItem;
|
||||
mCurrentVisibleItemCount = visibleItemCount;
|
||||
|
||||
mPreviousFirstVisibleItem = mPreviousFirstVisibleItem == -1 ? mCurrentFirstVisibleItem
|
||||
: mPreviousFirstVisibleItem;
|
||||
mPreviousVisibleItemCount = mPreviousVisibleItemCount == -1 ? mCurrentVisibleItemCount
|
||||
: mPreviousVisibleItemCount;
|
||||
|
||||
checkAndHandleFirstVisibleCellChange();
|
||||
checkAndHandleLastVisibleCellChange();
|
||||
|
||||
mPreviousFirstVisibleItem = mCurrentFirstVisibleItem;
|
||||
mPreviousVisibleItemCount = mCurrentVisibleItemCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScrollStateChanged(final AbsListView view, final int scrollState) {
|
||||
mCurrentScrollState = scrollState;
|
||||
mScrollState = scrollState;
|
||||
isScrollCompleted();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is in charge of invoking 1 of 2 actions. Firstly, if the
|
||||
* listview is in a state of scrolling invoked by the hover cell being
|
||||
* outside the bounds of the listview, then this scrolling event is
|
||||
* continued. Secondly, if the hover cell has already been released,
|
||||
* this invokes the animation for the hover cell to return to its
|
||||
* correct position after the listview has entered an idle scroll state.
|
||||
*/
|
||||
private void isScrollCompleted() {
|
||||
if (mCurrentVisibleItemCount > 0 && mCurrentScrollState == SCROLL_STATE_IDLE) {
|
||||
if (mCellIsMobile && mIsMobileScrolling) {
|
||||
handleMobileCellScroll();
|
||||
} else if (mIsWaitingForScrollFinish) {
|
||||
touchEventsEnded();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public DynamicListView(final Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public DynamicListView(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public DynamicListView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
init(context);
|
||||
}
|
||||
|
||||
/** Retrieves the position in the list corresponding to itemID */
|
||||
public int getPositionForID(final long itemID) {
|
||||
final View v = getViewForID(itemID);
|
||||
if (v == null)
|
||||
return -1;
|
||||
else
|
||||
return getPositionForView(v);
|
||||
}
|
||||
|
||||
/** Retrieves the view in the list corresponding to itemID */
|
||||
public View getViewForID(final long itemID) {
|
||||
final int firstVisiblePosition = getFirstVisiblePosition();
|
||||
final ListAdapter adapter = getAdapter();
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
final View v = getChildAt(i);
|
||||
final int position = firstVisiblePosition + i;
|
||||
final long id = adapter.getItemId(position);
|
||||
if (id == itemID) return v;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is in charge of determining if the hover cell is above or
|
||||
* below the bounds of the listview. If so, the listview does an appropriate
|
||||
* upward or downward smooth scroll so as to reveal new items.
|
||||
*/
|
||||
public boolean handleMobileCellScroll(final Rect r) {
|
||||
final int offset = computeVerticalScrollOffset();
|
||||
final int height = getHeight();
|
||||
final int extent = computeVerticalScrollExtent();
|
||||
final int range = computeVerticalScrollRange();
|
||||
final int hoverViewTop = r.top;
|
||||
final int hoverHeight = r.height();
|
||||
|
||||
if (hoverViewTop <= 0 && offset > 0) {
|
||||
smoothScrollBy(-mSmoothScrollAmountAtEdge, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (hoverViewTop + hoverHeight >= height && offset + extent < range) {
|
||||
smoothScrollBy(mSmoothScrollAmountAtEdge, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void init(final Context context) {
|
||||
setOnItemLongClickListener(mOnItemLongClickListener);
|
||||
setOnScrollListener(mScrollListener);
|
||||
final DisplayMetrics metrics = context.getResources().getDisplayMetrics();
|
||||
mSmoothScrollAmountAtEdge = (int) (SMOOTH_SCROLL_AMOUNT_AT_EDGE / metrics.density);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(final MotionEvent event) {
|
||||
|
||||
switch (event.getAction() & MotionEvent.ACTION_MASK) {
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
mDownX = (int) event.getX();
|
||||
mDownY = (int) event.getY();
|
||||
mActivePointerId = event.getPointerId(0);
|
||||
break;
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if (mActivePointerId == INVALID_POINTER_ID) {
|
||||
break;
|
||||
}
|
||||
|
||||
int pointerIndex = event.findPointerIndex(mActivePointerId);
|
||||
|
||||
mLastEventY = (int) event.getY(pointerIndex);
|
||||
final int deltaY = mLastEventY - mDownY;
|
||||
|
||||
if (mCellIsMobile) {
|
||||
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mHoverCellOriginalBounds.top
|
||||
+ deltaY + mTotalOffset);
|
||||
mHoverCell.setBounds(mHoverCellCurrentBounds);
|
||||
invalidate();
|
||||
|
||||
handleCellSwitch();
|
||||
|
||||
mIsMobileScrolling = false;
|
||||
handleMobileCellScroll();
|
||||
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
touchEventsEnded();
|
||||
break;
|
||||
case MotionEvent.ACTION_CANCEL:
|
||||
touchEventsCancelled();
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
/*
|
||||
* If a multitouch event took place and the original touch
|
||||
* dictating the movement of the hover cell has ended, then the
|
||||
* dragging event ends and the hover cell is animated to its
|
||||
* corresponding position in the listview.
|
||||
*/
|
||||
pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
|
||||
final int pointerId = event.getPointerId(pointerIndex);
|
||||
if (pointerId == mActivePointerId) {
|
||||
touchEventsEnded();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAdapter(final ListAdapter adapter) {
|
||||
if (!(adapter instanceof DraggableAdapter))
|
||||
throw new IllegalArgumentException("Adapter have to implement DraggableAdapter");
|
||||
super.setAdapter(adapter);
|
||||
}
|
||||
|
||||
/**
|
||||
* dispatchDraw gets invoked when all the child views are about to be drawn.
|
||||
* By overriding this method, the hover cell (BitmapDrawable) can be drawn
|
||||
* over the listview's items whenever the listview is redrawn.
|
||||
*/
|
||||
@Override
|
||||
protected void dispatchDraw(final Canvas canvas) {
|
||||
super.dispatchDraw(canvas);
|
||||
if (mHoverCell != null) {
|
||||
mHoverCell.draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the hover cell with the appropriate bitmap and of appropriate
|
||||
* size. The hover cell's BitmapDrawable is drawn on top of the bitmap every
|
||||
* single time an invalidate call is made.
|
||||
*/
|
||||
private BitmapDrawable getAndAddHoverView(final View v) {
|
||||
|
||||
final int w = v.getWidth();
|
||||
final int h = v.getHeight();
|
||||
final int top = v.getTop();
|
||||
final int left = v.getLeft();
|
||||
|
||||
final Bitmap b = getBitmapWithBorder(v);
|
||||
|
||||
final BitmapDrawable drawable = new BitmapDrawable(getResources(), b);
|
||||
|
||||
mHoverCellOriginalBounds = new Rect(left, top, left + w, top + h);
|
||||
mHoverCellCurrentBounds = new Rect(mHoverCellOriginalBounds);
|
||||
|
||||
drawable.setBounds(mHoverCellCurrentBounds);
|
||||
|
||||
return drawable;
|
||||
}
|
||||
|
||||
/** Returns a bitmap showing a screenshot of the view passed in. */
|
||||
private Bitmap getBitmapFromView(final View v) {
|
||||
final Bitmap bitmap = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
|
||||
final Canvas canvas = new Canvas(bitmap);
|
||||
v.draw(canvas);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/** Draws a black border over the screenshot of the view passed in. */
|
||||
private Bitmap getBitmapWithBorder(final View v) {
|
||||
final Bitmap bitmap = getBitmapFromView(v);
|
||||
final Canvas can = new Canvas(bitmap);
|
||||
|
||||
final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
|
||||
|
||||
final Paint paint = new Paint();
|
||||
paint.setStyle(Paint.Style.STROKE);
|
||||
paint.setStrokeWidth(LINE_THICKNESS);
|
||||
paint.setColor(Color.BLACK);
|
||||
|
||||
can.drawBitmap(bitmap, 0, 0, null);
|
||||
can.drawRect(rect, paint);
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method determines whether the hover cell has been shifted far enough
|
||||
* to invoke a cell swap. If so, then the respective cell swap candidate is
|
||||
* determined and the data set is changed. Upon posting a notification of
|
||||
* the data set change, a layout is invoked to place the cells in the right
|
||||
* place. Using a ViewTreeObserver and a corresponding OnPreDrawListener, we
|
||||
* can offset the cell being swapped to where it previously was and then
|
||||
* animate it to its new position.
|
||||
*/
|
||||
private void handleCellSwitch() {
|
||||
final int deltaY = mLastEventY - mDownY;
|
||||
final int deltaYTotal = mHoverCellOriginalBounds.top + mTotalOffset + deltaY;
|
||||
|
||||
final View belowView = getViewForID(mBelowItemId);
|
||||
final View mobileView = getViewForID(mMobileItemId);
|
||||
final View aboveView = getViewForID(mAboveItemId);
|
||||
|
||||
final boolean isBelow = belowView != null && deltaYTotal > belowView.getTop();
|
||||
final boolean isAbove = aboveView != null && deltaYTotal < aboveView.getTop();
|
||||
|
||||
if (isBelow || isAbove) {
|
||||
|
||||
final long switchItemID = isBelow ? mBelowItemId : mAboveItemId;
|
||||
final View switchView = isBelow ? belowView : aboveView;
|
||||
final int originalItem = getPositionForView(mobileView);
|
||||
|
||||
if (switchView == null) {
|
||||
updateNeighborViewsForID(mMobileItemId);
|
||||
return;
|
||||
}
|
||||
|
||||
final int newItemPosition = getPositionForID(switchItemID);
|
||||
((DraggableAdapter) getAdapter()).swapElements(originalItem, newItemPosition);
|
||||
|
||||
mDownY = mLastEventY;
|
||||
|
||||
final int switchViewStartTop = switchView.getTop();
|
||||
|
||||
mobileView.setVisibility(View.VISIBLE);
|
||||
switchView.setVisibility(View.INVISIBLE);
|
||||
|
||||
updateNeighborViewsForID(mMobileItemId);
|
||||
|
||||
final ViewTreeObserver observer = getViewTreeObserver();
|
||||
observer.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
|
||||
@Override
|
||||
public boolean onPreDraw() {
|
||||
observer.removeOnPreDrawListener(this);
|
||||
|
||||
final View switchView = getViewForID(switchItemID);
|
||||
|
||||
mTotalOffset += deltaY;
|
||||
|
||||
final int switchViewNewTop = switchView.getTop();
|
||||
final int delta = switchViewStartTop - switchViewNewTop;
|
||||
|
||||
switchView.setTranslationY(delta);
|
||||
|
||||
final ObjectAnimator animator = ObjectAnimator.ofFloat(switchView, View.TRANSLATION_Y, 0);
|
||||
animator.setDuration(MOVE_DURATION);
|
||||
animator.start();
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this listview is in a scrolling state invoked by the
|
||||
* fact that the hover cell is out of the bounds of the listview;
|
||||
*/
|
||||
private void handleMobileCellScroll() {
|
||||
mIsMobileScrolling = handleMobileCellScroll(mHoverCellCurrentBounds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all the appropriate fields to a default state.
|
||||
*/
|
||||
private void touchEventsCancelled() {
|
||||
final View mobileView = getViewForID(mMobileItemId);
|
||||
if (mCellIsMobile) {
|
||||
mAboveItemId = INVALID_ID;
|
||||
mMobileItemId = INVALID_ID;
|
||||
mBelowItemId = INVALID_ID;
|
||||
mobileView.setVisibility(VISIBLE);
|
||||
mHoverCell = null;
|
||||
invalidate();
|
||||
}
|
||||
mCellIsMobile = false;
|
||||
mIsMobileScrolling = false;
|
||||
mActivePointerId = INVALID_POINTER_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all the appropriate fields to a default state while also animating
|
||||
* the hover cell back to its correct location.
|
||||
*/
|
||||
private void touchEventsEnded() {
|
||||
final View mobileView = getViewForID(mMobileItemId);
|
||||
if (mCellIsMobile || mIsWaitingForScrollFinish) {
|
||||
mCellIsMobile = false;
|
||||
mIsWaitingForScrollFinish = false;
|
||||
mIsMobileScrolling = false;
|
||||
mActivePointerId = INVALID_POINTER_ID;
|
||||
|
||||
// If the autoscroller has not completed scrolling, we need to wait
|
||||
// for it to
|
||||
// finish in order to determine the final location of where the
|
||||
// hover cell
|
||||
// should be animated to.
|
||||
if (mScrollState != OnScrollListener.SCROLL_STATE_IDLE) {
|
||||
mIsWaitingForScrollFinish = true;
|
||||
return;
|
||||
}
|
||||
|
||||
mHoverCellCurrentBounds.offsetTo(mHoverCellOriginalBounds.left, mobileView.getTop());
|
||||
|
||||
final ObjectAnimator hoverViewAnimator = ObjectAnimator.ofObject(mHoverCell, "bounds", sBoundEvaluator,
|
||||
mHoverCellCurrentBounds);
|
||||
hoverViewAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
|
||||
@Override
|
||||
public void onAnimationUpdate(final ValueAnimator valueAnimator) {
|
||||
invalidate();
|
||||
}
|
||||
});
|
||||
hoverViewAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(final Animator animation) {
|
||||
mAboveItemId = INVALID_ID;
|
||||
mMobileItemId = INVALID_ID;
|
||||
mBelowItemId = INVALID_ID;
|
||||
mobileView.setVisibility(VISIBLE);
|
||||
mHoverCell = null;
|
||||
setEnabled(true);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationStart(final Animator animation) {
|
||||
setEnabled(false);
|
||||
}
|
||||
});
|
||||
hoverViewAnimator.start();
|
||||
} else {
|
||||
touchEventsCancelled();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores a reference to the views above and below the item currently
|
||||
* corresponding to the hover cell. It is important to note that if this
|
||||
* item is either at the top or bottom of the list, mAboveItemId or
|
||||
* mBelowItemId may be invalid.
|
||||
*/
|
||||
private void updateNeighborViewsForID(final long itemID) {
|
||||
final int position = getPositionForID(itemID);
|
||||
final ListAdapter adapter = getAdapter();
|
||||
mAboveItemId = adapter.getItemId(position - 1);
|
||||
mBelowItemId = adapter.getItemId(position + 1);
|
||||
}
|
||||
}
|
@ -20,10 +20,7 @@
|
||||
package org.mariotaku.twidere.activity;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.Resources.Theme;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.NavUtils;
|
||||
|
||||
import org.mariotaku.twidere.activity.iface.IThemedActivity;
|
||||
import org.mariotaku.twidere.util.CompareUtils;
|
||||
|
@ -29,96 +29,95 @@ import java.io.File;
|
||||
|
||||
public class CameraCropActivity extends Activity {
|
||||
|
||||
private static final int REQUEST_TAKE_PHOTO = 1;
|
||||
private static final int REQUEST_CROP_IMAGE = 2;
|
||||
private static final int REQUEST_TAKE_PHOTO = 1;
|
||||
private static final int REQUEST_CROP_IMAGE = 2;
|
||||
|
||||
private Uri mImageUri;
|
||||
private Uri mImageUriUncropped;
|
||||
private Uri mImageUri;
|
||||
private Uri mImageUriUncropped;
|
||||
|
||||
public static final String INTENT_ACTION = "org.mariotaku.twidere.CAMERA_CROP";
|
||||
public static final String INTENT_ACTION = "org.mariotaku.twidere.CAMERA_CROP";
|
||||
|
||||
public static final String EXTRA_OUTPUT_X = "outputX";
|
||||
public static final String EXTRA_OUTPUT_Y = "outputY";
|
||||
public static final String EXTRA_ASPECT_X = "aspectX";
|
||||
public static final String EXTRA_ASPECT_Y = "aspectY";
|
||||
public static final String EXTRA_SCALE_UP_IF_NEEDED = "scaleUpIfNeeded";
|
||||
public static final String EXTRA_OUTPUT_X = "outputX";
|
||||
public static final String EXTRA_OUTPUT_Y = "outputY";
|
||||
public static final String EXTRA_ASPECT_X = "aspectX";
|
||||
public static final String EXTRA_ASPECT_Y = "aspectY";
|
||||
public static final String EXTRA_SCALE_UP_IF_NEEDED = "scaleUpIfNeeded";
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
if (mImageUriUncropped != null) {
|
||||
final String path = mImageUriUncropped.getPath();
|
||||
if (path != null) {
|
||||
new File(path).delete();
|
||||
}
|
||||
}
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
switch (requestCode) {
|
||||
case REQUEST_TAKE_PHOTO: {
|
||||
if (mImageUriUncropped == null) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final Intent intent = getIntent();
|
||||
final int aspectX = intent.getIntExtra(EXTRA_ASPECT_X, 1), aspectY = intent.getIntExtra(EXTRA_ASPECT_Y,
|
||||
1);
|
||||
final int outputX = intent.getIntExtra(EXTRA_OUTPUT_X, 512), outputY = intent.getIntExtra(
|
||||
EXTRA_OUTPUT_Y, 512);
|
||||
final boolean scaleUpIfNeeded = intent.getBooleanExtra(EXTRA_SCALE_UP_IF_NEEDED, false);
|
||||
final Intent crop_intent = new Intent("com.android.camera.action.CROP");
|
||||
crop_intent.setDataAndType(mImageUriUncropped, "image/*");
|
||||
crop_intent.putExtra(EXTRA_OUTPUT_X, outputX);
|
||||
crop_intent.putExtra(EXTRA_OUTPUT_Y, outputY);
|
||||
crop_intent.putExtra(EXTRA_ASPECT_X, aspectX);
|
||||
crop_intent.putExtra(EXTRA_ASPECT_Y, aspectY);
|
||||
crop_intent.putExtra("scale", true);
|
||||
crop_intent.putExtra("crop", "true");
|
||||
crop_intent.putExtra("scaleUpIfNeeded", scaleUpIfNeeded);
|
||||
crop_intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
|
||||
try {
|
||||
startActivityForResult(crop_intent, REQUEST_CROP_IMAGE);
|
||||
} catch (final Exception e) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REQUEST_CROP_IMAGE: {
|
||||
if (mImageUriUncropped != null) {
|
||||
final String path = mImageUriUncropped.getPath();
|
||||
if (path != null) {
|
||||
new File(path).delete();
|
||||
}
|
||||
}
|
||||
final Intent intent = new Intent();
|
||||
intent.setData(mImageUri);
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
if (mImageUriUncropped != null) {
|
||||
final String path = mImageUriUncropped.getPath();
|
||||
if (path != null) {
|
||||
new File(path).delete();
|
||||
}
|
||||
}
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
switch (requestCode) {
|
||||
case REQUEST_TAKE_PHOTO: {
|
||||
if (mImageUriUncropped == null) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final Intent intent = getIntent();
|
||||
final int aspectX = intent.getIntExtra(EXTRA_ASPECT_X, 1), aspectY = intent.getIntExtra(EXTRA_ASPECT_Y,
|
||||
1);
|
||||
final int outputX = intent.getIntExtra(EXTRA_OUTPUT_X, 512), outputY = intent.getIntExtra(
|
||||
EXTRA_OUTPUT_Y, 512);
|
||||
final boolean scaleUpIfNeeded = intent.getBooleanExtra(EXTRA_SCALE_UP_IF_NEEDED, false);
|
||||
final Intent crop_intent = new Intent("com.android.camera.action.CROP");
|
||||
crop_intent.setDataAndType(mImageUriUncropped, "image/*");
|
||||
crop_intent.putExtra(EXTRA_OUTPUT_X, outputX);
|
||||
crop_intent.putExtra(EXTRA_OUTPUT_Y, outputY);
|
||||
crop_intent.putExtra(EXTRA_ASPECT_X, aspectX);
|
||||
crop_intent.putExtra(EXTRA_ASPECT_Y, aspectY);
|
||||
crop_intent.putExtra("scale", true);
|
||||
crop_intent.putExtra("crop", "true");
|
||||
crop_intent.putExtra("scaleUpIfNeeded", scaleUpIfNeeded);
|
||||
crop_intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUri);
|
||||
try {
|
||||
startActivityForResult(crop_intent, REQUEST_CROP_IMAGE);
|
||||
} catch (final Exception e) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REQUEST_CROP_IMAGE: {
|
||||
if (mImageUriUncropped != null) {
|
||||
final String path = mImageUriUncropped.getPath();
|
||||
if (path != null) {
|
||||
new File(path).delete();
|
||||
}
|
||||
}
|
||||
final Intent intent = new Intent();
|
||||
intent.setData(mImageUri);
|
||||
setResult(RESULT_OK, intent);
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final Intent intent = getIntent();
|
||||
try {
|
||||
mImageUri = intent.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
|
||||
mImageUriUncropped = Uri.parse(mImageUri.toString() + "_uncropped");
|
||||
final Intent camera_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUriUncropped);
|
||||
startActivityForResult(camera_intent, REQUEST_TAKE_PHOTO);
|
||||
} catch (final Exception e) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final Intent intent = getIntent();
|
||||
try {
|
||||
mImageUri = intent.getParcelableExtra(MediaStore.EXTRA_OUTPUT);
|
||||
mImageUriUncropped = Uri.parse(mImageUri.toString() + "_uncropped");
|
||||
final Intent camera_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, mImageUriUncropped);
|
||||
startActivityForResult(camera_intent, REQUEST_TAKE_PHOTO);
|
||||
} catch (final Exception e) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -524,7 +524,7 @@ public class SettingsWizardActivity extends Activity implements Constants {
|
||||
if (wasConfigured(tabs)) return true;
|
||||
Collections.sort(tabs);
|
||||
int i = 0;
|
||||
final List<ContentValues> values_list = new ArrayList<ContentValues>();
|
||||
final List<ContentValues> values_list = new ArrayList<>();
|
||||
for (final String type : DEFAULT_TAB_TYPES) {
|
||||
final ContentValues values = new ContentValues();
|
||||
final CustomTabConfiguration conf = CustomTabUtils.getTabConfiguration(type);
|
||||
|
@ -90,7 +90,6 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants {
|
||||
intent.setClassName(activityInfo.packageName, activityInfo.name);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,8 +19,6 @@
|
||||
|
||||
package org.mariotaku.twidere.activity.iface;
|
||||
|
||||
import android.content.res.Resources;
|
||||
|
||||
public interface IThemedActivity {
|
||||
|
||||
int getCurrentThemeBackgroundAlpha();
|
||||
|
@ -50,7 +50,7 @@ public class APIEditorActivity extends BaseSupportDialogActivity implements Twit
|
||||
private CheckBox mEditSameOAuthSigningUrl, mEditNoVersionSuffix;
|
||||
private EditText mEditConsumerKey, mEditConsumerSecret;
|
||||
private RadioGroup mEditAuthType;
|
||||
private RadioButton mButtonOAuth, mButtonxAuth, mButtonBasic, mButtonTwipOMode;
|
||||
private RadioButton mButtonOAuth, mButtonXAuth, mButtonBasic, mButtonTWIPOMode;
|
||||
private Button mSaveButton;
|
||||
private View mAPIFormatHelpButton;
|
||||
private boolean mEditNoVersionSuffixChanged;
|
||||
@ -93,9 +93,9 @@ public class APIEditorActivity extends BaseSupportDialogActivity implements Twit
|
||||
mEditAPIUrlFormat = (EditText) findViewById(R.id.api_url_format);
|
||||
mEditAuthType = (RadioGroup) findViewById(R.id.auth_type);
|
||||
mButtonOAuth = (RadioButton) findViewById(R.id.oauth);
|
||||
mButtonxAuth = (RadioButton) findViewById(R.id.xauth);
|
||||
mButtonXAuth = (RadioButton) findViewById(R.id.xauth);
|
||||
mButtonBasic = (RadioButton) findViewById(R.id.basic);
|
||||
mButtonTwipOMode = (RadioButton) findViewById(R.id.twip_o);
|
||||
mButtonTWIPOMode = (RadioButton) findViewById(R.id.twip_o);
|
||||
mEditSameOAuthSigningUrl = (CheckBox) findViewById(R.id.same_oauth_signing_url);
|
||||
mEditNoVersionSuffix = (CheckBox) findViewById(R.id.no_version_suffix);
|
||||
mEditConsumerKey = (EditText) findViewById(R.id.consumer_key);
|
||||
@ -188,9 +188,9 @@ public class APIEditorActivity extends BaseSupportDialogActivity implements Twit
|
||||
mEditConsumerSecret.setText(consumerSecret);
|
||||
|
||||
mButtonOAuth.setChecked(authType == Accounts.AUTH_TYPE_OAUTH);
|
||||
mButtonxAuth.setChecked(authType == Accounts.AUTH_TYPE_XAUTH);
|
||||
mButtonXAuth.setChecked(authType == Accounts.AUTH_TYPE_XAUTH);
|
||||
mButtonBasic.setChecked(authType == Accounts.AUTH_TYPE_BASIC);
|
||||
mButtonTwipOMode.setChecked(authType == Accounts.AUTH_TYPE_TWIP_O_MODE);
|
||||
mButtonTWIPOMode.setChecked(authType == Accounts.AUTH_TYPE_TWIP_O_MODE);
|
||||
if (mEditAuthType.getCheckedRadioButtonId() == -1) {
|
||||
mButtonOAuth.setChecked(true);
|
||||
}
|
||||
|
@ -31,10 +31,8 @@ import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.activity.iface.IControlBarActivity;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
||||
import org.mariotaku.twidere.fragment.iface.IBasePullToRefreshFragment;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
||||
import org.mariotaku.twidere.util.MessagesManager;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.view.iface.IExtendedView.OnFitSystemWindowsListener;
|
||||
|
||||
@ -45,15 +43,12 @@ public class BaseActionBarActivity extends ThemedActionBarActivity implements Co
|
||||
OnFitSystemWindowsListener, SystemWindowsInsetsCallback, IControlBarActivity,
|
||||
ShortcutCallback {
|
||||
|
||||
private boolean mInstanceStateSaved, mIsVisible, mIsOnTop;
|
||||
private boolean mInstanceStateSaved;
|
||||
private boolean mIsVisible;
|
||||
|
||||
private Rect mSystemWindowsInsets;
|
||||
private ArrayList<ControlBarOffsetListener> mControlBarOffsetListeners = new ArrayList<>();
|
||||
|
||||
public MessagesManager getMessagesManager() {
|
||||
return getTwidereApplication() != null ? getTwidereApplication().getMessagesManager() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getSystemWindowsInsets(Rect insets) {
|
||||
if (mSystemWindowsInsets == null) return false;
|
||||
@ -79,10 +74,6 @@ public class BaseActionBarActivity extends ThemedActionBarActivity implements Co
|
||||
return getTwidereApplication() != null ? getTwidereApplication().getTwitterWrapper() : null;
|
||||
}
|
||||
|
||||
public boolean isOnTop() {
|
||||
return mIsOnTop;
|
||||
}
|
||||
|
||||
public boolean isVisible() {
|
||||
return mIsVisible;
|
||||
}
|
||||
@ -126,10 +117,6 @@ public class BaseActionBarActivity extends ThemedActionBarActivity implements Co
|
||||
super.startActivity(intent);
|
||||
}
|
||||
|
||||
protected IBasePullToRefreshFragment getCurrentPullToRefreshFragment() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||
return false;
|
||||
@ -153,22 +140,16 @@ public class BaseActionBarActivity extends ThemedActionBarActivity implements Co
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
mIsVisible = true;
|
||||
final MessagesManager manager = getMessagesManager();
|
||||
if (manager != null) {
|
||||
manager.addMessageCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
mInstanceStateSaved = false;
|
||||
mIsOnTop = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
mIsOnTop = false;
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@ -186,10 +167,6 @@ public class BaseActionBarActivity extends ThemedActionBarActivity implements Co
|
||||
@Override
|
||||
protected void onStop() {
|
||||
mIsVisible = false;
|
||||
final MessagesManager manager = getMessagesManager();
|
||||
if (manager != null) {
|
||||
manager.removeMessageCallback(this);
|
||||
}
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,6 @@ import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
@ -44,9 +44,7 @@ import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.NotificationCompat;
|
||||
@ -63,6 +61,7 @@ import android.support.v7.widget.RecyclerView.ItemDecoration;
|
||||
import android.support.v7.widget.RecyclerView.State;
|
||||
import android.support.v7.widget.RecyclerView.ViewHolder;
|
||||
import android.text.Editable;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.ActionMode;
|
||||
@ -135,7 +134,6 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import static android.os.Environment.getExternalStorageState;
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.ParseUtils.parseString;
|
||||
import static org.mariotaku.twidere.util.ThemeUtils.getComposeThemeResource;
|
||||
@ -148,22 +146,17 @@ import static org.mariotaku.twidere.util.Utils.getDefaultTextSize;
|
||||
import static org.mariotaku.twidere.util.Utils.getImageUploadStatus;
|
||||
import static org.mariotaku.twidere.util.Utils.getQuoteStatus;
|
||||
import static org.mariotaku.twidere.util.Utils.getShareStatus;
|
||||
import static org.mariotaku.twidere.util.Utils.showErrorMessage;
|
||||
import static org.mariotaku.twidere.util.Utils.showMenuItemToast;
|
||||
|
||||
public class ComposeActivity extends ThemedFragmentActivity implements TextWatcher, LocationListener,
|
||||
OnMenuItemClickListener, OnClickListener, OnEditorActionListener, OnLongClickListener, Callback {
|
||||
|
||||
private static final String FAKE_IMAGE_LINK = "https://www.example.com/fake_image.jpg";
|
||||
|
||||
private static final String EXTRA_IS_POSSIBLY_SENSITIVE = "is_possibly_sensitive";
|
||||
|
||||
private static final String EXTRA_SHOULD_SAVE_ACCOUNTS = "should_save_accounts";
|
||||
|
||||
private static final String EXTRA_ORIGINAL_TEXT = "original_text";
|
||||
|
||||
private static final String EXTRA_TEMP_URI = "temp_uri";
|
||||
private static final String EXTRA_SHARE_SCREENSHOT = "share_screenshot";
|
||||
|
||||
private final Extractor mExtractor = new Extractor();
|
||||
private final Rect mWindowDecorHitRect = new Rect();
|
||||
private TwidereValidator mValidator;
|
||||
@ -182,7 +175,6 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
private View mAccountSelectorContainer;
|
||||
private MediaPreviewAdapter mMediaPreviewAdapter;
|
||||
private boolean mIsPossiblySensitive, mShouldSaveAccounts;
|
||||
private Uri mTempPhotoUri;
|
||||
private boolean mImageUploaderUsed, mStatusShortenerUsed;
|
||||
private ParcelableStatus mInReplyToStatus;
|
||||
private ParcelableUser mMentionUser;
|
||||
@ -269,7 +261,6 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
outState.putParcelable(EXTRA_DRAFT, mDraftItem);
|
||||
outState.putBoolean(EXTRA_SHOULD_SAVE_ACCOUNTS, mShouldSaveAccounts);
|
||||
outState.putString(EXTRA_ORIGINAL_TEXT, mOriginalText);
|
||||
outState.putParcelable(EXTRA_TEMP_URI, mTempPhotoUri);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@ -296,27 +287,13 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
@Override
|
||||
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
|
||||
switch (requestCode) {
|
||||
case REQUEST_TAKE_PHOTO: {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
mTask = AsyncTaskUtils.executeTask(new AddMediaTask(this, mTempPhotoUri,
|
||||
createTempImageUri(), ParcelableMedia.TYPE_IMAGE, true));
|
||||
mTempPhotoUri = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REQUEST_PICK_IMAGE: {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
final Uri src = intent.getData();
|
||||
mTask = AsyncTaskUtils.executeTask(new AddMediaTask(this, src,
|
||||
createTempImageUri(), ParcelableMedia.TYPE_IMAGE, false));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case REQUEST_TAKE_PHOTO:
|
||||
case REQUEST_PICK_IMAGE:
|
||||
case REQUEST_OPEN_DOCUMENT: {
|
||||
if (resultCode == Activity.RESULT_OK) {
|
||||
final Uri src = intent.getData();
|
||||
mTask = AsyncTaskUtils.executeTask(new AddMediaTask(this, src,
|
||||
createTempImageUri(), ParcelableMedia.TYPE_IMAGE, false));
|
||||
createTempImageUri(), ParcelableMedia.TYPE_IMAGE, true));
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -475,9 +452,7 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
}
|
||||
case MENU_ADD_IMAGE:
|
||||
case R.id.add_image_sub_item: {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT || !openDocument()) {
|
||||
pickImage();
|
||||
}
|
||||
pickImage();
|
||||
break;
|
||||
}
|
||||
case MENU_ADD_LOCATION: {
|
||||
@ -679,7 +654,6 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
mDraftItem = savedInstanceState.getParcelable(EXTRA_DRAFT);
|
||||
mShouldSaveAccounts = savedInstanceState.getBoolean(EXTRA_SHOULD_SAVE_ACCOUNTS);
|
||||
mOriginalText = savedInstanceState.getString(EXTRA_ORIGINAL_TEXT);
|
||||
mTempPhotoUri = savedInstanceState.getParcelable(EXTRA_TEMP_URI);
|
||||
} else {
|
||||
// The context was first created
|
||||
final int notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1);
|
||||
@ -778,7 +752,11 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
|
||||
builder.setTicker(getString(R.string.draft_saved));
|
||||
builder.setContentTitle(getString(R.string.draft_saved));
|
||||
builder.setContentText(text);
|
||||
if (TextUtils.isEmpty(text)) {
|
||||
builder.setContentText(getString(R.string.empty_content));
|
||||
} else {
|
||||
builder.setContentText(text);
|
||||
}
|
||||
builder.setSmallIcon(R.drawable.ic_stat_info);
|
||||
builder.setAutoCancel(true);
|
||||
final Intent draftsIntent = new Intent(this, DraftsActivity.class);
|
||||
@ -1019,15 +997,9 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
}
|
||||
|
||||
private boolean pickImage() {
|
||||
final Intent intent = new Intent(Intent.ACTION_PICK);
|
||||
intent.setType("image/*");
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_PICK_IMAGE);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
showErrorMessage(this, null, e, false);
|
||||
return false;
|
||||
}
|
||||
final Intent intent = new Intent(this, ImagePickerActivity.class);
|
||||
intent.setAction(INTENT_ACTION_PICK_IMAGE);
|
||||
startActivityForResult(intent, REQUEST_PICK_IMAGE);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1102,18 +1074,9 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
}
|
||||
|
||||
private boolean takePhoto() {
|
||||
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
if (!getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) return false;
|
||||
final File cache_dir = getExternalCacheDir();
|
||||
final File file = new File(cache_dir, "tmp_photo_" + System.currentTimeMillis());
|
||||
mTempPhotoUri = Uri.fromFile(file);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, mTempPhotoUri);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
showErrorMessage(this, null, e, false);
|
||||
return false;
|
||||
}
|
||||
final Intent intent = new Intent(this, ImagePickerActivity.class);
|
||||
intent.setAction(INTENT_ACTION_TAKE_PHOTO);
|
||||
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1166,7 +1129,6 @@ public class ComposeActivity extends ThemedFragmentActivity implements TextWatch
|
||||
&& (mInReplyToStatus == null || mInReplyToStatusId <= 0)) {
|
||||
mIsPossiblySensitive = false;
|
||||
mShouldSaveAccounts = true;
|
||||
mTempPhotoUri = null;
|
||||
mInReplyToStatus = null;
|
||||
mMentionUser = null;
|
||||
mDraftItem = null;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.mariotaku.twidere.activity.support;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.mariotaku.twidere.activity.support;
|
||||
|
||||
import android.content.res.Resources;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
@ -19,182 +18,167 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class DataImportActivity extends BaseActionBarActivity implements FileSelectorDialogFragment.Callback,
|
||||
DataExportImportTypeSelectorDialogFragment.Callback {
|
||||
DataExportImportTypeSelectorDialogFragment.Callback {
|
||||
|
||||
private ImportSettingsTask mImportSettingsTask;
|
||||
private OpenImportTypeTask mOpenImportTypeTask;
|
||||
private ImportSettingsTask mImportSettingsTask;
|
||||
private OpenImportTypeTask mOpenImportTypeTask;
|
||||
|
||||
@Override
|
||||
public int getThemeResourceId() {
|
||||
return ThemeUtils.getNoDisplayThemeResource(this);
|
||||
}
|
||||
@Override
|
||||
public int getThemeResourceId() {
|
||||
return ThemeUtils.getNoDisplayThemeResource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancelled(final DialogFragment df) {
|
||||
if (!isFinishing()) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onCancelled(final DialogFragment df) {
|
||||
if (!isFinishing()) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismissed(final DialogFragment df) {
|
||||
if (df instanceof DataExportImportTypeSelectorDialogFragment) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onDismissed(final DialogFragment df) {
|
||||
if (df instanceof DataExportImportTypeSelectorDialogFragment) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFilePicked(final File file) {
|
||||
if (file == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final String path = file.getAbsolutePath();
|
||||
if (mOpenImportTypeTask == null || mOpenImportTypeTask.getStatus() != AsyncTask.Status.RUNNING) {
|
||||
mOpenImportTypeTask = new OpenImportTypeTask(this, path);
|
||||
mOpenImportTypeTask.execute();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onFilePicked(final File file) {
|
||||
if (file == null) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final String path = file.getAbsolutePath();
|
||||
if (mOpenImportTypeTask == null || mOpenImportTypeTask.getStatus() != AsyncTask.Status.RUNNING) {
|
||||
mOpenImportTypeTask = new OpenImportTypeTask(this, path);
|
||||
mOpenImportTypeTask.execute();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPositiveButtonClicked(final String path, final int flags) {
|
||||
if (path == null || flags == 0) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (mImportSettingsTask == null || mImportSettingsTask.getStatus() != AsyncTask.Status.RUNNING) {
|
||||
mImportSettingsTask = new ImportSettingsTask(this, path, flags);
|
||||
mImportSettingsTask.execute();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onPositiveButtonClicked(final String path, final int flags) {
|
||||
if (path == null || flags == 0) {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
if (mImportSettingsTask == null || mImportSettingsTask.getStatus() != AsyncTask.Status.RUNNING) {
|
||||
mImportSettingsTask = new ImportSettingsTask(this, path, flags);
|
||||
mImportSettingsTask.execute();
|
||||
}
|
||||
}
|
||||
|
||||
public void showImportTypeDialog(final String path, final Integer flags) {
|
||||
final DialogFragment df = new DataExportImportTypeSelectorDialogFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(EXTRA_PATH, path);
|
||||
args.putString(EXTRA_TITLE, getString(R.string.export_settings_type_dialog_title));
|
||||
if (flags != null) {
|
||||
args.putInt(EXTRA_FLAGS, flags);
|
||||
} else {
|
||||
args.putInt(EXTRA_FLAGS, 0);
|
||||
}
|
||||
df.setArguments(args);
|
||||
df.show(getSupportFragmentManager(), "select_import_type");
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState == null) {
|
||||
final File extStorage = Environment.getExternalStorageDirectory();
|
||||
final String storagePath = extStorage != null ? extStorage.getAbsolutePath() : "/";
|
||||
final FileSelectorDialogFragment f = new FileSelectorDialogFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(EXTRA_ACTION, INTENT_ACTION_PICK_FILE);
|
||||
args.putString(EXTRA_PATH, storagePath);
|
||||
f.setArguments(args);
|
||||
f.show(getSupportFragmentManager(), "select_file");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
static class ImportSettingsTask extends AsyncTask<Object, Object, Boolean> {
|
||||
private static final String FRAGMENT_TAG = "import_settings_dialog";
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (savedInstanceState == null) {
|
||||
final File extStorage = Environment.getExternalStorageDirectory();
|
||||
final String storagePath = extStorage != null ? extStorage.getAbsolutePath() : "/";
|
||||
final FileSelectorDialogFragment f = new FileSelectorDialogFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(EXTRA_ACTION, INTENT_ACTION_PICK_FILE);
|
||||
args.putString(EXTRA_PATH, storagePath);
|
||||
f.setArguments(args);
|
||||
f.show(getSupportFragmentManager(), "select_file");
|
||||
}
|
||||
}
|
||||
private final DataImportActivity mActivity;
|
||||
private final String mPath;
|
||||
private final int mFlags;
|
||||
|
||||
static class ImportSettingsTask extends AsyncTask<Object, Object, Boolean> {
|
||||
private static final String FRAGMENT_TAG = "import_settings_dialog";
|
||||
ImportSettingsTask(final DataImportActivity activity, final String path, final int flags) {
|
||||
mActivity = activity;
|
||||
mPath = path;
|
||||
mFlags = flags;
|
||||
}
|
||||
|
||||
private final DataImportActivity mActivity;
|
||||
private final String mPath;
|
||||
private final int mFlags;
|
||||
@Override
|
||||
protected Boolean doInBackground(final Object... params) {
|
||||
if (mPath == null) return false;
|
||||
final File file = new File(mPath);
|
||||
if (!file.isFile()) return false;
|
||||
try {
|
||||
DataImportExportUtils.importData(mActivity, file, mFlags);
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ImportSettingsTask(final DataImportActivity activity, final String path, final int flags) {
|
||||
mActivity = activity;
|
||||
mPath = path;
|
||||
mFlags = flags;
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(final Boolean result) {
|
||||
final FragmentManager fm = mActivity.getSupportFragmentManager();
|
||||
final Fragment f = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (f instanceof DialogFragment) {
|
||||
((DialogFragment) f).dismiss();
|
||||
}
|
||||
if (result != null && result) {
|
||||
mActivity.setResult(RESULT_OK);
|
||||
} else {
|
||||
mActivity.setResult(RESULT_CANCELED);
|
||||
}
|
||||
mActivity.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(final Object... params) {
|
||||
if (mPath == null) return false;
|
||||
final File file = new File(mPath);
|
||||
if (!file.isFile()) return false;
|
||||
try {
|
||||
DataImportExportUtils.importData(mActivity, file, mFlags);
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
ProgressDialogFragment.show(mActivity, FRAGMENT_TAG).setCancelable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Boolean result) {
|
||||
final FragmentManager fm = mActivity.getSupportFragmentManager();
|
||||
final Fragment f = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (f instanceof DialogFragment) {
|
||||
((DialogFragment) f).dismiss();
|
||||
}
|
||||
if (result != null && result) {
|
||||
mActivity.setResult(RESULT_OK);
|
||||
} else {
|
||||
mActivity.setResult(RESULT_CANCELED);
|
||||
}
|
||||
mActivity.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
ProgressDialogFragment.show(mActivity, FRAGMENT_TAG).setCancelable(false);
|
||||
}
|
||||
static class OpenImportTypeTask extends AsyncTask<Object, Object, Integer> {
|
||||
|
||||
}
|
||||
private static final String FRAGMENT_TAG = "read_settings_data_dialog";
|
||||
|
||||
static class OpenImportTypeTask extends AsyncTask<Object, Object, Integer> {
|
||||
private final DataImportActivity mActivity;
|
||||
private final String mPath;
|
||||
|
||||
private static final String FRAGMENT_TAG = "read_settings_data_dialog";
|
||||
OpenImportTypeTask(final DataImportActivity activity, final String path) {
|
||||
mActivity = activity;
|
||||
mPath = path;
|
||||
}
|
||||
|
||||
private final DataImportActivity mActivity;
|
||||
private final String mPath;
|
||||
@Override
|
||||
protected Integer doInBackground(final Object... params) {
|
||||
if (mPath == null) return 0;
|
||||
final File file = new File(mPath);
|
||||
if (!file.isFile()) return 0;
|
||||
try {
|
||||
return DataImportExportUtils.getImportedSettingsFlags(file);
|
||||
} catch (final IOException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
OpenImportTypeTask(final DataImportActivity activity, final String path) {
|
||||
mActivity = activity;
|
||||
mPath = path;
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(final Integer flags) {
|
||||
final FragmentManager fm = mActivity.getSupportFragmentManager();
|
||||
final Fragment f = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (f instanceof DialogFragment) {
|
||||
((DialogFragment) f).dismiss();
|
||||
}
|
||||
final DialogFragment df = new DataExportImportTypeSelectorDialogFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(EXTRA_PATH, mPath);
|
||||
args.putString(EXTRA_TITLE, mActivity.getString(R.string.import_settings_type_dialog_title));
|
||||
if (flags != null) {
|
||||
args.putInt(EXTRA_FLAGS, flags);
|
||||
} else {
|
||||
args.putInt(EXTRA_FLAGS, 0);
|
||||
}
|
||||
df.setArguments(args);
|
||||
df.show(mActivity.getSupportFragmentManager(), "select_import_type");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Integer doInBackground(final Object... params) {
|
||||
if (mPath == null) return 0;
|
||||
final File file = new File(mPath);
|
||||
if (!file.isFile()) return 0;
|
||||
try {
|
||||
return DataImportExportUtils.getImportedSettingsFlags(file);
|
||||
} catch (final IOException e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
ProgressDialogFragment.show(mActivity, FRAGMENT_TAG).setCancelable(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final Integer flags) {
|
||||
final FragmentManager fm = mActivity.getSupportFragmentManager();
|
||||
final Fragment f = fm.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (f instanceof DialogFragment) {
|
||||
((DialogFragment) f).dismiss();
|
||||
}
|
||||
final DialogFragment df = new DataExportImportTypeSelectorDialogFragment();
|
||||
final Bundle args = new Bundle();
|
||||
args.putString(EXTRA_PATH, mPath);
|
||||
args.putString(EXTRA_TITLE, mActivity.getString(R.string.import_settings_type_dialog_title));
|
||||
if (flags != null) {
|
||||
args.putInt(EXTRA_FLAGS, flags);
|
||||
} else {
|
||||
args.putInt(EXTRA_FLAGS, 0);
|
||||
}
|
||||
df.setArguments(args);
|
||||
df.show(mActivity.getSupportFragmentManager(), "select_import_type");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
ProgressDialogFragment.show(mActivity, FRAGMENT_TAG).setCancelable(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +74,6 @@ import org.mariotaku.twidere.adapter.support.SupportTabsAdapter;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.CustomTabsFragment;
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment;
|
||||
import org.mariotaku.twidere.fragment.iface.IBasePullToRefreshFragment;
|
||||
import org.mariotaku.twidere.fragment.iface.RefreshScrollTopInterface;
|
||||
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
|
||||
import org.mariotaku.twidere.fragment.support.AccountsDashboardFragment;
|
||||
@ -90,7 +89,6 @@ import org.mariotaku.twidere.util.AsyncTaskUtils;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.ColorUtils;
|
||||
import org.mariotaku.twidere.util.CustomTabUtils;
|
||||
import org.mariotaku.twidere.util.FlymeUtils;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler.ShortcutCallback;
|
||||
import org.mariotaku.twidere.util.MathUtils;
|
||||
@ -277,19 +275,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBasePullToRefreshFragment getCurrentPullToRefreshFragment() {
|
||||
final Fragment fragment = getCurrentVisibleFragment();
|
||||
if (fragment instanceof IBasePullToRefreshFragment)
|
||||
return (IBasePullToRefreshFragment) fragment;
|
||||
else if (fragment instanceof SupportFragmentCallback) {
|
||||
final Fragment curr = ((SupportFragmentCallback) fragment).getCurrentVisibleFragment();
|
||||
if (curr instanceof IBasePullToRefreshFragment)
|
||||
return (IBasePullToRefreshFragment) curr;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||
if (handleFragmentKeyboardShortcutSingle(keyCode, event)) return true;
|
||||
@ -371,7 +356,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||
showDataProfilingRequest();
|
||||
initUnreadCount();
|
||||
updateActionsButton();
|
||||
updateSmartBar();
|
||||
updateSlidingMenuTouchMode();
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
@ -419,7 +403,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||
invalidateOptionsMenu();
|
||||
updateActionsButtonStyle();
|
||||
updateActionsButton();
|
||||
updateSmartBar();
|
||||
updateSlidingMenuTouchMode();
|
||||
}
|
||||
|
||||
@ -467,7 +450,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||
@Subscribe
|
||||
public void notifyTaskStateChanged(TaskStateChangedEvent event) {
|
||||
updateActionsButton();
|
||||
updateSmartBar();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@ -524,7 +506,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||
}
|
||||
updateSlidingMenuTouchMode();
|
||||
updateActionsButton();
|
||||
updateSmartBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -738,11 +719,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasActivatedTask() {
|
||||
if (mTwitterWrapper == null) return false;
|
||||
return mTwitterWrapper.hasActivatedTask();
|
||||
}
|
||||
|
||||
private void initUnreadCount() {
|
||||
for (int i = 0, j = mTabIndicator.getCount(); i < j; i++) {
|
||||
mTabIndicator.setBadge(i, 0);
|
||||
@ -937,12 +913,6 @@ public class HomeActivity extends BaseActionBarActivity implements OnClickListen
|
||||
mSlidingMenu.setTouchModeAbove(mode);
|
||||
}
|
||||
|
||||
private void updateSmartBar() {
|
||||
final boolean useBottomActionItems = FlymeUtils.hasSmartBar();
|
||||
if (useBottomActionItems) {
|
||||
invalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
|
||||
private static final class AccountChangeObserver extends ContentObserver {
|
||||
private final HomeActivity mActivity;
|
||||
|
@ -13,6 +13,7 @@ import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
@ -37,212 +38,213 @@ import static android.os.Environment.getExternalStorageState;
|
||||
|
||||
public class ImagePickerActivity extends ThemedActionBarActivity {
|
||||
|
||||
public static final int REQUEST_PICK_IMAGE = 101;
|
||||
public static final int REQUEST_TAKE_PHOTO = 102;
|
||||
public static final int REQUEST_PICK_IMAGE = 101;
|
||||
public static final int REQUEST_TAKE_PHOTO = 102;
|
||||
|
||||
private Uri mTempPhotoUri;
|
||||
private CopyImageTask mTask;
|
||||
private Runnable mImageSelectedRunnable;
|
||||
private Uri mTempPhotoUri;
|
||||
private CopyImageTask mTask;
|
||||
private Runnable mImageSelectedRunnable;
|
||||
|
||||
@Override
|
||||
public int getThemeColor() {
|
||||
return 0;
|
||||
}
|
||||
@Override
|
||||
public int getThemeColor() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getThemeResourceId() {
|
||||
return ThemeUtils.getNoDisplayThemeResource(this);
|
||||
}
|
||||
@Override
|
||||
public int getThemeResourceId() {
|
||||
return ThemeUtils.getNoDisplayThemeResource(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final Uri src;
|
||||
switch (requestCode) {
|
||||
case REQUEST_PICK_IMAGE: {
|
||||
src = intent.getData();
|
||||
break;
|
||||
}
|
||||
case REQUEST_TAKE_PHOTO: {
|
||||
src = mTempPhotoUri;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (src == null) return;
|
||||
mImageSelectedRunnable = new Runnable() {
|
||||
@Override
|
||||
public void onActivityResult(final int requestCode, final int resultCode, final Intent intent) {
|
||||
if (resultCode != RESULT_OK) {
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final Uri src;
|
||||
switch (requestCode) {
|
||||
case REQUEST_PICK_IMAGE: {
|
||||
src = intent.getData();
|
||||
break;
|
||||
}
|
||||
case REQUEST_TAKE_PHOTO: {
|
||||
src = mTempPhotoUri;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (src == null) return;
|
||||
mImageSelectedRunnable = new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
imageSelected(src);
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override
|
||||
public void run() {
|
||||
imageSelected(src);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final Intent intent = getIntent();
|
||||
final String action = intent.getAction();
|
||||
if (INTENT_ACTION_TAKE_PHOTO.equals(action)) {
|
||||
takePhoto();
|
||||
} else if (INTENT_ACTION_PICK_FILE.equals(action)) {
|
||||
pickImage();
|
||||
} else {
|
||||
new ImageSourceDialogFragment().show(getSupportFragmentManager(), "image_source");
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
final Intent intent = getIntent();
|
||||
final String action = intent.getAction();
|
||||
if (INTENT_ACTION_TAKE_PHOTO.equals(action)) {
|
||||
takePhoto();
|
||||
} else if (INTENT_ACTION_PICK_IMAGE.equals(action)) {
|
||||
pickImage();
|
||||
} else {
|
||||
new ImageSourceDialogFragment().show(getSupportFragmentManager(), "image_source");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResumeFragments() {
|
||||
super.onResumeFragments();
|
||||
if (mImageSelectedRunnable != null) {
|
||||
runOnUiThread(mImageSelectedRunnable);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onResumeFragments() {
|
||||
super.onResumeFragments();
|
||||
if (mImageSelectedRunnable != null) {
|
||||
runOnUiThread(mImageSelectedRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
mImageSelectedRunnable = null;
|
||||
super.onStop();
|
||||
}
|
||||
@Override
|
||||
protected void onStop() {
|
||||
mImageSelectedRunnable = null;
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
private void imageSelected(final Uri uri) {
|
||||
final CopyImageTask task = mTask;
|
||||
if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) return;
|
||||
mTask = new CopyImageTask(this, uri);
|
||||
mTask.execute();
|
||||
}
|
||||
private void imageSelected(final Uri uri) {
|
||||
final CopyImageTask task = mTask;
|
||||
if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) return;
|
||||
mTask = new CopyImageTask(this, uri);
|
||||
mTask.execute();
|
||||
}
|
||||
|
||||
private void pickImage() {
|
||||
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType("image/*");
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_PICK_IMAGE);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
}
|
||||
}
|
||||
private void pickImage() {
|
||||
final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
|
||||
intent.setType("image/*");
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_PICK_IMAGE);
|
||||
} catch (final ActivityNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
private void takePhoto() {
|
||||
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
if (!getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) return;
|
||||
final File extCacheDir = getExternalCacheDir();
|
||||
final File file;
|
||||
try {
|
||||
file = File.createTempFile("temp_image_", ".tmp", extCacheDir);
|
||||
} catch (final IOException e) {
|
||||
return;
|
||||
}
|
||||
mTempPhotoUri = Uri.fromFile(file);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, mTempPhotoUri);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
|
||||
} catch (final ActivityNotFoundException e) {
|
||||
}
|
||||
}
|
||||
private void takePhoto() {
|
||||
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
if (!getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) return;
|
||||
final File extCacheDir = getExternalCacheDir();
|
||||
final File file;
|
||||
try {
|
||||
file = File.createTempFile("temp_image_", ".tmp", extCacheDir);
|
||||
} catch (final IOException e) {
|
||||
return;
|
||||
}
|
||||
mTempPhotoUri = Uri.fromFile(file);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, mTempPhotoUri);
|
||||
try {
|
||||
startActivityForResult(intent, REQUEST_TAKE_PHOTO);
|
||||
} catch (final ActivityNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ImageSourceDialogFragment extends BaseSupportDialogFragment implements OnClickListener {
|
||||
public static class ImageSourceDialogFragment extends BaseSupportDialogFragment implements OnClickListener {
|
||||
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
final FragmentActivity a = getActivity();
|
||||
if (a != null) {
|
||||
a.finish();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onCancel(final DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
final FragmentActivity a = getActivity();
|
||||
if (a != null) {
|
||||
a.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (!(activity instanceof ImagePickerActivity)) return;
|
||||
final ImagePickerActivity addImageActivity = (ImagePickerActivity) activity;
|
||||
final String source = getResources().getStringArray(R.array.value_image_sources)[which];
|
||||
if ("gallery".equals(source)) {
|
||||
addImageActivity.pickImage();
|
||||
} else if ("camera".equals(source)) {
|
||||
addImageActivity.takePhoto();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final FragmentActivity activity = getActivity();
|
||||
if (!(activity instanceof ImagePickerActivity)) return;
|
||||
final ImagePickerActivity addImageActivity = (ImagePickerActivity) activity;
|
||||
final String source = getResources().getStringArray(R.array.value_image_sources)[which];
|
||||
if ("gallery".equals(source)) {
|
||||
addImageActivity.pickImage();
|
||||
} else if ("camera".equals(source)) {
|
||||
addImageActivity.takePhoto();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setItems(R.array.entries_image_sources, this);
|
||||
return builder.create();
|
||||
}
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setItems(R.array.entries_image_sources, this);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(final DialogInterface dialog) {
|
||||
super.onDismiss(dialog);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onDismiss(final DialogInterface dialog) {
|
||||
super.onDismiss(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
private static class CopyImageTask extends AsyncTask<Object, Object, SingleResponse<File>> {
|
||||
private final ImagePickerActivity mActivity;
|
||||
private final Uri mUri;
|
||||
private static class CopyImageTask extends AsyncTask<Object, Object, SingleResponse<File>> {
|
||||
private final ImagePickerActivity mActivity;
|
||||
private final Uri mUri;
|
||||
|
||||
private static final String TAG_COPYING_IMAGE = "copying_image";
|
||||
private static final String TAG_COPYING_IMAGE = "copying_image";
|
||||
|
||||
public CopyImageTask(final ImagePickerActivity activity, final Uri uri) {
|
||||
mActivity = activity;
|
||||
mUri = uri;
|
||||
}
|
||||
public CopyImageTask(final ImagePickerActivity activity, final Uri uri) {
|
||||
mActivity = activity;
|
||||
mUri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SingleResponse<File> doInBackground(final Object... params) {
|
||||
final ContentResolver cr = mActivity.getContentResolver();
|
||||
InputStream is = null;
|
||||
OutputStream os = null;
|
||||
try {
|
||||
final File cacheDir = mActivity.getCacheDir();
|
||||
is = cr.openInputStream(mUri);
|
||||
final BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeStream(cr.openInputStream(mUri), null, opts);
|
||||
final String mimeType = opts.outMimeType;
|
||||
final String suffix = mimeType != null ? "."
|
||||
+ MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType) : null;
|
||||
final File outFile = File.createTempFile("temp_image_", suffix, cacheDir);
|
||||
os = new FileOutputStream(outFile);
|
||||
IoUtils.copyStream(is, os, null);
|
||||
return SingleResponse.getInstance(outFile);
|
||||
} catch (final IOException e) {
|
||||
return SingleResponse.getInstance(e);
|
||||
} finally {
|
||||
IoUtils.closeSilently(os);
|
||||
IoUtils.closeSilently(is);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected SingleResponse<File> doInBackground(final Object... params) {
|
||||
final ContentResolver cr = mActivity.getContentResolver();
|
||||
InputStream is = null;
|
||||
OutputStream os = null;
|
||||
try {
|
||||
final File cacheDir = mActivity.getCacheDir();
|
||||
is = cr.openInputStream(mUri);
|
||||
final BitmapFactory.Options opts = new BitmapFactory.Options();
|
||||
opts.inJustDecodeBounds = true;
|
||||
BitmapFactory.decodeStream(cr.openInputStream(mUri), null, opts);
|
||||
final String mimeType = opts.outMimeType;
|
||||
final String suffix = mimeType != null ? "."
|
||||
+ MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType) : null;
|
||||
final File outFile = File.createTempFile("temp_image_", suffix, cacheDir);
|
||||
os = new FileOutputStream(outFile);
|
||||
IoUtils.copyStream(is, os, null);
|
||||
return SingleResponse.getInstance(outFile);
|
||||
} catch (final IOException e) {
|
||||
return SingleResponse.getInstance(e);
|
||||
} finally {
|
||||
IoUtils.closeSilently(os);
|
||||
IoUtils.closeSilently(is);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(final SingleResponse<File> result) {
|
||||
final Fragment f = mActivity.getSupportFragmentManager().findFragmentByTag(TAG_COPYING_IMAGE);
|
||||
if (f instanceof DialogFragment) {
|
||||
((DialogFragment) f).dismiss();
|
||||
}
|
||||
if (result.hasData()) {
|
||||
final Intent data = new Intent();
|
||||
data.setData(Uri.fromFile(result.getData()));
|
||||
mActivity.setResult(RESULT_OK, data);
|
||||
} else if (result.hasException()) {
|
||||
Log.w(LOGTAG, result.getException());
|
||||
}
|
||||
mActivity.finish();
|
||||
}
|
||||
@Override
|
||||
protected void onPostExecute(final SingleResponse<File> result) {
|
||||
final Fragment f = mActivity.getSupportFragmentManager().findFragmentByTag(TAG_COPYING_IMAGE);
|
||||
if (f instanceof DialogFragment) {
|
||||
((DialogFragment) f).dismiss();
|
||||
}
|
||||
if (result.hasData()) {
|
||||
final Intent data = new Intent();
|
||||
data.setData(Uri.fromFile(result.getData()));
|
||||
mActivity.setResult(RESULT_OK, data);
|
||||
} else if (result.hasException()) {
|
||||
Log.w(LOGTAG, result.getException());
|
||||
}
|
||||
mActivity.finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
final ProgressDialogFragment f = ProgressDialogFragment.show(mActivity, TAG_COPYING_IMAGE);
|
||||
f.setCancelable(false);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
final ProgressDialogFragment f = ProgressDialogFragment.show(mActivity, TAG_COPYING_IMAGE);
|
||||
f.setCancelable(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,6 @@ import org.mariotaku.twidere.activity.iface.IControlBarActivity;
|
||||
import org.mariotaku.twidere.app.TwidereApplication;
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment;
|
||||
import org.mariotaku.twidere.fragment.iface.IBaseFragment.SystemWindowsInsetsCallback;
|
||||
import org.mariotaku.twidere.fragment.iface.IBasePullToRefreshFragment;
|
||||
import org.mariotaku.twidere.fragment.iface.SupportFragmentCallback;
|
||||
import org.mariotaku.twidere.fragment.support.SearchFragment;
|
||||
import org.mariotaku.twidere.util.ColorUtils;
|
||||
@ -123,19 +122,6 @@ public class LinkHandlerActivity extends BaseActionBarActivity implements System
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IBasePullToRefreshFragment getCurrentPullToRefreshFragment() {
|
||||
final Fragment fragment = getCurrentVisibleFragment();
|
||||
if (fragment instanceof IBasePullToRefreshFragment)
|
||||
return (IBasePullToRefreshFragment) fragment;
|
||||
else if (fragment instanceof SupportFragmentCallback) {
|
||||
final Fragment curr = ((SupportFragmentCallback) fragment).getCurrentVisibleFragment();
|
||||
if (curr instanceof IBasePullToRefreshFragment)
|
||||
return (IBasePullToRefreshFragment) curr;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleKeyboardShortcutSingle(int keyCode, @NonNull KeyEvent event) {
|
||||
if (handleFragmentKeyboardShortcutSingle(keyCode, event)) return true;
|
||||
|
@ -20,10 +20,8 @@
|
||||
package org.mariotaku.twidere.activity.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
|
@ -20,11 +20,9 @@
|
||||
package org.mariotaku.twidere.activity.support;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
|
@ -23,6 +23,7 @@ import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.AsyncTask.Status;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
@ -57,15 +58,11 @@ import org.mariotaku.twidere.util.ViewUtils;
|
||||
import org.mariotaku.twidere.view.ForegroundColorView;
|
||||
import org.mariotaku.twidere.view.iface.IExtendedView.OnSizeChangedListener;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import twitter4j.Twitter;
|
||||
import twitter4j.TwitterException;
|
||||
import twitter4j.User;
|
||||
|
||||
import static android.text.TextUtils.isEmpty;
|
||||
import static org.mariotaku.twidere.util.Utils.createPickImageIntent;
|
||||
import static org.mariotaku.twidere.util.Utils.createTakePhotoIntent;
|
||||
import static org.mariotaku.twidere.util.Utils.getTwitterInstance;
|
||||
import static org.mariotaku.twidere.util.Utils.isMyAccount;
|
||||
import static org.mariotaku.twidere.util.Utils.showErrorMessage;
|
||||
@ -201,23 +198,20 @@ public class UserProfileEditorActivity extends BaseActionBarActivity implements
|
||||
break;
|
||||
}
|
||||
case R.id.profile_image_camera: {
|
||||
final Uri uri = createTempFileUri();
|
||||
final Intent intent = createTakePhotoIntent(uri, null, null, 1, 1, true);
|
||||
mTask = new UpdateProfileImageTaskInternal(this, mAsyncTaskManager, mAccountId, uri, true);
|
||||
final Intent intent = new Intent(this, ImagePickerActivity.class);
|
||||
intent.setAction(INTENT_ACTION_PICK_IMAGE);
|
||||
startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_IMAGE);
|
||||
break;
|
||||
}
|
||||
case R.id.profile_image_gallery: {
|
||||
final Uri uri = createTempFileUri();
|
||||
final Intent intent = createPickImageIntent(uri, null, null, 1, 1, true);
|
||||
mTask = new UpdateProfileImageTaskInternal(this, mAsyncTaskManager, mAccountId, uri, true);
|
||||
final Intent intent = new Intent(this, ImagePickerActivity.class);
|
||||
intent.setAction(INTENT_ACTION_TAKE_PHOTO);
|
||||
startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_IMAGE);
|
||||
break;
|
||||
}
|
||||
case R.id.profile_banner_gallery: {
|
||||
final Uri uri = createTempFileUri();
|
||||
final Intent intent = createPickImageIntent(uri, null, null, 2, 1, true);
|
||||
mTask = new UpdateProfileBannerImageTaskInternal(this, mAsyncTaskManager, mAccountId, uri, true);
|
||||
final Intent intent = new Intent(this, ImagePickerActivity.class);
|
||||
intent.setAction(INTENT_ACTION_PICK_IMAGE);
|
||||
startActivityForResult(intent, REQUEST_UPLOAD_PROFILE_BANNER_IMAGE);
|
||||
break;
|
||||
}
|
||||
@ -316,12 +310,14 @@ public class UserProfileEditorActivity extends BaseActionBarActivity implements
|
||||
if (resultCode == RESULT_CANCELED) return;
|
||||
switch (requestCode) {
|
||||
case REQUEST_UPLOAD_PROFILE_BANNER_IMAGE: {
|
||||
if (mTask == null || mTask.getStatus() != AsyncTask.Status.PENDING) return;
|
||||
if (mTask != null && mTask.getStatus() == Status.RUNNING) return;
|
||||
mTask = new UpdateProfileBannerImageTaskInternal(this, mAsyncTaskManager, mAccountId, data.getData(), true);
|
||||
AsyncTaskUtils.executeTask(mTask);
|
||||
break;
|
||||
}
|
||||
case REQUEST_UPLOAD_PROFILE_IMAGE: {
|
||||
if (mTask == null || mTask.getStatus() != AsyncTask.Status.PENDING) return;
|
||||
if (mTask != null && mTask.getStatus() == Status.RUNNING) return;
|
||||
mTask = new UpdateProfileImageTaskInternal(this, mAsyncTaskManager, mAccountId, data.getData(), true);
|
||||
AsyncTaskUtils.executeTask(mTask);
|
||||
break;
|
||||
}
|
||||
@ -356,12 +352,6 @@ public class UserProfileEditorActivity extends BaseActionBarActivity implements
|
||||
return false;
|
||||
}
|
||||
|
||||
private Uri createTempFileUri() {
|
||||
final File cache_dir = getExternalCacheDir();
|
||||
final File file = new File(cache_dir, "tmp_image_" + System.currentTimeMillis());
|
||||
return Uri.fromFile(file);
|
||||
}
|
||||
|
||||
private void displayUser(final ParcelableUser user) {
|
||||
if (!mGetUserInfoCalled) return;
|
||||
mGetUserInfoCalled = false;
|
||||
|
@ -14,7 +14,7 @@ import java.util.List;
|
||||
*/
|
||||
public abstract class ArrayRecyclerAdapter<T, H extends ViewHolder> extends Adapter<H> {
|
||||
|
||||
protected final ArrayList<T> mData = new ArrayList<T>();
|
||||
protected final ArrayList<T> mData = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public final void onBindViewHolder(H holder, int position) {
|
||||
|
@ -51,7 +51,6 @@ import org.mariotaku.twidere.util.AsyncTaskManager;
|
||||
import org.mariotaku.twidere.util.AsyncTwitterWrapper;
|
||||
import org.mariotaku.twidere.util.KeyboardShortcutsHandler;
|
||||
import org.mariotaku.twidere.util.MediaLoaderWrapper;
|
||||
import org.mariotaku.twidere.util.MessagesManager;
|
||||
import org.mariotaku.twidere.util.MultiSelectManager;
|
||||
import org.mariotaku.twidere.util.ReadStateManager;
|
||||
import org.mariotaku.twidere.util.StrictModeUtils;
|
||||
@ -92,7 +91,6 @@ public class TwidereApplication extends MultiDexApplication implements Constants
|
||||
private MultiSelectManager mMultiSelectManager;
|
||||
private TwidereImageDownloader mImageDownloader, mFullImageDownloader;
|
||||
private DiskCache mDiskCache, mFullDiskCache;
|
||||
private MessagesManager mCroutonsManager;
|
||||
private SQLiteOpenHelper mSQLiteOpenHelper;
|
||||
private HostAddressResolver mResolver;
|
||||
private SQLiteDatabase mDatabase;
|
||||
@ -193,11 +191,6 @@ public class TwidereApplication extends MultiDexApplication implements Constants
|
||||
return mMessageBus;
|
||||
}
|
||||
|
||||
public MessagesManager getMessagesManager() {
|
||||
if (mCroutonsManager != null) return mCroutonsManager;
|
||||
return mCroutonsManager = new MessagesManager(this);
|
||||
}
|
||||
|
||||
public MultiSelectManager getMultiSelectManager() {
|
||||
if (mMultiSelectManager != null) return mMultiSelectManager;
|
||||
return mMultiSelectManager = new MultiSelectManager();
|
||||
|
@ -68,12 +68,6 @@ public class BaseFragment extends Fragment implements Constants {
|
||||
return app != null ? app.getTwitterWrapper() : null;
|
||||
}
|
||||
|
||||
public void invalidateOptionsMenu() {
|
||||
final Activity activity = getActivity();
|
||||
if (activity == null) return;
|
||||
activity.invalidateOptionsMenu();
|
||||
}
|
||||
|
||||
public void registerReceiver(final BroadcastReceiver receiver, final IntentFilter filter) {
|
||||
final Activity activity = getActivity();
|
||||
if (activity == null) return;
|
||||
@ -83,7 +77,7 @@ public class BaseFragment extends Fragment implements Constants {
|
||||
public void setProgressBarIndeterminateVisibility(final boolean visible) {
|
||||
final Activity activity = getActivity();
|
||||
if (activity instanceof BaseActionBarActivity) {
|
||||
((BaseActionBarActivity) activity).setProgressBarIndeterminateVisibility(visible);
|
||||
activity.setProgressBarIndeterminateVisibility(visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +72,7 @@ public abstract class AbsActivitiesFragment<Data> extends BaseSupportFragment im
|
||||
private RecyclerView mRecyclerView;
|
||||
private AbsActivitiesAdapter<Data> mAdapter;
|
||||
private SimpleDrawerCallback mDrawerCallback;
|
||||
private OnScrollListener mOnScrollListener = new OnScrollListener() {
|
||||
private final OnScrollListener mOnScrollListener = new OnScrollListener() {
|
||||
|
||||
private int mScrollState;
|
||||
|
||||
|
@ -198,9 +198,9 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
||||
case "status.favorite": {
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
if (status.is_favorite) {
|
||||
twitter.destroyFavoriteAsync(status);
|
||||
twitter.destroyFavoriteAsync(status.account_id, status.id);
|
||||
} else {
|
||||
twitter.createFavoriteAsync(status);
|
||||
twitter.createFavoriteAsync(status.account_id, status.id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -472,9 +472,9 @@ public abstract class AbsStatusesFragment<Data> extends BaseSupportFragment impl
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
if (twitter == null) return;
|
||||
if (status.is_favorite) {
|
||||
twitter.destroyFavoriteAsync(status);
|
||||
twitter.destroyFavoriteAsync(status.account_id, status.id);
|
||||
} else {
|
||||
twitter.createFavoriteAsync(status);
|
||||
twitter.createFavoriteAsync(status.account_id, status.id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.DialogInterface.OnMultiChoiceClickListener;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import com.twitter.Extractor;
|
||||
@ -51,180 +52,181 @@ import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkDelete
|
||||
import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkInsert;
|
||||
|
||||
public class AddStatusFilterDialogFragment extends BaseSupportDialogFragment implements OnMultiChoiceClickListener,
|
||||
OnClickListener {
|
||||
OnClickListener {
|
||||
|
||||
public static final String FRAGMENT_TAG = "add_status_filter";
|
||||
public static final String FRAGMENT_TAG = "add_status_filter";
|
||||
|
||||
private final Extractor mExtractor = new Extractor();
|
||||
private FilterItemInfo[] mFilterItems;
|
||||
private final Set<FilterItemInfo> mCheckedFilterItems = new HashSet<FilterItemInfo>();
|
||||
private final Extractor mExtractor = new Extractor();
|
||||
private FilterItemInfo[] mFilterItems;
|
||||
private final Set<FilterItemInfo> mCheckedFilterItems = new HashSet<>();
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final Set<Long> user_ids = new HashSet<Long>();
|
||||
final Set<String> keywords = new HashSet<String>();
|
||||
final Set<String> sources = new HashSet<String>();
|
||||
final ArrayList<ContentValues> user_values = new ArrayList<ContentValues>();
|
||||
final ArrayList<ContentValues> keyword_values = new ArrayList<ContentValues>();
|
||||
final ArrayList<ContentValues> source_values = new ArrayList<ContentValues>();
|
||||
for (final FilterItemInfo info : mCheckedFilterItems) {
|
||||
final Object value = info.value;
|
||||
if (value instanceof ParcelableUserMention) {
|
||||
final ParcelableUserMention mention = (ParcelableUserMention) value;
|
||||
user_ids.add(mention.id);
|
||||
user_values.add(createFilteredUser(mention));
|
||||
} else if (value instanceof ParcelableStatus) {
|
||||
final ParcelableStatus status = (ParcelableStatus) value;
|
||||
user_ids.add(status.user_id);
|
||||
user_values.add(ContentValuesCreator.createFilteredUser(status));
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_KEYWORD) {
|
||||
if (value != null) {
|
||||
final String keyword = ParseUtils.parseString(value);
|
||||
keywords.add(keyword);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Keywords.VALUE, "#" + keyword);
|
||||
keyword_values.add(values);
|
||||
}
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_SOURCE) {
|
||||
if (value != null) {
|
||||
final String source = ParseUtils.parseString(value);
|
||||
sources.add(source);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Sources.VALUE, source);
|
||||
source_values.add(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
final ContentResolver resolver = getContentResolver();
|
||||
bulkDelete(resolver, Filters.Users.CONTENT_URI, Filters.Users.USER_ID, user_ids, null, false);
|
||||
bulkDelete(resolver, Filters.Keywords.CONTENT_URI, Filters.Keywords.VALUE, keywords, null, true);
|
||||
bulkDelete(resolver, Filters.Sources.CONTENT_URI, Filters.Sources.VALUE, sources, null, true);
|
||||
bulkInsert(resolver, Filters.Users.CONTENT_URI, user_values);
|
||||
bulkInsert(resolver, Filters.Keywords.CONTENT_URI, keyword_values);
|
||||
bulkInsert(resolver, Filters.Sources.CONTENT_URI, source_values);
|
||||
}
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
final Set<Long> user_ids = new HashSet<>();
|
||||
final Set<String> keywords = new HashSet<>();
|
||||
final Set<String> sources = new HashSet<>();
|
||||
final ArrayList<ContentValues> user_values = new ArrayList<>();
|
||||
final ArrayList<ContentValues> keyword_values = new ArrayList<>();
|
||||
final ArrayList<ContentValues> source_values = new ArrayList<>();
|
||||
for (final FilterItemInfo info : mCheckedFilterItems) {
|
||||
final Object value = info.value;
|
||||
if (value instanceof ParcelableUserMention) {
|
||||
final ParcelableUserMention mention = (ParcelableUserMention) value;
|
||||
user_ids.add(mention.id);
|
||||
user_values.add(createFilteredUser(mention));
|
||||
} else if (value instanceof ParcelableStatus) {
|
||||
final ParcelableStatus status = (ParcelableStatus) value;
|
||||
user_ids.add(status.user_id);
|
||||
user_values.add(ContentValuesCreator.createFilteredUser(status));
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_KEYWORD) {
|
||||
if (value != null) {
|
||||
final String keyword = ParseUtils.parseString(value);
|
||||
keywords.add(keyword);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Keywords.VALUE, "#" + keyword);
|
||||
keyword_values.add(values);
|
||||
}
|
||||
} else if (info.type == FilterItemInfo.FILTER_TYPE_SOURCE) {
|
||||
if (value != null) {
|
||||
final String source = ParseUtils.parseString(value);
|
||||
sources.add(source);
|
||||
final ContentValues values = new ContentValues();
|
||||
values.put(Filters.Sources.VALUE, source);
|
||||
source_values.add(values);
|
||||
}
|
||||
}
|
||||
}
|
||||
final ContentResolver resolver = getContentResolver();
|
||||
bulkDelete(resolver, Filters.Users.CONTENT_URI, Filters.Users.USER_ID, user_ids, null, false);
|
||||
bulkDelete(resolver, Filters.Keywords.CONTENT_URI, Filters.Keywords.VALUE, keywords, null, true);
|
||||
bulkDelete(resolver, Filters.Sources.CONTENT_URI, Filters.Sources.VALUE, sources, null, true);
|
||||
bulkInsert(resolver, Filters.Users.CONTENT_URI, user_values);
|
||||
bulkInsert(resolver, Filters.Keywords.CONTENT_URI, keyword_values);
|
||||
bulkInsert(resolver, Filters.Sources.CONTENT_URI, source_values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which, final boolean isChecked) {
|
||||
if (isChecked) {
|
||||
mCheckedFilterItems.add(mFilterItems[which]);
|
||||
} else {
|
||||
mCheckedFilterItems.remove(mFilterItems[which]);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which, final boolean isChecked) {
|
||||
if (isChecked) {
|
||||
mCheckedFilterItems.add(mFilterItems[which]);
|
||||
} else {
|
||||
mCheckedFilterItems.remove(mFilterItems[which]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
mFilterItems = getFilterItemsInfo();
|
||||
final String[] entries = new String[mFilterItems.length];
|
||||
for (int i = 0, j = entries.length; i < j; i++) {
|
||||
final FilterItemInfo info = mFilterItems[i];
|
||||
switch (info.type) {
|
||||
case FilterItemInfo.FILTER_TYPE_USER:
|
||||
entries[i] = getString(R.string.user_filter_name, getName(info.value));
|
||||
break;
|
||||
case FilterItemInfo.FILTER_TYPE_KEYWORD:
|
||||
entries[i] = getString(R.string.keyword_filter_name, getName(info.value));
|
||||
break;
|
||||
case FilterItemInfo.FILTER_TYPE_SOURCE:
|
||||
entries[i] = getString(R.string.source_filter_name, getName(info.value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.setTitle(R.string.add_to_filter);
|
||||
builder.setMultiChoiceItems(entries, null, this);
|
||||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
return builder.create();
|
||||
}
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
mFilterItems = getFilterItemsInfo();
|
||||
final String[] entries = new String[mFilterItems.length];
|
||||
for (int i = 0, j = entries.length; i < j; i++) {
|
||||
final FilterItemInfo info = mFilterItems[i];
|
||||
switch (info.type) {
|
||||
case FilterItemInfo.FILTER_TYPE_USER:
|
||||
entries[i] = getString(R.string.user_filter_name, getName(info.value));
|
||||
break;
|
||||
case FilterItemInfo.FILTER_TYPE_KEYWORD:
|
||||
entries[i] = getString(R.string.keyword_filter_name, getName(info.value));
|
||||
break;
|
||||
case FilterItemInfo.FILTER_TYPE_SOURCE:
|
||||
entries[i] = getString(R.string.source_filter_name, getName(info.value));
|
||||
break;
|
||||
}
|
||||
}
|
||||
builder.setTitle(R.string.add_to_filter);
|
||||
builder.setMultiChoiceItems(entries, null, this);
|
||||
builder.setPositiveButton(android.R.string.ok, this);
|
||||
builder.setNegativeButton(android.R.string.cancel, null);
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
private FilterItemInfo[] getFilterItemsInfo() {
|
||||
final Bundle args = getArguments();
|
||||
if (args == null || !args.containsKey(EXTRA_STATUS)) return new FilterItemInfo[0];
|
||||
final ParcelableStatus status = args.getParcelable(EXTRA_STATUS);
|
||||
final ArrayList<FilterItemInfo> list = new ArrayList<FilterItemInfo>();
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, status));
|
||||
final ParcelableUserMention[] mentions = status.mentions;
|
||||
if (mentions != null) {
|
||||
for (final ParcelableUserMention mention : mentions) {
|
||||
if (mention.id != status.user_id) {
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, mention));
|
||||
}
|
||||
}
|
||||
}
|
||||
final HashSet<String> hashtags = new HashSet<String>();
|
||||
hashtags.addAll(mExtractor.extractHashtags(status.text_plain));
|
||||
for (final String hashtag : hashtags) {
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_KEYWORD, hashtag));
|
||||
}
|
||||
final String source = HtmlEscapeHelper.toPlainText(status.source);
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_SOURCE, source));
|
||||
return list.toArray(new FilterItemInfo[list.size()]);
|
||||
}
|
||||
private FilterItemInfo[] getFilterItemsInfo() {
|
||||
final Bundle args = getArguments();
|
||||
if (args == null || !args.containsKey(EXTRA_STATUS)) return new FilterItemInfo[0];
|
||||
final ParcelableStatus status = args.getParcelable(EXTRA_STATUS);
|
||||
final ArrayList<FilterItemInfo> list = new ArrayList<>();
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, status));
|
||||
final ParcelableUserMention[] mentions = status.mentions;
|
||||
if (mentions != null) {
|
||||
for (final ParcelableUserMention mention : mentions) {
|
||||
if (mention.id != status.user_id) {
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_USER, mention));
|
||||
}
|
||||
}
|
||||
}
|
||||
final HashSet<String> hashtags = new HashSet<>();
|
||||
hashtags.addAll(mExtractor.extractHashtags(status.text_plain));
|
||||
for (final String hashtag : hashtags) {
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_KEYWORD, hashtag));
|
||||
}
|
||||
final String source = HtmlEscapeHelper.toPlainText(status.source);
|
||||
list.add(new FilterItemInfo(FilterItemInfo.FILTER_TYPE_SOURCE, source));
|
||||
return list.toArray(new FilterItemInfo[list.size()]);
|
||||
}
|
||||
|
||||
private String getName(final Object value) {
|
||||
if (value instanceof ParcelableUserMention) {
|
||||
final ParcelableUserMention mention = (ParcelableUserMention) value;
|
||||
return UserColorNameUtils.getDisplayName(getActivity(), mention.id, mention.name, mention.screen_name);
|
||||
} else if (value instanceof ParcelableStatus) {
|
||||
final ParcelableStatus status = (ParcelableStatus) value;
|
||||
return UserColorNameUtils.getDisplayName(getActivity(), status.user_id, status.user_name, status.user_screen_name);
|
||||
} else
|
||||
return ParseUtils.parseString(value);
|
||||
}
|
||||
private String getName(final Object value) {
|
||||
if (value instanceof ParcelableUserMention) {
|
||||
final ParcelableUserMention mention = (ParcelableUserMention) value;
|
||||
return UserColorNameUtils.getDisplayName(getActivity(), mention.id, mention.name, mention.screen_name);
|
||||
} else if (value instanceof ParcelableStatus) {
|
||||
final ParcelableStatus status = (ParcelableStatus) value;
|
||||
return UserColorNameUtils.getDisplayName(getActivity(), status.user_id, status.user_name, status.user_screen_name);
|
||||
} else
|
||||
return ParseUtils.parseString(value);
|
||||
}
|
||||
|
||||
public static AddStatusFilterDialogFragment show(final FragmentManager fm, final ParcelableStatus status) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EXTRA_STATUS, status);
|
||||
final AddStatusFilterDialogFragment f = new AddStatusFilterDialogFragment();
|
||||
f.setArguments(args);
|
||||
f.show(fm, FRAGMENT_TAG);
|
||||
return f;
|
||||
}
|
||||
public static AddStatusFilterDialogFragment show(final FragmentManager fm, final ParcelableStatus status) {
|
||||
final Bundle args = new Bundle();
|
||||
args.putParcelable(EXTRA_STATUS, status);
|
||||
final AddStatusFilterDialogFragment f = new AddStatusFilterDialogFragment();
|
||||
f.setArguments(args);
|
||||
f.show(fm, FRAGMENT_TAG);
|
||||
return f;
|
||||
}
|
||||
|
||||
private static class FilterItemInfo {
|
||||
private static class FilterItemInfo {
|
||||
|
||||
static final int FILTER_TYPE_USER = 1;
|
||||
static final int FILTER_TYPE_KEYWORD = 2;
|
||||
static final int FILTER_TYPE_SOURCE = 3;
|
||||
static final int FILTER_TYPE_USER = 1;
|
||||
static final int FILTER_TYPE_KEYWORD = 2;
|
||||
static final int FILTER_TYPE_SOURCE = 3;
|
||||
|
||||
final int type;
|
||||
final Object value;
|
||||
final int type;
|
||||
final Object value;
|
||||
|
||||
FilterItemInfo(final int type, final Object value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
FilterItemInfo(final int type, final Object value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof FilterItemInfo)) return false;
|
||||
final FilterItemInfo other = (FilterItemInfo) obj;
|
||||
if (type != other.type) return false;
|
||||
if (value == null) {
|
||||
if (other.value != null) return false;
|
||||
} else if (!value.equals(other.value)) return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (this == obj) return true;
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof FilterItemInfo)) return false;
|
||||
final FilterItemInfo other = (FilterItemInfo) obj;
|
||||
if (type != other.type) return false;
|
||||
if (value == null) {
|
||||
if (other.value != null) return false;
|
||||
} else if (!value.equals(other.value)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + type;
|
||||
result = prime * result + (value == null ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + type;
|
||||
result = prime * result + (value == null ? 0 : value.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FilterItemInfo{type=" + type + ", value=" + value + "}";
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FilterItemInfo{type=" + type + ", value=" + value + "}";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ public class BaseSupportFragment extends Fragment implements IBaseFragment, Cons
|
||||
public void setProgressBarIndeterminateVisibility(final boolean visible) {
|
||||
final Activity activity = getActivity();
|
||||
if (activity instanceof BaseActionBarActivity) {
|
||||
((BaseActionBarActivity) activity).setProgressBarIndeterminateVisibility(visible);
|
||||
activity.setProgressBarIndeterminateVisibility(visible);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
@ -50,7 +51,8 @@ public class CreateUserBlockDialogFragment extends BaseSupportDialogFragment imp
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
|
@ -24,6 +24,7 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.CheckBox;
|
||||
@ -60,7 +61,8 @@ public class CreateUserListDialogFragment extends BaseSupportDialogFragment impl
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
mTwitterWrapper = getApplication().getTwitterWrapper();
|
||||
final Bundle bundle = savedInstanceState == null ? getArguments() : savedInstanceState;
|
||||
|
@ -26,6 +26,7 @@ import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
@ -55,7 +56,8 @@ public class DeleteUserListMembersDialogFragment extends BaseSupportDialogFragme
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
|
@ -24,6 +24,7 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
@ -50,7 +51,8 @@ public class DestroySavedSearchDialogFragment extends BaseSupportDialogFragment
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
|
@ -24,6 +24,7 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
@ -49,7 +50,8 @@ public class DestroyStatusDialogFragment extends BaseSupportDialogFragment imple
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
|
@ -24,6 +24,7 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
@ -49,7 +50,8 @@ public class DestroyUserListDialogFragment extends BaseSupportDialogFragment imp
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
|
@ -24,6 +24,7 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
@ -50,7 +51,8 @@ public class DestroyUserListSubscriptionDialogFragment extends BaseSupportDialog
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
|
@ -27,6 +27,7 @@ import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
@ -51,7 +52,8 @@ public class PhishingLinkWarningDialogFragment extends BaseSupportDialogFragment
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
|
@ -34,7 +34,6 @@ import org.mariotaku.twidere.fragment.support.TrendsSuggectionsFragment.TrendsAd
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.CachedTrends;
|
||||
import org.mariotaku.twidere.util.ThemeUtils;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
import org.mariotaku.twidere.util.ViewUtils;
|
||||
import org.mariotaku.twidere.view.ExtendedFrameLayout;
|
||||
import org.mariotaku.twidere.view.iface.IExtendedView.OnFitSystemWindowsListener;
|
||||
|
||||
|
@ -24,6 +24,7 @@ import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
|
||||
import org.mariotaku.twidere.R;
|
||||
@ -50,7 +51,8 @@ public class ReportSpamDialogFragment extends BaseSupportDialogFragment implemen
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Context wrapped = ThemeUtils.getDialogThemedContext(getActivity());
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(wrapped);
|
||||
|
@ -25,6 +25,7 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.text.TextUtils;
|
||||
import android.widget.EditText;
|
||||
@ -65,7 +66,8 @@ public class SetUserNicknameDialogFragment extends BaseSupportDialogFragment imp
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(final Bundle savedInstanceState) {
|
||||
final Bundle args = getArguments();
|
||||
final String nick = args.getString(EXTRA_NAME);
|
||||
|
@ -34,7 +34,6 @@ import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
|
||||
import android.nfc.NfcEvent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
@ -836,13 +836,11 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
|
||||
if (!shouldUseNativeMenu()) return;
|
||||
inflater.inflate(R.menu.menu_user_profile, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareOptionsMenu(final Menu menu) {
|
||||
if (!shouldUseNativeMenu() || !menu.hasVisibleItems()) return;
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
final ParcelableUser user = getUser();
|
||||
final Relationship relationship = mRelationship;
|
||||
@ -1356,10 +1354,6 @@ public class UserFragment extends BaseSupportFragment implements OnClickListener
|
||||
mPagerAdapter.addTab(UserFavoritesFragment.class, tabArgs, getString(R.string.favorites), R.drawable.ic_action_star, TAB_TYPE_FAVORITES, TAB_POSITION_FAVORITES, null);
|
||||
}
|
||||
|
||||
private boolean shouldUseNativeMenu() {
|
||||
return getActivity() instanceof LinkHandlerActivity;
|
||||
}
|
||||
|
||||
private void updateFollowProgressState() {
|
||||
final AsyncTwitterWrapper twitter = getTwitterWrapper();
|
||||
final ParcelableUser user = getUser();
|
||||
|
@ -78,7 +78,7 @@ public class UserMediaTimelineFragment extends BaseSupportFragment
|
||||
|
||||
private SimpleDrawerCallback mDrawerCallback;
|
||||
|
||||
private OnScrollListener mOnScrollListener = new OnScrollListener() {
|
||||
private final OnScrollListener mOnScrollListener = new OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ public class ExtensionsListLoader extends AsyncTaskLoader<List<ExtensionsListLoa
|
||||
@Override
|
||||
public List<ExtensionInfo> loadInBackground() {
|
||||
final List<ApplicationInfo> apps = mPackageManager.getInstalledApplications(PackageManager.GET_META_DATA);
|
||||
final List<ExtensionInfo> extensions = new ArrayList<ExtensionInfo>();
|
||||
final List<ExtensionInfo> extensions = new ArrayList<>();
|
||||
for (final ApplicationInfo info : apps) {
|
||||
final Bundle meta = info.metaData;
|
||||
if (meta != null && meta.getBoolean(METADATA_KEY_EXTENSION, false)) {
|
||||
|
@ -38,71 +38,71 @@ import static org.mariotaku.twidere.util.Utils.getTwitterInstance;
|
||||
|
||||
public abstract class BaseUserListsLoader extends AsyncTaskLoader<List<ParcelableUserList>> {
|
||||
|
||||
protected final NoDuplicatesArrayList<ParcelableUserList> mData = new NoDuplicatesArrayList<ParcelableUserList>();
|
||||
protected final long mAccountId;
|
||||
private final long mCursor;
|
||||
protected final NoDuplicatesArrayList<ParcelableUserList> mData = new NoDuplicatesArrayList<>();
|
||||
protected final long mAccountId;
|
||||
private final long mCursor;
|
||||
|
||||
private long mNextCursor, mPrevCursor;
|
||||
private long mNextCursor, mPrevCursor;
|
||||
|
||||
public BaseUserListsLoader(final Context context, final long account_id, final long cursor,
|
||||
final List<ParcelableUserList> data) {
|
||||
super(context);
|
||||
if (data != null) {
|
||||
mData.addAll(data);
|
||||
}
|
||||
mCursor = cursor;
|
||||
mAccountId = account_id;
|
||||
}
|
||||
public BaseUserListsLoader(final Context context, final long account_id, final long cursor,
|
||||
final List<ParcelableUserList> data) {
|
||||
super(context);
|
||||
if (data != null) {
|
||||
mData.addAll(data);
|
||||
}
|
||||
mCursor = cursor;
|
||||
mAccountId = account_id;
|
||||
}
|
||||
|
||||
public long getCursor() {
|
||||
return mCursor;
|
||||
}
|
||||
public long getCursor() {
|
||||
return mCursor;
|
||||
}
|
||||
|
||||
public long getNextCursor() {
|
||||
return mNextCursor;
|
||||
}
|
||||
public long getNextCursor() {
|
||||
return mNextCursor;
|
||||
}
|
||||
|
||||
public long getPrevCursor() {
|
||||
return mPrevCursor;
|
||||
}
|
||||
public long getPrevCursor() {
|
||||
return mPrevCursor;
|
||||
}
|
||||
|
||||
public abstract List<UserList> getUserLists(final Twitter twitter) throws TwitterException;;
|
||||
public abstract List<UserList> getUserLists(final Twitter twitter) throws TwitterException;
|
||||
|
||||
@Override
|
||||
public List<ParcelableUserList> loadInBackground() {
|
||||
final Twitter twitter = getTwitterInstance(getContext(), mAccountId, true);
|
||||
List<UserList> list_loaded = null;
|
||||
try {
|
||||
list_loaded = getUserLists(twitter);
|
||||
} catch (final TwitterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (list_loaded != null) {
|
||||
final int list_size = list_loaded.size();
|
||||
if (list_loaded instanceof PageableResponseList) {
|
||||
mNextCursor = ((CursorSupport) list_loaded).getNextCursor();
|
||||
mPrevCursor = ((CursorSupport) list_loaded).getPreviousCursor();
|
||||
for (int i = 0; i < list_size; i++) {
|
||||
final UserList list = list_loaded.get(i);
|
||||
mData.add(new ParcelableUserList(list, mAccountId, (mCursor + 1) * 20 + i, isFollowing(list)));
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < list_size; i++) {
|
||||
final UserList list = list_loaded.get(i);
|
||||
mData.add(new ParcelableUserList(list_loaded.get(i), mAccountId, i, isFollowing(list)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(mData);
|
||||
return mData;
|
||||
}
|
||||
@Override
|
||||
public List<ParcelableUserList> loadInBackground() {
|
||||
final Twitter twitter = getTwitterInstance(getContext(), mAccountId, true);
|
||||
List<UserList> list_loaded = null;
|
||||
try {
|
||||
list_loaded = getUserLists(twitter);
|
||||
} catch (final TwitterException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (list_loaded != null) {
|
||||
final int list_size = list_loaded.size();
|
||||
if (list_loaded instanceof PageableResponseList) {
|
||||
mNextCursor = ((CursorSupport) list_loaded).getNextCursor();
|
||||
mPrevCursor = ((CursorSupport) list_loaded).getPreviousCursor();
|
||||
for (int i = 0; i < list_size; i++) {
|
||||
final UserList list = list_loaded.get(i);
|
||||
mData.add(new ParcelableUserList(list, mAccountId, (mCursor + 1) * 20 + i, isFollowing(list)));
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < list_size; i++) {
|
||||
final UserList list = list_loaded.get(i);
|
||||
mData.add(new ParcelableUserList(list_loaded.get(i), mAccountId, i, isFollowing(list)));
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(mData);
|
||||
return mData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartLoading() {
|
||||
forceLoad();
|
||||
}
|
||||
@Override
|
||||
public void onStartLoading() {
|
||||
forceLoad();
|
||||
}
|
||||
|
||||
protected boolean isFollowing(final UserList list) {
|
||||
return list.isFollowing();
|
||||
}
|
||||
protected boolean isFollowing(final UserList list) {
|
||||
return list.isFollowing();
|
||||
}
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public class IntentActivitiesLoader extends AsyncTaskLoader<List<ResolveInfo>> i
|
||||
@Override
|
||||
public List<ResolveInfo> loadInBackground() {
|
||||
final List<ResolveInfo> activities = mPackageManager.queryIntentActivities(mIntent, mFlags);
|
||||
final List<ResolveInfo> result = new ArrayList<ResolveInfo>();
|
||||
final List<ResolveInfo> result = new ArrayList<>();
|
||||
for (final ResolveInfo activity : activities) {
|
||||
final ActivityInfo activityInfo = activity.activityInfo;
|
||||
if (mPackagesBlacklist == null || !ArrayUtils.contains(mPackagesBlacklist, activityInfo.packageName)) {
|
||||
|
@ -46,7 +46,7 @@ public class RawSharedPreferencesData implements JSONParcelable, Constants {
|
||||
}
|
||||
};
|
||||
|
||||
private final Map<String, Object> preferencesMap = new HashMap<String, Object>();
|
||||
private final Map<String, Object> preferencesMap = new HashMap<>();
|
||||
|
||||
public RawSharedPreferencesData(final JSONParcel in) {
|
||||
final JSONIterable json = new JSONIterable(in.getJSON());
|
||||
|
@ -48,7 +48,7 @@ public class SharedPreferencesData implements JSONParcelable, Constants {
|
||||
}
|
||||
};
|
||||
|
||||
private final Map<String, Object> preferencesMap = new HashMap<String, Object>();
|
||||
private final Map<String, Object> preferencesMap = new HashMap<>();
|
||||
|
||||
public SharedPreferencesData(final JSONParcel in) {
|
||||
final Map<String, Preference> supportedMap = DataImportExportUtils.getSupportedPreferencesMap();
|
||||
|
@ -52,9 +52,7 @@ public class StringLongPair {
|
||||
|
||||
StringLongPair that = (StringLongPair) o;
|
||||
|
||||
if (!key.equals(that.key)) return false;
|
||||
|
||||
return true;
|
||||
return key.equals(that.key);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -79,7 +77,7 @@ public class StringLongPair {
|
||||
}
|
||||
|
||||
public static String toString(StringLongPair[] pairs) {
|
||||
if (pairs==null)return null;
|
||||
if (pairs == null) return null;
|
||||
return TwidereArrayUtils.toString(pairs, ';', false);
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ public abstract class AccountsListPreference extends PreferenceCategory implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) {
|
||||
protected void onAttachedToHierarchy(@NonNull final PreferenceManager preferenceManager) {
|
||||
super.onAttachedToHierarchy(preferenceManager);
|
||||
AsyncTaskUtils.executeTask(new LoadAccountsTask(this));
|
||||
}
|
||||
|
@ -27,38 +27,38 @@ import org.mariotaku.twidere.R;
|
||||
|
||||
public class AutoRefreshContentPreference extends MultiSelectListPreference implements Constants {
|
||||
|
||||
public static final boolean DEFAULT_ENABLE_HOME_TTMELINE = false;
|
||||
public static final boolean DEFAULT_ENABLE_MENTIONS = true;
|
||||
public static final boolean DEFAULT_ENABLE_DIRECT_MESSAGES = true;
|
||||
public static final boolean DEFAULT_ENABLE_TRENDS = false;
|
||||
public static final boolean DEFAULT_ENABLE_HOME_TIMELINE = false;
|
||||
public static final boolean DEFAULT_ENABLE_MENTIONS = true;
|
||||
public static final boolean DEFAULT_ENABLE_DIRECT_MESSAGES = true;
|
||||
public static final boolean DEFAULT_ENABLE_TRENDS = false;
|
||||
|
||||
public AutoRefreshContentPreference(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
public AutoRefreshContentPreference(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public AutoRefreshContentPreference(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.preferenceStyle);
|
||||
}
|
||||
public AutoRefreshContentPreference(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.preferenceStyle);
|
||||
}
|
||||
|
||||
public AutoRefreshContentPreference(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
public AutoRefreshContentPreference(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean[] getDefaults() {
|
||||
return new boolean[] { DEFAULT_ENABLE_HOME_TTMELINE, DEFAULT_ENABLE_MENTIONS, DEFAULT_ENABLE_DIRECT_MESSAGES,
|
||||
DEFAULT_ENABLE_TRENDS };
|
||||
}
|
||||
@Override
|
||||
protected boolean[] getDefaults() {
|
||||
return new boolean[]{DEFAULT_ENABLE_HOME_TIMELINE, DEFAULT_ENABLE_MENTIONS, DEFAULT_ENABLE_DIRECT_MESSAGES,
|
||||
DEFAULT_ENABLE_TRENDS};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getKeys() {
|
||||
return new String[] { KEY_AUTO_REFRESH_HOME_TIMELINE, KEY_AUTO_REFRESH_MENTIONS,
|
||||
KEY_AUTO_REFRESH_DIRECT_MESSAGES, KEY_AUTO_REFRESH_TRENDS };
|
||||
}
|
||||
@Override
|
||||
protected String[] getKeys() {
|
||||
return new String[]{KEY_AUTO_REFRESH_HOME_TIMELINE, KEY_AUTO_REFRESH_MENTIONS,
|
||||
KEY_AUTO_REFRESH_DIRECT_MESSAGES, KEY_AUTO_REFRESH_TRENDS};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String[] getNames() {
|
||||
return getContext().getResources().getStringArray(R.array.entries_auto_refresh_content);
|
||||
}
|
||||
@Override
|
||||
protected String[] getNames() {
|
||||
return getContext().getResources().getStringArray(R.array.entries_auto_refresh_content);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -19,14 +19,17 @@
|
||||
|
||||
package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.preference.Preference;
|
||||
import android.os.Bundle;
|
||||
import android.preference.DialogPreference;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
@ -36,18 +39,12 @@ import org.mariotaku.twidere.util.ColorUtils;
|
||||
|
||||
import me.uucky.colorpicker.ColorPickerDialog;
|
||||
|
||||
public class ColorPickerPreference extends Preference implements DialogInterface.OnClickListener, Constants {
|
||||
public class ColorPickerPreference extends DialogPreference implements DialogInterface.OnClickListener, Constants {
|
||||
|
||||
protected int mDefaultValue = Color.WHITE;
|
||||
private int mDefaultValue = Color.WHITE;
|
||||
private boolean mAlphaSliderEnabled = false;
|
||||
|
||||
private static final String ANDROID_NS = "http://schemas.android.com/apk/res/android";
|
||||
private static final String ATTR_DEFAULTVALUE = "defaultValue";
|
||||
private static final String ATTR_ALPHASLIDER = "alphaSlider";
|
||||
|
||||
private final Resources mResources;
|
||||
|
||||
private ColorPickerDialog mDialog;
|
||||
private ColorPickerDialog.Controller mController;
|
||||
|
||||
public ColorPickerPreference(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, android.R.attr.preferenceStyle);
|
||||
@ -55,57 +52,12 @@ public class ColorPickerPreference extends Preference implements DialogInterface
|
||||
|
||||
public ColorPickerPreference(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
mResources = context.getResources();
|
||||
setWidgetLayoutResource(R.layout.preference_widget_color_picker);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public void onActivityDestroy() {
|
||||
if (mDialog == null || !mDialog.isShowing()) return;
|
||||
mDialog.dismiss();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
if (mDialog == null) return;
|
||||
final int color = mDialog.getColor();
|
||||
if (isPersistent()) {
|
||||
persistInt(color);
|
||||
}
|
||||
final OnPreferenceChangeListener listener = getOnPreferenceChangeListener();
|
||||
if (listener != null) {
|
||||
listener.onPreferenceChange(this, color);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDefaultValue(final Object value) {
|
||||
if (!(value instanceof Integer)) return;
|
||||
mDefaultValue = (Integer) value;
|
||||
}
|
||||
|
||||
protected void init(final Context context, final AttributeSet attrs) {
|
||||
if (attrs != null) {
|
||||
final String defaultValue = attrs.getAttributeValue(ANDROID_NS, ATTR_DEFAULTVALUE);
|
||||
if (defaultValue != null && defaultValue.startsWith("#")) {
|
||||
try {
|
||||
setDefaultValue(Color.parseColor(defaultValue));
|
||||
} catch (final IllegalArgumentException e) {
|
||||
Log.e("ColorPickerPreference", "Wrong color: " + defaultValue);
|
||||
setDefaultValue(Color.WHITE);
|
||||
}
|
||||
} else {
|
||||
final int colorResourceId = attrs.getAttributeResourceValue(ANDROID_NS, ATTR_DEFAULTVALUE, 0);
|
||||
if (colorResourceId != 0) {
|
||||
setDefaultValue(context.getResources().getColor(colorResourceId));
|
||||
}
|
||||
}
|
||||
mAlphaSliderEnabled = attrs.getAttributeBooleanValue(null, ATTR_ALPHASLIDER, false);
|
||||
}
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ColorPickerPreferences);
|
||||
mAlphaSliderEnabled = a.getBoolean(R.styleable.ColorPickerPreferences_alphaSlider, false);
|
||||
setDefaultValue(a.getColor(R.styleable.ColorPickerPreferences_defaultColor, 0));
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -116,20 +68,9 @@ public class ColorPickerPreference extends Preference implements DialogInterface
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onClick() {
|
||||
if (mDialog != null && mDialog.isShowing()) return;
|
||||
final Context context = getContext();
|
||||
mDialog = new ColorPickerDialog(context);
|
||||
final Resources res = context.getResources();
|
||||
for (int presetColor : PRESET_COLORS) {
|
||||
mDialog.addColor(res.getColor(presetColor));
|
||||
}
|
||||
mDialog.setInitialColor(getValue());
|
||||
mDialog.setAlphaEnabled(mAlphaSliderEnabled);
|
||||
mDialog.setButton(DialogInterface.BUTTON_POSITIVE, mResources.getString(android.R.string.ok), this);
|
||||
mDialog.setButton(DialogInterface.BUTTON_NEGATIVE, mResources.getString(android.R.string.cancel), this);
|
||||
mDialog.show();
|
||||
return;
|
||||
public void setDefaultValue(final Object value) {
|
||||
if (!(value instanceof Integer)) return;
|
||||
mDefaultValue = (Integer) value;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,6 +80,45 @@ public class ColorPickerPreference extends Preference implements DialogInterface
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(Builder builder) {
|
||||
mController = ColorPickerDialog.Controller.applyToDialogBuilder(builder);
|
||||
final Resources res = builder.getContext().getResources();
|
||||
for (int presetColor : PRESET_COLORS) {
|
||||
mController.addColor(res.getColor(presetColor));
|
||||
}
|
||||
mController.setInitialColor(getValue());
|
||||
mController.setAlphaEnabled(mAlphaSliderEnabled);
|
||||
builder.setPositiveButton(res.getString(android.R.string.ok), this);
|
||||
builder.setNegativeButton(res.getString(android.R.string.cancel), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showDialog(Bundle state) {
|
||||
super.showDialog(state);
|
||||
final Dialog dialog = getDialog();
|
||||
if (dialog != null && mController != null) {
|
||||
dialog.setOnShowListener(mController);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(final DialogInterface dialog, final int which) {
|
||||
switch (which) {
|
||||
case DialogInterface.BUTTON_POSITIVE:
|
||||
if (mController == null) return;
|
||||
final int color = mController.getColor();
|
||||
if (isPersistent()) {
|
||||
persistInt(color);
|
||||
}
|
||||
final OnPreferenceChangeListener listener = getOnPreferenceChangeListener();
|
||||
if (listener != null) {
|
||||
listener.onPreferenceChange(this, color);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private int getValue() {
|
||||
try {
|
||||
if (isPersistent()) return getPersistedInt(mDefaultValue);
|
||||
|
@ -38,7 +38,7 @@ public class ComponentStatePreference extends CheckBoxPreference {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object onGetDefaultValue(final TypedArray a, final int index) {
|
||||
protected Object onGetDefaultValue(@NonNull final TypedArray a, final int index) {
|
||||
return isComponentEnabled();
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,7 @@ package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.KeyCharacterMap;
|
||||
import android.view.KeyEvent;
|
||||
|
||||
import org.mariotaku.twidere.activity.AssistLauncherActivity;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.Preference;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.mariotaku.twidere.util.FlymeUtils;
|
||||
|
||||
public class LeftsideComposeButtonPreference extends AutoFixCheckBoxPreference {
|
||||
|
||||
public LeftsideComposeButtonPreference(final Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public LeftsideComposeButtonPreference(final Context context, final AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public LeftsideComposeButtonPreference(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDependencyChanged(final Preference dependency, final boolean disableDependent) {
|
||||
super.onDependencyChanged(dependency, disableDependent || FlymeUtils.hasSmartBar());
|
||||
}
|
||||
|
||||
}
|
@ -20,6 +20,7 @@
|
||||
package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.SpannableString;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@ -55,7 +56,7 @@ public class LinkHighlightPreference extends AutoInvalidateListPreference implem
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(final View view) {
|
||||
protected void onBindView(@NonNull final View view) {
|
||||
super.onBindView(view);
|
||||
final TextView summary = (TextView) view.findViewById(android.R.id.summary);
|
||||
summary.setVisibility(View.VISIBLE);
|
||||
|
@ -27,6 +27,7 @@ import android.database.Cursor;
|
||||
import android.media.Ringtone;
|
||||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
@ -69,7 +70,7 @@ public class RingtonePreference extends AutoInvalidateListPreference {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(final Builder builder) {
|
||||
protected void onPrepareDialogBuilder(@NonNull final Builder builder) {
|
||||
loadRingtones(getContext());
|
||||
setSelectedItem(ArrayUtils.indexOf(mValues, getPersistedString(null)));
|
||||
builder.setSingleChoiceItems(getEntries(), getSelectedItem(), new OnClickListener() {
|
||||
|
@ -24,6 +24,7 @@ import android.content.res.TypedArray;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.preference.DialogPreference;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
@ -132,7 +133,7 @@ public class SeekBarDialogPreference extends DialogPreference {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindDialogView(final View view) {
|
||||
protected void onBindDialogView(@NonNull final View view) {
|
||||
super.onBindDialogView(view);
|
||||
|
||||
final CharSequence message = getDialogMessage();
|
||||
@ -261,7 +262,7 @@ public class SeekBarDialogPreference extends DialogPreference {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(final Parcel dest, final int flags) {
|
||||
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
|
||||
super.writeToParcel(dest, flags);
|
||||
|
||||
dest.writeInt(minProgress);
|
||||
|
@ -64,7 +64,7 @@ public class SwitchSettingsDetailsPreference extends SwitchPreference implements
|
||||
if (view instanceof ViewGroup) {
|
||||
((ViewGroup) view).setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
|
||||
}
|
||||
final Switch switchView = (Switch) ViewUtils.findViewByType(view, Switch.class);
|
||||
final Switch switchView = ViewUtils.findViewByType(view, Switch.class);
|
||||
if (switchView != null) {
|
||||
switchView.setClickable(true);
|
||||
switchView.setFocusable(true);
|
||||
|
@ -21,6 +21,7 @@ package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.TypefaceSpan;
|
||||
import android.util.AttributeSet;
|
||||
@ -59,7 +60,7 @@ public class ThemeFontFamilyPreference extends AutoInvalidateListPreference impl
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(final View view) {
|
||||
protected void onBindView(@NonNull final View view) {
|
||||
super.onBindView(view);
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return;
|
||||
final TextView summary = (TextView) view.findViewById(android.R.id.summary);
|
||||
|
@ -25,6 +25,7 @@ import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
@ -72,7 +73,7 @@ public class ValueDependencySeekBarDialogPreference extends SeekBarDialogPrefere
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToHierarchy(final PreferenceManager preferenceManager) {
|
||||
protected void onAttachedToHierarchy(@NonNull final PreferenceManager preferenceManager) {
|
||||
super.onAttachedToHierarchy(preferenceManager);
|
||||
final SharedPreferences prefs = getSharedPreferences();
|
||||
if (prefs != null) {
|
||||
|
@ -21,6 +21,7 @@ package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.Preference;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
@ -44,7 +45,7 @@ public final class WizardPageHeaderPreference extends Preference {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(final View view) {
|
||||
protected void onBindView(@NonNull final View view) {
|
||||
super.onBindView(view);
|
||||
final TextView title = (TextView) view.findViewById(android.R.id.title);
|
||||
final TextView summary = (TextView) view.findViewById(android.R.id.summary);
|
||||
|
@ -21,6 +21,7 @@ package org.mariotaku.twidere.preference;
|
||||
|
||||
import android.content.Context;
|
||||
import android.preference.Preference;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
@ -43,7 +44,7 @@ public final class WizardPageNavPreference extends Preference {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(final View view) {
|
||||
protected void onBindView(@NonNull final View view) {
|
||||
super.onBindView(view);
|
||||
final TextView title = (TextView) view.findViewById(android.R.id.title);
|
||||
title.setText(getTitle());
|
||||
|
@ -30,7 +30,6 @@ import android.util.Log;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.util.Utils;
|
||||
|
||||
import edu.tsinghua.spice.SpiceService;
|
||||
import edu.tsinghua.spice.Utilies.NetworkStateUtil;
|
||||
import edu.tsinghua.spice.Utilies.SpiceProfilingUtil;
|
||||
|
||||
|
@ -68,7 +68,6 @@ import org.mariotaku.twidere.util.BitmapUtils;
|
||||
import org.mariotaku.twidere.util.ContentValuesCreator;
|
||||
import org.mariotaku.twidere.util.ListUtils;
|
||||
import org.mariotaku.twidere.util.MediaUploaderInterface;
|
||||
import org.mariotaku.twidere.util.MessagesManager;
|
||||
import org.mariotaku.twidere.util.ParseUtils;
|
||||
import org.mariotaku.twidere.util.StatusCodeMessageUtils;
|
||||
import org.mariotaku.twidere.util.StatusShortenerInterface;
|
||||
@ -110,7 +109,6 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
private ContentResolver mResolver;
|
||||
private NotificationManager mNotificationManager;
|
||||
private AsyncTwitterWrapper mTwitter;
|
||||
private MessagesManager mMessagesManager;
|
||||
|
||||
private MediaUploaderInterface mUploader;
|
||||
private StatusShortenerInterface mShortener;
|
||||
@ -131,7 +129,6 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
mResolver = getContentResolver();
|
||||
mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
mTwitter = app.getTwitterWrapper();
|
||||
mMessagesManager = app.getMessagesManager();
|
||||
final String uploaderComponent = mPreferences.getString(KEY_MEDIA_UPLOADER, null);
|
||||
final String shortenerComponent = mPreferences.getString(KEY_STATUS_SHORTENER, null);
|
||||
mUseUploader = !ServicePickerPreference.isNoneValue(uploaderComponent);
|
||||
@ -146,44 +143,45 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
return START_STICKY;
|
||||
}
|
||||
|
||||
public void showErrorMessage(final CharSequence message, final boolean long_message) {
|
||||
public void showErrorMessage(final CharSequence message, final boolean longMessage) {
|
||||
mHandler.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mMessagesManager.showErrorMessage(message, long_message);
|
||||
Utils.showErrorMessage(BackgroundOperationService.this, message, longMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showErrorMessage(final int action_res, final Exception e, final boolean long_message) {
|
||||
|
||||
public void showErrorMessage(final int actionRes, final Exception e, final boolean longMessage) {
|
||||
mHandler.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mMessagesManager.showErrorMessage(action_res, e, long_message);
|
||||
Utils.showErrorMessage(BackgroundOperationService.this, actionRes, e, longMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showErrorMessage(final int action_res, final String message, final boolean long_message) {
|
||||
|
||||
public void showErrorMessage(final int actionRes, final String message, final boolean longMessage) {
|
||||
mHandler.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
mMessagesManager.showErrorMessage(action_res, message, long_message);
|
||||
Utils.showErrorMessage(BackgroundOperationService.this, actionRes, message, longMessage);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void showOkMessage(final int message_res, final boolean long_message) {
|
||||
mHandler.post(new Runnable() {
|
||||
public void showOkMessage(final int messageRes, final boolean longMessage) {
|
||||
showToast(getString(messageRes), longMessage);
|
||||
}
|
||||
|
||||
private void showToast(final CharSequence message, final boolean longMessage) {
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMessagesManager.showOkMessage(message_res, long_message);
|
||||
Toast.makeText(BackgroundOperationService.this, message, longMessage ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -297,10 +295,10 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
statuses[0] = status;
|
||||
} else
|
||||
return;
|
||||
startForeground(NOTIFICATION_ID_UPDATE_STATUS, updateUpdateStatusNotificaion(this, builder, 0, null));
|
||||
startForeground(NOTIFICATION_ID_UPDATE_STATUS, updateUpdateStatusNotification(this, builder, 0, null));
|
||||
for (final ParcelableStatusUpdate item : statuses) {
|
||||
mNotificationManager.notify(NOTIFICATION_ID_UPDATE_STATUS,
|
||||
updateUpdateStatusNotificaion(this, builder, 0, item));
|
||||
updateUpdateStatusNotification(this, builder, 0, item));
|
||||
final ContentValues draftValues = ContentValuesCreator.createStatusDraft(item,
|
||||
ParcelableAccount.getAccountIds(item.accounts));
|
||||
final Uri draftUri = mResolver.insert(Drafts.CONTENT_URI, draftValues);
|
||||
@ -459,16 +457,16 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
final boolean hasMedia = statusUpdate.media != null && statusUpdate.media.length > 0;
|
||||
|
||||
final String overrideStatusText;
|
||||
if (mUseUploader && hasMedia) {
|
||||
if (mUseUploader && mUploader != null && hasMedia) {
|
||||
final MediaUploadResult uploadResult;
|
||||
try {
|
||||
if (mUploader != null) {
|
||||
mUploader.waitForService();
|
||||
}
|
||||
mUploader.waitForService();
|
||||
uploadResult = mUploader.upload(statusUpdate,
|
||||
UploaderMediaItem.getFromStatusUpdate(this, statusUpdate));
|
||||
} catch (final Exception e) {
|
||||
throw new UploadException(this);
|
||||
} finally {
|
||||
mUploader.unbindService();
|
||||
}
|
||||
if (mUseUploader && hasMedia && uploadResult == null)
|
||||
throw new UploadException(this);
|
||||
@ -491,6 +489,8 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
shortenedResult = mShortener.shorten(statusUpdate, unShortenedText);
|
||||
} catch (final Exception e) {
|
||||
throw new ShortenException(this);
|
||||
} finally {
|
||||
mShortener.unbindService();
|
||||
}
|
||||
if (shortenedResult == null || shortenedResult.shortened == null)
|
||||
throw new ShortenException(this);
|
||||
@ -605,8 +605,8 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
}
|
||||
}
|
||||
|
||||
private static Notification updateSendDirectMessageNotificaion(final Context context,
|
||||
final NotificationCompat.Builder builder, final int progress, final String message) {
|
||||
private static Notification updateSendDirectMessageNotification(final Context context,
|
||||
final NotificationCompat.Builder builder, final int progress, final String message) {
|
||||
builder.setContentTitle(context.getString(R.string.sending_direct_message));
|
||||
if (message != null) {
|
||||
builder.setContentText(message);
|
||||
@ -617,8 +617,8 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static Notification updateUpdateStatusNotificaion(final Context context,
|
||||
final NotificationCompat.Builder builder, final int progress, final ParcelableStatusUpdate status) {
|
||||
private static Notification updateUpdateStatusNotification(final Context context,
|
||||
final NotificationCompat.Builder builder, final int progress, final ParcelableStatusUpdate status) {
|
||||
builder.setContentTitle(context.getString(R.string.updating_status_notification));
|
||||
if (status != null) {
|
||||
builder.setContentText(status.text);
|
||||
@ -670,7 +670,7 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
final int percent = length > 0 ? (int) (position * 100 / length) : 0;
|
||||
if (this.percent != percent) {
|
||||
manager.notify(NOTIFICATION_ID_SEND_DIRECT_MESSAGE,
|
||||
updateSendDirectMessageNotificaion(context, builder, percent, message));
|
||||
updateSendDirectMessageNotification(context, builder, percent, message));
|
||||
}
|
||||
this.percent = percent;
|
||||
}
|
||||
@ -714,7 +714,7 @@ public class BackgroundOperationService extends IntentService implements Constan
|
||||
final int percent = length > 0 ? (int) (position * 100 / length) : 0;
|
||||
if (this.percent != percent) {
|
||||
manager.notify(NOTIFICATION_ID_UPDATE_STATUS,
|
||||
updateUpdateStatusNotificaion(context, builder, percent, statusUpdate));
|
||||
updateUpdateStatusNotification(context, builder, percent, statusUpdate));
|
||||
}
|
||||
this.percent = percent;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
package org.mariotaku.twidere.text.method;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.Layout;
|
||||
import android.text.NoCopySpan;
|
||||
import android.text.Selection;
|
||||
@ -47,7 +48,7 @@ public class StatusContentMovementMethod extends ArrowKeyMovementMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTakeFocus(final TextView view, final Spannable text, final int dir) {
|
||||
public void onTakeFocus(@NonNull final TextView view, @NonNull final Spannable text, final int dir) {
|
||||
Selection.removeSelection(text);
|
||||
|
||||
if ((dir & View.FOCUS_BACKWARD) != 0) {
|
||||
@ -58,7 +59,7 @@ public class StatusContentMovementMethod extends ArrowKeyMovementMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(final TextView widget, final Spannable buffer, final MotionEvent event) {
|
||||
public boolean onTouchEvent(@NonNull final TextView widget, @NonNull final Spannable buffer, @NonNull final MotionEvent event) {
|
||||
final int action = event.getAction();
|
||||
|
||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
|
||||
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.util;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.os.IInterface;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.util.ServiceUtils.ServiceToken;
|
||||
|
||||
import static org.mariotaku.twidere.util.ServiceUtils.bindToService;
|
||||
import static org.mariotaku.twidere.util.ServiceUtils.unbindFromService;
|
||||
|
||||
public abstract class AbsServiceInterface<I extends IInterface> implements Constants, IInterface {
|
||||
|
||||
private final Context mContext;
|
||||
private final String mShortenerName;
|
||||
private I mIInterface;
|
||||
|
||||
private ServiceToken mToken;
|
||||
|
||||
private final ServiceConnection mConnection = new ServiceConnection() {
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName service, final IBinder obj) {
|
||||
mIInterface = AbsServiceInterface.this.onServiceConnected(service, obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName service) {
|
||||
mIInterface = null;
|
||||
}
|
||||
};
|
||||
|
||||
protected abstract I onServiceConnected(ComponentName service, IBinder obj);
|
||||
|
||||
protected AbsServiceInterface(final Context context, final String shortenerName) {
|
||||
mContext = context;
|
||||
mShortenerName = shortenerName;
|
||||
}
|
||||
|
||||
public final I getInterface() {
|
||||
return mIInterface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBinder asBinder() {
|
||||
// Useless here
|
||||
return mIInterface.asBinder();
|
||||
}
|
||||
|
||||
public final void unbindService() {
|
||||
unbindFromService(mToken);
|
||||
}
|
||||
|
||||
public final void waitForService() {
|
||||
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
|
||||
final ComponentName component = ComponentName.unflattenFromString(mShortenerName);
|
||||
intent.setComponent(component);
|
||||
mToken = bindToService(mContext, intent, mConnection);
|
||||
while (mIInterface == null) {
|
||||
try {
|
||||
Thread.sleep(100L);
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,342 +0,0 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2015 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.DecelerateInterpolator;
|
||||
|
||||
/**
|
||||
* {@link RecyclerView.SmoothScroller} implementation which uses
|
||||
* {@link android.view.animation.LinearInterpolator} until the target position becames a child of
|
||||
* the RecyclerView and then uses
|
||||
* {@link android.view.animation.DecelerateInterpolator} to slowly approach to target position.
|
||||
*/
|
||||
abstract public class AccelerateSmoothScroller extends RecyclerView.SmoothScroller {
|
||||
|
||||
private static final String TAG = "LinearSmoothScroller";
|
||||
|
||||
private static final boolean DEBUG = false;
|
||||
|
||||
private static final float MILLISECONDS_PER_INCH = 25f;
|
||||
|
||||
private static final int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000;
|
||||
|
||||
/**
|
||||
* Align child view's left or top with parent view's left or top
|
||||
*
|
||||
* @see #calculateDtToFit(int, int, int, int, int)
|
||||
* @see #calculateDxToMakeVisible(android.view.View, int)
|
||||
* @see #calculateDyToMakeVisible(android.view.View, int)
|
||||
*/
|
||||
public static final int SNAP_TO_START = -1;
|
||||
|
||||
/**
|
||||
* Align child view's right or bottom with parent view's right or bottom
|
||||
*
|
||||
* @see #calculateDtToFit(int, int, int, int, int)
|
||||
* @see #calculateDxToMakeVisible(android.view.View, int)
|
||||
* @see #calculateDyToMakeVisible(android.view.View, int)
|
||||
*/
|
||||
public static final int SNAP_TO_END = 1;
|
||||
|
||||
/**
|
||||
* <p>Decides if the child should be snapped from start or end, depending on where it
|
||||
* currently is in relation to its parent.</p>
|
||||
* <p>For instance, if the view is virtually on the left of RecyclerView, using
|
||||
* {@code SNAP_TO_ANY} is the same as using {@code SNAP_TO_START}</p>
|
||||
*
|
||||
* @see #calculateDtToFit(int, int, int, int, int)
|
||||
* @see #calculateDxToMakeVisible(android.view.View, int)
|
||||
* @see #calculateDyToMakeVisible(android.view.View, int)
|
||||
*/
|
||||
public static final int SNAP_TO_ANY = 0;
|
||||
|
||||
// Trigger a scroll to a further distance than TARGET_SEEK_SCROLL_DISTANCE_PX so that if target
|
||||
// view is not laid out until interim target position is reached, we can detect the case before
|
||||
// scrolling slows down and reschedule another interim target scroll
|
||||
private static final float TARGET_SEEK_EXTRA_SCROLL_RATIO = 1.2f;
|
||||
|
||||
protected final AccelerateInterpolator mLinearInterpolator = new AccelerateInterpolator();
|
||||
|
||||
protected final DecelerateInterpolator mDecelerateInterpolator = new DecelerateInterpolator();
|
||||
|
||||
protected PointF mTargetVector;
|
||||
|
||||
private final float MILLISECONDS_PER_PX;
|
||||
|
||||
// Temporary variables to keep track of the interim scroll target. These values do not
|
||||
// point to a real item position, rather point to an estimated location pixels.
|
||||
protected int mInterimTargetDx = 0, mInterimTargetDy = 0;
|
||||
|
||||
public AccelerateSmoothScroller(Context context, float factor) {
|
||||
MILLISECONDS_PER_PX = calculateSpeedPerPixel(context.getResources().getDisplayMetrics()) * factor;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onStart() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onTargetFound(View targetView, RecyclerView.State state, Action action) {
|
||||
final int dx = calculateDxToMakeVisible(targetView, getHorizontalSnapPreference());
|
||||
final int dy = calculateDyToMakeVisible(targetView, getVerticalSnapPreference());
|
||||
final int distance = (int) Math.sqrt(dx * dx + dy * dy);
|
||||
final int time = calculateTimeForDeceleration(distance);
|
||||
if (time > 0) {
|
||||
action.update(-dx, -dy, time, mDecelerateInterpolator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onSeekTargetStep(int dx, int dy, RecyclerView.State state, Action action) {
|
||||
if (getChildCount() == 0) {
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
if (DEBUG && mTargetVector != null
|
||||
&& ((mTargetVector.x * dx < 0 || mTargetVector.y * dy < 0))) {
|
||||
throw new IllegalStateException("Scroll happened in the opposite direction"
|
||||
+ " of the target. Some calculations are wrong");
|
||||
}
|
||||
mInterimTargetDx = clampApplyScroll(mInterimTargetDx, dx);
|
||||
mInterimTargetDy = clampApplyScroll(mInterimTargetDy, dy);
|
||||
|
||||
if (mInterimTargetDx == 0 && mInterimTargetDy == 0) {
|
||||
updateActionForInterimTarget(action);
|
||||
} // everything is valid, keep going
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
protected void onStop() {
|
||||
mInterimTargetDx = mInterimTargetDy = 0;
|
||||
mTargetVector = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the scroll speed.
|
||||
*
|
||||
* @param displayMetrics DisplayMetrics to be used for real dimension calculations
|
||||
* @return The time (in ms) it should take for each pixel. For instance, if returned value is
|
||||
* 2 ms, it means scrolling 1000 pixels with LinearInterpolation should take 2 seconds.
|
||||
*/
|
||||
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
|
||||
return MILLISECONDS_PER_INCH / displayMetrics.densityDpi;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Calculates the time for deceleration so that transition from LinearInterpolator to
|
||||
* DecelerateInterpolator looks smooth.</p>
|
||||
*
|
||||
* @param dx Distance to scroll
|
||||
* @return Time for DecelerateInterpolator to smoothly traverse the distance when transitioning
|
||||
* from LinearInterpolation
|
||||
*/
|
||||
protected int calculateTimeForDeceleration(int dx) {
|
||||
// we want to cover same area with the linear interpolator for the first 10% of the
|
||||
// interpolation. After that, deceleration will take control.
|
||||
// area under curve (1-(1-x)^2) can be calculated as (1 - x/3) * x * x
|
||||
// which gives 0.100028 when x = .3356
|
||||
// this is why we divide linear scrolling time with .3356
|
||||
return (int) Math.ceil(calculateTimeForScrolling(dx) / .3356);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the time it should take to scroll the given distance (in pixels)
|
||||
*
|
||||
* @param dx Distance in pixels that we want to scroll
|
||||
* @return Time in milliseconds
|
||||
* @see #calculateSpeedPerPixel(android.util.DisplayMetrics)
|
||||
*/
|
||||
protected int calculateTimeForScrolling(int dx) {
|
||||
// In a case where dx is very small, rounding may return 0 although dx > 0.
|
||||
// To avoid that issue, ceil the result so that if dx > 0, we'll always return positive
|
||||
// time.
|
||||
return (int) Math.ceil(Math.abs(dx) * MILLISECONDS_PER_PX);
|
||||
}
|
||||
|
||||
/**
|
||||
* When scrolling towards a child view, this method defines whether we should align the left
|
||||
* or the right edge of the child with the parent RecyclerView.
|
||||
*
|
||||
* @return SNAP_TO_START, SNAP_TO_END or SNAP_TO_ANY; depending on the current target vector
|
||||
* @see #SNAP_TO_START
|
||||
* @see #SNAP_TO_END
|
||||
* @see #SNAP_TO_ANY
|
||||
*/
|
||||
protected int getHorizontalSnapPreference() {
|
||||
return mTargetVector == null || mTargetVector.x == 0 ? SNAP_TO_ANY :
|
||||
mTargetVector.x > 0 ? SNAP_TO_END : SNAP_TO_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* When scrolling towards a child view, this method defines whether we should align the top
|
||||
* or the bottom edge of the child with the parent RecyclerView.
|
||||
*
|
||||
* @return SNAP_TO_START, SNAP_TO_END or SNAP_TO_ANY; depending on the current target vector
|
||||
* @see #SNAP_TO_START
|
||||
* @see #SNAP_TO_END
|
||||
* @see #SNAP_TO_ANY
|
||||
*/
|
||||
protected int getVerticalSnapPreference() {
|
||||
return mTargetVector == null || mTargetVector.y == 0 ? SNAP_TO_ANY :
|
||||
mTargetVector.y > 0 ? SNAP_TO_END : SNAP_TO_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* When the target scroll position is not a child of the RecyclerView, this method calculates
|
||||
* a direction vector towards that child and triggers a smooth scroll.
|
||||
*
|
||||
* @see #computeScrollVectorForPosition(int)
|
||||
*/
|
||||
protected void updateActionForInterimTarget(Action action) {
|
||||
// find an interim target position
|
||||
PointF scrollVector = computeScrollVectorForPosition(getTargetPosition());
|
||||
if (scrollVector == null || (scrollVector.x == 0 && scrollVector.y == 0)) {
|
||||
Log.e(TAG, "To support smooth scrolling, you should override \n"
|
||||
+ "LayoutManager#computeScrollVectorForPosition.\n"
|
||||
+ "Falling back to instant scroll");
|
||||
final int target = getTargetPosition();
|
||||
stop();
|
||||
instantScrollToPosition(target);
|
||||
return;
|
||||
}
|
||||
normalize(scrollVector);
|
||||
mTargetVector = scrollVector;
|
||||
|
||||
mInterimTargetDx = (int) (TARGET_SEEK_SCROLL_DISTANCE_PX * scrollVector.x);
|
||||
mInterimTargetDy = (int) (TARGET_SEEK_SCROLL_DISTANCE_PX * scrollVector.y);
|
||||
final int time = calculateTimeForScrolling(TARGET_SEEK_SCROLL_DISTANCE_PX);
|
||||
// To avoid UI hiccups, trigger a smooth scroll to a distance little further than the
|
||||
// interim target. Since we track the distance travelled in onSeekTargetStep callback, it
|
||||
// won't actually scroll more than what we need.
|
||||
action.update((int) (mInterimTargetDx * TARGET_SEEK_EXTRA_SCROLL_RATIO)
|
||||
, (int) (mInterimTargetDy * TARGET_SEEK_EXTRA_SCROLL_RATIO)
|
||||
, (int) (time * TARGET_SEEK_EXTRA_SCROLL_RATIO), mLinearInterpolator);
|
||||
}
|
||||
|
||||
private int clampApplyScroll(int tmpDt, int dt) {
|
||||
final int before = tmpDt;
|
||||
tmpDt -= dt;
|
||||
if (before * tmpDt <= 0) { // changed sign, reached 0 or was 0, reset
|
||||
return 0;
|
||||
}
|
||||
return tmpDt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for {@link #calculateDxToMakeVisible(android.view.View, int)} and
|
||||
* {@link #calculateDyToMakeVisible(android.view.View, int)}
|
||||
*/
|
||||
public int calculateDtToFit(int viewStart, int viewEnd, int boxStart, int boxEnd, int
|
||||
snapPreference) {
|
||||
switch (snapPreference) {
|
||||
case SNAP_TO_START:
|
||||
return boxStart - viewStart;
|
||||
case SNAP_TO_END:
|
||||
return boxEnd - viewEnd;
|
||||
case SNAP_TO_ANY:
|
||||
final int dtStart = boxStart - viewStart;
|
||||
if (dtStart > 0) {
|
||||
return dtStart;
|
||||
}
|
||||
final int dtEnd = boxEnd - viewEnd;
|
||||
if (dtEnd < 0) {
|
||||
return dtEnd;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("snap preference should be one of the"
|
||||
+ " constants defined in SmoothScroller, starting with SNAP_");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the vertical scroll amount necessary to make the given view fully visible
|
||||
* inside the RecyclerView.
|
||||
*
|
||||
* @param view The view which we want to make fully visible
|
||||
* @param snapPreference The edge which the view should snap to when entering the visible
|
||||
* area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or
|
||||
* {@link #SNAP_TO_END}.
|
||||
* @return The vertical scroll amount necessary to make the view visible with the given
|
||||
* snap preference.
|
||||
*/
|
||||
public int calculateDyToMakeVisible(View view, int snapPreference) {
|
||||
final RecyclerView.LayoutManager layoutManager = getLayoutManager();
|
||||
if (!layoutManager.canScrollVertically()) {
|
||||
return 0;
|
||||
}
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
final int top = layoutManager.getDecoratedTop(view) - params.topMargin;
|
||||
final int bottom = layoutManager.getDecoratedBottom(view) + params.bottomMargin;
|
||||
final int start = layoutManager.getPaddingTop();
|
||||
final int end = layoutManager.getHeight() - layoutManager.getPaddingBottom();
|
||||
return calculateDtToFit(top, bottom, start, end, snapPreference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the horizontal scroll amount necessary to make the given view fully visible
|
||||
* inside the RecyclerView.
|
||||
*
|
||||
* @param view The view which we want to make fully visible
|
||||
* @param snapPreference The edge which the view should snap to when entering the visible
|
||||
* area. One of {@link #SNAP_TO_START}, {@link #SNAP_TO_END} or
|
||||
* {@link #SNAP_TO_END}
|
||||
* @return The vertical scroll amount necessary to make the view visible with the given
|
||||
* snap preference.
|
||||
*/
|
||||
public int calculateDxToMakeVisible(View view, int snapPreference) {
|
||||
final RecyclerView.LayoutManager layoutManager = getLayoutManager();
|
||||
if (!layoutManager.canScrollHorizontally()) {
|
||||
return 0;
|
||||
}
|
||||
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
|
||||
view.getLayoutParams();
|
||||
final int left = layoutManager.getDecoratedLeft(view) - params.leftMargin;
|
||||
final int right = layoutManager.getDecoratedRight(view) + params.rightMargin;
|
||||
final int start = layoutManager.getPaddingLeft();
|
||||
final int end = layoutManager.getWidth() - layoutManager.getPaddingRight();
|
||||
return calculateDtToFit(left, right, start, end, snapPreference);
|
||||
}
|
||||
|
||||
abstract public PointF computeScrollVectorForPosition(int targetPosition);
|
||||
}
|
@ -116,8 +116,7 @@ public final class AsyncTaskManager {
|
||||
|
||||
public boolean isExecuting(final int hashCode) {
|
||||
final ManagedAsyncTask<?, ?, ?> task = findTask(hashCode);
|
||||
if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) return true;
|
||||
return false;
|
||||
return task != null && task.getStatus() == AsyncTask.Status.RUNNING;
|
||||
}
|
||||
|
||||
public void remove(final int hashCode) {
|
||||
@ -128,7 +127,7 @@ public final class AsyncTaskManager {
|
||||
}
|
||||
}
|
||||
|
||||
private <T> ManagedAsyncTask<?, ?, ?> findTask(final int hashCode) {
|
||||
private ManagedAsyncTask<?, ?, ?> findTask(final int hashCode) {
|
||||
for (final ManagedAsyncTask<?, ?, ?> task : getTaskSpecList()) {
|
||||
if (hashCode == task.hashCode()) return task;
|
||||
}
|
||||
|
@ -110,6 +110,9 @@ import static org.mariotaku.twidere.util.Utils.getNewestStatusIdsFromDatabase;
|
||||
import static org.mariotaku.twidere.util.Utils.getStatusCountInDatabase;
|
||||
import static org.mariotaku.twidere.util.Utils.getTwitterInstance;
|
||||
import static org.mariotaku.twidere.util.Utils.getUserName;
|
||||
import static org.mariotaku.twidere.util.Utils.showErrorMessage;
|
||||
import static org.mariotaku.twidere.util.Utils.showInfoMessage;
|
||||
import static org.mariotaku.twidere.util.Utils.showOkMessage;
|
||||
import static org.mariotaku.twidere.util.Utils.truncateMessages;
|
||||
import static org.mariotaku.twidere.util.Utils.truncateStatuses;
|
||||
import static org.mariotaku.twidere.util.content.ContentResolverUtils.bulkDelete;
|
||||
@ -122,7 +125,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
private final Context mContext;
|
||||
private final AsyncTaskManager mAsyncTaskManager;
|
||||
private final SharedPreferences mPreferences;
|
||||
private final MessagesManager mMessagesManager;
|
||||
private final ContentResolver mResolver;
|
||||
|
||||
private int mGetHomeTimelineTaskId, mGetMentionsTaskId;
|
||||
@ -140,7 +142,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
mContext = context;
|
||||
final TwidereApplication app = TwidereApplication.getInstance(context);
|
||||
mAsyncTaskManager = app.getAsyncTaskManager();
|
||||
mMessagesManager = app.getMessagesManager();
|
||||
mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
mResolver = context.getContentResolver();
|
||||
}
|
||||
@ -168,10 +169,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int cancelRetweetAsync(@NonNull final ParcelableStatus status) {
|
||||
return cancelRetweetAsync(status.account_id, status.id, status.my_retweet_id);
|
||||
}
|
||||
|
||||
public void clearNotificationAsync(final int notificationType) {
|
||||
clearNotificationAsync(notificationType, 0);
|
||||
}
|
||||
@ -196,10 +193,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
public int createFavoriteAsync(final ParcelableStatus status) {
|
||||
return createFavoriteAsync(status.account_id, status.id);
|
||||
}
|
||||
|
||||
public int createFriendshipAsync(final long accountId, final long userId) {
|
||||
final CreateFriendshipTask task = new CreateFriendshipTask(accountId, userId);
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
@ -256,10 +249,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
public int destroyFavoriteAsync(final ParcelableStatus status) {
|
||||
return destroyFavoriteAsync(status.account_id, status.id);
|
||||
}
|
||||
|
||||
public int destroyFriendshipAsync(final long accountId, final long user_id) {
|
||||
final DestroyFriendshipTask task = new DestroyFriendshipTask(accountId, user_id);
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
@ -478,25 +467,6 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int updateProfile(final long accountId, final String name, final String url, final String location,
|
||||
final String description) {
|
||||
final UpdateProfileTask task = new UpdateProfileTask(mContext, mAsyncTaskManager, accountId, name, url,
|
||||
location, description);
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
public int updateProfileBannerImage(final long accountId, final Uri image_uri, final boolean delete_image) {
|
||||
final UpdateProfileBannerImageTask task = new UpdateProfileBannerImageTask(mContext, mAsyncTaskManager,
|
||||
accountId, image_uri, delete_image);
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
public int updateProfileImage(final long accountId, final Uri imageUri, final boolean deleteImage) {
|
||||
final UpdateProfileImageTask task = new UpdateProfileImageTask(mContext, mAsyncTaskManager, accountId,
|
||||
imageUri, deleteImage);
|
||||
return mAsyncTaskManager.add(task, true);
|
||||
}
|
||||
|
||||
public int updateStatusAsync(final long[] accountIds, final String text, final ParcelableLocation location,
|
||||
final ParcelableMediaUpdate[] media, final long inReplyToStatusId,
|
||||
final boolean isPossiblySensitive) {
|
||||
@ -580,11 +550,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
protected void onPostExecute(final SingleResponse<ParcelableUser> result) {
|
||||
super.onPostExecute(result);
|
||||
if (result.hasData()) {
|
||||
Utils.showOkMessage(mContext, R.string.profile_banner_image_updated, false);
|
||||
showOkMessage(mContext, R.string.profile_banner_image_updated, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new ProfileUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
Utils.showErrorMessage(mContext, R.string.action_updating_profile_banner_image, result.getException(),
|
||||
showErrorMessage(mContext, R.string.action_updating_profile_banner_image, result.getException(),
|
||||
true);
|
||||
}
|
||||
}
|
||||
@ -650,11 +620,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
protected void onPostExecute(final SingleResponse<ParcelableUser> result) {
|
||||
super.onPostExecute(result);
|
||||
if (result.hasData()) {
|
||||
Utils.showOkMessage(mContext, R.string.profile_image_updated, false);
|
||||
showOkMessage(mContext, R.string.profile_image_updated, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new ProfileUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
Utils.showErrorMessage(mContext, R.string.action_updating_profile_image, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_updating_profile_image, result.getException(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -685,11 +655,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
@Override
|
||||
protected void onPostExecute(final SingleResponse<ParcelableUser> result) {
|
||||
if (result.hasData()) {
|
||||
Utils.showOkMessage(context, R.string.profile_updated, false);
|
||||
showOkMessage(context, R.string.profile_updated, false);
|
||||
final Bus bus = TwidereApplication.getInstance(context).getMessageBus();
|
||||
bus.post(new ProfileUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
Utils.showErrorMessage(context, context.getString(R.string.action_updating_profile),
|
||||
showErrorMessage(context, context.getString(R.string.action_updating_profile),
|
||||
result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
@ -735,10 +705,10 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
final User user = result.getData();
|
||||
final String message = mContext.getString(R.string.accepted_users_follow_request,
|
||||
getUserName(mContext, user));
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_accepting_follow_request, result.getException(),
|
||||
false);
|
||||
showErrorMessage(mContext, R.string.action_accepting_follow_request,
|
||||
result.getException(), false);
|
||||
}
|
||||
final Intent intent = new Intent(BROADCAST_FRIENDSHIP_ACCEPTED);
|
||||
intent.putExtra(EXTRA_USER_ID, mUserId);
|
||||
@ -792,9 +762,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
message = res.getQuantityString(R.plurals.added_N_users_to_list, users.length, users.length,
|
||||
result.getData().name);
|
||||
}
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_adding_member, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_adding_member, result.getException(), true);
|
||||
}
|
||||
final Intent intent = new Intent(BROADCAST_USER_LIST_MEMBERS_ADDED);
|
||||
intent.putExtra(EXTRA_USER_LIST, result.getData());
|
||||
@ -873,11 +843,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
if (result.hasData()) {
|
||||
final String message = mContext.getString(R.string.blocked_user,
|
||||
getUserName(mContext, result.getData()));
|
||||
mMessagesManager.showInfoMessage(message, false);
|
||||
showInfoMessage(mContext, message, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FriendshipUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_blocking, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_blocking, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -950,9 +920,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FavoriteCreatedEvent(status));
|
||||
mMessagesManager.showOkMessage(R.string.status_favorited, false);
|
||||
showOkMessage(mContext, R.string.status_favorited, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_favoriting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_favoriting, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1002,11 +972,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
} else {
|
||||
message = mContext.getString(R.string.followed_user, getUserName(mContext, user));
|
||||
}
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FriendshipUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_following, result.getException(), false);
|
||||
showErrorMessage(mContext, R.string.action_following, result.getException(), false);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1058,9 +1028,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
@Override
|
||||
protected void onPostExecute(final ListResponse<Long> result) {
|
||||
if (result.list != null) {
|
||||
mMessagesManager.showInfoMessage(R.string.users_blocked, false);
|
||||
showInfoMessage(mContext, R.string.users_blocked, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_blocking, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_blocking, result.getException(), true);
|
||||
}
|
||||
final Intent intent = new Intent(BROADCAST_MULTI_BLOCKSTATE_CHANGED);
|
||||
intent.putExtra(EXTRA_USER_ID, user_ids);
|
||||
@ -1103,11 +1073,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
if (result.hasData()) {
|
||||
final String message = mContext.getString(R.string.muted_user,
|
||||
getUserName(mContext, result.getData()));
|
||||
mMessagesManager.showInfoMessage(message, false);
|
||||
showInfoMessage(mContext, message, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FriendshipUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_muting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_muting, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1140,9 +1110,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
protected void onPostExecute(final SingleResponse<SavedSearch> result) {
|
||||
if (result.hasData()) {
|
||||
final String message = mContext.getString(R.string.search_name_saved, result.getData().getQuery());
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_saving_search, result.getException(), false);
|
||||
showErrorMessage(mContext, R.string.action_saving_search, result.getException(), false);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1179,12 +1149,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
final boolean succeed = result.hasData();
|
||||
if (succeed) {
|
||||
final String message = mContext.getString(R.string.subscribed_to_list, result.getData().name);
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
final Intent intent = new Intent(BROADCAST_USER_LIST_SUBSCRIBED);
|
||||
intent.putExtra(EXTRA_USER_LIST, result.getData());
|
||||
mContext.sendBroadcast(intent);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_subscribing_to_list, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_subscribing_to_list, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1223,12 +1193,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
if (result.hasData()) {
|
||||
final UserList userList = result.getData();
|
||||
final String message = mContext.getString(R.string.created_list, userList.getName());
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
final Intent intent = new Intent(BROADCAST_USER_LIST_CREATED);
|
||||
intent.putExtra(EXTRA_USER_LIST, new ParcelableUserList(userList, account_id));
|
||||
mContext.sendBroadcast(intent);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_creating_list, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_creating_list, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1279,13 +1249,13 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
message = res.getQuantityString(R.plurals.deleted_N_users_from_list, users.length, users.length,
|
||||
result.getData().name);
|
||||
}
|
||||
mMessagesManager.showInfoMessage(message, false);
|
||||
showInfoMessage(mContext, message, false);
|
||||
final Intent intent = new Intent(BROADCAST_USER_LIST_MEMBERS_DELETED);
|
||||
intent.putExtra(EXTRA_USER_LIST, result.getData());
|
||||
intent.putExtra(EXTRA_USERS, users);
|
||||
mContext.sendBroadcast(intent);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_deleting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_deleting, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1330,9 +1300,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
final User user = result.getData();
|
||||
final String message = mContext.getString(R.string.denied_users_follow_request,
|
||||
getUserName(mContext, user));
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_denying_follow_request, result.getException(), false);
|
||||
showErrorMessage(mContext, R.string.action_denying_follow_request, result.getException(), false);
|
||||
}
|
||||
final Intent intent = new Intent(BROADCAST_FRIENDSHIP_DENIED);
|
||||
intent.putExtra(EXTRA_USER_ID, mUserId);
|
||||
@ -1372,11 +1342,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
if (result.hasData()) {
|
||||
final String message = mContext.getString(R.string.unblocked_user,
|
||||
getUserName(mContext, result.getData()));
|
||||
mMessagesManager.showInfoMessage(message, false);
|
||||
showInfoMessage(mContext, message, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FriendshipUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_unblocking, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_unblocking, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1430,9 +1400,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
super.onPostExecute(result);
|
||||
if (result == null) return;
|
||||
if (result.hasData() || isMessageNotFound(result.getException())) {
|
||||
mMessagesManager.showInfoMessage(R.string.direct_message_deleted, false);
|
||||
showInfoMessage(mContext, R.string.direct_message_deleted, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_deleting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_deleting, result.getException(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1506,9 +1476,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FavoriteDestroyedEvent(status));
|
||||
mMessagesManager.showInfoMessage(R.string.status_unfavorited, false);
|
||||
showInfoMessage(mContext, R.string.status_unfavorited, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_unfavoriting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_unfavoriting, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1560,11 +1530,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
if (result.hasData()) {
|
||||
final String message = mContext.getString(R.string.unfollowed_user,
|
||||
getUserName(mContext, result.getData()));
|
||||
mMessagesManager.showInfoMessage(message, false);
|
||||
showInfoMessage(mContext, message, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FriendshipUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_unfollowing, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_unfollowing, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1601,11 +1571,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
if (result.hasData()) {
|
||||
final String message = mContext.getString(R.string.unmuted_user,
|
||||
getUserName(mContext, result.getData()));
|
||||
mMessagesManager.showInfoMessage(message, false);
|
||||
showInfoMessage(mContext, message, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FriendshipUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_unmuting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_unmuting, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1638,9 +1608,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
protected void onPostExecute(final SingleResponse<SavedSearch> result) {
|
||||
if (result.hasData()) {
|
||||
final String message = mContext.getString(R.string.search_name_deleted, result.getData().getQuery());
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_deleting_search, result.getException(), false);
|
||||
showErrorMessage(mContext, R.string.action_deleting_search, result.getException(), false);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1695,14 +1665,14 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
if (result.hasData()) {
|
||||
final ParcelableStatus status = result.getData();
|
||||
if (status.retweet_id > 0) {
|
||||
mMessagesManager.showInfoMessage(R.string.retweet_cancelled, false);
|
||||
showInfoMessage(mContext, R.string.retweet_cancelled, false);
|
||||
} else {
|
||||
mMessagesManager.showInfoMessage(R.string.status_deleted, false);
|
||||
showInfoMessage(mContext, R.string.status_deleted, false);
|
||||
}
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new StatusDestroyedEvent(status));
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_deleting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_deleting, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1741,12 +1711,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
final boolean succeed = result.hasData();
|
||||
if (succeed) {
|
||||
final String message = mContext.getString(R.string.unsubscribed_from_list, result.getData().name);
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
final Intent intent = new Intent(BROADCAST_USER_LIST_UNSUBSCRIBED);
|
||||
intent.putExtra(EXTRA_USER_LIST, result.getData());
|
||||
mContext.sendBroadcast(intent);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_unsubscribing_from_list, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_unsubscribing_from_list, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -1787,12 +1757,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
final boolean succeed = result.hasData();
|
||||
if (succeed) {
|
||||
final String message = mContext.getString(R.string.deleted_list, result.getData().name);
|
||||
mMessagesManager.showInfoMessage(message, false);
|
||||
showInfoMessage(mContext, message, false);
|
||||
final Intent intent = new Intent(BROADCAST_USER_LIST_DELETED);
|
||||
intent.putExtra(EXTRA_USER_LIST, result.getData());
|
||||
mContext.sendBroadcast(intent);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_deleting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_deleting, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -2300,7 +2270,7 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
new Expression(String.format(Locale.ROOT, "%s IN (%s)", Statuses.USER_ID, user_id_where)));
|
||||
mResolver.delete(uri, where.getSQL(), null);
|
||||
}
|
||||
mMessagesManager.showInfoMessage(R.string.reported_users_for_spam, false);
|
||||
showInfoMessage(mContext, R.string.reported_users_for_spam, false);
|
||||
final Intent intent = new Intent(BROADCAST_MULTI_BLOCKSTATE_CHANGED);
|
||||
intent.putExtra(EXTRA_USER_IDS, user_ids);
|
||||
intent.putExtra(EXTRA_ACCOUNT_ID, account_id);
|
||||
@ -2344,11 +2314,11 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
+ user_id;
|
||||
mResolver.delete(uri, where, null);
|
||||
}
|
||||
mMessagesManager.showInfoMessage(R.string.reported_user_for_spam, false);
|
||||
showInfoMessage(mContext, R.string.reported_user_for_spam, false);
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new FriendshipUpdatedEvent(result.getData()));
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_reporting_for_spam, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_reporting_for_spam, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -2433,9 +2403,9 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
//end
|
||||
final Bus bus = TwidereApplication.getInstance(mContext).getMessageBus();
|
||||
bus.post(new StatusRetweetedEvent(status));
|
||||
mMessagesManager.showOkMessage(R.string.status_retweeted, false);
|
||||
showOkMessage(mContext, R.string.status_retweeted, false);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_retweeting, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_retweeting, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
@ -2538,12 +2508,12 @@ public class AsyncTwitterWrapper extends TwitterWrapper {
|
||||
protected void onPostExecute(final SingleResponse<ParcelableUserList> result) {
|
||||
if (result.hasData() && result.getData().id > 0) {
|
||||
final String message = mContext.getString(R.string.updated_list_details, result.getData().name);
|
||||
mMessagesManager.showOkMessage(message, false);
|
||||
showOkMessage(mContext, message, false);
|
||||
final Intent intent = new Intent(BROADCAST_USER_LIST_DETAILS_UPDATED);
|
||||
intent.putExtra(EXTRA_LIST_ID, listId);
|
||||
mContext.sendBroadcast(intent);
|
||||
} else {
|
||||
mMessagesManager.showErrorMessage(R.string.action_updating_details, result.getException(), true);
|
||||
showErrorMessage(mContext, R.string.action_updating_details, result.getException(), true);
|
||||
}
|
||||
super.onPostExecute(result);
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ public class BitmapUtils {
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
final Bitmap b = BitmapDecodeHelper.decode(path, o);
|
||||
final Bitmap.CompressFormat format = Utils.getBitmapCompressFormatByMimetype(o.outMimeType,
|
||||
final Bitmap.CompressFormat format = Utils.getBitmapCompressFormatByMimeType(o.outMimeType,
|
||||
Bitmap.CompressFormat.PNG);
|
||||
fos = new FileOutputStream(imageFile);
|
||||
return b.compress(format, quality, fos);
|
||||
|
@ -40,9 +40,9 @@ public class ColorUtils {
|
||||
final Bitmap bm = Bitmap.createBitmap(width, height, Config.ARGB_8888);
|
||||
final Canvas canvas = new Canvas(bm);
|
||||
|
||||
final int rectrangleSize = (int) (density * 5);
|
||||
final int numRectanglesHorizontal = (int) Math.ceil(width / rectrangleSize);
|
||||
final int numRectanglesVertical = (int) Math.ceil(height / rectrangleSize);
|
||||
final int rectangleSize = (int) (density * 5);
|
||||
final int numRectanglesHorizontal = (int) Math.ceil(width / rectangleSize);
|
||||
final int numRectanglesVertical = (int) Math.ceil(height / rectangleSize);
|
||||
final Rect r = new Rect();
|
||||
boolean verticalStartWhite = true;
|
||||
for (int i = 0; i <= numRectanglesVertical; i++) {
|
||||
@ -50,10 +50,10 @@ public class ColorUtils {
|
||||
boolean isWhite = verticalStartWhite;
|
||||
for (int j = 0; j <= numRectanglesHorizontal; j++) {
|
||||
|
||||
r.top = i * rectrangleSize;
|
||||
r.left = j * rectrangleSize;
|
||||
r.bottom = r.top + rectrangleSize;
|
||||
r.right = r.left + rectrangleSize;
|
||||
r.top = i * rectangleSize;
|
||||
r.left = j * rectangleSize;
|
||||
r.bottom = r.top + rectangleSize;
|
||||
r.right = r.left + rectangleSize;
|
||||
final Paint paint = new Paint();
|
||||
paint.setColor(isWhite ? Color.WHITE : Color.GRAY);
|
||||
|
||||
|
@ -23,15 +23,11 @@ import android.os.Bundle;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
public class CompareUtils {
|
||||
|
||||
public static boolean bundleEquals(final Bundle bundle1, final Bundle bundle2, final String... ignoredKeys) {
|
||||
if (bundle1 == null || bundle2 == null) return bundle1 == bundle2;
|
||||
final Iterator<String> keys = bundle1.keySet().iterator();
|
||||
while (keys.hasNext()) {
|
||||
final String key = keys.next();
|
||||
for (String key : bundle1.keySet()) {
|
||||
if (!ArrayUtils.contains(ignoredKeys, key) && !objectEquals(bundle1.get(key), bundle2.get(key)))
|
||||
return false;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ public class DataImportExportUtils implements Constants {
|
||||
|
||||
public static HashMap<String, Preference> getSupportedPreferencesMap() {
|
||||
final Field[] fields = SharedPreferenceConstants.class.getDeclaredFields();
|
||||
final HashMap<String, Preference> supportedPrefsMap = new HashMap<String, Preference>();
|
||||
final HashMap<String, Preference> supportedPrefsMap = new HashMap<>();
|
||||
for (final Field field : fields) {
|
||||
final Preference annotation = field.getAnnotation(Preference.class);
|
||||
if (Modifier.isStatic(field.getModifiers()) && CompareUtils.classEquals(field.getType(), String.class)
|
||||
|
@ -31,214 +31,216 @@ import java.nio.channels.FileChannel;
|
||||
|
||||
public final class FileUtils {
|
||||
|
||||
/**
|
||||
* The number of bytes in a megabyte.
|
||||
*/
|
||||
private static final long ONE_MB = 1048576;
|
||||
/**
|
||||
* The number of bytes in a megabyte.
|
||||
*/
|
||||
private static final long ONE_MB = 1048576;
|
||||
|
||||
/**
|
||||
* The file copy buffer size (30 MB)
|
||||
*/
|
||||
private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30;
|
||||
/**
|
||||
* The file copy buffer size (30 MB)
|
||||
*/
|
||||
private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30;
|
||||
|
||||
/**
|
||||
* Copies a file to a new location preserving the file date.
|
||||
* <p>
|
||||
* This method copies the contents of the specified source file to the
|
||||
* specified destination file. The directory holding the destination file is
|
||||
* created if it does not exist. If the destination file exists, then this
|
||||
* method will overwrite it.
|
||||
* <p>
|
||||
* <strong>Note:</strong> This method tries to preserve the file's last
|
||||
* modified date/times using {@link File#setLastModified(long)}, however it
|
||||
* is not guaranteed that the operation will succeed. If the modification
|
||||
* operation fails, no indication is provided.
|
||||
*
|
||||
* @param srcFile an existing file to copy, must not be {@code null}
|
||||
* @param destFile the new file, must not be {@code null}
|
||||
* @throws NullPointerException if source or destination is {@code null}
|
||||
* @throws IOException if source or destination is invalid
|
||||
* @throws IOException if an IO error occurs during copying
|
||||
* @see #copyFileToDirectory(File, File)
|
||||
*/
|
||||
public static void copyFile(final File srcFile, final File destFile) throws IOException {
|
||||
if (srcFile == null) throw new NullPointerException("Source must not be null");
|
||||
if (destFile == null) throw new NullPointerException("Destination must not be null");
|
||||
if (srcFile.exists() == false) throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
|
||||
if (srcFile.isDirectory()) throw new IOException("Source '" + srcFile + "' exists but is a directory");
|
||||
if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath()))
|
||||
throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same");
|
||||
final File parentFile = destFile.getParentFile();
|
||||
if (parentFile != null) {
|
||||
if (!parentFile.mkdirs() && !parentFile.isDirectory())
|
||||
throw new IOException("Destination '" + parentFile + "' directory cannot be created");
|
||||
}
|
||||
if (destFile.exists() && destFile.canWrite() == false)
|
||||
throw new IOException("Destination '" + destFile + "' exists but is read-only");
|
||||
doCopyFile(srcFile, destFile, true);
|
||||
}
|
||||
/**
|
||||
* Copies a file to a new location preserving the file date.
|
||||
* <p/>
|
||||
* This method copies the contents of the specified source file to the
|
||||
* specified destination file. The directory holding the destination file is
|
||||
* created if it does not exist. If the destination file exists, then this
|
||||
* method will overwrite it.
|
||||
* <p/>
|
||||
* <strong>Note:</strong> This method tries to preserve the file's last
|
||||
* modified date/times using {@link File#setLastModified(long)}, however it
|
||||
* is not guaranteed that the operation will succeed. If the modification
|
||||
* operation fails, no indication is provided.
|
||||
*
|
||||
* @param srcFile an existing file to copy, must not be {@code null}
|
||||
* @param destFile the new file, must not be {@code null}
|
||||
* @throws NullPointerException if source or destination is {@code null}
|
||||
* @throws IOException if source or destination is invalid
|
||||
* @throws IOException if an IO error occurs during copying
|
||||
* @see #copyFileToDirectory(File, File)
|
||||
*/
|
||||
public static void copyFile(final File srcFile, final File destFile) throws IOException {
|
||||
if (srcFile == null) throw new NullPointerException("Source must not be null");
|
||||
if (destFile == null) throw new NullPointerException("Destination must not be null");
|
||||
if (!srcFile.exists())
|
||||
throw new FileNotFoundException("Source '" + srcFile + "' does not exist");
|
||||
if (srcFile.isDirectory())
|
||||
throw new IOException("Source '" + srcFile + "' exists but is a directory");
|
||||
if (srcFile.getCanonicalPath().equals(destFile.getCanonicalPath()))
|
||||
throw new IOException("Source '" + srcFile + "' and destination '" + destFile + "' are the same");
|
||||
final File parentFile = destFile.getParentFile();
|
||||
if (parentFile != null) {
|
||||
if (!parentFile.mkdirs() && !parentFile.isDirectory())
|
||||
throw new IOException("Destination '" + parentFile + "' directory cannot be created");
|
||||
}
|
||||
if (destFile.exists() && destFile.canWrite() == false)
|
||||
throw new IOException("Destination '" + destFile + "' exists but is read-only");
|
||||
doCopyFile(srcFile, destFile, true);
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Copies a file to a directory preserving the file date.
|
||||
* <p>
|
||||
* This method copies the contents of the specified source file to a file of
|
||||
* the same name in the specified destination directory. The destination
|
||||
* directory is created if it does not exist. If the destination file
|
||||
* exists, then this method will overwrite it.
|
||||
* <p>
|
||||
* <strong>Note:</strong> This method tries to preserve the file's last
|
||||
* modified date/times using {@link File#setLastModified(long)}, however it
|
||||
* is not guaranteed that the operation will succeed. If the modification
|
||||
* operation fails, no indication is provided.
|
||||
*
|
||||
* @param srcFile an existing file to copy, must not be {@code null}
|
||||
* @param destDir the directory to place the copy in, must not be
|
||||
* {@code null}
|
||||
* @throws NullPointerException if source or destination is null
|
||||
* @throws IOException if source or destination is invalid
|
||||
* @throws IOException if an IO error occurs during copying
|
||||
* @see #copyFile(File, File, boolean)
|
||||
*/
|
||||
public static void copyFileToDirectory(final File srcFile, final File destDir) throws IOException {
|
||||
if (destDir == null) throw new NullPointerException("Destination must not be null");
|
||||
if (destDir.exists() && destDir.isDirectory() == false)
|
||||
throw new IllegalArgumentException("Destination '" + destDir + "' is not a directory");
|
||||
final File destFile = new File(destDir, srcFile.getName());
|
||||
copyFile(srcFile, destFile);
|
||||
}
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Unconditionally close a <code>Closeable</code>.
|
||||
* <p>
|
||||
* Equivalent to {@link Closeable#close()}, except any exceptions will be
|
||||
* ignored. This is typically used in finally blocks.
|
||||
* <p>
|
||||
* Example code:
|
||||
*
|
||||
* <pre>
|
||||
* Closeable closeable = null;
|
||||
* try {
|
||||
* closeable = new FileReader("foo.txt");
|
||||
* // process closeable
|
||||
* closeable.close();
|
||||
* } catch (Exception e) {
|
||||
* // error handling
|
||||
* } finally {
|
||||
* IOUtils.closeQuietly(closeable);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param closeable the object to close, may be null or already closed
|
||||
* @since 2.0
|
||||
*/
|
||||
private static void closeQuietly(final Closeable closeable) {
|
||||
try {
|
||||
if (closeable != null) {
|
||||
closeable.close();
|
||||
}
|
||||
} catch (final IOException ioe) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Copies a file to a directory preserving the file date.
|
||||
* <p/>
|
||||
* This method copies the contents of the specified source file to a file of
|
||||
* the same name in the specified destination directory. The destination
|
||||
* directory is created if it does not exist. If the destination file
|
||||
* exists, then this method will overwrite it.
|
||||
* <p/>
|
||||
* <strong>Note:</strong> This method tries to preserve the file's last
|
||||
* modified date/times using {@link File#setLastModified(long)}, however it
|
||||
* is not guaranteed that the operation will succeed. If the modification
|
||||
* operation fails, no indication is provided.
|
||||
*
|
||||
* @param srcFile an existing file to copy, must not be {@code null}
|
||||
* @param destDir the directory to place the copy in, must not be
|
||||
* {@code null}
|
||||
* @throws NullPointerException if source or destination is null
|
||||
* @throws IOException if source or destination is invalid
|
||||
* @throws IOException if an IO error occurs during copying
|
||||
*/
|
||||
public static void copyFileToDirectory(final File srcFile, final File destDir) throws IOException {
|
||||
if (destDir == null) throw new NullPointerException("Destination must not be null");
|
||||
if (destDir.exists() && !destDir.isDirectory())
|
||||
throw new IllegalArgumentException("Destination '" + destDir + "' is not a directory");
|
||||
final File destFile = new File(destDir, srcFile.getName());
|
||||
copyFile(srcFile, destFile);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally close an <code>InputStream</code>.
|
||||
* <p>
|
||||
* Equivalent to {@link InputStream#close()}, except any exceptions will be
|
||||
* ignored. This is typically used in finally blocks.
|
||||
* <p>
|
||||
* Example code:
|
||||
*
|
||||
* <pre>
|
||||
* byte[] data = new byte[1024];
|
||||
* InputStream in = null;
|
||||
* try {
|
||||
* in = new FileInputStream("foo.txt");
|
||||
* in.read(data);
|
||||
* in.close(); // close errors are handled
|
||||
* } catch (Exception e) {
|
||||
* // error handling
|
||||
* } finally {
|
||||
* IOUtils.closeQuietly(in);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param input the InputStream to close, may be null or already closed
|
||||
*/
|
||||
private static void closeQuietly(final InputStream input) {
|
||||
closeQuietly((Closeable) input);
|
||||
}
|
||||
/**
|
||||
* Unconditionally close a <code>Closeable</code>.
|
||||
* <p/>
|
||||
* Equivalent to {@link Closeable#close()}, except any exceptions will be
|
||||
* ignored. This is typically used in finally blocks.
|
||||
* <p/>
|
||||
* Example code:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* Closeable closeable = null;
|
||||
* try {
|
||||
* closeable = new FileReader("foo.txt");
|
||||
* // process closeable
|
||||
* closeable.close();
|
||||
* } catch (Exception e) {
|
||||
* // error handling
|
||||
* } finally {
|
||||
* IOUtils.closeQuietly(closeable);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param closeable the object to close, may be null or already closed
|
||||
* @since 2.0
|
||||
*/
|
||||
private static void closeQuietly(final Closeable closeable) {
|
||||
try {
|
||||
if (closeable != null) {
|
||||
closeable.close();
|
||||
}
|
||||
} catch (final IOException ioe) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally close an <code>OutputStream</code>.
|
||||
* <p>
|
||||
* Equivalent to {@link OutputStream#close()}, except any exceptions will be
|
||||
* ignored. This is typically used in finally blocks.
|
||||
* <p>
|
||||
* Example code:
|
||||
*
|
||||
* <pre>
|
||||
* byte[] data = "Hello, World".getBytes();
|
||||
*
|
||||
* OutputStream out = null;
|
||||
* try {
|
||||
* out = new FileOutputStream("foo.txt");
|
||||
* out.write(data);
|
||||
* out.close(); // close errors are handled
|
||||
* } catch (IOException e) {
|
||||
* // error handling
|
||||
* } finally {
|
||||
* IOUtils.closeQuietly(out);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param output the OutputStream to close, may be null or already closed
|
||||
*/
|
||||
private static void closeQuietly(final OutputStream output) {
|
||||
closeQuietly((Closeable) output);
|
||||
}
|
||||
/**
|
||||
* Unconditionally close an <code>InputStream</code>.
|
||||
* <p/>
|
||||
* Equivalent to {@link InputStream#close()}, except any exceptions will be
|
||||
* ignored. This is typically used in finally blocks.
|
||||
* <p/>
|
||||
* Example code:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* byte[] data = new byte[1024];
|
||||
* InputStream in = null;
|
||||
* try {
|
||||
* in = new FileInputStream("foo.txt");
|
||||
* in.read(data);
|
||||
* in.close(); // close errors are handled
|
||||
* } catch (Exception e) {
|
||||
* // error handling
|
||||
* } finally {
|
||||
* IOUtils.closeQuietly(in);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param input the InputStream to close, may be null or already closed
|
||||
*/
|
||||
private static void closeQuietly(final InputStream input) {
|
||||
closeQuietly((Closeable) input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal copy file method.
|
||||
*
|
||||
* @param srcFile the validated source file, must not be {@code null}
|
||||
* @param destFile the validated destination file, must not be {@code null}
|
||||
* @param preserveFileDate whether to preserve the file date
|
||||
* @throws IOException if an error occurs
|
||||
*/
|
||||
private static void doCopyFile(final File srcFile, final File destFile, final boolean preserveFileDate)
|
||||
throws IOException {
|
||||
if (destFile.exists() && destFile.isDirectory())
|
||||
throw new IOException("Destination '" + destFile + "' exists but is a directory");
|
||||
/**
|
||||
* Unconditionally close an <code>OutputStream</code>.
|
||||
* <p/>
|
||||
* Equivalent to {@link OutputStream#close()}, except any exceptions will be
|
||||
* ignored. This is typically used in finally blocks.
|
||||
* <p/>
|
||||
* Example code:
|
||||
* <p/>
|
||||
* <pre>
|
||||
* byte[] data = "Hello, World".getBytes();
|
||||
*
|
||||
* OutputStream out = null;
|
||||
* try {
|
||||
* out = new FileOutputStream("foo.txt");
|
||||
* out.write(data);
|
||||
* out.close(); // close errors are handled
|
||||
* } catch (IOException e) {
|
||||
* // error handling
|
||||
* } finally {
|
||||
* IOUtils.closeQuietly(out);
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param output the OutputStream to close, may be null or already closed
|
||||
*/
|
||||
private static void closeQuietly(final OutputStream output) {
|
||||
closeQuietly((Closeable) output);
|
||||
}
|
||||
|
||||
FileInputStream fis = null;
|
||||
FileOutputStream fos = null;
|
||||
FileChannel input = null;
|
||||
FileChannel output = null;
|
||||
try {
|
||||
fis = new FileInputStream(srcFile);
|
||||
fos = new FileOutputStream(destFile);
|
||||
input = fis.getChannel();
|
||||
output = fos.getChannel();
|
||||
final long size = input.size();
|
||||
long pos = 0;
|
||||
long count = 0;
|
||||
while (pos < size) {
|
||||
count = size - pos > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : size - pos;
|
||||
pos += output.transferFrom(input, pos, count);
|
||||
}
|
||||
} finally {
|
||||
closeQuietly(output);
|
||||
closeQuietly(fos);
|
||||
closeQuietly(input);
|
||||
closeQuietly(fis);
|
||||
}
|
||||
/**
|
||||
* Internal copy file method.
|
||||
*
|
||||
* @param srcFile the validated source file, must not be {@code null}
|
||||
* @param destFile the validated destination file, must not be {@code null}
|
||||
* @param preserveFileDate whether to preserve the file date
|
||||
* @throws IOException if an error occurs
|
||||
*/
|
||||
private static void doCopyFile(final File srcFile, final File destFile, final boolean preserveFileDate)
|
||||
throws IOException {
|
||||
if (destFile.exists() && destFile.isDirectory())
|
||||
throw new IOException("Destination '" + destFile + "' exists but is a directory");
|
||||
|
||||
if (srcFile.length() != destFile.length())
|
||||
throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'");
|
||||
if (preserveFileDate) {
|
||||
destFile.setLastModified(srcFile.lastModified());
|
||||
}
|
||||
}
|
||||
FileInputStream fis = null;
|
||||
FileOutputStream fos = null;
|
||||
FileChannel input = null;
|
||||
FileChannel output = null;
|
||||
try {
|
||||
fis = new FileInputStream(srcFile);
|
||||
fos = new FileOutputStream(destFile);
|
||||
input = fis.getChannel();
|
||||
output = fos.getChannel();
|
||||
final long size = input.size();
|
||||
long pos = 0;
|
||||
long count;
|
||||
while (pos < size) {
|
||||
count = size - pos > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : size - pos;
|
||||
pos += output.transferFrom(input, pos, count);
|
||||
}
|
||||
} finally {
|
||||
closeQuietly(output);
|
||||
closeQuietly(fos);
|
||||
closeQuietly(input);
|
||||
closeQuietly(fis);
|
||||
}
|
||||
|
||||
if (srcFile.length() != destFile.length())
|
||||
throw new IOException("Failed to copy full contents from '" + srcFile + "' to '" + destFile + "'");
|
||||
if (preserveFileDate) {
|
||||
destFile.setLastModified(srcFile.lastModified());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.os.Build;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class FlymeUtils {
|
||||
|
||||
private static String[] SMARTBAR_SUPPORTED_DEVICES = {"mx2", "mx3"};
|
||||
|
||||
public static boolean hasSmartBar() {
|
||||
try {
|
||||
// Invoke Build.hasSmartBar()
|
||||
final Method method = Build.class.getMethod("hasSmartBar");
|
||||
return (Boolean) method.invoke(null);
|
||||
} catch (final Exception ignored) {
|
||||
}
|
||||
// Detect by Build.DEVICE
|
||||
return isDeviceWithSmartBar(Build.DEVICE);
|
||||
}
|
||||
|
||||
public static boolean isDeviceWithSmartBar(final String buildDevice) {
|
||||
for (final String dev : SMARTBAR_SUPPORTED_DEVICES) {
|
||||
if (dev.equals(buildDevice)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isFlyme() {
|
||||
try {
|
||||
// Invoke Build.hasSmartBar()
|
||||
final Method method = Build.class.getMethod("hasSmartBar");
|
||||
return method != null;
|
||||
} catch (final Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void setActionModeHeaderHidden(final ActionBar actionbar, final boolean hidden) {
|
||||
try {
|
||||
final Method method = ActionBar.class.getMethod("setActionModeHeaderHidden", new Class[]{boolean.class});
|
||||
method.invoke(actionbar, hidden);
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
@ -27,7 +27,7 @@ import java.util.Map;
|
||||
|
||||
public class HostsFileParser {
|
||||
|
||||
private final Map<String, String> mHosts = new HashMap<String, String>();
|
||||
private final Map<String, String> mHosts = new HashMap<>();
|
||||
private final String mPath;
|
||||
|
||||
public HostsFileParser() {
|
||||
@ -47,7 +47,7 @@ public class HostsFileParser {
|
||||
}
|
||||
|
||||
public Map<String, String> getAll() {
|
||||
return new HashMap<String, String>(mHosts);
|
||||
return new HashMap<>(mHosts);
|
||||
}
|
||||
|
||||
public boolean reload() {
|
||||
|
@ -26,7 +26,7 @@ public class ListUtils {
|
||||
|
||||
public static List<Long> fromArray(final long[] array) {
|
||||
if (array == null) return null;
|
||||
final List<Long> list = new ArrayList<Long>();
|
||||
final List<Long> list = new ArrayList<>();
|
||||
for (final long item : array) {
|
||||
list.add(item);
|
||||
}
|
||||
|
@ -23,68 +23,17 @@ import android.app.Application;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.IMediaUploader;
|
||||
import org.mariotaku.twidere.model.MediaUploadResult;
|
||||
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
|
||||
import org.mariotaku.twidere.model.UploaderMediaItem;
|
||||
|
||||
import static org.mariotaku.twidere.util.ServiceUtils.bindToService;
|
||||
|
||||
public final class MediaUploaderInterface implements Constants, IMediaUploader {
|
||||
|
||||
private IMediaUploader mUploader;
|
||||
|
||||
private final ServiceConnection mConntecion = new ServiceConnection() {
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName service, final IBinder obj) {
|
||||
mUploader = IMediaUploader.Stub.asInterface(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName service) {
|
||||
mUploader = null;
|
||||
}
|
||||
};
|
||||
|
||||
private MediaUploaderInterface(final Context context, final String uploader_name) {
|
||||
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_UPLOAD_MEDIA);
|
||||
final ComponentName component = ComponentName.unflattenFromString(uploader_name);
|
||||
intent.setComponent(component);
|
||||
bindToService(context, intent, mConntecion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder asBinder() {
|
||||
// Useless here
|
||||
return mUploader.asBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaUploadResult upload(final ParcelableStatusUpdate status, final UploaderMediaItem[] media)
|
||||
throws RemoteException {
|
||||
if (mUploader == null) return null;
|
||||
try {
|
||||
return mUploader.upload(status, media);
|
||||
} catch (final RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void waitForService() {
|
||||
while (mUploader == null) {
|
||||
try {
|
||||
Thread.sleep(100L);
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
public final class MediaUploaderInterface extends AbsServiceInterface<IMediaUploader> implements IMediaUploader {
|
||||
protected MediaUploaderInterface(Context context, String shortenerName) {
|
||||
super(context, shortenerName);
|
||||
}
|
||||
|
||||
public static MediaUploaderInterface getInstance(final Application application, final String uploaderName) {
|
||||
@ -95,4 +44,22 @@ public final class MediaUploaderInterface implements Constants, IMediaUploader {
|
||||
if (application.getPackageManager().queryIntentServices(intent, 0).size() != 1) return null;
|
||||
return new MediaUploaderInterface(application, uploaderName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MediaUploadResult upload(final ParcelableStatusUpdate status, final UploaderMediaItem[] media)
|
||||
throws RemoteException {
|
||||
final IMediaUploader iface = getInterface();
|
||||
if (iface == null) return null;
|
||||
try {
|
||||
return iface.upload(status, media);
|
||||
} catch (final RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected IMediaUploader onServiceConnected(ComponentName service, IBinder obj) {
|
||||
return IMediaUploader.Stub.asInterface(obj);
|
||||
}
|
||||
}
|
||||
|
@ -1,152 +0,0 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
|
||||
public final class MessagesManager implements Constants {
|
||||
|
||||
private final Context mContext;
|
||||
private final SharedPreferences mPreferences;
|
||||
|
||||
public MessagesManager(final Context context) {
|
||||
mContext = context;
|
||||
mPreferences = context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
public boolean addMessageCallback(final Activity activity) {
|
||||
if (activity == null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean removeMessageCallback(final Activity activity) {
|
||||
if (activity == null) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showErrorMessage(final CharSequence message, final boolean long_message) {
|
||||
final Activity best = getBestActivity();
|
||||
if (best != null) {
|
||||
Utils.showErrorMessage(best, message, long_message);
|
||||
return;
|
||||
}
|
||||
if (showToast()) {
|
||||
Utils.showErrorMessage(mContext, message, long_message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void showErrorMessage(final int actionRes, final Exception e, final boolean long_message) {
|
||||
final String action = mContext.getString(actionRes);
|
||||
final Activity best = getBestActivity();
|
||||
if (best != null) {
|
||||
Utils.showErrorMessage(best, action, e, long_message);
|
||||
return;
|
||||
}
|
||||
if (showToast()) {
|
||||
Utils.showErrorMessage(mContext, action, e, long_message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void showErrorMessage(final int action_res, final String message, final boolean longMessage) {
|
||||
final String action = mContext.getString(action_res);
|
||||
final Activity best = getBestActivity();
|
||||
if (best != null) {
|
||||
Utils.showErrorMessage(best, action, message, longMessage);
|
||||
return;
|
||||
}
|
||||
if (showToast()) {
|
||||
Utils.showErrorMessage(mContext, action, message, longMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void showInfoMessage(final CharSequence message, final boolean longMessage) {
|
||||
final Activity best = getBestActivity();
|
||||
if (best != null) {
|
||||
Utils.showInfoMessage(best, message, longMessage);
|
||||
return;
|
||||
}
|
||||
if (showToast()) {
|
||||
Utils.showInfoMessage(mContext, message, longMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void showInfoMessage(final int messageRes, final boolean longMessage) {
|
||||
final Activity best = getBestActivity();
|
||||
if (best != null) {
|
||||
Utils.showInfoMessage(best, messageRes, longMessage);
|
||||
return;
|
||||
}
|
||||
if (showToast()) {
|
||||
Utils.showInfoMessage(mContext, messageRes, longMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void showOkMessage(final CharSequence message, final boolean longMessage) {
|
||||
final Activity best = getBestActivity();
|
||||
if (best != null) {
|
||||
Utils.showOkMessage(best, message, longMessage);
|
||||
return;
|
||||
}
|
||||
if (showToast()) {
|
||||
Utils.showOkMessage(mContext, message, longMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void showOkMessage(final int messageRes, final boolean longMessage) {
|
||||
final Activity best = getBestActivity();
|
||||
if (best != null) {
|
||||
Utils.showOkMessage(best, messageRes, longMessage);
|
||||
return;
|
||||
}
|
||||
if (showToast()) {
|
||||
Utils.showOkMessage(mContext, messageRes, longMessage);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public void showWarnMessage(final int messageRes, final boolean longMessage) {
|
||||
final Activity best = getBestActivity();
|
||||
if (best != null) {
|
||||
Utils.showWarnMessage(best, messageRes, longMessage);
|
||||
return;
|
||||
}
|
||||
if (showToast()) {
|
||||
Utils.showWarnMessage(mContext, messageRes, longMessage);
|
||||
}
|
||||
}
|
||||
|
||||
private Activity getBestActivity() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean showToast() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -108,7 +108,7 @@ public class MultiSelectEventHandler implements Constants, ActionMode.Callback,
|
||||
final Intent intent = new Intent(INTENT_ACTION_REPLY_MULTIPLE);
|
||||
final Bundle bundle = new Bundle();
|
||||
final String[] accountScreenNames = getAccountScreenNames(mActivity);
|
||||
final Collection<String> allMentions = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
|
||||
final Collection<String> allMentions = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
|
||||
for (final Object object : selectedItems) {
|
||||
if (object instanceof ParcelableStatus) {
|
||||
final ParcelableStatus status = (ParcelableStatus) object;
|
||||
@ -135,8 +135,8 @@ public class MultiSelectEventHandler implements Constants, ActionMode.Callback,
|
||||
}
|
||||
case MENU_MUTE_USER: {
|
||||
final ContentResolver resolver = mActivity.getContentResolver();
|
||||
final ArrayList<ContentValues> valuesList = new ArrayList<ContentValues>();
|
||||
final Set<Long> userIds = new HashSet<Long>();
|
||||
final ArrayList<ContentValues> valuesList = new ArrayList<>();
|
||||
final Set<Long> userIds = new HashSet<>();
|
||||
for (final Object object : selectedItems) {
|
||||
if (object instanceof ParcelableStatus) {
|
||||
final ParcelableStatus status = (ParcelableStatus) object;
|
||||
@ -146,8 +146,6 @@ public class MultiSelectEventHandler implements Constants, ActionMode.Callback,
|
||||
final ParcelableUser user = (ParcelableUser) object;
|
||||
userIds.add(user.id);
|
||||
valuesList.add(ContentValuesCreator.createFilteredUser(user));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
bulkDelete(resolver, Filters.Users.CONTENT_URI, Filters.Users.USER_ID, userIds, null, false);
|
||||
|
@ -29,9 +29,9 @@ import java.util.List;
|
||||
|
||||
public class MultiSelectManager implements Constants {
|
||||
|
||||
private final NoDuplicatesArrayList<Long> mSelectedStatusIds = new NoDuplicatesArrayList<Long>();
|
||||
private final NoDuplicatesArrayList<Long> mSelectedUserIds = new NoDuplicatesArrayList<Long>();
|
||||
private final NoDuplicatesArrayList<Callback> mCallbacks = new NoDuplicatesArrayList<Callback>();
|
||||
private final NoDuplicatesArrayList<Long> mSelectedStatusIds = new NoDuplicatesArrayList<>();
|
||||
private final NoDuplicatesArrayList<Long> mSelectedUserIds = new NoDuplicatesArrayList<>();
|
||||
private final NoDuplicatesArrayList<Callback> mCallbacks = new NoDuplicatesArrayList<>();
|
||||
private final ItemsList mSelectedItems = new ItemsList(this);
|
||||
private long mAccountId;
|
||||
|
||||
@ -121,7 +121,7 @@ public class MultiSelectManager implements Constants {
|
||||
}
|
||||
|
||||
public static long[] getSelectedUserIds(final List<Object> selected_items) {
|
||||
final ArrayList<Long> ids_list = new ArrayList<Long>();
|
||||
final ArrayList<Long> ids_list = new ArrayList<>();
|
||||
for (final Object item : selected_items) {
|
||||
if (item instanceof ParcelableUser) {
|
||||
ids_list.add(((ParcelableUser) item).id);
|
||||
|
@ -94,7 +94,7 @@ public class PermissionsManager implements Constants {
|
||||
}
|
||||
|
||||
public Map<String, String> getAll() {
|
||||
final Map<String, String> map = new HashMap<String, String>();
|
||||
final Map<String, String> map = new HashMap<>();
|
||||
for (final Map.Entry<String, ?> entry : mPreferences.getAll().entrySet()) {
|
||||
if (entry.getValue() instanceof String) {
|
||||
map.put(entry.getKey(), (String) entry.getValue());
|
||||
|
@ -21,12 +21,9 @@ package org.mariotaku.twidere.util;
|
||||
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
|
||||
/**
|
||||
* Created by mariotaku on 15/4/13.
|
||||
*/
|
||||
@ -64,8 +61,7 @@ public class RecyclerViewUtils {
|
||||
viewToFocus = firstVisibleView;
|
||||
firstVisibleView.requestFocus();
|
||||
} else if (view != null) {
|
||||
final View recyclerViewChild = findRecyclerViewChild(recyclerView, view);
|
||||
viewToFocus = recyclerViewChild;
|
||||
viewToFocus = findRecyclerViewChild(recyclerView, view);
|
||||
} else {
|
||||
viewToFocus = null;
|
||||
}
|
||||
|
@ -32,62 +32,63 @@ import java.util.HashMap;
|
||||
|
||||
public final class ServiceUtils implements Constants {
|
||||
|
||||
private static HashMap<Context, ServiceUtils.ServiceBinder> sConnectionMap = new HashMap<Context, ServiceUtils.ServiceBinder>();
|
||||
private static HashMap<Context, ServiceUtils.ServiceBinder> sConnectionMap = new HashMap<>();
|
||||
|
||||
public static ServiceToken bindToService(final Context context, final Intent intent) {
|
||||
public static ServiceToken bindToService(final Context context, final Intent intent) {
|
||||
return bindToService(context, intent, null);
|
||||
}
|
||||
|
||||
return bindToService(context, intent, null);
|
||||
}
|
||||
public static ServiceToken bindToService(final Context context, final Intent intent,
|
||||
final ServiceConnection callback) {
|
||||
|
||||
public static ServiceToken bindToService(final Context context, final Intent intent,
|
||||
final ServiceConnection callback) {
|
||||
final ContextWrapper cw = new ContextWrapper(context);
|
||||
final ComponentName cn = cw.startService(intent);
|
||||
if (cn != null) {
|
||||
final ServiceUtils.ServiceBinder sb = new ServiceBinder(callback);
|
||||
if (cw.bindService(intent, sb, 0)) {
|
||||
sConnectionMap.put(cw, sb);
|
||||
return new ServiceToken(cw);
|
||||
}
|
||||
}
|
||||
Log.e(LOGTAG, "Failed to bind to service");
|
||||
return null;
|
||||
}
|
||||
|
||||
final ContextWrapper cw = new ContextWrapper(context);
|
||||
final ComponentName cn = cw.startService(intent);
|
||||
if (cn != null) {
|
||||
final ServiceUtils.ServiceBinder sb = new ServiceBinder(callback);
|
||||
if (cw.bindService(intent, sb, 0)) {
|
||||
sConnectionMap.put(cw, sb);
|
||||
return new ServiceToken(cw);
|
||||
}
|
||||
}
|
||||
Log.e(LOGTAG, "Failed to bind to service");
|
||||
return null;
|
||||
}
|
||||
public static void unbindFromService(final ServiceToken token) {
|
||||
final ServiceBinder serviceBinder = sConnectionMap.get(token.wrappedContext);
|
||||
if (serviceBinder == null) return;
|
||||
token.wrappedContext.unbindService(serviceBinder);
|
||||
}
|
||||
|
||||
public static class ServiceToken {
|
||||
public static class ServiceToken {
|
||||
|
||||
ContextWrapper wrapped_context;
|
||||
private final ContextWrapper wrappedContext;
|
||||
|
||||
ServiceToken(final ContextWrapper context) {
|
||||
ServiceToken(final ContextWrapper context) {
|
||||
wrappedContext = context;
|
||||
}
|
||||
}
|
||||
|
||||
wrapped_context = context;
|
||||
}
|
||||
}
|
||||
static class ServiceBinder implements ServiceConnection {
|
||||
|
||||
static class ServiceBinder implements ServiceConnection {
|
||||
private final ServiceConnection mCallback;
|
||||
|
||||
private final ServiceConnection mCallback;
|
||||
public ServiceBinder(final ServiceConnection callback) {
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
public ServiceBinder(final ServiceConnection callback) {
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName className, final android.os.IBinder service) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onServiceConnected(className, service);
|
||||
}
|
||||
}
|
||||
|
||||
mCallback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName className, final android.os.IBinder service) {
|
||||
|
||||
if (mCallback != null) {
|
||||
mCallback.onServiceConnected(className, service);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName className) {
|
||||
|
||||
if (mCallback != null) {
|
||||
mCallback.onServiceDisconnected(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName className) {
|
||||
if (mCallback != null) {
|
||||
mCallback.onServiceDisconnected(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,76 +23,44 @@ import android.app.Application;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.IStatusShortener;
|
||||
import org.mariotaku.twidere.model.ParcelableStatusUpdate;
|
||||
import org.mariotaku.twidere.model.StatusShortenResult;
|
||||
|
||||
import static org.mariotaku.twidere.util.ServiceUtils.bindToService;
|
||||
public final class StatusShortenerInterface extends AbsServiceInterface<IStatusShortener> implements IStatusShortener {
|
||||
|
||||
public final class StatusShortenerInterface implements Constants, IStatusShortener {
|
||||
protected StatusShortenerInterface(Context context, String shortenerName) {
|
||||
super(context, shortenerName);
|
||||
}
|
||||
|
||||
private IStatusShortener mShortener;
|
||||
@Override
|
||||
protected IStatusShortener onServiceConnected(ComponentName service, IBinder obj) {
|
||||
return IStatusShortener.Stub.asInterface(obj);
|
||||
}
|
||||
|
||||
private final ServiceConnection mConntecion = new ServiceConnection() {
|
||||
@Override
|
||||
public StatusShortenResult shorten(final ParcelableStatusUpdate status, final String overrideStatusText)
|
||||
throws RemoteException {
|
||||
final IStatusShortener iface = getInterface();
|
||||
if (iface == null) return null;
|
||||
try {
|
||||
return iface.shorten(status, overrideStatusText);
|
||||
} catch (final RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceConnected(final ComponentName service, final IBinder obj) {
|
||||
mShortener = IStatusShortener.Stub.asInterface(obj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServiceDisconnected(final ComponentName service) {
|
||||
mShortener = null;
|
||||
}
|
||||
};
|
||||
|
||||
private StatusShortenerInterface(final Context context, final String shortenerName) {
|
||||
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
|
||||
final ComponentName component = ComponentName.unflattenFromString(shortenerName);
|
||||
intent.setComponent(component);
|
||||
bindToService(context, intent, mConntecion);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBinder asBinder() {
|
||||
// Useless here
|
||||
return mShortener.asBinder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StatusShortenResult shorten(final ParcelableStatusUpdate status, final String overrideStatusText)
|
||||
throws RemoteException {
|
||||
if (mShortener == null) return null;
|
||||
try {
|
||||
return mShortener.shorten(status, overrideStatusText);
|
||||
} catch (final RemoteException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void waitForService() {
|
||||
while (mShortener == null) {
|
||||
try {
|
||||
Thread.sleep(100L);
|
||||
} catch (final InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static StatusShortenerInterface getInstance(final Application application, final String shortener_name) {
|
||||
if (shortener_name == null) return null;
|
||||
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
|
||||
final ComponentName component = ComponentName.unflattenFromString(shortener_name);
|
||||
intent.setComponent(component);
|
||||
if (application.getPackageManager().queryIntentServices(intent, 0).size() != 1) return null;
|
||||
return new StatusShortenerInterface(application, shortener_name);
|
||||
}
|
||||
public static StatusShortenerInterface getInstance(final Application application, final String shortener_name) {
|
||||
if (shortener_name == null) return null;
|
||||
final Intent intent = new Intent(INTENT_ACTION_EXTENSION_SHORTEN_STATUS);
|
||||
final ComponentName component = ComponentName.unflattenFromString(shortener_name);
|
||||
intent.setComponent(component);
|
||||
if (application.getPackageManager().queryIntentServices(intent, 0).size() != 1) return null;
|
||||
return new StatusShortenerInterface(application, shortener_name);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.graphics.Rect;
|
||||
import android.os.SystemClock;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.VelocityTracker;
|
||||
import android.view.View;
|
||||
@ -81,7 +82,7 @@ public class SwipeDismissListViewTouchListener implements View.OnTouchListener {
|
||||
private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
|
||||
|
||||
// Transient properties
|
||||
private List<PendingDismissData> mPendingDismisses = new ArrayList<PendingDismissData>();
|
||||
private List<PendingDismissData> mPendingDismisses = new ArrayList<>();
|
||||
private int mDismissAnimationRefCount = 0;
|
||||
private float mDownX;
|
||||
private float mDownY;
|
||||
@ -329,7 +330,7 @@ public class SwipeDismissListViewTouchListener implements View.OnTouchListener {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(PendingDismissData other) {
|
||||
public int compareTo(@NonNull PendingDismissData other) {
|
||||
// Sort by descending position
|
||||
return other.position - position;
|
||||
}
|
||||
|
@ -277,10 +277,6 @@ public final class TwidereLinkify implements Constants {
|
||||
addCashtagLinks(string, accountId, extraId, listener, highlightOption);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,8 +35,8 @@ import static android.text.TextUtils.isEmpty;
|
||||
|
||||
public class UserColorNameUtils implements TwidereConstants {
|
||||
|
||||
private static LongSparseArray<Integer> sUserColors = new LongSparseArray<>();
|
||||
private static LongSparseArray<String> sUserNicknames = new LongSparseArray<>();
|
||||
private static final LongSparseArray<Integer> sUserColors = new LongSparseArray<>();
|
||||
private static final LongSparseArray<String> sUserNicknames = new LongSparseArray<>();
|
||||
|
||||
private UserColorNameUtils() {
|
||||
throw new AssertionError();
|
||||
|
@ -131,7 +131,6 @@ import org.mariotaku.querybuilder.query.SQLSelectQuery;
|
||||
import org.mariotaku.twidere.BuildConfig;
|
||||
import org.mariotaku.twidere.Constants;
|
||||
import org.mariotaku.twidere.R;
|
||||
import org.mariotaku.twidere.activity.CameraCropActivity;
|
||||
import org.mariotaku.twidere.activity.support.AccountSelectorActivity;
|
||||
import org.mariotaku.twidere.activity.support.ColorPickerDialogActivity;
|
||||
import org.mariotaku.twidere.activity.support.MediaViewerActivity;
|
||||
@ -1010,31 +1009,6 @@ public final class Utils implements Constants, TwitterConstants {
|
||||
return fragment;
|
||||
}
|
||||
|
||||
public static Intent createPickImageIntent(final Uri uri) {
|
||||
final Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||
intent.setType("image/*");
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent createPickImageIntent(final Uri uri, final Integer outputX, final Integer outputY,
|
||||
final Integer aspectX, final Integer aspectY, final boolean scaleUpIfNeeded) {
|
||||
final Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||
intent.setType("image/*");
|
||||
if (outputX != null && outputY != null) {
|
||||
intent.putExtra(CameraCropActivity.EXTRA_OUTPUT_X, outputX);
|
||||
intent.putExtra(CameraCropActivity.EXTRA_OUTPUT_Y, outputY);
|
||||
}
|
||||
if (aspectX != null && aspectY != null) {
|
||||
intent.putExtra(CameraCropActivity.EXTRA_ASPECT_X, aspectX);
|
||||
intent.putExtra(CameraCropActivity.EXTRA_ASPECT_Y, aspectY);
|
||||
}
|
||||
intent.putExtra("scale", true);
|
||||
intent.putExtra("scaleUpIfNeeded", scaleUpIfNeeded);
|
||||
intent.putExtra("crop", "true");
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent createStatusShareIntent(final Context context, final ParcelableStatus status) {
|
||||
final Intent intent = new Intent(Intent.ACTION_SEND);
|
||||
intent.setType("text/plain");
|
||||
@ -1093,28 +1067,6 @@ public final class Utils implements Constants, TwitterConstants {
|
||||
status.user_name, status.user_screen_name, timeString);
|
||||
}
|
||||
|
||||
public static Intent createTakePhotoIntent(final Uri uri) {
|
||||
final Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static Intent createTakePhotoIntent(final Uri uri, final Integer outputX, final Integer outputY,
|
||||
final Integer aspectX, final Integer aspectY, final boolean scaleUpIfNeeded) {
|
||||
final Intent intent = new Intent(CameraCropActivity.INTENT_ACTION);
|
||||
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
|
||||
if (outputX != null && outputY != null) {
|
||||
intent.putExtra(CameraCropActivity.EXTRA_OUTPUT_X, outputX);
|
||||
intent.putExtra(CameraCropActivity.EXTRA_OUTPUT_Y, outputY);
|
||||
}
|
||||
if (aspectX != null && aspectY != null) {
|
||||
intent.putExtra(CameraCropActivity.EXTRA_ASPECT_X, aspectX);
|
||||
intent.putExtra(CameraCropActivity.EXTRA_ASPECT_Y, aspectY);
|
||||
}
|
||||
intent.putExtra(CameraCropActivity.EXTRA_SCALE_UP_IF_NEEDED, scaleUpIfNeeded);
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static String encodeQueryParams(final String value) throws IOException {
|
||||
final String encoded = URLEncoder.encode(value, "UTF-8");
|
||||
final StringBuilder buf = new StringBuilder();
|
||||
@ -1655,7 +1607,7 @@ public final class Utils implements Constants, TwitterConstants {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Bitmap.CompressFormat getBitmapCompressFormatByMimetype(final String mimeType,
|
||||
public static Bitmap.CompressFormat getBitmapCompressFormatByMimeType(final String mimeType,
|
||||
final Bitmap.CompressFormat def) {
|
||||
final String extension = MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType);
|
||||
if ("jpeg".equalsIgnoreCase(extension) || "jpg".equalsIgnoreCase(extension))
|
||||
@ -2979,6 +2931,7 @@ public final class Utils implements Constants, TwitterConstants {
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("SuspiciousSystemArraycopy")
|
||||
public static <T extends Parcelable> T[] newParcelableArray(Parcelable[] array, Parcelable.Creator<T> creator) {
|
||||
if (array == null) return null;
|
||||
final T[] result = creator.newArray(array.length);
|
||||
@ -3682,10 +3635,10 @@ public final class Utils implements Constants, TwitterConstants {
|
||||
showErrorMessage(context, getErrorMessage(context, action, t), longMessage);
|
||||
}
|
||||
|
||||
public static void showErrorMessage(final Context context, final int action, final String desc,
|
||||
final boolean long_message) {
|
||||
public static void showErrorMessage(final Context context, final int actionRes, final String desc,
|
||||
final boolean longMessage) {
|
||||
if (context == null) return;
|
||||
showErrorMessage(context, context.getString(action), desc, long_message);
|
||||
showErrorMessage(context, context.getString(actionRes), desc, longMessage);
|
||||
}
|
||||
|
||||
public static void showErrorMessage(final Context context, final int action, final Throwable t,
|
||||
@ -3943,9 +3896,9 @@ public final class Utils implements Constants, TwitterConstants {
|
||||
}
|
||||
case MENU_FAVORITE: {
|
||||
if (status.is_favorite) {
|
||||
twitter.destroyFavoriteAsync(status);
|
||||
twitter.destroyFavoriteAsync(status.account_id, status.id);
|
||||
} else {
|
||||
twitter.createFavoriteAsync(status);
|
||||
twitter.createFavoriteAsync(status.account_id, status.id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -34,10 +34,8 @@ public class BackStackEntryAccessor {
|
||||
final Field fragmentField = mHead.getClass().getField("fragment");
|
||||
final Object fragment = fragmentField.get(mHead);
|
||||
if (fragment instanceof Fragment) return (Fragment) fragment;
|
||||
} catch (final NoSuchFieldException e) {
|
||||
} catch (final IllegalArgumentException e) {
|
||||
} catch (final IllegalAccessException e) {
|
||||
} catch (final NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
|
||||
}
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,8 @@ package org.mariotaku.twidere.util.collection;
|
||||
// update CompactIdentityHashSet.java, UniqueSet.java and
|
||||
// SoftHashMapIndex.java accordingly.
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.Iterator;
|
||||
@ -30,387 +32,390 @@ import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* INTERNAL: Implements the Set interface more compactly than
|
||||
* java.util.HashSet by using a closed hashtable.
|
||||
* java.util.HashSet by using a closed hashtable.
|
||||
*/
|
||||
public class CompactHashSet<E> extends java.util.AbstractSet<E> {
|
||||
|
||||
protected final static int INITIAL_SIZE = 3;
|
||||
protected final static double LOAD_FACTOR = 0.75;
|
||||
|
||||
/**
|
||||
* This object is used to represent null, should clients add that to the set.
|
||||
*/
|
||||
protected final static Object nullObject = new Object();
|
||||
/**
|
||||
* When an object is deleted this object is put into the hashtable
|
||||
* in its place, so that other objects with the same key
|
||||
* (collisions) further down the hashtable are not lost after we
|
||||
* delete an object in the collision chain.
|
||||
*/
|
||||
protected final static Object deletedObject = new Object();
|
||||
protected int elements;
|
||||
/**
|
||||
* This is the number of empty (null) cells. It's not necessarily
|
||||
* the same as objects.length - elements, because some cells may
|
||||
* contain deletedObject.
|
||||
*/
|
||||
protected int freecells;
|
||||
protected E[] objects;
|
||||
protected int modCount;
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set.
|
||||
*/
|
||||
public CompactHashSet() {
|
||||
this(INITIAL_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public CompactHashSet(int size) {
|
||||
// NOTE: If array size is 0, we get a
|
||||
// "java.lang.ArithmeticException: / by zero" in add(Object).
|
||||
objects = (E[]) new Object[(size==0 ? 1 : size)];
|
||||
elements = 0;
|
||||
freecells = objects.length;
|
||||
modCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new set containing the elements in the specified
|
||||
* collection.
|
||||
*
|
||||
* @param c the collection whose elements are to be placed into this set.
|
||||
*/
|
||||
public CompactHashSet(Collection<E> c) {
|
||||
this(c.size());
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
// ===== SET IMPLEMENTATION =============================================
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this set. The elements
|
||||
* are returned in no particular order.
|
||||
*
|
||||
* @return an Iterator over the elements in this set.
|
||||
* @see ConcurrentModificationException
|
||||
*/
|
||||
public Iterator<E> iterator() {
|
||||
return new CompactHashIterator<E>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this set (its cardinality).
|
||||
*/
|
||||
public int size() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this set contains no elements.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return elements == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this set contains the specified element.
|
||||
*
|
||||
* @param o element whose presence in this set is to be tested.
|
||||
* @return <tt>true</tt> if this set contains the specified element.
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
if (o == null) o = nullObject;
|
||||
|
||||
int hash = o.hashCode();
|
||||
int index = (hash & 0x7FFFFFFF) % objects.length;
|
||||
int offset = 1;
|
||||
|
||||
// search for the object (continue while !null and !this object)
|
||||
while(objects[index] != null &&
|
||||
!(objects[index].hashCode() == hash &&
|
||||
objects[index].equals(o))) {
|
||||
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
|
||||
offset = offset*2 + 1;
|
||||
|
||||
if (offset == -1)
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
return objects[index] != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified element to this set if it is not already
|
||||
* present.
|
||||
*
|
||||
* @param o element to be added to this set.
|
||||
* @return <tt>true</tt> if the set did not already contain the specified
|
||||
* element.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean add(Object o) {
|
||||
if (o == null) o = nullObject;
|
||||
|
||||
int hash = o.hashCode();
|
||||
int index = (hash & 0x7FFFFFFF) % objects.length;
|
||||
int offset = 1;
|
||||
int deletedix = -1;
|
||||
|
||||
// search for the object (continue while !null and !this object)
|
||||
while(objects[index] != null &&
|
||||
!(objects[index].hashCode() == hash &&
|
||||
objects[index].equals(o))) {
|
||||
|
||||
// if there's a deleted object here we can put this object here,
|
||||
// provided it's not in here somewhere else already
|
||||
if (objects[index] == deletedObject)
|
||||
deletedix = index;
|
||||
|
||||
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
|
||||
offset = offset*2 + 1;
|
||||
|
||||
if (offset == -1)
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
if (objects[index] == null) { // wasn't present already
|
||||
if (deletedix != -1) // reusing a deleted cell
|
||||
index = deletedix;
|
||||
else
|
||||
freecells--;
|
||||
|
||||
modCount++;
|
||||
elements++;
|
||||
|
||||
// here we face a problem regarding generics:
|
||||
// add(E o) is not possible because of the null Object. We cant do 'new E()' or '(E) new Object()'
|
||||
// so adding an empty object is a problem here
|
||||
// If (! o instanceof E) : This will cause a class cast exception
|
||||
// If (o instanceof E) : This will work fine
|
||||
|
||||
objects[index] = (E) o;
|
||||
|
||||
// do we need to rehash?
|
||||
if (1 - (freecells / (double) objects.length) > LOAD_FACTOR)
|
||||
rehash();
|
||||
return true;
|
||||
} else // was there already
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified element from the set.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean remove(Object o) {
|
||||
if (o == null) o = nullObject;
|
||||
|
||||
int hash = o.hashCode();
|
||||
int index = (hash & 0x7FFFFFFF) % objects.length;
|
||||
int offset = 1;
|
||||
|
||||
// search for the object (continue while !null and !this object)
|
||||
while(objects[index] != null &&
|
||||
!(objects[index].hashCode() == hash &&
|
||||
objects[index].equals(o))) {
|
||||
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
|
||||
offset = offset*2 + 1;
|
||||
|
||||
if (offset == -1)
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
// we found the right position, now do the removal
|
||||
if (objects[index] != null) {
|
||||
// we found the object
|
||||
|
||||
// same problem here as with add
|
||||
objects[index] = (E) deletedObject;
|
||||
modCount++;
|
||||
elements--;
|
||||
return true;
|
||||
} else
|
||||
// we did not find the object
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this set.
|
||||
*/
|
||||
public void clear() {
|
||||
elements = 0;
|
||||
for (int ix = 0; ix < objects.length; ix++)
|
||||
objects[ix] = null;
|
||||
freecells = objects.length;
|
||||
modCount++;
|
||||
}
|
||||
|
||||
public Object[] toArray() {
|
||||
Object[] result = new Object[elements];
|
||||
Object[] objects = this.objects;
|
||||
int pos = 0;
|
||||
for (int i = 0; i < objects.length; i++)
|
||||
if (objects[i] != null && objects[i] != deletedObject) {
|
||||
if (objects[i] == nullObject)
|
||||
result[pos++] = null;
|
||||
else
|
||||
result[pos++] = objects[i];
|
||||
}
|
||||
// unchecked because it should only contain E
|
||||
return result;
|
||||
}
|
||||
|
||||
// not sure if this needs to have generics
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] toArray(T[] a) {
|
||||
int size = elements;
|
||||
if (a.length < size)
|
||||
a = (T[])java.lang.reflect.Array.newInstance(
|
||||
a.getClass().getComponentType(), size);
|
||||
E[] objects = this.objects;
|
||||
int pos = 0;
|
||||
for (int i = 0; i < objects.length; i++)
|
||||
if (objects[i] != null && objects[i] != deletedObject) {
|
||||
if (objects[i] == nullObject)
|
||||
a[pos++] = null;
|
||||
else
|
||||
a[pos++] = (T) objects[i];
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// ===== INTERNAL METHODS ===============================================
|
||||
|
||||
/**
|
||||
* INTERNAL: Used for debugging only.
|
||||
*/
|
||||
public void dump() {
|
||||
System.out.println("Size: " + objects.length);
|
||||
System.out.println("Elements: " + elements);
|
||||
System.out.println("Free cells: " + freecells);
|
||||
System.out.println();
|
||||
for (int ix = 0; ix < objects.length; ix++)
|
||||
System.out.println("[" + ix + "]: " + objects[ix]);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Figures out correct size for rehashed set, then does
|
||||
* the rehash.
|
||||
*/
|
||||
protected void rehash() {
|
||||
// do we need to increase capacity, or are there so many
|
||||
// deleted objects hanging around that rehashing to the same
|
||||
// size is sufficient? if 5% (arbitrarily chosen number) of
|
||||
// cells can be freed up by a rehash, we do it.
|
||||
|
||||
int gargagecells = objects.length - (elements + freecells);
|
||||
if (gargagecells / (double) objects.length > 0.05)
|
||||
// rehash with same size
|
||||
rehash(objects.length);
|
||||
else
|
||||
// rehash with increased capacity
|
||||
rehash(objects.length*2 + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Rehashes the hashset to a bigger size.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void rehash(int newCapacity) {
|
||||
int oldCapacity = objects.length;
|
||||
@SuppressWarnings("unchecked")
|
||||
E[] newObjects = (E[]) new Object[newCapacity];
|
||||
|
||||
for (int ix = 0; ix < oldCapacity; ix++) {
|
||||
Object o = objects[ix];
|
||||
if (o == null || o == deletedObject)
|
||||
continue;
|
||||
|
||||
int hash = o.hashCode();
|
||||
int index = (hash & 0x7FFFFFFF) % newCapacity;
|
||||
int offset = 1;
|
||||
|
||||
// search for the object
|
||||
while(newObjects[index] != null) { // no need to test for duplicates
|
||||
index = ((index + offset) & 0x7FFFFFFF) % newCapacity;
|
||||
offset = offset*2 + 1;
|
||||
|
||||
if (offset == -1)
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
newObjects[index] = (E) o;
|
||||
}
|
||||
|
||||
objects = newObjects;
|
||||
freecells = objects.length - elements;
|
||||
}
|
||||
|
||||
// ===== ITERATOR IMPLEMENTATON =========================================
|
||||
|
||||
private class CompactHashIterator<T> implements Iterator<T> {
|
||||
private int index;
|
||||
private int lastReturned = -1;
|
||||
protected final static int INITIAL_SIZE = 3;
|
||||
protected final static double LOAD_FACTOR = 0.75;
|
||||
|
||||
/**
|
||||
* The modCount value that the iterator believes that the backing
|
||||
* CompactHashSet should have. If this expectation is violated,
|
||||
* the iterator has detected concurrent modification.
|
||||
* This object is used to represent null, should clients add that to the set.
|
||||
*/
|
||||
private int expectedModCount;
|
||||
protected final static Object nullObject = new Object();
|
||||
/**
|
||||
* When an object is deleted this object is put into the hashtable
|
||||
* in its place, so that other objects with the same key
|
||||
* (collisions) further down the hashtable are not lost after we
|
||||
* delete an object in the collision chain.
|
||||
*/
|
||||
protected final static Object deletedObject = new Object();
|
||||
protected int elements;
|
||||
/**
|
||||
* This is the number of empty (null) cells. It's not necessarily
|
||||
* the same as objects.length - elements, because some cells may
|
||||
* contain deletedObject.
|
||||
*/
|
||||
protected int freecells;
|
||||
protected E[] objects;
|
||||
protected int modCount;
|
||||
|
||||
@SuppressWarnings("empty-statement")
|
||||
public CompactHashIterator() {
|
||||
for (index = 0; index < objects.length &&
|
||||
(objects[index] == null ||
|
||||
objects[index] == deletedObject); index++)
|
||||
;
|
||||
expectedModCount = modCount;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index < objects.length;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"empty-statement", "unchecked"})
|
||||
public T next() {
|
||||
if (modCount != expectedModCount)
|
||||
throw new ConcurrentModificationException();
|
||||
int length = objects.length;
|
||||
if (index >= length) {
|
||||
lastReturned = -2;
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
lastReturned = index;
|
||||
for (index += 1; index < length &&
|
||||
(objects[index] == null ||
|
||||
objects[index] == deletedObject); index++)
|
||||
;
|
||||
if (objects[lastReturned] == nullObject)
|
||||
return null;
|
||||
else
|
||||
return (T) objects[lastReturned];
|
||||
/**
|
||||
* Constructs a new, empty set.
|
||||
*/
|
||||
public CompactHashSet() {
|
||||
this(INITIAL_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new, empty set.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void remove() {
|
||||
if (modCount != expectedModCount)
|
||||
throw new ConcurrentModificationException();
|
||||
if (lastReturned == -1 || lastReturned == -2)
|
||||
throw new IllegalStateException();
|
||||
// delete object
|
||||
if (objects[lastReturned] != null && objects[lastReturned] != deletedObject) {
|
||||
objects[lastReturned] = (E) deletedObject;
|
||||
elements--;
|
||||
modCount++;
|
||||
expectedModCount = modCount; // this is expected; we made the change
|
||||
}
|
||||
public CompactHashSet(int size) {
|
||||
// NOTE: If array size is 0, we get a
|
||||
// "java.lang.ArithmeticException: / by zero" in add(Object).
|
||||
objects = (E[]) new Object[(size == 0 ? 1 : size)];
|
||||
elements = 0;
|
||||
freecells = objects.length;
|
||||
modCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new set containing the elements in the specified
|
||||
* collection.
|
||||
*
|
||||
* @param c the collection whose elements are to be placed into this set.
|
||||
*/
|
||||
public CompactHashSet(Collection<E> c) {
|
||||
this(c.size());
|
||||
addAll(c);
|
||||
}
|
||||
|
||||
// ===== SET IMPLEMENTATION =============================================
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this set. The elements
|
||||
* are returned in no particular order.
|
||||
*
|
||||
* @return an Iterator over the elements in this set.
|
||||
* @see ConcurrentModificationException
|
||||
*/
|
||||
@NonNull
|
||||
public Iterator<E> iterator() {
|
||||
return new CompactHashIterator<E>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this set (its cardinality).
|
||||
*/
|
||||
public int size() {
|
||||
return elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this set contains no elements.
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return elements == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this set contains the specified element.
|
||||
*
|
||||
* @param o element whose presence in this set is to be tested.
|
||||
* @return <tt>true</tt> if this set contains the specified element.
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
if (o == null) o = nullObject;
|
||||
|
||||
int hash = o.hashCode();
|
||||
int index = (hash & 0x7FFFFFFF) % objects.length;
|
||||
int offset = 1;
|
||||
|
||||
// search for the object (continue while !null and !this object)
|
||||
while (objects[index] != null &&
|
||||
!(objects[index].hashCode() == hash &&
|
||||
objects[index].equals(o))) {
|
||||
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
|
||||
offset = offset * 2 + 1;
|
||||
|
||||
if (offset == -1)
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
return objects[index] != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified element to this set if it is not already
|
||||
* present.
|
||||
*
|
||||
* @param o element to be added to this set.
|
||||
* @return <tt>true</tt> if the set did not already contain the specified
|
||||
* element.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean add(Object o) {
|
||||
if (o == null) o = nullObject;
|
||||
|
||||
int hash = o.hashCode();
|
||||
int index = (hash & 0x7FFFFFFF) % objects.length;
|
||||
int offset = 1;
|
||||
int deletedix = -1;
|
||||
|
||||
// search for the object (continue while !null and !this object)
|
||||
while (objects[index] != null &&
|
||||
!(objects[index].hashCode() == hash &&
|
||||
objects[index].equals(o))) {
|
||||
|
||||
// if there's a deleted object here we can put this object here,
|
||||
// provided it's not in here somewhere else already
|
||||
if (objects[index] == deletedObject)
|
||||
deletedix = index;
|
||||
|
||||
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
|
||||
offset = offset * 2 + 1;
|
||||
|
||||
if (offset == -1)
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
if (objects[index] == null) { // wasn't present already
|
||||
if (deletedix != -1) // reusing a deleted cell
|
||||
index = deletedix;
|
||||
else
|
||||
freecells--;
|
||||
|
||||
modCount++;
|
||||
elements++;
|
||||
|
||||
// here we face a problem regarding generics:
|
||||
// add(E o) is not possible because of the null Object. We cant do 'new E()' or '(E) new Object()'
|
||||
// so adding an empty object is a problem here
|
||||
// If (! o instanceof E) : This will cause a class cast exception
|
||||
// If (o instanceof E) : This will work fine
|
||||
|
||||
objects[index] = (E) o;
|
||||
|
||||
// do we need to rehash?
|
||||
if (1 - (freecells / (double) objects.length) > LOAD_FACTOR)
|
||||
rehash();
|
||||
return true;
|
||||
} else // was there already
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the specified element from the set.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public boolean remove(Object o) {
|
||||
if (o == null) o = nullObject;
|
||||
|
||||
int hash = o.hashCode();
|
||||
int index = (hash & 0x7FFFFFFF) % objects.length;
|
||||
int offset = 1;
|
||||
|
||||
// search for the object (continue while !null and !this object)
|
||||
while (objects[index] != null &&
|
||||
!(objects[index].hashCode() == hash &&
|
||||
objects[index].equals(o))) {
|
||||
index = ((index + offset) & 0x7FFFFFFF) % objects.length;
|
||||
offset = offset * 2 + 1;
|
||||
|
||||
if (offset == -1)
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
// we found the right position, now do the removal
|
||||
if (objects[index] != null) {
|
||||
// we found the object
|
||||
|
||||
// same problem here as with add
|
||||
objects[index] = (E) deletedObject;
|
||||
modCount++;
|
||||
elements--;
|
||||
return true;
|
||||
} else
|
||||
// we did not find the object
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this set.
|
||||
*/
|
||||
public void clear() {
|
||||
elements = 0;
|
||||
for (int ix = 0; ix < objects.length; ix++)
|
||||
objects[ix] = null;
|
||||
freecells = objects.length;
|
||||
modCount++;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Object[] toArray() {
|
||||
Object[] result = new Object[elements];
|
||||
Object[] objects = this.objects;
|
||||
int pos = 0;
|
||||
for (int i = 0; i < objects.length; i++)
|
||||
if (objects[i] != null && objects[i] != deletedObject) {
|
||||
if (objects[i] == nullObject)
|
||||
result[pos++] = null;
|
||||
else
|
||||
result[pos++] = objects[i];
|
||||
}
|
||||
// unchecked because it should only contain E
|
||||
return result;
|
||||
}
|
||||
|
||||
// not sure if this needs to have generics
|
||||
@NonNull
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T[] toArray(@NonNull T[] a) {
|
||||
int size = elements;
|
||||
if (a.length < size)
|
||||
a = (T[]) java.lang.reflect.Array.newInstance(
|
||||
a.getClass().getComponentType(), size);
|
||||
E[] objects = this.objects;
|
||||
int pos = 0;
|
||||
for (int i = 0; i < objects.length; i++)
|
||||
if (objects[i] != null && objects[i] != deletedObject) {
|
||||
if (objects[i] == nullObject)
|
||||
a[pos++] = null;
|
||||
else
|
||||
a[pos++] = (T) objects[i];
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
// ===== INTERNAL METHODS ===============================================
|
||||
|
||||
/**
|
||||
* INTERNAL: Used for debugging only.
|
||||
*/
|
||||
public void dump() {
|
||||
System.out.println("Size: " + objects.length);
|
||||
System.out.println("Elements: " + elements);
|
||||
System.out.println("Free cells: " + freecells);
|
||||
System.out.println();
|
||||
for (int ix = 0; ix < objects.length; ix++)
|
||||
System.out.println("[" + ix + "]: " + objects[ix]);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Figures out correct size for rehashed set, then does
|
||||
* the rehash.
|
||||
*/
|
||||
protected void rehash() {
|
||||
// do we need to increase capacity, or are there so many
|
||||
// deleted objects hanging around that rehashing to the same
|
||||
// size is sufficient? if 5% (arbitrarily chosen number) of
|
||||
// cells can be freed up by a rehash, we do it.
|
||||
|
||||
int gargagecells = objects.length - (elements + freecells);
|
||||
if (gargagecells / (double) objects.length > 0.05)
|
||||
// rehash with same size
|
||||
rehash(objects.length);
|
||||
else
|
||||
// rehash with increased capacity
|
||||
rehash(objects.length * 2 + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Rehashes the hashset to a bigger size.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void rehash(int newCapacity) {
|
||||
int oldCapacity = objects.length;
|
||||
@SuppressWarnings("unchecked")
|
||||
E[] newObjects = (E[]) new Object[newCapacity];
|
||||
|
||||
for (int ix = 0; ix < oldCapacity; ix++) {
|
||||
Object o = objects[ix];
|
||||
if (o == null || o == deletedObject)
|
||||
continue;
|
||||
|
||||
int hash = o.hashCode();
|
||||
int index = (hash & 0x7FFFFFFF) % newCapacity;
|
||||
int offset = 1;
|
||||
|
||||
// search for the object
|
||||
while (newObjects[index] != null) { // no need to test for duplicates
|
||||
index = ((index + offset) & 0x7FFFFFFF) % newCapacity;
|
||||
offset = offset * 2 + 1;
|
||||
|
||||
if (offset == -1)
|
||||
offset = 2;
|
||||
}
|
||||
|
||||
newObjects[index] = (E) o;
|
||||
}
|
||||
|
||||
objects = newObjects;
|
||||
freecells = objects.length - elements;
|
||||
}
|
||||
|
||||
// ===== ITERATOR IMPLEMENTATON =========================================
|
||||
|
||||
private class CompactHashIterator<T> implements Iterator<T> {
|
||||
private int index;
|
||||
private int lastReturned = -1;
|
||||
|
||||
/**
|
||||
* The modCount value that the iterator believes that the backing
|
||||
* CompactHashSet should have. If this expectation is violated,
|
||||
* the iterator has detected concurrent modification.
|
||||
*/
|
||||
private int expectedModCount;
|
||||
|
||||
@SuppressWarnings("empty-statement")
|
||||
public CompactHashIterator() {
|
||||
for (index = 0; index < objects.length &&
|
||||
(objects[index] == null ||
|
||||
objects[index] == deletedObject); index++)
|
||||
;
|
||||
expectedModCount = modCount;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index < objects.length;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"empty-statement", "unchecked"})
|
||||
public T next() {
|
||||
if (modCount != expectedModCount)
|
||||
throw new ConcurrentModificationException();
|
||||
int length = objects.length;
|
||||
if (index >= length) {
|
||||
lastReturned = -2;
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
lastReturned = index;
|
||||
for (index += 1; index < length &&
|
||||
(objects[index] == null ||
|
||||
objects[index] == deletedObject); index++)
|
||||
;
|
||||
if (objects[lastReturned] == nullObject)
|
||||
return null;
|
||||
else
|
||||
return (T) objects[lastReturned];
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void remove() {
|
||||
if (modCount != expectedModCount)
|
||||
throw new ConcurrentModificationException();
|
||||
if (lastReturned == -1 || lastReturned == -2)
|
||||
throw new IllegalStateException();
|
||||
// delete object
|
||||
if (objects[lastReturned] != null && objects[lastReturned] != deletedObject) {
|
||||
objects[lastReturned] = (E) deletedObject;
|
||||
elements--;
|
||||
modCount++;
|
||||
expectedModCount = modCount; // this is expected; we made the change
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -56,14 +56,14 @@ public class NoDuplicatesArrayList<E> extends ArrayList<E> {
|
||||
|
||||
@Override
|
||||
public boolean addAll(final Collection<? extends E> collection) {
|
||||
final Collection<E> copy = new ArrayList<E>(collection);
|
||||
final Collection<E> copy = new ArrayList<>(collection);
|
||||
copy.removeAll(this);
|
||||
return super.addAll(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(final int index, final Collection<? extends E> collection) {
|
||||
final Collection<E> copy = new ArrayList<E>(collection);
|
||||
final Collection<E> copy = new ArrayList<>(collection);
|
||||
copy.removeAll(this);
|
||||
return super.addAll(index, copy);
|
||||
}
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Twidere - Twitter client for Android
|
||||
*
|
||||
* Copyright (C) 2012-2014 Mariotaku Lee <mariotaku.lee@gmail.com>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.mariotaku.twidere.util.collection;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
public class NoDuplicatesCopyOnWriteArrayList<E> extends CopyOnWriteArrayList<E> {
|
||||
|
||||
private static final long serialVersionUID = -7277301117508689125L;
|
||||
|
||||
public NoDuplicatesCopyOnWriteArrayList() {
|
||||
super();
|
||||
}
|
||||
|
||||
public NoDuplicatesCopyOnWriteArrayList(final Collection<? extends E> collection) {
|
||||
super(collection);
|
||||
}
|
||||
|
||||
public NoDuplicatesCopyOnWriteArrayList(final E[] array) {
|
||||
super(array);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(final E e) {
|
||||
if (contains(e))
|
||||
return false;
|
||||
else
|
||||
return super.add(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(final int index, final E element) {
|
||||
if (contains(element))
|
||||
return;
|
||||
else {
|
||||
super.add(index, element);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(final Collection<? extends E> collection) {
|
||||
final Collection<E> copy = new ArrayList<E>(collection);
|
||||
copy.removeAll(this);
|
||||
return super.addAll(copy);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(final int index, final Collection<? extends E> collection) {
|
||||
final Collection<E> copy = new ArrayList<E>(collection);
|
||||
copy.removeAll(this);
|
||||
return super.addAll(index, copy);
|
||||
}
|
||||
}
|
@ -19,6 +19,8 @@
|
||||
|
||||
package org.mariotaku.twidere.util.io;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
@ -27,86 +29,86 @@ import java.io.InputStream;
|
||||
|
||||
public class ContentLengthInputStream extends InputStream {
|
||||
|
||||
private final InputStream stream;
|
||||
private final long length;
|
||||
private ReadListener readListener;
|
||||
private final InputStream stream;
|
||||
private final long length;
|
||||
private ReadListener readListener;
|
||||
|
||||
private long pos;
|
||||
private long pos;
|
||||
|
||||
public ContentLengthInputStream(final File file) throws FileNotFoundException {
|
||||
this(new FileInputStream(file), file.length());
|
||||
}
|
||||
public ContentLengthInputStream(final File file) throws FileNotFoundException {
|
||||
this(new FileInputStream(file), file.length());
|
||||
}
|
||||
|
||||
public ContentLengthInputStream(final InputStream stream, final long length) {
|
||||
this.stream = stream;
|
||||
this.length = length;
|
||||
}
|
||||
public ContentLengthInputStream(final InputStream stream, final long length) {
|
||||
this.stream = stream;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
public ContentLengthInputStream(final String file) throws FileNotFoundException {
|
||||
this(new FileInputStream(file), file.length());
|
||||
}
|
||||
public ContentLengthInputStream(final String file) throws FileNotFoundException {
|
||||
this(new FileInputStream(file), file.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized int available() {
|
||||
return (int) (length - pos);
|
||||
}
|
||||
@Override
|
||||
public synchronized int available() {
|
||||
return (int) (length - pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
stream.close();
|
||||
}
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
stream.close();
|
||||
}
|
||||
|
||||
public long length() {
|
||||
return length;
|
||||
}
|
||||
public long length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mark(final int readlimit) {
|
||||
pos = readlimit;
|
||||
stream.mark(readlimit);
|
||||
}
|
||||
@Override
|
||||
public void mark(final int readLimit) {
|
||||
pos = readLimit;
|
||||
stream.mark(readLimit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
pos++;
|
||||
if (readListener != null) {
|
||||
readListener.onRead(length, pos);
|
||||
}
|
||||
return stream.read();
|
||||
}
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
pos++;
|
||||
if (readListener != null) {
|
||||
readListener.onRead(length, pos);
|
||||
}
|
||||
return stream.read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final byte[] buffer) throws IOException {
|
||||
return read(buffer, 0, buffer.length);
|
||||
}
|
||||
@Override
|
||||
public int read(@NonNull final byte[] buffer) throws IOException {
|
||||
return read(buffer, 0, buffer.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(final byte[] buffer, final int byteOffset, final int byteCount) throws IOException {
|
||||
pos += byteCount;
|
||||
if (readListener != null) {
|
||||
readListener.onRead(length, pos);
|
||||
}
|
||||
return stream.read(buffer, byteOffset, byteCount);
|
||||
}
|
||||
@Override
|
||||
public int read(@NonNull final byte[] buffer, final int byteOffset, final int byteCount) throws IOException {
|
||||
pos += byteCount;
|
||||
if (readListener != null) {
|
||||
readListener.onRead(length, pos);
|
||||
}
|
||||
return stream.read(buffer, byteOffset, byteCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void reset() throws IOException {
|
||||
pos = 0;
|
||||
stream.reset();
|
||||
}
|
||||
@Override
|
||||
public synchronized void reset() throws IOException {
|
||||
pos = 0;
|
||||
stream.reset();
|
||||
}
|
||||
|
||||
public void setReadListener(final ReadListener readListener) {
|
||||
this.readListener = readListener;
|
||||
}
|
||||
public void setReadListener(final ReadListener readListener) {
|
||||
this.readListener = readListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(final long byteCount) throws IOException {
|
||||
pos += byteCount;
|
||||
return stream.skip(byteCount);
|
||||
}
|
||||
@Override
|
||||
public long skip(final long byteCount) throws IOException {
|
||||
pos += byteCount;
|
||||
return stream.skip(byteCount);
|
||||
}
|
||||
|
||||
public interface ReadListener {
|
||||
void onRead(long length, long position);
|
||||
}
|
||||
public interface ReadListener {
|
||||
void onRead(long length, long position);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import android.content.Context;
|
||||
import java.security.cert.CertificateException;
|
||||
import java.security.cert.X509Certificate;
|
||||
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
/**
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user