optimized code (fixed some lint problems)

This commit is contained in:
Mariotaku Lee 2015-04-16 02:40:28 +08:00
parent 9641290502
commit 162ac1af42
169 changed files with 2460 additions and 4065 deletions

View File

@ -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'

View File

@ -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>

View File

@ -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;

View File

@ -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.

View File

@ -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();
}
}

View File

@ -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();
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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();
}
}
}

View File

@ -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);

View File

@ -90,7 +90,6 @@ public class TwitterLinkHandlerActivity extends Activity implements Constants {
intent.setClassName(activityInfo.packageName, activityInfo.name);
startActivity(intent);
finish();
return;
}
}
}

View File

@ -19,8 +19,6 @@
package org.mariotaku.twidere.activity.iface;
import android.content.res.Resources;
public interface IThemedActivity {
int getCurrentThemeBackgroundAlpha();

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}
}
}

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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 + "}";
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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();

View File

@ -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) {
}

View File

@ -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)) {

View File

@ -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();
}
}

View File

@ -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)) {

View File

@ -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());

View File

@ -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();

View File

@ -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);
}

View File

@ -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));
}

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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();
}

View File

@ -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;

View File

@ -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());
}
}

View File

@ -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);

View File

@ -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() {

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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());

View File

@ -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;

View File

@ -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;
}

View File

@ -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) {

View File

@ -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();
}
}
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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(&quot;foo.txt&quot;);
* // 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(&quot;foo.txt&quot;);
* 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(&quot;foo.txt&quot;);
* // 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 = &quot;Hello, World&quot;.getBytes();
*
* OutputStream out = null;
* try {
* out = new FileOutputStream(&quot;foo.txt&quot;);
* 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(&quot;foo.txt&quot;);
* 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 = &quot;Hello, World&quot;.getBytes();
*
* OutputStream out = null;
* try {
* out = new FileOutputStream(&quot;foo.txt&quot;);
* 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());
}
}
}

View File

@ -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();
}
}
}

View File

@ -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() {

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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());

View File

@ -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;
}

View File

@ -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);
}
}
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -277,10 +277,6 @@ public final class TwidereLinkify implements Constants {
addCashtagLinks(string, accountId, extraId, listener, highlightOption);
break;
}
default: {
return;
}
}
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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
}
}
}
}

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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