{
mSize++;
}
+ /**
+ * Removes all items from the SortedList.
+ */
+ public void clear() {
+ if (mSize == 0) {
+ return;
+ }
+ final int prevSize = mSize;
+ Arrays.fill(mData, 0, prevSize, null);
+ mSize = 0;
+ mCallback.onRemoved(0, prevSize);
+ }
+
/**
* The class that controls the behavior of the {@link SortedList}.
*
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/AdapterHelper.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/AdapterHelper.java
index 3b4c28c1a..d56fb0b99 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/AdapterHelper.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/AdapterHelper.java
@@ -19,6 +19,9 @@ package org.telegram.android.support.widget;
import android.support.v4.util.Pools;
import android.util.Log;
+import org.telegram.android.support.widget.OpReorderer;
+import org.telegram.android.support.widget.RecyclerView;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/DefaultItemAnimator.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/DefaultItemAnimator.java
index bbbc20a54..0d7e11af7 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/DefaultItemAnimator.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/DefaultItemAnimator.java
@@ -18,6 +18,7 @@ package org.telegram.android.support.widget;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListener;
+
import org.telegram.android.support.widget.RecyclerView.ViewHolder;
import android.view.View;
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/GridLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/GridLayoutManager.java
index 790bf06f8..37453d67c 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/GridLayoutManager.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/GridLayoutManager.java
@@ -24,6 +24,8 @@ import android.util.SparseIntArray;
import android.view.View;
import android.view.ViewGroup;
+import org.telegram.android.support.widget.RecyclerView;
+
import java.util.Arrays;
/**
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/LayoutState.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/LayoutState.java
index c431b6149..b91274a1e 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/LayoutState.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/LayoutState.java
@@ -60,11 +60,14 @@ class LayoutState {
int mLayoutDirection;
/**
- * Used if you want to pre-layout items that are not yet visible.
- * The difference with {@link #mAvailable} is that, when recycling, distance rendered for
- * {@link #mExtra} is not considered not to recycle visible children.
+ * This is the target pixel closest to the start of the layout that we are trying to fill
*/
- int mExtra = 0;
+ int mStartLine = 0;
+
+ /**
+ * This is the target pixel closest to the end of the layout that we are trying to fill
+ */
+ int mEndLine = 0;
/**
* @return true if there are more items in the data adapter
@@ -84,4 +87,16 @@ class LayoutState {
mCurrentPosition += mItemDirection;
return view;
}
+
+ @Override
+ public String toString() {
+ return "LayoutState{" +
+ "mAvailable=" + mAvailable +
+ ", mCurrentPosition=" + mCurrentPosition +
+ ", mItemDirection=" + mItemDirection +
+ ", mLayoutDirection=" + mLayoutDirection +
+ ", mStartLine=" + mStartLine +
+ ", mEndLine=" + mEndLine +
+ '}';
+ }
}
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/LinearLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/LinearLayoutManager.java
index a52bbffe5..a0508ad5f 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/LinearLayoutManager.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/LinearLayoutManager.java
@@ -23,6 +23,12 @@ import android.os.Parcelable;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityEventCompat;
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
+import android.util.AttributeSet;
+
+import org.telegram.android.support.widget.OrientationHelper;
+import org.telegram.android.support.widget.RecyclerView;
+import org.telegram.android.support.widget.ScrollbarHelper;
+import org.telegram.android.support.widget.helper.ItemTouchHelper;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
@@ -33,10 +39,11 @@ import java.util.List;
import static org.telegram.android.support.widget.RecyclerView.NO_POSITION;
/**
- * A {@link android.support.v7.widget.RecyclerView.LayoutManager} implementation which provides
+ * A {@link RecyclerView.LayoutManager} implementation which provides
* similar functionality to {@link android.widget.ListView}.
*/
-public class LinearLayoutManager extends RecyclerView.LayoutManager {
+public class LinearLayoutManager extends RecyclerView.LayoutManager implements
+ ItemTouchHelper.ViewDropHandler {
private static final String TAG = "LinearLayoutManager";
@@ -130,7 +137,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
* Re-used variable to keep anchor information on re-layout.
* Anchor position and coordinate defines the reference point for LLM while doing a layout.
* */
- final AnchorInfo mAnchorInfo;
+ final AnchorInfo mAnchorInfo = new AnchorInfo();
/**
* Creates a vertical LinearLayoutManager
@@ -148,7 +155,6 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
* @param reverseLayout When set to true, layouts from end to start.
*/
public LinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
- mAnchorInfo = new AnchorInfo();
setOrientation(orientation);
setReverseLayout(reverseLayout);
}
@@ -342,8 +348,8 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
* laid out at the end of the UI, second item is laid out before it etc.
*
* For horizontal layouts, it depends on the layout direction.
- * When set to true, If {@link android.support.v7.widget.RecyclerView} is LTR, than it will
- * layout from RTL, if {@link android.support.v7.widget.RecyclerView}} is RTL, it will layout
+ * When set to true, If {@link RecyclerView} is LTR, than it will
+ * layout from RTL, if {@link RecyclerView}} is RTL, it will layout
* from LTR.
*
* If you are looking for the exact same behavior of
@@ -371,9 +377,13 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
final int firstChild = getPosition(getChildAt(0));
final int viewPosition = position - firstChild;
if (viewPosition >= 0 && viewPosition < childCount) {
- return getChildAt(viewPosition);
+ final View child = getChildAt(viewPosition);
+ if (getPosition(child) == position) {
+ return child; // in pre-layout, this may not match
+ }
}
- return null;
+ // fallback to traversal. This might be necessary in pre-layout.
+ return super.findViewByPosition(position);
}
/**
@@ -796,6 +806,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
}
// override layout from end values for consistency
anchorInfo.mLayoutFromEnd = mShouldReverseLayout;
+ // if this changes, we should update prepareForDrop as well
if (mShouldReverseLayout) {
anchorInfo.mCoordinate = mOrientationHelper.getEndAfterPadding() -
mPendingScrollPositionOffset;
@@ -941,7 +952,6 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
* item[10]
's bottom is 20 pixels above the RecyclerView's bottom.
*
* Note that scroll position change will not be reflected until the next layout call.
- *
*
* If you are just trying to make a position visible, use {@link #scrollToPosition(int)}.
*
@@ -1175,11 +1185,10 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
/**
* Recycles views that went out of bounds after scrolling towards the end of the layout.
*
- * @param recycler Recycler instance of {@link android.support.v7.widget.RecyclerView}
+ * @param recycler Recycler instance of {@link RecyclerView}
* @param dt This can be used to add additional padding to the visible area. This is used
- * to
- * detect children that will go out of bounds after scrolling, without actually
- * moving them.
+ * to detect children that will go out of bounds after scrolling, without
+ * actually moving them.
*/
private void recycleViewsFromStart(RecyclerView.Recycler recycler, int dt) {
if (dt < 0) {
@@ -1215,7 +1224,7 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
/**
* Recycles views that went out of bounds after scrolling towards the start of the layout.
*
- * @param recycler Recycler instance of {@link android.support.v7.widget.RecyclerView}
+ * @param recycler Recycler instance of {@link RecyclerView}
* @param dt This can be used to add additional padding to the visible area. This is used
* to detect children that will go out of bounds after scrolling, without
* actually moving them.
@@ -1257,8 +1266,8 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
* @param layoutState Current layout state. Right now, this object does not change but
* we may consider moving it out of this view so passing around as a
* parameter for now, rather than accessing {@link #mLayoutState}
- * @see #recycleViewsFromStart(android.support.v7.widget.RecyclerView.Recycler, int)
- * @see #recycleViewsFromEnd(android.support.v7.widget.RecyclerView.Recycler, int)
+ * @see #recycleViewsFromStart(RecyclerView.Recycler, int)
+ * @see #recycleViewsFromEnd(RecyclerView.Recycler, int)
* @see android.support.v7.widget.LinearLayoutManager.LayoutState#mLayoutDirection
*/
private void recycleByLayoutState(RecyclerView.Recycler recycler, LayoutState layoutState) {
@@ -1788,6 +1797,40 @@ public class LinearLayoutManager extends RecyclerView.LayoutManager {
return mPendingSavedState == null && mLastStackFromEnd == mStackFromEnd;
}
+ /**
+ * @hide This method should be called by ItemTouchHelper only.
+ */
+ @Override
+ public void prepareForDrop(View view, View target, int x, int y) {
+ assertNotInLayoutOrScroll("Cannot drop a view during a scroll or layout calculation");
+ ensureLayoutState();
+ resolveShouldLayoutReverse();
+ final int myPos = getPosition(view);
+ final int targetPos = getPosition(target);
+ final int dropDirection = myPos < targetPos ? LayoutState.ITEM_DIRECTION_TAIL :
+ LayoutState.ITEM_DIRECTION_HEAD;
+ if (mShouldReverseLayout) {
+ if (dropDirection == LayoutState.ITEM_DIRECTION_TAIL) {
+ scrollToPositionWithOffset(targetPos,
+ mOrientationHelper.getEndAfterPadding() -
+ (mOrientationHelper.getDecoratedStart(target) +
+ mOrientationHelper.getDecoratedMeasurement(view)));
+ } else {
+ scrollToPositionWithOffset(targetPos,
+ mOrientationHelper.getEndAfterPadding() -
+ mOrientationHelper.getDecoratedEnd(target));
+ }
+ } else {
+ if (dropDirection == LayoutState.ITEM_DIRECTION_HEAD) {
+ scrollToPositionWithOffset(targetPos, mOrientationHelper.getDecoratedStart(target));
+ } else {
+ scrollToPositionWithOffset(targetPos,
+ mOrientationHelper.getDecoratedEnd(target) -
+ mOrientationHelper.getDecoratedMeasurement(view));
+ }
+ }
+ }
+
/**
* Helper class that keeps temporary state while {LayoutManager} is filling out the empty
* space.
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/OpReorderer.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/OpReorderer.java
index 3d56822f7..05d0e93a9 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/OpReorderer.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/OpReorderer.java
@@ -16,14 +16,14 @@
package org.telegram.android.support.widget;
-import java.util.List;
-
import org.telegram.android.support.widget.AdapterHelper.UpdateOp;
import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.ADD;
import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.MOVE;
import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.REMOVE;
import static org.telegram.android.support.widget.AdapterHelper.UpdateOp.UPDATE;
+import java.util.List;
+
class OpReorderer {
final Callback mCallback;
@@ -58,7 +58,7 @@ class OpReorderer {
}
void swapMoveRemove(List list, int movePos, UpdateOp moveOp,
- int removePos, UpdateOp removeOp) {
+ int removePos, UpdateOp removeOp) {
UpdateOp extraRm = null;
// check if move is nulled out by remove
boolean revertedMove = false;
@@ -83,7 +83,7 @@ class OpReorderer {
removeOp.positionStart--;
} else if (moveOp.itemCount < removeOp.positionStart + removeOp.itemCount) {
// move is removed.
- removeOp.itemCount --;
+ removeOp.itemCount--;
moveOp.cmd = REMOVE;
moveOp.itemCount = 1;
if (removeOp.itemCount == 0) {
@@ -157,7 +157,7 @@ class OpReorderer {
}
private void swapMoveAdd(List list, int move, UpdateOp moveOp, int add,
- UpdateOp addOp) {
+ UpdateOp addOp) {
int offset = 0;
// going in reverse, first revert the effect of add
if (moveOp.itemCount < addOp.positionStart) {
@@ -178,7 +178,7 @@ class OpReorderer {
}
void swapMoveUpdate(List list, int move, UpdateOp moveOp, int update,
- UpdateOp updateOp) {
+ UpdateOp updateOp) {
UpdateOp extraUp1 = null;
UpdateOp extraUp2 = null;
// going in reverse, first revert the effect of add
@@ -228,7 +228,7 @@ class OpReorderer {
return -1;
}
- static interface Callback {
+ interface Callback {
UpdateOp obtainUpdateOp(int cmd, int startPosition, int itemCount);
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/PositionMap.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/PositionMap.java
index b97bd5a65..15a41191d 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/PositionMap.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/PositionMap.java
@@ -456,5 +456,4 @@ class PositionMap implements Cloneable {
return ~lo; // value not present
}
}
-
}
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java
index f6a17a1d8..4aa003c75 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/RecyclerView.java
@@ -18,6 +18,7 @@
package org.telegram.android.support.widget;
import android.content.Context;
+import android.content.res.TypedArray;
import android.database.Observable;
import android.graphics.Canvas;
import android.graphics.PointF;
@@ -30,6 +31,8 @@ import android.support.annotation.Nullable;
import android.support.v4.util.ArrayMap;
import android.support.v4.view.InputDeviceCompat;
import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.NestedScrollingChild;
+import android.support.v4.view.NestedScrollingChildHelper;
import android.support.v4.view.ScrollingView;
import android.support.v4.view.VelocityTrackerCompat;
import android.support.v4.view.ViewCompat;
@@ -39,9 +42,6 @@ import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityRecordCompat;
import android.support.v4.widget.EdgeEffectCompat;
import android.support.v4.widget.ScrollerCompat;
-import static org.telegram.android.support.widget.AdapterHelper.UpdateOp;
-import static org.telegram.android.support.widget.AdapterHelper.Callback;
-
import android.util.AttributeSet;
import android.util.Log;
import android.util.SparseArray;
@@ -58,12 +58,15 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Interpolator;
-import org.telegram.android.AndroidUtilities;
-
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import static org.telegram.android.support.widget.AdapterHelper.Callback;
+import static org.telegram.android.support.widget.AdapterHelper.UpdateOp;
+
/**
* A flexible view for providing a limited window into a large data set.
*
@@ -128,8 +131,10 @@ import java.util.List;
*
* When writing a {@link LayoutManager} you almost always want to use layout positions whereas when
* writing an {@link Adapter}, you probably want to use adapter positions.
+ *
+ * @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_layoutManager
*/
-public class RecyclerView extends ViewGroup implements ScrollingView {
+public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {
private static final String TAG = "RecyclerView";
@@ -221,6 +226,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
* >Try increasing your pool size and item cache size.
*/
private static final String TRACE_CREATE_VIEW_TAG = "RV CreateView";
+ private static final Class>[] LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE =
+ new Class[]{Context.class, AttributeSet.class, int.class, int.class};
private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
@@ -283,6 +290,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
private boolean mAdapterUpdateDuringMeasure;
private final boolean mPostUpdatesOnAnimation;
private final AccessibilityManager mAccessibilityManager;
+ private List mOnChildAttachStateListeners;
/**
* Set to true when an adapter data set changed notification is received.
@@ -354,11 +362,17 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
new ItemAnimatorRestoreListener();
private boolean mPostedAnimatorRunner = false;
private RecyclerViewAccessibilityDelegate mAccessibilityDelegate;
+ private ChildDrawingOrderCallback mChildDrawingOrderCallback;
// simple array to keep min and max child position during a layout calculation
// preserved not to create a new one in each layout pass
private final int[] mMinMaxLayoutPositions = new int[2];
+ private final NestedScrollingChildHelper mScrollingChildHelper;
+ private final int[] mScrollOffset = new int[2];
+ private final int[] mScrollConsumed = new int[2];
+ private final int[] mNestedOffsets = new int[2];
+
private Runnable mItemAnimatorRunner = new Runnable() {
@Override
public void run() {
@@ -408,6 +422,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
mAccessibilityManager = (AccessibilityManager) getContext()
.getSystemService(Context.ACCESSIBILITY_SERVICE);
setAccessibilityDelegateCompat(new RecyclerViewAccessibilityDelegate(this));
+ // Create the layoutManager if specified.
+
+ mScrollingChildHelper = new NestedScrollingChildHelper(this);
+ setNestedScrollingEnabled(true);
}
/**
@@ -428,6 +446,72 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
ViewCompat.setAccessibilityDelegate(this, mAccessibilityDelegate);
}
+ /**
+ * Instantiate and set a LayoutManager, if specified in the attributes.
+ */
+ private void createLayoutManager(Context context, String className, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ if (className != null) {
+ className = className.trim();
+ if (className.length() != 0) { // Can't use isEmpty since it was added in API 9.
+ className = getFullClassName(context, className);
+ try {
+ ClassLoader classLoader;
+ if (isInEditMode()) {
+ // Stupid layoutlib cannot handle simple class loaders.
+ classLoader = this.getClass().getClassLoader();
+ } else {
+ classLoader = context.getClassLoader();
+ }
+ Class extends LayoutManager> layoutManagerClass =
+ classLoader.loadClass(className).asSubclass(LayoutManager.class);
+ Constructor extends LayoutManager> constructor;
+ Object[] constructorArgs = null;
+ try {
+ constructor = layoutManagerClass
+ .getConstructor(LAYOUT_MANAGER_CONSTRUCTOR_SIGNATURE);
+ constructorArgs = new Object[]{context, attrs, defStyleAttr, defStyleRes};
+ } catch (NoSuchMethodException e) {
+ try {
+ constructor = layoutManagerClass.getConstructor();
+ } catch (NoSuchMethodException e1) {
+ e1.initCause(e);
+ throw new IllegalStateException(attrs.getPositionDescription() +
+ ": Error creating LayoutManager " + className, e1);
+ }
+ }
+ constructor.setAccessible(true);
+ setLayoutManager(constructor.newInstance(constructorArgs));
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(attrs.getPositionDescription()
+ + ": Unable to find LayoutManager " + className, e);
+ } catch (InvocationTargetException e) {
+ throw new IllegalStateException(attrs.getPositionDescription()
+ + ": Could not instantiate the LayoutManager: " + className, e);
+ } catch (InstantiationException e) {
+ throw new IllegalStateException(attrs.getPositionDescription()
+ + ": Could not instantiate the LayoutManager: " + className, e);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException(attrs.getPositionDescription()
+ + ": Cannot access non-public constructor " + className, e);
+ } catch (ClassCastException e) {
+ throw new IllegalStateException(attrs.getPositionDescription()
+ + ": Class is not a LayoutManager " + className, e);
+ }
+ }
+ }
+ }
+
+ private String getFullClassName(Context context, String className) {
+ if (className.charAt(0) == '.') {
+ return context.getPackageName() + className;
+ }
+ if (className.contains("")) {
+ return className;
+ }
+ return RecyclerView.class.getPackage().getName() + '.' + className;
+ }
+
private void initChildrenHelper() {
mChildHelper = new ChildHelper(new ChildHelper.Callback() {
@Override
@@ -769,6 +853,46 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
}
}
+ /**
+ * Register a listener that will be notified whenever a child view is attached to or detached
+ * from RecyclerView.
+ *
+ * This listener will be called when a LayoutManager or the RecyclerView decides
+ * that a child view is no longer needed. If an application associates expensive
+ * or heavyweight data with item views, this may be a good place to release
+ * or free those resources.
+ *
+ * @param listener Listener to register
+ */
+ public void addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) {
+ if (mOnChildAttachStateListeners == null) {
+ mOnChildAttachStateListeners = new ArrayList();
+ }
+ mOnChildAttachStateListeners.add(listener);
+ }
+
+ /**
+ * Removes the provided listener from child attached state listeners list.
+ *
+ * @param listener Listener to unregister
+ */
+ public void removeOnChildAttachStateChangeListener(OnChildAttachStateChangeListener listener) {
+ if (mOnChildAttachStateListeners == null) {
+ return;
+ }
+ mOnChildAttachStateListeners.remove(listener);
+ }
+
+ /**
+ * Removes all listeners that were added via
+ * {@link #addOnChildAttachStateChangeListener(OnChildAttachStateChangeListener)}.
+ */
+ public void clearOnChildAttachStateChangeListeners() {
+ if (mOnChildAttachStateListeners != null) {
+ mOnChildAttachStateListeners.clear();
+ }
+ }
+
/**
* Set the {@link LayoutManager} that this RecyclerView will use.
*
@@ -993,7 +1117,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
public void addItemDecoration(ItemDecoration decor, int index) {
if (mLayout != null) {
mLayout.assertNotInLayoutOrScroll("Cannot add item decoration during a scroll or"
- + " layout");
+ + "layout");
}
if (mItemDecorations.isEmpty()) {
setWillNotDraw(false);
@@ -1035,7 +1159,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
public void removeItemDecoration(ItemDecoration decor) {
if (mLayout != null) {
mLayout.assertNotInLayoutOrScroll("Cannot remove item decoration during a scroll or"
- + " layout");
+ + "layout");
}
mItemDecorations.remove(decor);
if (mItemDecorations.isEmpty()) {
@@ -1045,6 +1169,26 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
requestLayout();
}
+ /**
+ * Sets the {@link ChildDrawingOrderCallback} to be used for drawing children.
+ *
+ * See {@link ViewGroup#getChildDrawingOrder(int, int)} for details. Calling this method will
+ * always call {@link ViewGroup#setChildrenDrawingOrderEnabled(boolean)}. The parameter will be
+ * true if childDrawingOrderCallback is not null, false otherwise.
+ *
+ * Note that child drawing order may be overridden by View's elevation.
+ *
+ * @param childDrawingOrderCallback The ChildDrawingOrderCallback to be used by the drawing
+ * system.
+ */
+ public void setChildDrawingOrderCallback(ChildDrawingOrderCallback childDrawingOrderCallback) {
+ if (childDrawingOrderCallback == mChildDrawingOrderCallback) {
+ return;
+ }
+ mChildDrawingOrderCallback = childDrawingOrderCallback;
+ setChildrenDrawingOrderEnabled(mChildDrawingOrderCallback != null);
+ }
+
/**
* Set a listener that will be notified of any changes in scroll state or position.
*
@@ -1153,7 +1297,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
final boolean canScrollHorizontal = mLayout.canScrollHorizontally();
final boolean canScrollVertical = mLayout.canScrollVertically();
if (canScrollHorizontal || canScrollVertical) {
- scrollByInternal(canScrollHorizontal ? x : 0, canScrollVertical ? y : 0, false, 0, 0);
+ scrollByInternal(canScrollHorizontal ? x : 0, canScrollVertical ? y : 0, null);
}
}
@@ -1176,29 +1320,25 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
*
* @param x The amount of horizontal scroll request
* @param y The amount of vertical scroll request
- * @param fromMotionEvent If request is originated from a MotionEvent, this should be set to
- * true and motionX/motionY should be provided, false otherwise.
- * @param motionX The x coordinate of the MotionEvent which triggered this scroll. Unused if
- * fromMotionEvent is false.
- * @param motionY The y coordinate of the MotionEvent which triggered this scroll. Unused if
- * fromMotionEvent is false.
+ * @param ev The originating MotionEvent, or null if not from a touch event.
*
* @return Whether any scroll was consumed in either direction.
*/
- boolean scrollByInternal(int x, int y, boolean fromMotionEvent, int motionX, int motionY) {
- int overscrollX = 0, overscrollY = 0;
- int hresult = 0, vresult = 0;
+ boolean scrollByInternal(int x, int y, MotionEvent ev) {
+ int unconsumedX = 0, unconsumedY = 0;
+ int consumedX = 0, consumedY = 0;
+
consumePendingUpdateOperations();
if (mAdapter != null) {
eatRequestLayout();
onEnterLayoutOrScroll();
if (x != 0) {
- hresult = mLayout.scrollHorizontallyBy(x, mRecycler, mState);
- overscrollX = x - hresult;
+ consumedX = mLayout.scrollHorizontallyBy(x, mRecycler, mState);
+ unconsumedX = x - consumedX;
}
if (y != 0) {
- vresult = mLayout.scrollVerticallyBy(y, mRecycler, mState);
- overscrollY = y - vresult;
+ consumedY = mLayout.scrollVerticallyBy(y, mRecycler, mState);
+ unconsumedY = y - consumedY;
}
if (supportsChangeAnimations()) {
// Fix up shadow views used by changing animations
@@ -1227,19 +1367,27 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
if (!mItemDecorations.isEmpty()) {
invalidate();
}
- if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) {
- if (fromMotionEvent) {
- pullGlows(motionX, overscrollX, motionY, overscrollY);
+
+ if (dispatchNestedScroll(consumedX, consumedY, unconsumedX, unconsumedY, mScrollOffset)) {
+ // Update the last touch co-ords, taking any scroll offset into account
+ mLastTouchX -= mScrollOffset[0];
+ mLastTouchY -= mScrollOffset[1];
+ ev.offsetLocation(mScrollOffset[0], mScrollOffset[1]);
+ mNestedOffsets[0] += mScrollOffset[0];
+ mNestedOffsets[1] += mScrollOffset[1];
+ } else if (ViewCompat.getOverScrollMode(this) != ViewCompat.OVER_SCROLL_NEVER) {
+ if (ev != null) {
+ pullGlows(ev.getX(), unconsumedX, ev.getY(), unconsumedY);
}
considerReleasingGlowsOnScroll(x, y);
}
- if (hresult != 0 || vresult != 0) {
- dispatchOnScrolled(hresult, vresult);
+ if (consumedX != 0 || consumedY != 0) {
+ dispatchOnScrolled(consumedX, consumedY);
}
if (!awakenScrollBars()) {
invalidate();
}
- return hresult != 0 || vresult != 0;
+ return consumedX != 0 || consumedY != 0;
}
/**
@@ -1432,19 +1580,31 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
"Call setLayoutManager with a non-null argument.");
return false;
}
+
final boolean canScrollHorizontal = mLayout.canScrollHorizontally();
final boolean canScrollVertical = mLayout.canScrollVertically();
+
if (!canScrollHorizontal || Math.abs(velocityX) < mMinFlingVelocity) {
velocityX = 0;
}
if (!canScrollVertical || Math.abs(velocityY) < mMinFlingVelocity) {
velocityY = 0;
}
- velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
- velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
- if (velocityX != 0 || velocityY != 0) {
- mViewFlinger.fling(velocityX, velocityY);
- return true;
+ if (velocityX == 0 && velocityY == 0) {
+ // If we don't have any velocity, return false
+ return false;
+ }
+
+ if (!dispatchNestedPreFling(velocityX, velocityY)) {
+ final boolean canScroll = canScrollHorizontal || canScrollVertical;
+ dispatchNestedFling(velocityX, velocityY, canScroll);
+
+ if (canScroll) {
+ velocityX = Math.max(-mMaxFlingVelocity, Math.min(velocityX, mMaxFlingVelocity));
+ velocityY = Math.max(-mMaxFlingVelocity, Math.min(velocityY, mMaxFlingVelocity));
+ mViewFlinger.fling(velocityX, velocityY);
+ return true;
+ }
}
return false;
}
@@ -1468,29 +1628,52 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
}
}
+ /**
+ * Returns the minimum velocity to start a fling.
+ *
+ * @return The minimum velocity to start a fling
+ */
+ public int getMinFlingVelocity() {
+ return mMinFlingVelocity;
+ }
+
+
+ /**
+ * Returns the maximum fling velocity used by this RecyclerView.
+ *
+ * @return The maximum fling velocity used by this RecyclerView.
+ */
+ public int getMaxFlingVelocity() {
+ return mMaxFlingVelocity;
+ }
+
/**
* Apply a pull to relevant overscroll glow effects
*/
- private void pullGlows(int x, int overscrollX, int y, int overscrollY) {
+ private void pullGlows(float x, float overscrollX, float y, float overscrollY) {
boolean invalidate = false;
if (overscrollX < 0) {
ensureLeftGlow();
- invalidate = mLeftGlow.onPull(-overscrollX / (float) getWidth(),
- 1f - y / (float) getHeight()) || invalidate;
+ if (mLeftGlow.onPull(-overscrollX / getWidth(), 1f - y / getHeight())) {
+ invalidate = true;
+ }
} else if (overscrollX > 0) {
ensureRightGlow();
- invalidate = mRightGlow.onPull(overscrollX / (float) getWidth(),
- y / (float) getHeight()) || invalidate;
+ if (mRightGlow.onPull(overscrollX / getWidth(), y / getHeight())) {
+ invalidate = true;
+ }
}
if (overscrollY < 0) {
ensureTopGlow();
- invalidate = mTopGlow.onPull(-overscrollY / (float) getHeight(),
- x / (float) getWidth()) || invalidate;
+ if (mTopGlow.onPull(-overscrollY / getHeight(), x / getWidth())) {
+ invalidate = true;
+ }
} else if (overscrollY > 0) {
ensureBottomGlow();
- invalidate = mBottomGlow.onPull(overscrollY / (float) getHeight(),
- 1f - x / (float) getWidth()) || invalidate;
+ if (mBottomGlow.onPull(overscrollY / getHeight(), 1f - x / getWidth())) {
+ invalidate = true;
+ }
}
if (invalidate || overscrollX != 0 || overscrollY != 0) {
@@ -1693,6 +1876,14 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
removeCallbacks(mItemAnimatorRunner);
}
+ /**
+ * Returns true if RecyclerView is attached to window.
+ */
+ // @override
+ public boolean isAttachedToWindow() {
+ return mIsAttached;
+ }
+
/**
* Checks if RecyclerView is in the middle of a layout or scroll and throws an
* {@link IllegalStateException} if it is not.
@@ -1739,6 +1930,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
* for each incoming MotionEvent until the end of the gesture.
*
* @param listener Listener to add
+ * @see SimpleOnItemTouchListener
*/
public void addOnItemTouchListener(OnItemTouchListener listener) {
mOnItemTouchListeners.add(listener);
@@ -1832,6 +2024,15 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
getParent().requestDisallowInterceptTouchEvent(true);
setScrollState(SCROLL_STATE_DRAGGING);
}
+
+ int nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE;
+ if (canScrollHorizontally) {
+ nestedScrollAxis |= ViewCompat.SCROLL_AXIS_HORIZONTAL;
+ }
+ if (canScrollVertically) {
+ nestedScrollAxis |= ViewCompat.SCROLL_AXIS_VERTICAL;
+ }
+ startNestedScroll(nestedScrollAxis);
break;
case MotionEventCompat.ACTION_POINTER_DOWN:
@@ -1874,6 +2075,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
case MotionEvent.ACTION_UP: {
mVelocityTracker.clear();
+ stopNestedScroll();
} break;
case MotionEvent.ACTION_CANCEL: {
@@ -1883,6 +2085,16 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
return mScrollState == SCROLL_STATE_DRAGGING;
}
+ @Override
+ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ final int listenerCount = mOnItemTouchListeners.size();
+ for (int i = 0; i < listenerCount; i++) {
+ final OnItemTouchListener listener = mOnItemTouchListeners.get(i);
+ listener.onRequestDisallowInterceptTouchEvent(disallowIntercept);
+ }
+ super.requestDisallowInterceptTouchEvent(disallowIntercept);
+ }
+
@Override
public boolean onTouchEvent(MotionEvent e) {
if (dispatchOnItemTouch(e)) {
@@ -1898,14 +2110,29 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
}
mVelocityTracker.addMovement(e);
+ final MotionEvent vtev = MotionEvent.obtain(e);
final int action = MotionEventCompat.getActionMasked(e);
final int actionIndex = MotionEventCompat.getActionIndex(e);
+ if (action == MotionEvent.ACTION_DOWN) {
+ mNestedOffsets[0] = mNestedOffsets[1] = 0;
+ }
+ vtev.offsetLocation(mNestedOffsets[0], mNestedOffsets[1]);
+
switch (action) {
case MotionEvent.ACTION_DOWN: {
mScrollPointerId = MotionEventCompat.getPointerId(e, 0);
mInitialTouchX = mLastTouchX = (int) (e.getX() + 0.5f);
mInitialTouchY = mLastTouchY = (int) (e.getY() + 0.5f);
+
+ int nestedScrollAxis = ViewCompat.SCROLL_AXIS_NONE;
+ if (canScrollHorizontally) {
+ nestedScrollAxis |= ViewCompat.SCROLL_AXIS_HORIZONTAL;
+ }
+ if (canScrollVertically) {
+ nestedScrollAxis |= ViewCompat.SCROLL_AXIS_VERTICAL;
+ }
+ startNestedScroll(nestedScrollAxis);
} break;
case MotionEventCompat.ACTION_POINTER_DOWN: {
@@ -1924,32 +2151,52 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
final int x = (int) (MotionEventCompat.getX(e, index) + 0.5f);
final int y = (int) (MotionEventCompat.getY(e, index) + 0.5f);
+ int dx = mLastTouchX - x;
+ int dy = mLastTouchY - y;
+
+ if (dispatchNestedPreScroll(dx, dy, mScrollConsumed, mScrollOffset)) {
+ dx -= mScrollConsumed[0];
+ dy -= mScrollConsumed[1];
+ vtev.offsetLocation(mScrollOffset[0], mScrollOffset[1]);
+ // Updated the nested offsets
+ mNestedOffsets[0] += mScrollOffset[0];
+ mNestedOffsets[1] += mScrollOffset[1];
+ }
+
if (mScrollState != SCROLL_STATE_DRAGGING) {
- final int dx = x - mInitialTouchX;
- final int dy = y - mInitialTouchY;
boolean startScroll = false;
if (canScrollHorizontally && Math.abs(dx) > mTouchSlop) {
- mLastTouchX = mInitialTouchX + mTouchSlop * (dx < 0 ? -1 : 1);
+ if (dx > 0) {
+ dx -= mTouchSlop;
+ } else {
+ dx += mTouchSlop;
+ }
startScroll = true;
}
if (canScrollVertically && Math.abs(dy) > mTouchSlop) {
- mLastTouchY = mInitialTouchY + mTouchSlop * (dy < 0 ? -1 : 1);
+ if (dy > 0) {
+ dy -= mTouchSlop;
+ } else {
+ dy += mTouchSlop;
+ }
startScroll = true;
}
if (startScroll) {
setScrollState(SCROLL_STATE_DRAGGING);
}
}
+
if (mScrollState == SCROLL_STATE_DRAGGING) {
- final int dx = x - mLastTouchX;
- final int dy = y - mLastTouchY;
- if (scrollByInternal(canScrollHorizontally ? -dx : 0,
- canScrollVertically ? -dy : 0, true, x, y)) {
+ mLastTouchX = x - mScrollOffset[0];
+ mLastTouchY = y - mScrollOffset[1];
+
+ if (scrollByInternal(
+ canScrollHorizontally ? dx : 0,
+ canScrollVertically ? dy : 0,
+ vtev)) {
getParent().requestDisallowInterceptTouchEvent(true);
}
}
- mLastTouchX = x;
- mLastTouchY = y;
} break;
case MotionEventCompat.ACTION_POINTER_UP: {
@@ -1965,6 +2212,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel))) {
setScrollState(SCROLL_STATE_IDLE);
}
+
mVelocityTracker.clear();
releaseGlows();
} break;
@@ -1974,6 +2222,8 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
} break;
}
+ vtev.recycle();
+
return true;
}
@@ -1981,6 +2231,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
if (mVelocityTracker != null) {
mVelocityTracker.clear();
}
+ stopNestedScroll();
releaseGlows();
setScrollState(SCROLL_STATE_IDLE);
}
@@ -2823,6 +3074,18 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
return mLayout.generateLayoutParams(p);
}
+ /**
+ * Returns true if RecyclerView is currently running some animations.
+ *
+ * If you want to be notified when animations are finished, use
+ * {@link ItemAnimator#isRunning(ItemAnimator.ItemAnimatorFinishedListener)}.
+ *
+ * @return True if there are some item animations currently running or waiting to be started.
+ */
+ public boolean isAnimating() {
+ return mItemAnimator != null && mItemAnimator.isRunning();
+ }
+
void saveOldPositions() {
final int childCount = mChildHelper.getUnfilteredChildCount();
for (int i = 0; i < childCount; i++) {
@@ -3232,6 +3495,11 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
return null;
}
+ @Override
+ public boolean drawChild(Canvas canvas, View child, long drawingTime) {
+ return super.drawChild(canvas, child, drawingTime);
+ }
+
/**
* Offset the bounds of all child views by dy
pixels.
* Useful for implementing simple scrolling in {@link LayoutManager LayoutManagers}.
@@ -5153,17 +5421,32 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
}
private void dispatchChildDetached(View child) {
- if (mAdapter != null) {
- mAdapter.onViewDetachedFromWindow(getChildViewHolderInt(child));
- }
+ final ViewHolder viewHolder = getChildViewHolderInt(child);
onChildDetachedFromWindow(child);
+ if (mAdapter != null && viewHolder != null) {
+ mAdapter.onViewDetachedFromWindow(viewHolder);
+ }
+ if (mOnChildAttachStateListeners != null) {
+ final int cnt = mOnChildAttachStateListeners.size();
+ for (int i = cnt - 1; i >= 0; i--) {
+ mOnChildAttachStateListeners.get(i).onChildViewDetachedFromWindow(child);
+ }
+ }
}
private void dispatchChildAttached(View child) {
- if (mAdapter != null) {
- mAdapter.onViewAttachedToWindow(getChildViewHolderInt(child));
- }
+ final ViewHolder viewHolder = getChildViewHolderInt(child);
onChildAttachedToWindow(child);
+ if (mAdapter != null && viewHolder != null) {
+ mAdapter.onViewAttachedToWindow(viewHolder);
+ }
+ if (mOnChildAttachStateListeners != null) {
+ final int cnt = mOnChildAttachStateListeners.size();
+ for (int i = cnt - 1; i >= 0; i--) {
+ mOnChildAttachStateListeners.get(i).onChildViewAttachedToWindow(child);
+ }
+ }
+
}
/**
@@ -5173,6 +5456,14 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
* a RecyclerView
can be used to implement a standard vertically scrolling list,
* a uniform grid, staggered grids, horizontally scrolling collections and more. Several stock
* layout managers are provided for general use.
+ *
+ * If the LayoutManager specifies a default constructor or one with the signature
+ * ({@link Context}, {@link AttributeSet}, {@code int}, {@code int}), RecyclerView will
+ * instantiate and set the LayoutManager when being inflated. Most used properties can
+ * be then obtained from {@link #getProperties(Context, AttributeSet, int, int)}. In case
+ * a LayoutManager specifies both constructors, the non-default constructor will take
+ * precedence.
+ *
*/
public static abstract class LayoutManager {
ChildHelper mChildHelper;
@@ -7259,6 +7550,20 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
int action, Bundle args) {
return false;
}
+
+ /**
+ * Some general properties that a LayoutManager may want to use.
+ */
+ public static class Properties {
+ /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_android_orientation */
+ public int orientation;
+ /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_spanCount */
+ public int spanCount;
+ /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_reverseLayout */
+ public boolean reverseLayout;
+ /** @attr ref android.support.v7.recyclerview.R.styleable#RecyclerView_stackFromEnd */
+ public boolean stackFromEnd;
+ }
}
/**
@@ -7359,8 +7664,10 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
* manipulation of item views within the RecyclerView. OnItemTouchListeners may intercept
* a touch interaction already in progress even if the RecyclerView is already handling that
* gesture stream itself for the purposes of scrolling.
+ *
+ * @see SimpleOnItemTouchListener
*/
- public interface OnItemTouchListener {
+ public static interface OnItemTouchListener {
/**
* Silently observe and/or take over touch events sent to the RecyclerView
* before they are handled by either the RecyclerView itself or its child views.
@@ -7385,8 +7692,44 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
* the RecyclerView's coordinate system.
*/
public void onTouchEvent(RecyclerView rv, MotionEvent e);
+
+ /**
+ * Called when a child of RecyclerView does not want RecyclerView and its ancestors to
+ * intercept touch events with
+ * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
+ *
+ * @param disallowIntercept True if the child does not want the parent to
+ * intercept touch events.
+ * @see ViewParent#requestDisallowInterceptTouchEvent(boolean)
+ */
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept);
}
+ /**
+ * An implementation of {@link RecyclerView.OnItemTouchListener} that has empty method bodies and
+ * default return values.
+ *
+ * You may prefer to extend this class if you don't need to override all methods. Another
+ * benefit of using this class is future compatibility. As the interface may change, we'll
+ * always provide a default implementation on this class so that your code won't break when
+ * you update to a new version of the support library.
+ */
+ public class SimpleOnItemTouchListener implements RecyclerView.OnItemTouchListener {
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
+ return false;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView rv, MotionEvent e) {
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ }
+ }
+
+
/**
* An OnScrollListener can be set on a RecyclerView to receive messages
* when a scrolling event has occurred on that RecyclerView.
@@ -7399,7 +7742,7 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
* want your components to be able to easily replace the listener use
* RecyclerView#setOnScrollListener.
*/
- abstract static public class OnScrollListener {
+ public abstract static class OnScrollListener {
/**
* Callback method to be invoked when RecyclerView's scroll state changes.
*
@@ -7444,6 +7787,27 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
public void onViewRecycled(ViewHolder holder);
}
+ /**
+ * A Listener interface that can be attached to a RecylcerView to get notified
+ * whenever a ViewHolder is attached to or detached from RecyclerView.
+ */
+ public interface OnChildAttachStateChangeListener {
+
+ /**
+ * Called when a view is attached to the RecyclerView.
+ *
+ * @param view The View which is attached to the RecyclerView
+ */
+ public void onChildViewAttachedToWindow(View view);
+
+ /**
+ * Called when a view is detached from RecyclerView.
+ *
+ * @param view The View which is being detached from the RecyclerView
+ */
+ public void onChildViewDetachedFromWindow(View view);
+ }
+
/**
* A ViewHolder describes an item view and metadata about its place within the RecyclerView.
*
@@ -7862,6 +8226,55 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
return mAdapterHelper.applyPendingUpdatesToPosition(viewHolder.mPosition);
}
+ // NestedScrollingChild
+
+ @Override
+ public void setNestedScrollingEnabled(boolean enabled) {
+ mScrollingChildHelper.setNestedScrollingEnabled(enabled);
+ }
+
+ @Override
+ public boolean isNestedScrollingEnabled() {
+ return mScrollingChildHelper.isNestedScrollingEnabled();
+ }
+
+ @Override
+ public boolean startNestedScroll(int axes) {
+ return mScrollingChildHelper.startNestedScroll(axes);
+ }
+
+ @Override
+ public void stopNestedScroll() {
+ mScrollingChildHelper.stopNestedScroll();
+ }
+
+ @Override
+ public boolean hasNestedScrollingParent() {
+ return mScrollingChildHelper.hasNestedScrollingParent();
+ }
+
+ @Override
+ public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
+ int dyUnconsumed, int[] offsetInWindow) {
+ return mScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed,
+ dxUnconsumed, dyUnconsumed, offsetInWindow);
+ }
+
+ @Override
+ public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
+ return mScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
+ }
+
+ @Override
+ public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
+ return mScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
+ }
+
+ @Override
+ public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
+ return mScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
+ }
+
/**
* {@link android.view.ViewGroup.MarginLayoutParams LayoutParams} subclass for children of
* {@link RecyclerView}. Custom {@link LayoutManager layout managers} are encouraged
@@ -9318,4 +9731,35 @@ public class RecyclerView extends ViewGroup implements ScrollingView {
this.bottom = bottom;
}
}
+
+ @Override
+ protected int getChildDrawingOrder(int childCount, int i) {
+ if (mChildDrawingOrderCallback == null) {
+ return super.getChildDrawingOrder(childCount, i);
+ } else {
+ return mChildDrawingOrderCallback.onGetChildDrawingOrder(childCount, i);
+ }
+ }
+
+ /**
+ * A callback interface that can be used to alter the drawing order of RecyclerView children.
+ *
+ * It works using the {@link ViewGroup#getChildDrawingOrder(int, int)} method, so any case
+ * that applies to that method also applies to this callback. For example, changing the drawing
+ * order of two views will not have any effect if their elevation values are different since
+ * elevation overrides the result of this callback.
+ */
+ public static interface ChildDrawingOrderCallback {
+ /**
+ * Returns the index of the child to draw for this iteration. Override this
+ * if you want to change the drawing order of children. By default, it
+ * returns i.
+ *
+ * @param i The current iteration.
+ * @return The index of the child to draw this iteration.
+ *
+ * @see RecyclerView#setChildDrawingOrderCallback(RecyclerView.ChildDrawingOrderCallback)
+ */
+ public int onGetChildDrawingOrder(int childCount, int i);
+ }
}
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/StaggeredGridLayoutManager.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/StaggeredGridLayoutManager.java
index d28434a60..166311dab 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/StaggeredGridLayoutManager.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/StaggeredGridLayoutManager.java
@@ -537,7 +537,6 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
ensureOrientationHelper();
-
final AnchorInfo anchorInfo = mAnchorInfo;
anchorInfo.reset();
@@ -577,21 +576,22 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
detachAndScrapAttachedViews(recycler);
mLaidOutInvalidFullSpan = false;
updateMeasureSpecs();
+ updateLayoutState(anchorInfo.mPosition, state);
if (anchorInfo.mLayoutFromEnd) {
// Layout start.
- updateLayoutStateToFillStart(anchorInfo.mPosition, state);
+ setLayoutStateDirection(LAYOUT_START);
fill(recycler, mLayoutState, state);
// Layout end.
- updateLayoutStateToFillEnd(anchorInfo.mPosition, state);
- mLayoutState.mCurrentPosition += mLayoutState.mItemDirection;
+ setLayoutStateDirection(LAYOUT_END);
+ mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection;
fill(recycler, mLayoutState, state);
} else {
// Layout end.
- updateLayoutStateToFillEnd(anchorInfo.mPosition, state);
+ setLayoutStateDirection(LAYOUT_END);
fill(recycler, mLayoutState, state);
// Layout start.
- updateLayoutStateToFillStart(anchorInfo.mPosition, state);
- mLayoutState.mCurrentPosition += mLayoutState.mItemDirection;
+ setLayoutStateDirection(LAYOUT_START);
+ mLayoutState.mCurrentPosition = anchorInfo.mPosition + mLayoutState.mItemDirection;
fill(recycler, mLayoutState, state);
}
@@ -1254,40 +1254,37 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
}
}
- private void updateLayoutStateToFillStart(int anchorPosition, RecyclerView.State state) {
+ private void updateLayoutState(int anchorPosition, RecyclerView.State state) {
mLayoutState.mAvailable = 0;
mLayoutState.mCurrentPosition = anchorPosition;
+ int startExtra = 0;
+ int endExtra = 0;
if (isSmoothScrolling()) {
final int targetPos = state.getTargetScrollPosition();
- if (mShouldReverseLayout == targetPos < anchorPosition) {
- mLayoutState.mExtra = 0;
- } else {
- mLayoutState.mExtra = mPrimaryOrientation.getTotalSpace();
+ if (targetPos != NO_POSITION) {
+ if (mShouldReverseLayout == targetPos < anchorPosition) {
+ endExtra = mPrimaryOrientation.getTotalSpace();
+ } else {
+ startExtra = mPrimaryOrientation.getTotalSpace();
+ }
}
- } else {
- mLayoutState.mExtra = 0;
}
- mLayoutState.mLayoutDirection = LAYOUT_START;
- mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_TAIL
- : ITEM_DIRECTION_HEAD;
+
+ // Line of the furthest row.
+ final boolean clipToPadding = getClipToPadding();
+ if (clipToPadding) {
+ mLayoutState.mStartLine = mPrimaryOrientation.getStartAfterPadding() - startExtra;
+ mLayoutState.mEndLine = mPrimaryOrientation.getEndAfterPadding() + endExtra;
+ } else {
+ mLayoutState.mEndLine = mPrimaryOrientation.getEnd() + endExtra;
+ mLayoutState.mStartLine = -startExtra;
+ }
}
- private void updateLayoutStateToFillEnd(int anchorPosition, RecyclerView.State state) {
- mLayoutState.mAvailable = 0;
- mLayoutState.mCurrentPosition = anchorPosition;
- if (isSmoothScrolling()) {
- final int targetPos = state.getTargetScrollPosition();
- if (mShouldReverseLayout == targetPos > anchorPosition) {
- mLayoutState.mExtra = 0;
- } else {
- mLayoutState.mExtra = mPrimaryOrientation.getTotalSpace();
- }
- } else {
- mLayoutState.mExtra = 0;
- }
- mLayoutState.mLayoutDirection = LAYOUT_END;
- mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_HEAD
- : ITEM_DIRECTION_TAIL;
+ private void setLayoutStateDirection(int direction) {
+ mLayoutState.mLayoutDirection = direction;
+ mLayoutState.mItemDirection = (mShouldReverseLayout == (direction == LAYOUT_START)) ?
+ ITEM_DIRECTION_TAIL : ITEM_DIRECTION_HEAD;
}
@Override
@@ -1383,31 +1380,25 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
mRemainingSpans.set(0, mSpanCount, true);
// The target position we are trying to reach.
final int targetLine;
- /*
- * The line until which we can recycle, as long as we add views.
- * Keep in mind, it is still the line in layout direction which means; to calculate the
- * actual recycle line, we should subtract/add the size in orientation.
- */
- final int recycleLine;
+
// Line of the furthest row.
if (layoutState.mLayoutDirection == LAYOUT_END) {
- // ignore padding for recycler
- recycleLine = mPrimaryOrientation.getEndAfterPadding() + mLayoutState.mAvailable;
- targetLine = recycleLine + mLayoutState.mExtra + mPrimaryOrientation.getEndPadding();
-
+ targetLine = layoutState.mEndLine + layoutState.mAvailable;
} else { // LAYOUT_START
- // ignore padding for recycler
- recycleLine = mPrimaryOrientation.getStartAfterPadding() - mLayoutState.mAvailable;
- targetLine = recycleLine - mLayoutState.mExtra -
- mPrimaryOrientation.getStartAfterPadding();
+ targetLine = layoutState.mStartLine - layoutState.mAvailable;
}
+
updateAllRemainingSpans(layoutState.mLayoutDirection, targetLine);
+ if (DEBUG) {
+ Log.d(TAG, "FILLING targetLine: " + targetLine + "," +
+ "remaining spans:" + mRemainingSpans + ", state: " + layoutState);
+ }
// the default coordinate to add new view.
final int defaultNewViewLine = mShouldReverseLayout
? mPrimaryOrientation.getEndAfterPadding()
: mPrimaryOrientation.getStartAfterPadding();
-
+ boolean added = false;
while (layoutState.hasMore(state) && !mRemainingSpans.isEmpty()) {
View view = layoutState.next(recycler);
LayoutParams lp = ((LayoutParams) view.getLayoutParams());
@@ -1500,18 +1491,21 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
} else {
updateRemainingSpans(currentSpan, mLayoutState.mLayoutDirection, targetLine);
}
- recycle(recycler, mLayoutState, currentSpan, recycleLine);
+ recycle(recycler, mLayoutState);
+ added = true;
}
- if (DEBUG) {
- Log.d(TAG, "fill, " + getChildCount());
+ if (!added) {
+ recycle(recycler, mLayoutState);
}
+ final int diff;
if (mLayoutState.mLayoutDirection == LAYOUT_START) {
final int minStart = getMinStart(mPrimaryOrientation.getStartAfterPadding());
- return Math.max(0, mLayoutState.mAvailable + (recycleLine - minStart));
+ diff = mPrimaryOrientation.getStartAfterPadding() - minStart;
} else {
- final int max = getMaxEnd(mPrimaryOrientation.getEndAfterPadding());
- return Math.max(0, mLayoutState.mAvailable + (max - recycleLine));
+ final int maxEnd = getMaxEnd(mPrimaryOrientation.getEndAfterPadding());
+ diff = maxEnd - mPrimaryOrientation.getEndAfterPadding();
}
+ return diff > 0 ? Math.min(layoutState.mAvailable, diff) : 0;
}
private LazySpanLookup.FullSpanItem createFullSpanItemFromEnd(int newItemTop) {
@@ -1548,19 +1542,40 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
}
}
- private void recycle(RecyclerView.Recycler recycler, LayoutState layoutState,
- Span updatedSpan, int recycleLine) {
- if (layoutState.mLayoutDirection == LAYOUT_START) {
- // calculate recycle line
- int maxStart = getMaxStart(updatedSpan.getStartLine());
- recycleFromEnd(recycler, Math.max(recycleLine, maxStart) +
- (mPrimaryOrientation.getEnd() - mPrimaryOrientation.getStartAfterPadding()));
+ private void recycle(RecyclerView.Recycler recycler, LayoutState layoutState) {
+ if (layoutState.mAvailable == 0) {
+ // easy, recycle line is still valid
+ if (layoutState.mLayoutDirection == LAYOUT_START) {
+ recycleFromEnd(recycler, layoutState.mEndLine);
+ } else {
+ recycleFromStart(recycler, layoutState.mStartLine);
+ }
} else {
- // calculate recycle line
- int minEnd = getMinEnd(updatedSpan.getEndLine());
- recycleFromStart(recycler, Math.min(recycleLine, minEnd) -
- (mPrimaryOrientation.getEnd() - mPrimaryOrientation.getStartAfterPadding()));
+ // scrolling case, recycle line can be shifted by how much space we could cover
+ // by adding new views
+ if (layoutState.mLayoutDirection == LAYOUT_START) {
+ // calculate recycle line
+ int scrolled = layoutState.mStartLine - getMaxStart(layoutState.mStartLine);
+ final int line;
+ if (scrolled < 0) {
+ line = layoutState.mEndLine;
+ } else {
+ line = layoutState.mEndLine - Math.min(scrolled, layoutState.mAvailable);
+ }
+ recycleFromEnd(recycler, line);
+ } else {
+ // calculate recycle line
+ int scrolled = getMinEnd(layoutState.mEndLine) - layoutState.mEndLine;
+ final int line;
+ if (scrolled < 0) {
+ line = layoutState.mStartLine;
+ } else {
+ line = layoutState.mStartLine + Math.min(scrolled, layoutState.mAvailable);
+ }
+ recycleFromStart(recycler, line);
+ }
}
+
}
private void appendViewToAllSpans(View view) {
@@ -1602,12 +1617,12 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
final int deletedSize = span.getDeletedSize();
if (layoutDir == LAYOUT_START) {
final int line = span.getStartLine();
- if (line + deletedSize < targetLine) {
+ if (line + deletedSize <= targetLine) {
mRemainingSpans.set(span.mIndex, false);
}
} else {
final int line = span.getEndLine();
- if (line - deletedSize > targetLine) {
+ if (line - deletedSize >= targetLine) {
mRemainingSpans.set(span.mIndex, false);
}
}
@@ -1678,18 +1693,24 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
}
private void recycleFromStart(RecyclerView.Recycler recycler, int line) {
- if (DEBUG) {
- Log.d(TAG, "recycling from start for line " + line);
- }
while (getChildCount() > 0) {
View child = getChildAt(0);
- if (mPrimaryOrientation.getDecoratedEnd(child) < line) {
+ if (mPrimaryOrientation.getDecoratedEnd(child) <= line) {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ // Don't recycle the last View in a span not to lose span's start/end lines
if (lp.mFullSpan) {
+ for (int j = 0; j < mSpanCount; j++) {
+ if (mSpans[j].mViews.size() == 1) {
+ return;
+ }
+ }
for (int j = 0; j < mSpanCount; j++) {
mSpans[j].popStart();
}
} else {
+ if (lp.mSpan.mViews.size() == 1) {
+ return;
+ }
lp.mSpan.popStart();
}
removeAndRecycleView(child, recycler);
@@ -1704,13 +1725,22 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
int i;
for (i = childCount - 1; i >= 0; i--) {
View child = getChildAt(i);
- if (mPrimaryOrientation.getDecoratedStart(child) > line) {
+ if (mPrimaryOrientation.getDecoratedStart(child) >= line) {
LayoutParams lp = (LayoutParams) child.getLayoutParams();
+ // Don't recycle the last View in a span not to lose span's start/end lines
if (lp.mFullSpan) {
+ for (int j = 0; j < mSpanCount; j++) {
+ if (mSpans[j].mViews.size() == 1) {
+ return;
+ }
+ }
for (int j = 0; j < mSpanCount; j++) {
mSpans[j].popEnd();
}
} else {
+ if (lp.mSpan.mViews.size() == 1) {
+ return;
+ }
lp.mSpan.popEnd();
}
removeAndRecycleView(child, recycler);
@@ -1860,21 +1890,19 @@ public class StaggeredGridLayoutManager extends RecyclerView.LayoutManager {
int scrollBy(int dt, RecyclerView.Recycler recycler, RecyclerView.State state) {
ensureOrientationHelper();
final int referenceChildPosition;
+ final int layoutDir;
if (dt > 0) { // layout towards end
- mLayoutState.mLayoutDirection = LAYOUT_END;
- mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_HEAD
- : ITEM_DIRECTION_TAIL;
+ layoutDir = LAYOUT_END;
referenceChildPosition = getLastChildPosition();
} else {
- mLayoutState.mLayoutDirection = LAYOUT_START;
- mLayoutState.mItemDirection = mShouldReverseLayout ? ITEM_DIRECTION_TAIL
- : ITEM_DIRECTION_HEAD;
+ layoutDir = LAYOUT_START;
referenceChildPosition = getFirstChildPosition();
}
+ updateLayoutState(referenceChildPosition, state);
+ setLayoutStateDirection(layoutDir);
mLayoutState.mCurrentPosition = referenceChildPosition + mLayoutState.mItemDirection;
final int absDt = Math.abs(dt);
mLayoutState.mAvailable = absDt;
- mLayoutState.mExtra = isSmoothScrolling() ? mPrimaryOrientation.getTotalSpace() : 0;
int consumed = fill(recycler, mLayoutState, state);
final int totalScroll;
if (absDt < consumed) {
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchHelper.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchHelper.java
new file mode 100644
index 000000000..c3ab9bd3c
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchHelper.java
@@ -0,0 +1,2331 @@
+/*
+ * Copyright (C) 2015 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.telegram.android.support.widget.helper;
+
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.os.Build;
+import android.support.v4.animation.ValueAnimatorCompat;
+import android.support.v4.animation.AnimatorCompatHelper;
+import android.support.v4.animation.AnimatorListenerCompat;
+import android.support.v4.animation.AnimatorUpdateListenerCompat;
+import android.support.v4.view.GestureDetectorCompat;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.VelocityTrackerCompat;
+import android.support.v4.view.ViewCompat;
+
+import org.telegram.android.AndroidUtilities;
+import org.telegram.android.support.widget.LinearLayoutManager;
+import org.telegram.android.support.widget.RecyclerView;
+import android.util.Log;
+import android.util.TypedValue;
+import android.view.GestureDetector;
+import android.view.HapticFeedbackConstants;
+import android.view.MotionEvent;
+import android.view.VelocityTracker;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewParent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.telegram.android.support.widget.RecyclerView.OnItemTouchListener;
+import org.telegram.android.support.widget.RecyclerView.ViewHolder;
+import android.view.animation.Interpolator;
+
+/**
+ * This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.
+ *
+ * It works with a RecyclerView and a Callback class, which configures what type of interactions
+ * are enabled and also receives events when user performs these actions.
+ *
+ * Depending on which functionality you support, you should override
+ * {@link Callback#onMove(RecyclerView, ViewHolder, ViewHolder)} and / or
+ * {@link Callback#onSwiped(ViewHolder, int)}.
+ *
+ * This class is designed to work with any LayoutManager but for certain situations, it can be
+ * optimized for your custom LayoutManager by extending methods in the
+ * {@link ItemTouchHelper.Callback} class or implementing {@link ItemTouchHelper.ViewDropHandler}
+ * interface in your LayoutManager.
+ *
+ * By default, ItemTouchHelper moves the items' translateX/Y properties to reposition them. On
+ * platforms older than Honeycomb, ItemTouchHelper uses canvas translations and View's visibility
+ * property to move items in response to touch events. You can customize these behaviors by
+ * overriding {@link Callback#onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int,
+ * boolean)}
+ * or {@link Callback#onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int,
+ * boolean)}.
+ *
+ * Most of the time, you only need to override onChildDraw
but due to limitations of
+ * platform prior to Honeycomb, you may need to implement onChildDrawOver
as well.
+ */
+public class ItemTouchHelper extends RecyclerView.ItemDecoration
+ implements RecyclerView.OnChildAttachStateChangeListener {
+
+ /**
+ * Up direction, used for swipe & drag control.
+ */
+ public static final int UP = 1;
+
+ /**
+ * Down direction, used for swipe & drag control.
+ */
+ public static final int DOWN = 1 << 1;
+
+ /**
+ * Left direction, used for swipe & drag control.
+ */
+ public static final int LEFT = 1 << 2;
+
+ /**
+ * Right direction, used for swipe & drag control.
+ */
+ public static final int RIGHT = 1 << 3;
+
+ // If you change these relative direction values, update Callback#convertToAbsoluteDirection,
+ // Callback#convertToRelativeDirection.
+ /**
+ * Horizontal start direction. Resolved to LEFT or RIGHT depending on RecyclerView's layout
+ * direction. Used for swipe & drag control.
+ */
+ public static final int START = LEFT << 2;
+
+ /**
+ * Horizontal end direction. Resolved to LEFT or RIGHT depending on RecyclerView's layout
+ * direction. Used for swipe & drag control.
+ */
+ public static final int END = RIGHT << 2;
+
+ /**
+ * ItemTouchHelper is in idle state. At this state, either there is no related motion event by
+ * the user or latest motion events have not yet triggered a swipe or drag.
+ */
+ public static final int ACTION_STATE_IDLE = 0;
+
+ /**
+ * A View is currently being swiped.
+ */
+ public static final int ACTION_STATE_SWIPE = 1;
+
+ /**
+ * A View is currently being dragged.
+ */
+ public static final int ACTION_STATE_DRAG = 2;
+
+ /**
+ * Animation type for views which are swiped successfully.
+ */
+ public static final int ANIMATION_TYPE_SWIPE_SUCCESS = 1 << 1;
+
+ /**
+ * Animation type for views which are not completely swiped thus will animate back to their
+ * original position.
+ */
+ public static final int ANIMATION_TYPE_SWIPE_CANCEL = 1 << 2;
+
+ /**
+ * Animation type for views that were dragged and now will animate to their final position.
+ */
+ public static final int ANIMATION_TYPE_DRAG = 1 << 3;
+
+ private static final String TAG = "ItemTouchHelper";
+
+ private static final boolean DEBUG = false;
+
+ private static final int ACTIVE_POINTER_ID_NONE = -1;
+
+ private static final int DIRECTION_FLAG_COUNT = 8;
+
+ private static final int ACTION_MODE_IDLE_MASK = (1 << DIRECTION_FLAG_COUNT) - 1;
+
+ private static final int ACTION_MODE_SWIPE_MASK = ACTION_MODE_IDLE_MASK << DIRECTION_FLAG_COUNT;
+
+ private static final int ACTION_MODE_DRAG_MASK = ACTION_MODE_SWIPE_MASK << DIRECTION_FLAG_COUNT;
+
+ /**
+ * Views, whose state should be cleared after they are detached from RecyclerView.
+ * This is necessary after swipe dismissing an item. We wait until animator finishes its job
+ * to clean these views.
+ */
+ final List mPendingCleanup = new ArrayList();
+
+ /**
+ * Re-use array to calculate dx dy for a ViewHolder
+ */
+ private final float[] mTmpPosition = new float[2];
+
+ /**
+ * Currently selected view holder
+ */
+ ViewHolder mSelected = null;
+
+ /**
+ * The reference coordinates for the action start. For drag & drop, this is the time long
+ * press is completed vs for swipe, this is the initial touch point.
+ */
+ float mInitialTouchX;
+
+ float mInitialTouchY;
+
+ /**
+ * The diff between the last event and initial touch.
+ */
+ float mDx;
+
+ float mDy;
+
+ /**
+ * The coordinates of the selected view at the time it is selected. We record these values
+ * when action starts so that we can consistently position it even if LayoutManager moves the
+ * View.
+ */
+ float mSelectedStartX;
+
+ float mSelectedStartY;
+
+ /**
+ * The pointer we are tracking.
+ */
+ int mActivePointerId = ACTIVE_POINTER_ID_NONE;
+
+ /**
+ * Developer callback which controls the behavior of ItemTouchHelper.
+ */
+ Callback mCallback;
+
+ /**
+ * Current mode.
+ */
+ int mActionState = ACTION_STATE_IDLE;
+
+ /**
+ * The direction flags obtained from unmasking
+ * {@link Callback#getAbsoluteMovementFlags(RecyclerView, ViewHolder)} for the current
+ * action state.
+ */
+ int mSelectedFlags;
+
+ /**
+ * When a View is dragged or swiped and needs to go back to where it was, we create a Recover
+ * Animation and animate it to its location using this custom Animator, instead of using
+ * framework Animators.
+ * Using framework animators has the side effect of clashing with ItemAnimator, creating
+ * jumpy UIs.
+ */
+ List mRecoverAnimations = new ArrayList();
+
+ private int mSlop;
+
+ private RecyclerView mRecyclerView;
+
+ /**
+ * When user drags a view to the edge, we start scrolling the LayoutManager as long as View
+ * is partially out of bounds.
+ */
+ private final Runnable mScrollRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mSelected != null && scrollIfNecessary()) {
+ if (mSelected != null) { //it might be lost during scrolling
+ moveIfNecessary(mSelected);
+ }
+ mRecyclerView.removeCallbacks(mScrollRunnable);
+ ViewCompat.postOnAnimation(mRecyclerView, this);
+ }
+ }
+ };
+
+ /**
+ * Used for detecting fling swipe
+ */
+ private VelocityTracker mVelocityTracker;
+
+ //re-used list for selecting a swap target
+ private List mSwapTargets;
+
+ //re used for for sorting swap targets
+ private List mDistances;
+
+ /**
+ * If drag & drop is supported, we use child drawing order to bring them to front.
+ */
+ private RecyclerView.ChildDrawingOrderCallback mChildDrawingOrderCallback = null;
+
+ /**
+ * This keeps a reference to the child dragged by the user. Even after user stops dragging,
+ * until view reaches its final position (end of recover animation), we keep a reference so
+ * that it can be drawn above other children.
+ */
+ private View mOverdrawChild = null;
+
+ /**
+ * We cache the position of the overdraw child to avoid recalculating it each time child
+ * position callback is called. This value is invalidated whenever a child is attached or
+ * detached.
+ */
+ private int mOverdrawChildPosition = -1;
+
+ /**
+ * Used to detect long press.
+ */
+ private GestureDetectorCompat mGestureDetector;
+
+ private final OnItemTouchListener mOnItemTouchListener
+ = new OnItemTouchListener() {
+ @Override
+ public boolean onInterceptTouchEvent(RecyclerView recyclerView, MotionEvent event) {
+ mGestureDetector.onTouchEvent(event);
+ if (DEBUG) {
+ Log.d(TAG, "intercept: x:" + event.getX() + ",y:" + event.getY() + ", " + event);
+ }
+ final int action = MotionEventCompat.getActionMasked(event);
+ if (action == MotionEvent.ACTION_DOWN) {
+ mActivePointerId = MotionEventCompat.getPointerId(event, 0);
+ mInitialTouchX = event.getX();
+ mInitialTouchY = event.getY();
+ obtainVelocityTracker();
+ if (mSelected == null) {
+ final RecoverAnimation animation = findAnimation(event);
+ if (animation != null) {
+ mInitialTouchX -= animation.mX;
+ mInitialTouchY -= animation.mY;
+ endRecoverAnimation(animation.mViewHolder, true);
+ if (mPendingCleanup.remove(animation.mViewHolder.itemView)) {
+ mCallback.clearView(mRecyclerView, animation.mViewHolder);
+ }
+ select(animation.mViewHolder, animation.mActionState);
+ updateDxDy(event, mSelectedFlags, 0);
+ }
+ }
+ } else if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
+ mActivePointerId = ACTIVE_POINTER_ID_NONE;
+ select(null, ACTION_STATE_IDLE);
+ } else if (mActivePointerId != ACTIVE_POINTER_ID_NONE) {
+ // in a non scroll orientation, if distance change is above threshold, we
+ // can select the item
+ final int index = MotionEventCompat.findPointerIndex(event, mActivePointerId);
+ if (DEBUG) {
+ Log.d(TAG, "pointer index " + index);
+ }
+ if (index >= 0) {
+ checkSelectForSwipe(action, event, index);
+ }
+ }
+ if (mVelocityTracker != null) {
+ mVelocityTracker.addMovement(event);
+ }
+ return mSelected != null;
+ }
+
+ @Override
+ public void onTouchEvent(RecyclerView recyclerView, MotionEvent event) {
+ mGestureDetector.onTouchEvent(event);
+ if (DEBUG) {
+ Log.d(TAG,
+ "on touch: x:" + mInitialTouchX + ",y:" + mInitialTouchY + ", :" + event);
+ }
+ if (mVelocityTracker != null) {
+ mVelocityTracker.addMovement(event);
+ }
+ if (mActivePointerId == ACTIVE_POINTER_ID_NONE) {
+ return;
+ }
+ final int action = MotionEventCompat.getActionMasked(event);
+ final int activePointerIndex = MotionEventCompat
+ .findPointerIndex(event, mActivePointerId);
+ if (activePointerIndex >= 0) {
+ checkSelectForSwipe(action, event, activePointerIndex);
+ }
+ ViewHolder viewHolder = mSelected;
+ if (viewHolder == null) {
+ return;
+ }
+ switch (action) {
+ case MotionEvent.ACTION_MOVE: {
+ // Find the index of the active pointer and fetch its position
+ if (activePointerIndex >= 0) {
+ updateDxDy(event, mSelectedFlags, activePointerIndex);
+ moveIfNecessary(viewHolder);
+ mRecyclerView.removeCallbacks(mScrollRunnable);
+ mScrollRunnable.run();
+ mRecyclerView.invalidate();
+ }
+ break;
+ }
+ case MotionEvent.ACTION_CANCEL:
+ case MotionEvent.ACTION_UP:
+ if (mVelocityTracker != null) {
+ mVelocityTracker
+ .computeCurrentVelocity(1000, mRecyclerView.getMaxFlingVelocity());
+ }
+ select(null, ACTION_STATE_IDLE);
+ mActivePointerId = ACTIVE_POINTER_ID_NONE;
+ break;
+ case MotionEvent.ACTION_POINTER_UP: {
+ final int pointerIndex = MotionEventCompat.getActionIndex(event);
+ final int pointerId = MotionEventCompat.getPointerId(event, pointerIndex);
+ if (pointerId == mActivePointerId) {
+ if (mVelocityTracker != null) {
+ mVelocityTracker
+ .computeCurrentVelocity(1000,
+ mRecyclerView.getMaxFlingVelocity());
+ }
+ // This was our active pointer going up. Choose a new
+ // active pointer and adjust accordingly.
+ final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
+ mActivePointerId = MotionEventCompat.getPointerId(event, newPointerIndex);
+ updateDxDy(event, mSelectedFlags, pointerIndex);
+ }
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+ if (!disallowIntercept) {
+ return;
+ }
+ select(null, ACTION_STATE_IDLE);
+ }
+ };
+
+ /**
+ * Temporary rect instance that is used when we need to lookup Item decorations.
+ */
+ private Rect mTmpRect;
+
+ /**
+ * When user started to drag scroll. Reset when we don't scroll
+ */
+ private long mDragScrollStartTimeInMs;
+
+ /**
+ * Creates an ItemTouchHelper that will work with the given Callback.
+ *
+ * You can attach ItemTouchHelper to a RecyclerView via
+ * {@link #attachToRecyclerView(RecyclerView)}. Upon attaching, it will add an item decoration,
+ * an onItemTouchListener and a Child attach / detach listener to the RecyclerView.
+ *
+ * @param callback The Callback which controls the behavior of this touch helper.
+ */
+ public ItemTouchHelper(Callback callback) {
+ mCallback = callback;
+ }
+
+ private static boolean hitTest(View child, float x, float y, float left, float top) {
+ return x >= left &&
+ x <= left + child.getWidth() &&
+ y >= top &&
+ y <= top + child.getHeight();
+ }
+
+ /**
+ * Attaches the ItemTouchHelper to the provided RecyclerView. If TouchHelper is already
+ * attached
+ * to a RecyclerView, it will first detach from the previous one.
+ *
+ * @param recyclerView The RecyclerView instance to which you want to add this helper.
+ */
+ public void attachToRecyclerView(RecyclerView recyclerView) {
+ if (mRecyclerView == recyclerView) {
+ return; // nothing to do
+ }
+ if (mRecyclerView != null) {
+ destroyCallbacks();
+ }
+ mRecyclerView = recyclerView;
+ if (mRecyclerView != null) {
+ setupCallbacks();
+ }
+ }
+
+ private void setupCallbacks() {
+ ViewConfiguration vc = ViewConfiguration.get(mRecyclerView.getContext());
+ mSlop = vc.getScaledTouchSlop();
+ mRecyclerView.addItemDecoration(this);
+ mRecyclerView.addOnItemTouchListener(mOnItemTouchListener);
+ mRecyclerView.addOnChildAttachStateChangeListener(this);
+ initGestureDetector();
+ }
+
+ private void destroyCallbacks() {
+ mRecyclerView.removeItemDecoration(this);
+ mRecyclerView.removeOnItemTouchListener(mOnItemTouchListener);
+ mRecyclerView.removeOnChildAttachStateChangeListener(this);
+ // clean all attached
+ final int recoverAnimSize = mRecoverAnimations.size();
+ for (int i = recoverAnimSize - 1; i >= 0; i--) {
+ final RecoverAnimation recoverAnimation = mRecoverAnimations.get(0);
+ mCallback.clearView(mRecyclerView, recoverAnimation.mViewHolder);
+ }
+ mRecoverAnimations.clear();
+ mOverdrawChild = null;
+ mOverdrawChildPosition = -1;
+ releaseVelocityTracker();
+ }
+
+ private void initGestureDetector() {
+ if (mGestureDetector != null) {
+ return;
+ }
+ mGestureDetector = new GestureDetectorCompat(mRecyclerView.getContext(),
+ new ItemTouchHelperGestureListener());
+ }
+
+ private void getSelectedDxDy(float[] outPosition) {
+ if ((mSelectedFlags & (LEFT | RIGHT)) != 0) {
+ outPosition[0] = mSelectedStartX + mDx - mSelected.itemView.getLeft();
+ } else {
+ outPosition[0] = ViewCompat.getTranslationX(mSelected.itemView);
+ }
+ if ((mSelectedFlags & (UP | DOWN)) != 0) {
+ outPosition[1] = mSelectedStartY + mDy - mSelected.itemView.getTop();
+ } else {
+ outPosition[1] = ViewCompat.getTranslationY(mSelected.itemView);
+ }
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ float dx = 0, dy = 0;
+ if (mSelected != null) {
+ getSelectedDxDy(mTmpPosition);
+ dx = mTmpPosition[0];
+ dy = mTmpPosition[1];
+ }
+ mCallback.onDrawOver(c, parent, mSelected,
+ mRecoverAnimations, mActionState, dx, dy);
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
+ // we don't know if RV changed something so we should invalidate this index.
+ mOverdrawChildPosition = -1;
+ float dx = 0, dy = 0;
+ if (mSelected != null) {
+ getSelectedDxDy(mTmpPosition);
+ dx = mTmpPosition[0];
+ dy = mTmpPosition[1];
+ }
+ mCallback.onDraw(c, parent, mSelected,
+ mRecoverAnimations, mActionState, dx, dy);
+ }
+
+ /**
+ * Starts dragging or swiping the given View. Call with null if you want to clear it.
+ *
+ * @param selected The ViewHolder to drag or swipe. Can be null if you want to cancel the
+ * current action
+ * @param actionState The type of action
+ */
+ private void select(ViewHolder selected, int actionState) {
+ if (selected == mSelected && actionState == mActionState) {
+ return;
+ }
+ mDragScrollStartTimeInMs = Long.MIN_VALUE;
+ final int prevActionState = mActionState;
+ // prevent duplicate animations
+ endRecoverAnimation(selected, true);
+ mActionState = actionState;
+ if (actionState == ACTION_STATE_DRAG) {
+ // we remove after animation is complete. this means we only elevate the last drag
+ // child but that should perform good enough as it is very hard to start dragging a
+ // new child before the previous one settles.
+ mOverdrawChild = selected.itemView;
+ addChildDrawingOrderCallback();
+ }
+ int actionStateMask = (1 << (DIRECTION_FLAG_COUNT + DIRECTION_FLAG_COUNT * actionState))
+ - 1;
+ boolean preventLayout = false;
+
+ if (mSelected != null) {
+ final ViewHolder prevSelected = mSelected;
+ if (prevSelected.itemView.getParent() != null) {
+ final int swipeDir = prevActionState == ACTION_STATE_DRAG ? 0
+ : swipeIfNecessary(prevSelected);
+ releaseVelocityTracker();
+ // find where we should animate to
+ final float targetTranslateX, targetTranslateY;
+ int animationType;
+ switch (swipeDir) {
+ case LEFT:
+ case RIGHT:
+ case START:
+ case END:
+ targetTranslateY = 0;
+ targetTranslateX = Math.signum(mDx) * mRecyclerView.getWidth();
+ break;
+ case UP:
+ case DOWN:
+ targetTranslateX = 0;
+ targetTranslateY = Math.signum(mDy) * mRecyclerView.getHeight();
+ break;
+ default:
+ targetTranslateX = 0;
+ targetTranslateY = 0;
+ }
+ if (prevActionState == ACTION_STATE_DRAG) {
+ animationType = ANIMATION_TYPE_DRAG;
+ } else if (swipeDir > 0) {
+ animationType = ANIMATION_TYPE_SWIPE_SUCCESS;
+ } else {
+ animationType = ANIMATION_TYPE_SWIPE_CANCEL;
+ }
+ getSelectedDxDy(mTmpPosition);
+ final float currentTranslateX = mTmpPosition[0];
+ final float currentTranslateY = mTmpPosition[1];
+ final RecoverAnimation rv = new RecoverAnimation(prevSelected, animationType,
+ prevActionState, currentTranslateX, currentTranslateY,
+ targetTranslateX, targetTranslateY) {
+ @Override
+ public void onAnimationEnd(ValueAnimatorCompat animation) {
+ super.onAnimationEnd(animation);
+ if (this.mOverridden) {
+ return;
+ }
+ if (swipeDir <= 0) {
+ // this is a drag or failed swipe. recover immediately
+ mCallback.clearView(mRecyclerView, prevSelected);
+ // full cleanup will happen on onDrawOver
+ } else {
+ // wait until remove animation is complete.
+ mPendingCleanup.add(prevSelected.itemView);
+ mIsPendingCleanup = true;
+ if (swipeDir > 0) {
+ // Animation might be ended by other animators during a layout.
+ // We defer callback to avoid editing adapter during a layout.
+ postDispatchSwipe(this, swipeDir);
+ }
+ }
+ // removed from the list after it is drawn for the last time
+ if (mOverdrawChild == prevSelected.itemView) {
+ removeChildDrawingOrderCallbackIfNecessary(prevSelected.itemView);
+ }
+ }
+ };
+ final long duration = mCallback.getAnimationDuration(mRecyclerView, animationType,
+ targetTranslateX - currentTranslateX, targetTranslateY - currentTranslateY);
+ rv.setDuration(duration);
+ mRecoverAnimations.add(rv);
+ rv.start();
+ preventLayout = true;
+ } else {
+ removeChildDrawingOrderCallbackIfNecessary(prevSelected.itemView);
+ mCallback.clearView(mRecyclerView, prevSelected);
+ }
+ mSelected = null;
+ }
+ if (selected != null) {
+ mSelectedFlags =
+ (mCallback.getAbsoluteMovementFlags(mRecyclerView, selected) & actionStateMask)
+ >> (mActionState * DIRECTION_FLAG_COUNT);
+ mSelectedStartX = selected.itemView.getLeft();
+ mSelectedStartY = selected.itemView.getTop();
+ mSelected = selected;
+
+ if (actionState == ACTION_STATE_DRAG) {
+ mSelected.itemView.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+ }
+ }
+ final ViewParent rvParent = mRecyclerView.getParent();
+ if (rvParent != null) {
+ rvParent.requestDisallowInterceptTouchEvent(mSelected != null);
+ }
+ if (!preventLayout) {
+ mRecyclerView.getLayoutManager().requestSimpleAnimationsInNextLayout();
+ }
+ mCallback.onSelectedChanged(mSelected, mActionState);
+ mRecyclerView.invalidate();
+ }
+
+ private void postDispatchSwipe(final RecoverAnimation anim, final int swipeDir) {
+ // wait until animations are complete.
+ mRecyclerView.post(new Runnable() {
+ @Override
+ public void run() {
+ if (mRecyclerView != null && mRecyclerView.isAttachedToWindow() &&
+ !anim.mOverridden &&
+ anim.mViewHolder.getAdapterPosition() != RecyclerView.NO_POSITION) {
+ final RecyclerView.ItemAnimator animator = mRecyclerView.getItemAnimator();
+ // if animator is running or we have other active recover animations, we try
+ // not to call onSwiped because DefaultItemAnimator is not good at merging
+ // animations. Instead, we wait and batch.
+ if ((animator == null || !animator.isRunning(null))
+ && !hasRunningRecoverAnim()) {
+ mCallback.onSwiped(anim.mViewHolder, swipeDir);
+ } else {
+ mRecyclerView.post(this);
+ }
+ }
+ }
+ });
+ }
+
+ private boolean hasRunningRecoverAnim() {
+ final int size = mRecoverAnimations.size();
+ for (int i = 0; i < size; i++) {
+ if (!mRecoverAnimations.get(i).mEnded) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * If user drags the view to the edge, trigger a scroll if necessary.
+ */
+ private boolean scrollIfNecessary() {
+ if (mSelected == null) {
+ mDragScrollStartTimeInMs = Long.MIN_VALUE;
+ return false;
+ }
+ final long now = System.currentTimeMillis();
+ final long scrollDuration = mDragScrollStartTimeInMs
+ == Long.MIN_VALUE ? 0 : now - mDragScrollStartTimeInMs;
+ RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();
+ if (mTmpRect == null) {
+ mTmpRect = new Rect();
+ }
+ int scrollX = 0;
+ int scrollY = 0;
+ lm.calculateItemDecorationsForChild(mSelected.itemView, mTmpRect);
+ if (lm.canScrollHorizontally()) {
+ int curX = (int) (mSelectedStartX + mDx);
+ final int leftDiff = curX - mTmpRect.left - mRecyclerView.getPaddingLeft();
+ if (mDx < 0 && leftDiff < 0) {
+ scrollX = leftDiff;
+ } else if (mDx > 0) {
+ final int rightDiff =
+ curX + mSelected.itemView.getWidth() + mTmpRect.right
+ - (mRecyclerView.getWidth() - mRecyclerView.getPaddingRight());
+ if (rightDiff > 0) {
+ scrollX = rightDiff;
+ }
+ }
+ }
+ if (lm.canScrollVertically()) {
+ int curY = (int) (mSelectedStartY + mDy);
+ final int topDiff = curY - mTmpRect.top - mRecyclerView.getPaddingTop();
+ if (mDy < 0 && topDiff < 0) {
+ scrollY = topDiff;
+ } else if (mDy > 0) {
+ final int bottomDiff = curY + mSelected.itemView.getHeight() + mTmpRect.bottom -
+ (mRecyclerView.getHeight() - mRecyclerView.getPaddingBottom());
+ if (bottomDiff > 0) {
+ scrollY = bottomDiff;
+ }
+ }
+ }
+ if (scrollX != 0) {
+ scrollX = mCallback.interpolateOutOfBoundsScroll(mRecyclerView,
+ mSelected.itemView.getWidth(), scrollX,
+ mRecyclerView.getWidth(), scrollDuration);
+ }
+ if (scrollY != 0) {
+ scrollY = mCallback.interpolateOutOfBoundsScroll(mRecyclerView,
+ mSelected.itemView.getHeight(), scrollY,
+ mRecyclerView.getHeight(), scrollDuration);
+ }
+ if (scrollX != 0 || scrollY != 0) {
+ if (mDragScrollStartTimeInMs == Long.MIN_VALUE) {
+ mDragScrollStartTimeInMs = now;
+ }
+ mRecyclerView.scrollBy(scrollX, scrollY);
+ return true;
+ }
+ mDragScrollStartTimeInMs = Long.MIN_VALUE;
+ return false;
+ }
+
+ private List findSwapTargets(ViewHolder viewHolder) {
+ if (mSwapTargets == null) {
+ mSwapTargets = new ArrayList();
+ mDistances = new ArrayList();
+ } else {
+ mSwapTargets.clear();
+ mDistances.clear();
+ }
+ final int margin = mCallback.getBoundingBoxMargin();
+ final int left = Math.round(mSelectedStartX + mDx) - margin;
+ final int top = Math.round(mSelectedStartY + mDy) - margin;
+ final int right = left + viewHolder.itemView.getWidth() + 2 * margin;
+ final int bottom = top + viewHolder.itemView.getHeight() + 2 * margin;
+ final int centerX = (left + right) / 2;
+ final int centerY = (top + bottom) / 2;
+ final RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();
+ final int childCount = lm.getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View other = lm.getChildAt(i);
+ if (other == viewHolder.itemView) {
+ continue;//myself!
+ }
+ if (other.getBottom() < top || other.getTop() > bottom
+ || other.getRight() < left || other.getLeft() > right) {
+ continue;
+ }
+ final ViewHolder otherVh = mRecyclerView.getChildViewHolder(other);
+ if (mCallback.canDropOver(mRecyclerView, mSelected, otherVh)) {
+ // find the index to add
+ final int dx = Math.abs(centerX - (other.getLeft() + other.getRight()) / 2);
+ final int dy = Math.abs(centerY - (other.getTop() + other.getBottom()) / 2);
+ final int dist = dx * dx + dy * dy;
+
+ int pos = 0;
+ final int cnt = mSwapTargets.size();
+ for (int j = 0; j < cnt; j++) {
+ if (dist > mDistances.get(j)) {
+ pos++;
+ } else {
+ break;
+ }
+ }
+ mSwapTargets.add(pos, otherVh);
+ mDistances.add(pos, dist);
+ }
+ }
+ return mSwapTargets;
+ }
+
+ /**
+ * Checks if we should swap w/ another view holder.
+ */
+ private void moveIfNecessary(ViewHolder viewHolder) {
+ if (mRecyclerView.isLayoutRequested()) {
+ return;
+ }
+ if (mActionState != ACTION_STATE_DRAG) {
+ return;
+ }
+
+ final float threshold = mCallback.getMoveThreshold(viewHolder);
+ final int x = (int) (mSelectedStartX + mDx);
+ final int y = (int) (mSelectedStartY + mDy);
+ if (Math.abs(y - viewHolder.itemView.getTop()) < viewHolder.itemView.getHeight() * threshold
+ && Math.abs(x - viewHolder.itemView.getLeft())
+ < viewHolder.itemView.getWidth() * threshold) {
+ return;
+ }
+ List swapTargets = findSwapTargets(viewHolder);
+ if (swapTargets.size() == 0) {
+ return;
+ }
+ // may swap.
+ ViewHolder target = mCallback.chooseDropTarget(viewHolder, swapTargets, x, y);
+ if (target == null) {
+ mSwapTargets.clear();
+ mDistances.clear();
+ return;
+ }
+ final int toPosition = target.getAdapterPosition();
+ final int fromPosition = viewHolder.getAdapterPosition();
+ if (mCallback.onMove(mRecyclerView, viewHolder, target)) {
+ // keep target visible
+ mCallback.onMoved(mRecyclerView, viewHolder, fromPosition,
+ target, toPosition, x, y);
+ }
+ }
+
+ @Override
+ public void onChildViewAttachedToWindow(View view) {
+ }
+
+ @Override
+ public void onChildViewDetachedFromWindow(View view) {
+ removeChildDrawingOrderCallbackIfNecessary(view);
+ final ViewHolder holder = mRecyclerView.getChildViewHolder(view);
+ if (holder == null) {
+ return;
+ }
+ if (mSelected != null && holder == mSelected) {
+ select(null, ACTION_STATE_IDLE);
+ } else {
+ endRecoverAnimation(holder, false); // this may push it into pending cleanup list.
+ if (mPendingCleanup.remove(holder.itemView)) {
+ mCallback.clearView(mRecyclerView, holder);
+ }
+ }
+ }
+
+ /**
+ * Returns the animation type or 0 if cannot be found.
+ */
+ private int endRecoverAnimation(ViewHolder viewHolder, boolean override) {
+ final int recoverAnimSize = mRecoverAnimations.size();
+ for (int i = recoverAnimSize - 1; i >= 0; i--) {
+ final RecoverAnimation anim = mRecoverAnimations.get(i);
+ if (anim.mViewHolder == viewHolder) {
+ anim.mOverridden |= override;
+ if (!anim.mEnded) {
+ anim.cancel();
+ }
+ mRecoverAnimations.remove(i);
+ anim.mViewHolder.setIsRecyclable(true);
+ return anim.mAnimationType;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
+ RecyclerView.State state) {
+ outRect.setEmpty();
+ }
+
+ private void obtainVelocityTracker() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ }
+ mVelocityTracker = VelocityTracker.obtain();
+ }
+
+ private void releaseVelocityTracker() {
+ if (mVelocityTracker != null) {
+ mVelocityTracker.recycle();
+ mVelocityTracker = null;
+ }
+ }
+
+ private ViewHolder findSwipedView(MotionEvent motionEvent) {
+ final RecyclerView.LayoutManager lm = mRecyclerView.getLayoutManager();
+ if (mActivePointerId == ACTIVE_POINTER_ID_NONE) {
+ return null;
+ }
+ final int pointerIndex = MotionEventCompat.findPointerIndex(motionEvent, mActivePointerId);
+ final float dx = MotionEventCompat.getX(motionEvent, pointerIndex) - mInitialTouchX;
+ final float dy = MotionEventCompat.getY(motionEvent, pointerIndex) - mInitialTouchY;
+ final float absDx = Math.abs(dx);
+ final float absDy = Math.abs(dy);
+
+ if (absDx < mSlop && absDy < mSlop) {
+ return null;
+ }
+ if (absDx > absDy && lm.canScrollHorizontally()) {
+ return null;
+ } else if (absDy > absDx && lm.canScrollVertically()) {
+ return null;
+ }
+ View child = findChildView(motionEvent);
+ if (child == null) {
+ return null;
+ }
+ return mRecyclerView.getChildViewHolder(child);
+ }
+
+ /**
+ * Checks whether we should select a View for swiping.
+ */
+ private boolean checkSelectForSwipe(int action, MotionEvent motionEvent, int pointerIndex) {
+ if (mSelected != null || action != MotionEvent.ACTION_MOVE
+ || mActionState == ACTION_STATE_DRAG || !mCallback.isItemViewSwipeEnabled()) {
+ return false;
+ }
+ if (mRecyclerView.getScrollState() == RecyclerView.SCROLL_STATE_DRAGGING) {
+ return false;
+ }
+ final ViewHolder vh = findSwipedView(motionEvent);
+ if (vh == null) {
+ return false;
+ }
+ final int movementFlags = mCallback.getAbsoluteMovementFlags(mRecyclerView, vh);
+
+ final int swipeFlags = (movementFlags & ACTION_MODE_SWIPE_MASK)
+ >> (DIRECTION_FLAG_COUNT * ACTION_STATE_SWIPE);
+
+ if (swipeFlags == 0) {
+ return false;
+ }
+
+ // mDx and mDy are only set in allowed directions. We use custom x/y here instead of
+ // updateDxDy to avoid swiping if user moves more in the other direction
+ final float x = MotionEventCompat.getX(motionEvent, pointerIndex);
+ final float y = MotionEventCompat.getY(motionEvent, pointerIndex);
+
+ // Calculate the distance moved
+ final float dx = x - mInitialTouchX;
+ final float dy = y - mInitialTouchY;
+ // swipe target is chose w/o applying flags so it does not really check if swiping in that
+ // direction is allowed. This why here, we use mDx mDy to check slope value again.
+ final float absDx = Math.abs(dx);
+ final float absDy = Math.abs(dy);
+
+ if (absDx < mSlop && absDy < mSlop) {
+ return false;
+ }
+ if (absDx > absDy) {
+ if (dx < 0 && (swipeFlags & LEFT) == 0) {
+ return false;
+ }
+ if (dx > 0 && (swipeFlags & RIGHT) == 0) {
+ return false;
+ }
+ } else {
+ if (dy < 0 && (swipeFlags & UP) == 0) {
+ return false;
+ }
+ if (dy > 0 && (swipeFlags & DOWN) == 0) {
+ return false;
+ }
+ }
+ mDx = mDy = 0f;
+ mActivePointerId = MotionEventCompat.getPointerId(motionEvent, 0);
+ select(vh, ACTION_STATE_SWIPE);
+ return true;
+ }
+
+ private View findChildView(MotionEvent event) {
+ // first check elevated views, if none, then call RV
+ final float x = event.getX();
+ final float y = event.getY();
+ if (mSelected != null) {
+ final View selectedView = mSelected.itemView;
+ if (hitTest(selectedView, x, y, mSelectedStartX + mDx, mSelectedStartY + mDy)) {
+ return selectedView;
+ }
+ }
+ for (int i = mRecoverAnimations.size() - 1; i >= 0; i--) {
+ final RecoverAnimation anim = mRecoverAnimations.get(i);
+ final View view = anim.mViewHolder.itemView;
+ if (hitTest(view, x, y, anim.mX, anim.mY)) {
+ return view;
+ }
+ }
+ return mRecyclerView.findChildViewUnder(x, y);
+ }
+
+ /**
+ * Starts dragging the provided ViewHolder. By default, ItemTouchHelper starts a drag when a
+ * View is long pressed. You can disable that behavior via
+ * {@link ItemTouchHelper.Callback#isLongPressDragEnabled()}.
+ *
+ * For this method to work:
+ *
+ * - The provided ViewHolder must be a child of the RecyclerView to which this
+ * ItemTouchHelper
+ * is attached.
+ * - {@link ItemTouchHelper.Callback} must have dragging enabled.
+ * - There must be a previous touch event that was reported to the ItemTouchHelper
+ * through RecyclerView's ItemTouchListener mechanism. As long as no other ItemTouchListener
+ * grabs previous events, this should work as expected.
+ *
+ *
+ * For example, if you would like to let your user to be able to drag an Item by touching one
+ * of its descendants, you may implement it as follows:
+ *
+ * viewHolder.dragButton.setOnTouchListener(new View.OnTouchListener() {
+ * public boolean onTouch(View v, MotionEvent event) {
+ * if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
+ * mItemTouchHelper.startDrag(viewHolder);
+ * }
+ * return false;
+ * }
+ * });
+ *
+ *
+ *
+ * @param viewHolder The ViewHolder to start dragging. It must be a direct child of
+ * RecyclerView.
+ * @see ItemTouchHelper.Callback#isItemViewSwipeEnabled()
+ */
+ public void startDrag(ViewHolder viewHolder) {
+ if (!mCallback.hasDragFlag(mRecyclerView, viewHolder)) {
+ Log.e(TAG, "Start drag has been called but swiping is not enabled");
+ return;
+ }
+ if (viewHolder.itemView.getParent() != mRecyclerView) {
+ Log.e(TAG, "Start drag has been called with a view holder which is not a child of "
+ + "the RecyclerView which is controlled by this ItemTouchHelper.");
+ return;
+ }
+ obtainVelocityTracker();
+ mDx = mDy = 0f;
+ select(viewHolder, ACTION_STATE_DRAG);
+ }
+
+ /**
+ * Starts swiping the provided ViewHolder. By default, ItemTouchHelper starts swiping a View
+ * when user swipes their finger (or mouse pointer) over the View. You can disable this
+ * behavior
+ * by overriding {@link ItemTouchHelper.Callback}
+ *
+ * For this method to work:
+ *
+ * - The provided ViewHolder must be a child of the RecyclerView to which this
+ * ItemTouchHelper is attached.
+ * - {@link ItemTouchHelper.Callback} must have swiping enabled.
+ * - There must be a previous touch event that was reported to the ItemTouchHelper
+ * through RecyclerView's ItemTouchListener mechanism. As long as no other ItemTouchListener
+ * grabs previous events, this should work as expected.
+ *
+ *
+ * For example, if you would like to let your user to be able to swipe an Item by touching one
+ * of its descendants, you may implement it as follows:
+ *
+ * viewHolder.dragButton.setOnTouchListener(new View.OnTouchListener() {
+ * public boolean onTouch(View v, MotionEvent event) {
+ * if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
+ * mItemTouchHelper.startSwipe(viewHolder);
+ * }
+ * return false;
+ * }
+ * });
+ *
+ *
+ * @param viewHolder The ViewHolder to start swiping. It must be a direct child of
+ * RecyclerView.
+ */
+ public void startSwipe(ViewHolder viewHolder) {
+ if (!mCallback.hasSwipeFlag(mRecyclerView, viewHolder)) {
+ Log.e(TAG, "Start swipe has been called but dragging is not enabled");
+ return;
+ }
+ if (viewHolder.itemView.getParent() != mRecyclerView) {
+ Log.e(TAG, "Start swipe has been called with a view holder which is not a child of "
+ + "the RecyclerView controlled by this ItemTouchHelper.");
+ return;
+ }
+ obtainVelocityTracker();
+ mDx = mDy = 0f;
+ select(viewHolder, ACTION_STATE_SWIPE);
+ }
+
+ private RecoverAnimation findAnimation(MotionEvent event) {
+ if (mRecoverAnimations.isEmpty()) {
+ return null;
+ }
+ View target = findChildView(event);
+ for (int i = mRecoverAnimations.size() - 1; i >= 0; i--) {
+ final RecoverAnimation anim = mRecoverAnimations.get(i);
+ if (anim.mViewHolder.itemView == target) {
+ return anim;
+ }
+ }
+ return null;
+ }
+
+ private void updateDxDy(MotionEvent ev, int directionFlags, int pointerIndex) {
+ final float x = MotionEventCompat.getX(ev, pointerIndex);
+ final float y = MotionEventCompat.getY(ev, pointerIndex);
+
+ // Calculate the distance moved
+ mDx = x - mInitialTouchX;
+ mDy = y - mInitialTouchY;
+ if ((directionFlags & LEFT) == 0) {
+ mDx = Math.max(0, mDx);
+ }
+ if ((directionFlags & RIGHT) == 0) {
+ mDx = Math.min(0, mDx);
+ }
+ if ((directionFlags & UP) == 0) {
+ mDy = Math.max(0, mDy);
+ }
+ if ((directionFlags & DOWN) == 0) {
+ mDy = Math.min(0, mDy);
+ }
+ }
+
+ private int swipeIfNecessary(ViewHolder viewHolder) {
+ if (mActionState == ACTION_STATE_DRAG) {
+ return 0;
+ }
+ final int originalMovementFlags = mCallback.getMovementFlags(mRecyclerView, viewHolder);
+ final int absoluteMovementFlags = mCallback.convertToAbsoluteDirection(
+ originalMovementFlags,
+ ViewCompat.getLayoutDirection(mRecyclerView));
+ final int flags = (absoluteMovementFlags
+ & ACTION_MODE_SWIPE_MASK) >> (ACTION_STATE_SWIPE * DIRECTION_FLAG_COUNT);
+ if (flags == 0) {
+ return 0;
+ }
+ final int originalFlags = (originalMovementFlags
+ & ACTION_MODE_SWIPE_MASK) >> (ACTION_STATE_SWIPE * DIRECTION_FLAG_COUNT);
+ int swipeDir;
+ if (Math.abs(mDx) > Math.abs(mDy)) {
+ if ((swipeDir = checkHorizontalSwipe(viewHolder, flags)) > 0) {
+ // if swipe dir is not in original flags, it should be the relative direction
+ if ((originalFlags & swipeDir) == 0) {
+ // convert to relative
+ return Callback.convertToRelativeDirection(swipeDir,
+ ViewCompat.getLayoutDirection(mRecyclerView));
+ }
+ return swipeDir;
+ }
+ if ((swipeDir = checkVerticalSwipe(viewHolder, flags)) > 0) {
+ return swipeDir;
+ }
+ } else {
+ if ((swipeDir = checkVerticalSwipe(viewHolder, flags)) > 0) {
+ return swipeDir;
+ }
+ if ((swipeDir = checkHorizontalSwipe(viewHolder, flags)) > 0) {
+ // if swipe dir is not in original flags, it should be the relative direction
+ if ((originalFlags & swipeDir) == 0) {
+ // convert to relative
+ return Callback.convertToRelativeDirection(swipeDir,
+ ViewCompat.getLayoutDirection(mRecyclerView));
+ }
+ return swipeDir;
+ }
+ }
+ return 0;
+ }
+
+ private int checkHorizontalSwipe(ViewHolder viewHolder, int flags) {
+ if ((flags & (LEFT | RIGHT)) != 0) {
+ final int dirFlag = mDx > 0 ? RIGHT : LEFT;
+ if (mVelocityTracker != null && mActivePointerId > -1) {
+ final float xVelocity = VelocityTrackerCompat
+ .getXVelocity(mVelocityTracker, mActivePointerId);
+ final int velDirFlag = xVelocity > 0f ? RIGHT : LEFT;
+ if ((velDirFlag & flags) != 0 && dirFlag == velDirFlag &&
+ Math.abs(xVelocity) >= mRecyclerView.getMinFlingVelocity()) {
+ return velDirFlag;
+ }
+ }
+
+ final float threshold = mRecyclerView.getWidth() * mCallback
+ .getSwipeThreshold(viewHolder);
+
+ if ((flags & dirFlag) != 0 && Math.abs(mDx) > threshold) {
+ return dirFlag;
+ }
+ }
+ return 0;
+ }
+
+ private int checkVerticalSwipe(ViewHolder viewHolder, int flags) {
+ if ((flags & (UP | DOWN)) != 0) {
+ final int dirFlag = mDy > 0 ? DOWN : UP;
+ if (mVelocityTracker != null && mActivePointerId > -1) {
+ final float yVelocity = VelocityTrackerCompat
+ .getYVelocity(mVelocityTracker, mActivePointerId);
+ final int velDirFlag = yVelocity > 0f ? DOWN : UP;
+ if ((velDirFlag & flags) != 0 && velDirFlag == dirFlag &&
+ Math.abs(yVelocity) >= mRecyclerView.getMinFlingVelocity()) {
+ return velDirFlag;
+ }
+ }
+
+ final float threshold = mRecyclerView.getHeight() * mCallback
+ .getSwipeThreshold(viewHolder);
+ if ((flags & dirFlag) != 0 && Math.abs(mDy) > threshold) {
+ return dirFlag;
+ }
+ }
+ return 0;
+ }
+
+ private void addChildDrawingOrderCallback() {
+ if (Build.VERSION.SDK_INT >= 21) {
+ return;// we use elevation on Lollipop
+ }
+ if (mChildDrawingOrderCallback == null) {
+ mChildDrawingOrderCallback = new RecyclerView.ChildDrawingOrderCallback() {
+ @Override
+ public int onGetChildDrawingOrder(int childCount, int i) {
+ if (mOverdrawChild == null) {
+ return i;
+ }
+ int childPosition = mOverdrawChildPosition;
+ if (childPosition == -1) {
+ childPosition = mRecyclerView.indexOfChild(mOverdrawChild);
+ mOverdrawChildPosition = childPosition;
+ }
+ if (i == childCount - 1) {
+ return childPosition;
+ }
+ return i < childPosition ? i : i + 1;
+ }
+ };
+ }
+ mRecyclerView.setChildDrawingOrderCallback(mChildDrawingOrderCallback);
+ }
+
+ private void removeChildDrawingOrderCallbackIfNecessary(View view) {
+ if (view == mOverdrawChild) {
+ mOverdrawChild = null;
+ // only remove if we've added
+ if (mChildDrawingOrderCallback != null) {
+ mRecyclerView.setChildDrawingOrderCallback(null);
+ }
+ }
+ }
+
+ /**
+ * An interface which can be implemented by LayoutManager for better integration with
+ * {@link ItemTouchHelper}.
+ */
+ public static interface ViewDropHandler {
+
+ /**
+ * Called by the {@link ItemTouchHelper} after a View is dropped over another View.
+ *
+ * A LayoutManager should implement this interface to get ready for the upcoming move
+ * operation.
+ *
+ * For example, LinearLayoutManager sets up a "scrollToPositionWithOffset" calls so that
+ * the View under drag will be used as an anchor View while calculating the next layout,
+ * making layout stay consistent.
+ *
+ * @param view The View which is being dragged. It is very likely that user is still
+ * dragging this View so there might be other
+ * {@link #prepareForDrop(View, View, int, int)} after this one.
+ * @param target The target view which is being dropped on.
+ * @param x The left
offset of the View that is being dragged. This value
+ * includes the movement caused by the user.
+ * @param y The top
offset of the View that is being dragged. This value
+ * includes the movement caused by the user.
+ */
+ public void prepareForDrop(View view, View target, int x, int y);
+ }
+
+ /**
+ * This class is the contract between ItemTouchHelper and your application. It lets you control
+ * which touch behaviors are enabled per each ViewHolder and also receive callbacks when user
+ * performs these actions.
+ *
+ * To control which actions user can take on each view, you should override
+ * {@link #getMovementFlags(RecyclerView, ViewHolder)} and return appropriate set
+ * of direction flags. ({@link #LEFT}, {@link #RIGHT}, {@link #START}, {@link #END},
+ * {@link #UP}, {@link #DOWN}). You can use
+ * {@link #makeMovementFlags(int, int)} to easily construct it. Alternatively, you can use
+ * {@link SimpleCallback}.
+ *
+ * If user drags an item, ItemTouchHelper will call
+ * {@link Callback#onMove(RecyclerView, ViewHolder, ViewHolder)
+ * onMove(recyclerView, dragged, target)}.
+ * Upon receiving this callback, you should move the item from the old position
+ * ({@code dragged.getAdapterPosition()}) to new position ({@code target.getAdapterPosition()})
+ * in your adapter and also call {@link RecyclerView.Adapter#notifyItemMoved(int, int)}.
+ * To control where a View can be dropped, you can override
+ * {@link #canDropOver(RecyclerView, ViewHolder, ViewHolder)}. When a
+ * dragging View overlaps multiple other views, Callback chooses the closest View with which
+ * dragged View might have changed positions. Although this approach works for many use cases,
+ * if you have a custom LayoutManager, you can override
+ * {@link #chooseDropTarget(ViewHolder, java.util.List, int, int)} to select a
+ * custom drop target.
+ *
+ * When a View is swiped, ItemTouchHelper animates it until it goes out of bounds, then calls
+ * {@link #onSwiped(ViewHolder, int)}. At this point, you should update your
+ * adapter (e.g. remove the item) and call related Adapter#notify event.
+ */
+ @SuppressWarnings("UnusedParameters")
+ public abstract static class Callback {
+
+ public static final int DEFAULT_DRAG_ANIMATION_DURATION = 200;
+
+ public static final int DEFAULT_SWIPE_ANIMATION_DURATION = 250;
+
+ static final int RELATIVE_DIR_FLAGS = START | END |
+ ((START | END) << DIRECTION_FLAG_COUNT) |
+ ((START | END) << (2 * DIRECTION_FLAG_COUNT));
+
+ private static final ItemTouchUIUtil sUICallback;
+
+ private static final int ABS_HORIZONTAL_DIR_FLAGS = LEFT | RIGHT |
+ ((LEFT | RIGHT) << DIRECTION_FLAG_COUNT) |
+ ((LEFT | RIGHT) << (2 * DIRECTION_FLAG_COUNT));
+
+ private static final Interpolator sDragScrollInterpolator = new Interpolator() {
+ public float getInterpolation(float t) {
+ return t * t * t * t * t;
+ }
+ };
+
+ private static final Interpolator sDragViewScrollCapInterpolator = new Interpolator() {
+ public float getInterpolation(float t) {
+ t -= 1.0f;
+ return t * t * t * t * t + 1.0f;
+ }
+ };
+
+ /**
+ * Drag scroll speed keeps accelerating until this many milliseconds before being capped.
+ */
+ private static final long DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS = 2000;
+
+ private int mCachedMaxScrollSpeed = -1;
+
+ static {
+ if (Build.VERSION.SDK_INT >= 21) {
+ sUICallback = new ItemTouchUIUtilImpl.Lollipop();
+ } else if (Build.VERSION.SDK_INT >= 11) {
+ sUICallback = new ItemTouchUIUtilImpl.Honeycomb();
+ } else {
+ sUICallback = new ItemTouchUIUtilImpl.Gingerbread();
+ }
+ }
+
+ /**
+ * Returns the {@link ItemTouchUIUtil} that is used by the {@link Callback} class for visual
+ * changes on Views in response to user interactions. {@link ItemTouchUIUtil} has different
+ * implementations for different platform versions.
+ *
+ * By default, {@link Callback} applies these changes on
+ * {@link RecyclerView.ViewHolder#itemView}.
+ *
+ * For example, if you have a use case where you only want the text to move when user
+ * swipes over the view, you can do the following:
+ *
+ * public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder){
+ * getDefaultUIUtil().clearView(((ItemTouchViewHolder) viewHolder).textView);
+ * }
+ * public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
+ * if (viewHolder != null){
+ * getDefaultUIUtil().onSelected(((ItemTouchViewHolder) viewHolder).textView);
+ * }
+ * }
+ * public void onChildDraw(Canvas c, RecyclerView recyclerView,
+ * RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
+ * boolean isCurrentlyActive) {
+ * getDefaultUIUtil().onDraw(c, recyclerView,
+ * ((ItemTouchViewHolder) viewHolder).textView, dX, dY,
+ * actionState, isCurrentlyActive);
+ * return true;
+ * }
+ * public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
+ * RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
+ * boolean isCurrentlyActive) {
+ * getDefaultUIUtil().onDrawOver(c, recyclerView,
+ * ((ItemTouchViewHolder) viewHolder).textView, dX, dY,
+ * actionState, isCurrentlyActive);
+ * return true;
+ * }
+ *
+ *
+ * @return The {@link ItemTouchUIUtil} instance that is used by the {@link Callback}
+ */
+ public static ItemTouchUIUtil getDefaultUIUtil() {
+ return sUICallback;
+ }
+
+ /**
+ * Replaces a movement direction with its relative version by taking layout direction into
+ * account.
+ *
+ * @param flags The flag value that include any number of movement flags.
+ * @param layoutDirection The layout direction of the View. Can be obtained from
+ * {@link ViewCompat#getLayoutDirection(android.view.View)}.
+ * @return Updated flags which uses relative flags ({@link #START}, {@link #END}) instead
+ * of {@link #LEFT}, {@link #RIGHT}.
+ * @see #convertToAbsoluteDirection(int, int)
+ */
+ public static int convertToRelativeDirection(int flags, int layoutDirection) {
+ int masked = flags & ABS_HORIZONTAL_DIR_FLAGS;
+ if (masked == 0) {
+ return flags;// does not have any abs flags, good.
+ }
+ flags &= ~masked; //remove left / right.
+ if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) {
+ // no change. just OR with 2 bits shifted mask and return
+ flags |= masked << 2; // START is 2 bits after LEFT, END is 2 bits after RIGHT.
+ return flags;
+ } else {
+ // add RIGHT flag as START
+ flags |= ((masked << 1) & ~ABS_HORIZONTAL_DIR_FLAGS);
+ // first clean RIGHT bit then add LEFT flag as END
+ flags |= ((masked << 1) & ABS_HORIZONTAL_DIR_FLAGS) << 2;
+ }
+ return flags;
+ }
+
+ /**
+ * Convenience method to create movement flags.
+ *
+ * For instance, if you want to let your items be drag & dropped vertically and swiped
+ * left to be dismissed, you can call this method with:
+ * makeMovementFlags(UP | DOWN, LEFT);
+ *
+ * @param dragFlags The directions in which the item can be dragged.
+ * @param swipeFlags The directions in which the item can be swiped.
+ * @return Returns an integer composed of the given drag and swipe flags.
+ */
+ public static int makeMovementFlags(int dragFlags, int swipeFlags) {
+ return makeFlag(ACTION_STATE_IDLE, swipeFlags | dragFlags) |
+ makeFlag(ACTION_STATE_SWIPE, swipeFlags) | makeFlag(ACTION_STATE_DRAG,
+ dragFlags);
+ }
+
+ /**
+ * Shifts the given direction flags to the offset of the given action state.
+ *
+ * @param actionState The action state you want to get flags in. Should be one of
+ * {@link #ACTION_STATE_IDLE}, {@link #ACTION_STATE_SWIPE} or
+ * {@link #ACTION_STATE_DRAG}.
+ * @param directions The direction flags. Can be composed from {@link #UP}, {@link #DOWN},
+ * {@link #RIGHT}, {@link #LEFT} {@link #START} and {@link #END}.
+ * @return And integer that represents the given directions in the provided actionState.
+ */
+ public static int makeFlag(int actionState, int directions) {
+ return directions << (actionState * DIRECTION_FLAG_COUNT);
+ }
+
+ /**
+ * Should return a composite flag which defines the enabled move directions in each state
+ * (idle, swiping, dragging).
+ *
+ * Instead of composing this flag manually, you can use {@link #makeMovementFlags(int,
+ * int)}
+ * or {@link #makeFlag(int, int)}.
+ *
+ * This flag is composed of 3 sets of 8 bits, where first 8 bits are for IDLE state, next
+ * 8 bits are for SWIPE state and third 8 bits are for DRAG state.
+ * Each 8 bit sections can be constructed by simply OR'ing direction flags defined in
+ * {@link ItemTouchHelper}.
+ *
+ * For example, if you want it to allow swiping LEFT and RIGHT but only allow starting to
+ * swipe by swiping RIGHT, you can return:
+ *
+ * makeFlag(ACTION_STATE_IDLE, RIGHT) | makeFlag(ACTION_STATE_SWIPE, LEFT | RIGHT);
+ *
+ * This means, allow right movement while IDLE and allow right and left movement while
+ * swiping.
+ *
+ * @param recyclerView The RecyclerView to which ItemTouchHelper is attached.
+ * @param viewHolder The ViewHolder for which the movement information is necessary.
+ * @return flags specifying which movements are allowed on this ViewHolder.
+ * @see #makeMovementFlags(int, int)
+ * @see #makeFlag(int, int)
+ */
+ public abstract int getMovementFlags(RecyclerView recyclerView,
+ ViewHolder viewHolder);
+
+ /**
+ * Converts a given set of flags to absolution direction which means {@link #START} and
+ * {@link #END} are replaced with {@link #LEFT} and {@link #RIGHT} depending on the layout
+ * direction.
+ *
+ * @param flags The flag value that include any number of movement flags.
+ * @param layoutDirection The layout direction of the RecyclerView.
+ * @return Updated flags which includes only absolute direction values.
+ */
+ public int convertToAbsoluteDirection(int flags, int layoutDirection) {
+ int masked = flags & RELATIVE_DIR_FLAGS;
+ if (masked == 0) {
+ return flags;// does not have any relative flags, good.
+ }
+ flags &= ~masked; //remove start / end
+ if (layoutDirection == ViewCompat.LAYOUT_DIRECTION_LTR) {
+ // no change. just OR with 2 bits shifted mask and return
+ flags |= masked >> 2; // START is 2 bits after LEFT, END is 2 bits after RIGHT.
+ return flags;
+ } else {
+ // add START flag as RIGHT
+ flags |= ((masked >> 1) & ~RELATIVE_DIR_FLAGS);
+ // first clean start bit then add END flag as LEFT
+ flags |= ((masked >> 1) & RELATIVE_DIR_FLAGS) >> 2;
+ }
+ return flags;
+ }
+
+ final int getAbsoluteMovementFlags(RecyclerView recyclerView,
+ ViewHolder viewHolder) {
+ final int flags = getMovementFlags(recyclerView, viewHolder);
+ return convertToAbsoluteDirection(flags, ViewCompat.getLayoutDirection(recyclerView));
+ }
+
+ private boolean hasDragFlag(RecyclerView recyclerView, ViewHolder viewHolder) {
+ final int flags = getAbsoluteMovementFlags(recyclerView, viewHolder);
+ return (flags & ACTION_MODE_DRAG_MASK) != 0;
+ }
+
+ private boolean hasSwipeFlag(RecyclerView recyclerView,
+ ViewHolder viewHolder) {
+ final int flags = getAbsoluteMovementFlags(recyclerView, viewHolder);
+ return (flags & ACTION_MODE_SWIPE_MASK) != 0;
+ }
+
+ /**
+ * Return true if the current ViewHolder can be dropped over the the target ViewHolder.
+ *
+ * This method is used when selecting drop target for the dragged View. After Views are
+ * eliminated either via bounds check or via this method, resulting set of views will be
+ * passed to {@link #chooseDropTarget(ViewHolder, java.util.List, int, int)}.
+ *
+ * Default implementation returns true.
+ *
+ * @param recyclerView The RecyclerView to which ItemTouchHelper is attached to.
+ * @param current The ViewHolder that user is dragging.
+ * @param target The ViewHolder which is below the dragged ViewHolder.
+ * @return True if the dragged ViewHolder can be replaced with the target ViewHolder, false
+ * otherwise.
+ */
+ public boolean canDropOver(RecyclerView recyclerView, ViewHolder current,
+ ViewHolder target) {
+ return true;
+ }
+
+ /**
+ * Called when ItemTouchHelper wants to move the dragged item from its old position to
+ * the new position.
+ *
+ * If this method returns true, ItemTouchHelper assumes {@code viewHolder} has been moved
+ * to the adapter position of {@code target} ViewHolder
+ * ({@link ViewHolder#getAdapterPosition()
+ * ViewHolder#getAdapterPosition()}).
+ *
+ * If you don't support drag & drop, this method will never be called.
+ *
+ * @param recyclerView The RecyclerView to which ItemTouchHelper is attached to.
+ * @param viewHolder The ViewHolder which is being dragged by the user.
+ * @param target The ViewHolder over which the currently active item is being
+ * dragged.
+ * @return True if the {@code viewHolder} has been moved to the adapter position of
+ * {@code target}.
+ * @see #onMoved(RecyclerView, ViewHolder, int, ViewHolder, int, int, int)
+ */
+ public abstract boolean onMove(RecyclerView recyclerView,
+ ViewHolder viewHolder, ViewHolder target);
+
+ /**
+ * Returns whether ItemTouchHelper should start a drag and drop operation if an item is
+ * long pressed.
+ *
+ * Default value returns true but you may want to disable this if you want to start
+ * dragging on a custom view touch using {@link #startDrag(ViewHolder)}.
+ *
+ * @return True if ItemTouchHelper should start dragging an item when it is long pressed,
+ * false otherwise. Default value is true
.
+ * @see #startDrag(ViewHolder)
+ */
+ public boolean isLongPressDragEnabled() {
+ return true;
+ }
+
+ /**
+ * Returns whether ItemTouchHelper should start a swipe operation if a pointer is swiped
+ * over the View.
+ *
+ * Default value returns true but you may want to disable this if you want to start
+ * swiping on a custom view touch using {@link #startSwipe(ViewHolder)}.
+ *
+ * @return True if ItemTouchHelper should start swiping an item when user swipes a pointer
+ * over the View, false otherwise. Default value is true
.
+ * @see #startSwipe(ViewHolder)
+ */
+ public boolean isItemViewSwipeEnabled() {
+ return true;
+ }
+
+ /**
+ * When finding views under a dragged view, by default, ItemTouchHelper searches for views
+ * that overlap with the dragged View. By overriding this method, you can extend or shrink
+ * the search box.
+ *
+ * @return The extra margin to be added to the hit box of the dragged View.
+ */
+ public int getBoundingBoxMargin() {
+ return 0;
+ }
+
+ /**
+ * Returns the fraction that the user should move the View to be considered as swiped.
+ * The fraction is calculated with respect to RecyclerView's bounds.
+ *
+ * Default value is .5f, which means, to swipe a View, user must move the View at least
+ * half of RecyclerView's width or height, depending on the swipe direction.
+ *
+ * @param viewHolder The ViewHolder that is being dragged.
+ * @return A float value that denotes the fraction of the View size. Default value
+ * is .5f .
+ */
+ public float getSwipeThreshold(ViewHolder viewHolder) {
+ return .5f;
+ }
+
+ /**
+ * Returns the fraction that the user should move the View to be considered as it is
+ * dragged. After a view is moved this amount, ItemTouchHelper starts checking for Views
+ * below it for a possible drop.
+ *
+ * @param viewHolder The ViewHolder that is being dragged.
+ * @return A float value that denotes the fraction of the View size. Default value is
+ * .5f .
+ */
+ public float getMoveThreshold(ViewHolder viewHolder) {
+ return .5f;
+ }
+
+ /**
+ * Called by ItemTouchHelper to select a drop target from the list of ViewHolders that
+ * are under the dragged View.
+ *
+ * Default implementation filters the View with which dragged item have changed position
+ * in the drag direction. For instance, if the view is dragged UP, it compares the
+ * view.getTop()
of the two views before and after drag started. If that value
+ * is different, the target view passes the filter.
+ *
+ * Among these Views which pass the test, the one closest to the dragged view is chosen.
+ *
+ * This method is called on the main thread every time user moves the View. If you want to
+ * override it, make sure it does not do any expensive operations.
+ *
+ * @param selected The ViewHolder being dragged by the user.
+ * @param dropTargets The list of ViewHolder that are under the dragged View and
+ * candidate as a drop.
+ * @param curX The updated left value of the dragged View after drag translations
+ * are applied. This value does not include margins added by
+ * {@link RecyclerView.ItemDecoration}s.
+ * @param curY The updated top value of the dragged View after drag translations
+ * are applied. This value does not include margins added by
+ * {@link RecyclerView.ItemDecoration}s.
+ * @return A ViewHolder to whose position the dragged ViewHolder should be
+ * moved to.
+ */
+ public ViewHolder chooseDropTarget(ViewHolder selected,
+ List dropTargets, int curX, int curY) {
+ int right = curX + selected.itemView.getWidth();
+ int bottom = curY + selected.itemView.getHeight();
+ ViewHolder winner = null;
+ int winnerScore = -1;
+ final int dx = curX - selected.itemView.getLeft();
+ final int dy = curY - selected.itemView.getTop();
+ final int targetsSize = dropTargets.size();
+ for (int i = 0; i < targetsSize; i++) {
+ final ViewHolder target = dropTargets.get(i);
+ if (dx > 0) {
+ int diff = target.itemView.getRight() - right;
+ if (diff < 0 && target.itemView.getRight() > selected.itemView.getRight()) {
+ final int score = Math.abs(diff);
+ if (score > winnerScore) {
+ winnerScore = score;
+ winner = target;
+ }
+ }
+ }
+ if (dx < 0) {
+ int diff = target.itemView.getLeft() - curX;
+ if (diff > 0 && target.itemView.getLeft() < selected.itemView.getLeft()) {
+ final int score = Math.abs(diff);
+ if (score > winnerScore) {
+ winnerScore = score;
+ winner = target;
+ }
+ }
+ }
+ if (dy < 0) {
+ int diff = target.itemView.getTop() - curY;
+ if (diff > 0 && target.itemView.getTop() < selected.itemView.getTop()) {
+ final int score = Math.abs(diff);
+ if (score > winnerScore) {
+ winnerScore = score;
+ winner = target;
+ }
+ }
+ }
+
+ if (dy > 0) {
+ int diff = target.itemView.getBottom() - bottom;
+ if (diff < 0 && target.itemView.getBottom() > selected.itemView.getBottom()) {
+ final int score = Math.abs(diff);
+ if (score > winnerScore) {
+ winnerScore = score;
+ winner = target;
+ }
+ }
+ }
+ }
+ return winner;
+ }
+
+ /**
+ * Called when a ViewHolder is swiped by the user.
+ *
+ * If you are returning relative directions ({@link #START} , {@link #END}) from the
+ * {@link #getMovementFlags(RecyclerView, ViewHolder)} method, this method
+ * will also use relative directions. Otherwise, it will use absolute directions.
+ *
+ * If you don't support swiping, this method will never be called.
+ *
+ * ItemTouchHelper will keep a reference to the View until it is detached from
+ * RecyclerView.
+ * As soon as it is detached, ItemTouchHelper will call
+ * {@link #clearView(RecyclerView, ViewHolder)}.
+ *
+ * @param viewHolder The ViewHolder which has been swiped by the user.
+ * @param direction The direction to which the ViewHolder is swiped. It is one of
+ * {@link #UP}, {@link #DOWN},
+ * {@link #LEFT} or {@link #RIGHT}. If your
+ * {@link #getMovementFlags(RecyclerView, ViewHolder)}
+ * method
+ * returned relative flags instead of {@link #LEFT} / {@link #RIGHT};
+ * `direction` will be relative as well. ({@link #START} or {@link
+ * #END}).
+ */
+ public abstract void onSwiped(ViewHolder viewHolder, int direction);
+
+ /**
+ * Called when the ViewHolder swiped or dragged by the ItemTouchHelper is changed.
+ *
+ * If you override this method, you should call super.
+ *
+ * @param viewHolder The new ViewHolder that is being swiped or dragged. Might be null if
+ * it is cleared.
+ * @param actionState One of {@link ItemTouchHelper#ACTION_STATE_IDLE},
+ * {@link ItemTouchHelper#ACTION_STATE_SWIPE} or
+ * {@link ItemTouchHelper#ACTION_STATE_DRAG}.
+ *
+ * @see #clearView(RecyclerView, RecyclerView.ViewHolder)
+ */
+ public void onSelectedChanged(ViewHolder viewHolder, int actionState) {
+ if (viewHolder != null) {
+ sUICallback.onSelected(viewHolder.itemView);
+ }
+ }
+
+ private int getMaxDragScroll(RecyclerView recyclerView) {
+ if (mCachedMaxScrollSpeed == -1) {
+ mCachedMaxScrollSpeed = AndroidUtilities.dp(20);
+ }
+ return mCachedMaxScrollSpeed;
+ }
+
+ /**
+ * Called when {@link #onMove(RecyclerView, ViewHolder, ViewHolder)} returns true.
+ *
+ * ItemTouchHelper does not create an extra Bitmap or View while dragging, instead, it
+ * modifies the existing View. Because of this reason, it is important that the View is
+ * still part of the layout after it is moved. This may not work as intended when swapped
+ * Views are close to RecyclerView bounds or there are gaps between them (e.g. other Views
+ * which were not eligible for dropping over).
+ *
+ * This method is responsible to give necessary hint to the LayoutManager so that it will
+ * keep the View in visible area. For example, for LinearLayoutManager, this is as simple
+ * as calling {@link LinearLayoutManager#scrollToPositionWithOffset(int, int)}.
+ *
+ * Default implementation calls {@link RecyclerView#scrollToPosition(int)} if the View's
+ * new position is likely to be out of bounds.
+ *
+ * It is important to ensure the ViewHolder will stay visible as otherwise, it might be
+ * removed by the LayoutManager if the move causes the View to go out of bounds. In that
+ * case, drag will end prematurely.
+ *
+ * @param recyclerView The RecyclerView controlled by the ItemTouchHelper.
+ * @param viewHolder The ViewHolder under user's control.
+ * @param fromPos The previous adapter position of the dragged item (before it was
+ * moved).
+ * @param target The ViewHolder on which the currently active item has been dropped.
+ * @param toPos The new adapter position of the dragged item.
+ * @param x The updated left value of the dragged View after drag translations
+ * are applied. This value does not include margins added by
+ * {@link RecyclerView.ItemDecoration}s.
+ * @param y The updated top value of the dragged View after drag translations
+ * are applied. This value does not include margins added by
+ * {@link RecyclerView.ItemDecoration}s.
+ */
+ public void onMoved(final RecyclerView recyclerView,
+ final ViewHolder viewHolder, int fromPos, final ViewHolder target, int toPos, int x,
+ int y) {
+ final RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
+ if (layoutManager instanceof ViewDropHandler) {
+ ((ViewDropHandler) layoutManager).prepareForDrop(viewHolder.itemView,
+ target.itemView, x, y);
+ return;
+ }
+
+ // if layout manager cannot handle it, do some guesswork
+ if (layoutManager.canScrollHorizontally()) {
+ final int minLeft = layoutManager.getDecoratedLeft(target.itemView);
+ if (minLeft <= recyclerView.getPaddingLeft()) {
+ recyclerView.scrollToPosition(toPos);
+ }
+ final int maxRight = layoutManager.getDecoratedRight(target.itemView);
+ if (maxRight >= recyclerView.getWidth() - recyclerView.getPaddingRight()) {
+ recyclerView.scrollToPosition(toPos);
+ }
+ }
+
+ if (layoutManager.canScrollVertically()) {
+ final int minTop = layoutManager.getDecoratedTop(target.itemView);
+ if (minTop <= recyclerView.getPaddingTop()) {
+ recyclerView.scrollToPosition(toPos);
+ }
+ final int maxBottom = layoutManager.getDecoratedBottom(target.itemView);
+ if (maxBottom >= recyclerView.getHeight() - recyclerView.getPaddingBottom()) {
+ recyclerView.scrollToPosition(toPos);
+ }
+ }
+ }
+
+ private void onDraw(Canvas c, RecyclerView parent, ViewHolder selected,
+ List recoverAnimationList,
+ int actionState, float dX, float dY) {
+ final int recoverAnimSize = recoverAnimationList.size();
+ for (int i = 0; i < recoverAnimSize; i++) {
+ final ItemTouchHelper.RecoverAnimation anim = recoverAnimationList.get(i);
+ anim.update();
+ final int count = c.save();
+ onChildDraw(c, parent, anim.mViewHolder, anim.mX, anim.mY, anim.mActionState,
+ false);
+ c.restoreToCount(count);
+ }
+ if (selected != null) {
+ final int count = c.save();
+ onChildDraw(c, parent, selected, dX, dY, actionState, true);
+ c.restoreToCount(count);
+ }
+ }
+
+ private void onDrawOver(Canvas c, RecyclerView parent, ViewHolder selected,
+ List recoverAnimationList,
+ int actionState, float dX, float dY) {
+ final int recoverAnimSize = recoverAnimationList.size();
+ for (int i = 0; i < recoverAnimSize; i++) {
+ final ItemTouchHelper.RecoverAnimation anim = recoverAnimationList.get(i);
+ final int count = c.save();
+ onChildDrawOver(c, parent, anim.mViewHolder, anim.mX, anim.mY, anim.mActionState,
+ false);
+ c.restoreToCount(count);
+ }
+ if (selected != null) {
+ final int count = c.save();
+ onChildDrawOver(c, parent, selected, dX, dY, actionState, true);
+ c.restoreToCount(count);
+ }
+ boolean hasRunningAnimation = false;
+ for (int i = recoverAnimSize - 1; i >= 0; i--) {
+ final RecoverAnimation anim = recoverAnimationList.get(i);
+ if (anim.mEnded && !anim.mIsPendingCleanup) {
+ recoverAnimationList.remove(i);
+ anim.mViewHolder.setIsRecyclable(true);
+ } else if (!anim.mEnded) {
+ hasRunningAnimation = true;
+ }
+ }
+ if (hasRunningAnimation) {
+ parent.invalidate();
+ }
+ }
+
+ /**
+ * Called by the ItemTouchHelper when the user interaction with an element is over and it
+ * also completed its animation.
+ *
+ * This is a good place to clear all changes on the View that was done in
+ * {@link #onSelectedChanged(RecyclerView.ViewHolder, int)},
+ * {@link #onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int,
+ * boolean)} or
+ * {@link #onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, boolean)}.
+ *
+ * @param recyclerView The RecyclerView which is controlled by the ItemTouchHelper.
+ * @param viewHolder The View that was interacted by the user.
+ */
+ public void clearView(RecyclerView recyclerView, ViewHolder viewHolder) {
+ sUICallback.clearView(viewHolder.itemView);
+ }
+
+ /**
+ * Called by ItemTouchHelper on RecyclerView's onDraw callback.
+ *
+ * If you would like to customize how your View's respond to user interactions, this is
+ * a good place to override.
+ *
+ * Default implementation translates the child by the given dX
,
+ * dY
.
+ * ItemTouchHelper also takes care of drawing the child after other children if it is being
+ * dragged. This is done using child re-ordering mechanism. On platforms prior to L, this
+ * is
+ * achieved via {@link android.view.ViewGroup#getChildDrawingOrder(int, int)} and on L
+ * and after, it changes View's elevation value to be greater than all other children.)
+ *
+ * @param c The canvas which RecyclerView is drawing its children
+ * @param recyclerView The RecyclerView to which ItemTouchHelper is attached to
+ * @param viewHolder The ViewHolder which is being interacted by the User or it was
+ * interacted and simply animating to its original position
+ * @param dX The amount of horizontal displacement caused by user's action
+ * @param dY The amount of vertical displacement caused by user's action
+ * @param actionState The type of interaction on the View. Is either {@link
+ * #ACTION_STATE_DRAG} or {@link #ACTION_STATE_SWIPE}.
+ * @param isCurrentlyActive True if this view is currently being controlled by the user or
+ * false it is simply animating back to its original state.
+ * @see #onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int,
+ * boolean)
+ */
+ public void onChildDraw(Canvas c, RecyclerView recyclerView,
+ ViewHolder viewHolder,
+ float dX, float dY, int actionState, boolean isCurrentlyActive) {
+ sUICallback.onDraw(c, recyclerView, viewHolder.itemView, dX, dY, actionState,
+ isCurrentlyActive);
+ }
+
+ /**
+ * Called by ItemTouchHelper on RecyclerView's onDraw callback.
+ *
+ * If you would like to customize how your View's respond to user interactions, this is
+ * a good place to override.
+ *
+ * Default implementation translates the child by the given dX
,
+ * dY
.
+ * ItemTouchHelper also takes care of drawing the child after other children if it is being
+ * dragged. This is done using child re-ordering mechanism. On platforms prior to L, this
+ * is
+ * achieved via {@link android.view.ViewGroup#getChildDrawingOrder(int, int)} and on L
+ * and after, it changes View's elevation value to be greater than all other children.)
+ *
+ * @param c The canvas which RecyclerView is drawing its children
+ * @param recyclerView The RecyclerView to which ItemTouchHelper is attached to
+ * @param viewHolder The ViewHolder which is being interacted by the User or it was
+ * interacted and simply animating to its original position
+ * @param dX The amount of horizontal displacement caused by user's action
+ * @param dY The amount of vertical displacement caused by user's action
+ * @param actionState The type of interaction on the View. Is either {@link
+ * #ACTION_STATE_DRAG} or {@link #ACTION_STATE_SWIPE}.
+ * @param isCurrentlyActive True if this view is currently being controlled by the user or
+ * false it is simply animating back to its original state.
+ * @see #onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int,
+ * boolean)
+ */
+ public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
+ ViewHolder viewHolder,
+ float dX, float dY, int actionState, boolean isCurrentlyActive) {
+ sUICallback.onDrawOver(c, recyclerView, viewHolder.itemView, dX, dY, actionState,
+ isCurrentlyActive);
+ }
+
+ /**
+ * Called by the ItemTouchHelper when user action finished on a ViewHolder and now the View
+ * will be animated to its final position.
+ *
+ * Default implementation uses ItemAnimator's duration values. If
+ * animationType
is {@link #ANIMATION_TYPE_DRAG}, it returns
+ * {@link RecyclerView.ItemAnimator#getMoveDuration()}, otherwise, it returns
+ * {@link RecyclerView.ItemAnimator#getRemoveDuration()}. If RecyclerView does not have
+ * any {@link RecyclerView.ItemAnimator} attached, this method returns
+ * {@code DEFAULT_DRAG_ANIMATION_DURATION} or {@code DEFAULT_SWIPE_ANIMATION_DURATION}
+ * depending on the animation type.
+ *
+ * @param recyclerView The RecyclerView to which the ItemTouchHelper is attached to.
+ * @param animationType The type of animation. Is one of {@link #ANIMATION_TYPE_DRAG},
+ * {@link #ANIMATION_TYPE_SWIPE_CANCEL} or
+ * {@link #ANIMATION_TYPE_SWIPE_SUCCESS}.
+ * @param animateDx The horizontal distance that the animation will offset
+ * @param animateDy The vertical distance that the animation will offset
+ * @return The duration for the animation
+ */
+ public long getAnimationDuration(RecyclerView recyclerView, int animationType,
+ float animateDx, float animateDy) {
+ final RecyclerView.ItemAnimator itemAnimator = recyclerView.getItemAnimator();
+ if (itemAnimator == null) {
+ return animationType == ANIMATION_TYPE_DRAG ? DEFAULT_DRAG_ANIMATION_DURATION
+ : DEFAULT_SWIPE_ANIMATION_DURATION;
+ } else {
+ return animationType == ANIMATION_TYPE_DRAG ? itemAnimator.getMoveDuration()
+ : itemAnimator.getRemoveDuration();
+ }
+ }
+
+ /**
+ * Called by the ItemTouchHelper when user is dragging a view out of bounds.
+ *
+ * You can override this method to decide how much RecyclerView should scroll in response
+ * to this action. Default implementation calculates a value based on the amount of View
+ * out of bounds and the time it spent there. The longer user keeps the View out of bounds,
+ * the faster the list will scroll. Similarly, the larger portion of the View is out of
+ * bounds, the faster the RecyclerView will scroll.
+ *
+ * @param recyclerView The RecyclerView instance to which ItemTouchHelper is attached
+ * to.
+ * @param viewSize The total size of the View in scroll direction, excluding
+ * item decorations.
+ * @param viewSizeOutOfBounds The total size of the View that is out of bounds. This value
+ * is negative if the View is dragged towards left or top edge.
+ * @param totalSize The total size of RecyclerView in the scroll direction.
+ * @param msSinceStartScroll The time passed since View is kept out of bounds.
+ *
+ * @return The amount that RecyclerView should scroll. Keep in mind that this value will
+ * be passed to {@link RecyclerView#scrollBy(int, int)} method.
+ */
+ public int interpolateOutOfBoundsScroll(RecyclerView recyclerView,
+ int viewSize, int viewSizeOutOfBounds,
+ int totalSize, long msSinceStartScroll) {
+ final int maxScroll = getMaxDragScroll(recyclerView);
+ final int absOutOfBounds = Math.abs(viewSizeOutOfBounds);
+ final int direction = (int) Math.signum(viewSizeOutOfBounds);
+ // might be negative if other direction
+ float outOfBoundsRatio = Math.min(1f, 1f * absOutOfBounds / viewSize);
+ final int cappedScroll = (int) (direction * maxScroll *
+ sDragViewScrollCapInterpolator.getInterpolation(outOfBoundsRatio));
+ final float timeRatio;
+ if (msSinceStartScroll > DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS) {
+ timeRatio = 1f;
+ } else {
+ timeRatio = (float) msSinceStartScroll / DRAG_SCROLL_ACCELERATION_LIMIT_TIME_MS;
+ }
+ final int value = (int) (cappedScroll * sDragScrollInterpolator
+ .getInterpolation(timeRatio));
+ if (value == 0) {
+ return viewSizeOutOfBounds > 0 ? 1 : -1;
+ }
+ return value;
+ }
+ }
+
+ /**
+ * A simple wrapper to the default Callback which you can construct with drag and swipe
+ * directions and this class will handle the flag callbacks. You should still override onMove
+ * or
+ * onSwiped depending on your use case.
+ *
+ *
+ * ItemTouchHelper mIth = new ItemTouchHelper(
+ * new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN,
+ * ItemTouchHelper.LEFT) {
+ * public abstract boolean onMove(RecyclerView recyclerView,
+ * ViewHolder viewHolder, ViewHolder target) {
+ * final int fromPos = viewHolder.getAdapterPosition();
+ * final int toPos = viewHolder.getAdapterPosition();
+ * // move item in `fromPos` to `toPos` in adapter.
+ * return true;// true if moved, false otherwise
+ * }
+ * public void onSwiped(ViewHolder viewHolder, int direction) {
+ * // remove from adapter
+ * }
+ * });
+ *
+ */
+ public abstract static class SimpleCallback extends Callback {
+
+ private int mDefaultSwipeDirs;
+
+ private int mDefaultDragDirs;
+
+ /**
+ * Creates a Callback for the given drag and swipe allowance. These values serve as
+ * defaults
+ * and if you want to customize behavior per ViewHolder, you can override
+ * {@link #getSwipeDirs(RecyclerView, ViewHolder)}
+ * and / or {@link #getDragDirs(RecyclerView, ViewHolder)}.
+ *
+ * @param dragDirs Binary OR of direction flags in which the Views can be dragged. Must be
+ * composed of {@link #LEFT}, {@link #RIGHT}, {@link #START}, {@link
+ * #END},
+ * {@link #UP} and {@link #DOWN}.
+ * @param swipeDirs Binary OR of direction flags in which the Views can be swiped. Must be
+ * composed of {@link #LEFT}, {@link #RIGHT}, {@link #START}, {@link
+ * #END},
+ * {@link #UP} and {@link #DOWN}.
+ */
+ public SimpleCallback(int dragDirs, int swipeDirs) {
+ mDefaultSwipeDirs = swipeDirs;
+ mDefaultDragDirs = dragDirs;
+ }
+
+ /**
+ * Updates the default swipe directions. For example, you can use this method to toggle
+ * certain directions depending on your use case.
+ *
+ * @param defaultSwipeDirs Binary OR of directions in which the ViewHolders can be swiped.
+ */
+ public void setDefaultSwipeDirs(int defaultSwipeDirs) {
+ mDefaultSwipeDirs = defaultSwipeDirs;
+ }
+
+ /**
+ * Updates the default drag directions. For example, you can use this method to toggle
+ * certain directions depending on your use case.
+ *
+ * @param defaultDragDirs Binary OR of directions in which the ViewHolders can be dragged.
+ */
+ public void setDefaultDragDirs(int defaultDragDirs) {
+ mDefaultDragDirs = defaultDragDirs;
+ }
+
+ /**
+ * Returns the swipe directions for the provided ViewHolder.
+ * Default implementation returns the swipe directions that was set via constructor or
+ * {@link #setDefaultSwipeDirs(int)}.
+ *
+ * @param recyclerView The RecyclerView to which the ItemTouchHelper is attached to.
+ * @param viewHolder The RecyclerView for which the swipe drection is queried.
+ * @return A binary OR of direction flags.
+ */
+ public int getSwipeDirs(RecyclerView recyclerView, ViewHolder viewHolder) {
+ return mDefaultSwipeDirs;
+ }
+
+ /**
+ * Returns the drag directions for the provided ViewHolder.
+ * Default implementation returns the drag directions that was set via constructor or
+ * {@link #setDefaultDragDirs(int)}.
+ *
+ * @param recyclerView The RecyclerView to which the ItemTouchHelper is attached to.
+ * @param viewHolder The RecyclerView for which the swipe drection is queried.
+ * @return A binary OR of direction flags.
+ */
+ public int getDragDirs(RecyclerView recyclerView, ViewHolder viewHolder) {
+ return mDefaultDragDirs;
+ }
+
+ @Override
+ public int getMovementFlags(RecyclerView recyclerView, ViewHolder viewHolder) {
+ return makeMovementFlags(getDragDirs(recyclerView, viewHolder),
+ getSwipeDirs(recyclerView, viewHolder));
+ }
+ }
+
+ private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return true;
+ }
+
+ @Override
+ public void onLongPress(MotionEvent e) {
+ View child = findChildView(e);
+ if (child != null) {
+ ViewHolder vh = mRecyclerView.getChildViewHolder(child);
+ if (vh != null) {
+ if (!mCallback.hasDragFlag(mRecyclerView, vh)) {
+ return;
+ }
+ int pointerId = MotionEventCompat.getPointerId(e, 0);
+ // Long press is deferred.
+ // Check w/ active pointer id to avoid selecting after motion
+ // event is canceled.
+ if (pointerId == mActivePointerId) {
+ final int index = MotionEventCompat
+ .findPointerIndex(e, mActivePointerId);
+ final float x = MotionEventCompat.getX(e, index);
+ final float y = MotionEventCompat.getY(e, index);
+ mInitialTouchX = x;
+ mInitialTouchY = y;
+ mDx = mDy = 0f;
+ if (DEBUG) {
+ Log.d(TAG,
+ "onlong press: x:" + mInitialTouchX + ",y:" + mInitialTouchY);
+ }
+ if (mCallback.isLongPressDragEnabled()) {
+ select(vh, ACTION_STATE_DRAG);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private class RecoverAnimation implements AnimatorListenerCompat {
+
+ final float mStartDx;
+
+ final float mStartDy;
+
+ final float mTargetX;
+
+ final float mTargetY;
+
+ final ViewHolder mViewHolder;
+
+ final int mActionState;
+
+ private final ValueAnimatorCompat mValueAnimator;
+
+ private final int mAnimationType;
+
+ public boolean mIsPendingCleanup;
+
+ float mX;
+
+ float mY;
+
+ // if user starts touching a recovering view, we put it into interaction mode again,
+ // instantly.
+ boolean mOverridden = false;
+
+ private boolean mEnded = false;
+
+ private float mFraction;
+
+ public RecoverAnimation(ViewHolder viewHolder, int animationType,
+ int actionState, float startDx, float startDy, float targetX, float targetY) {
+ mActionState = actionState;
+ mAnimationType = animationType;
+ mViewHolder = viewHolder;
+ mStartDx = startDx;
+ mStartDy = startDy;
+ mTargetX = targetX;
+ mTargetY = targetY;
+ mValueAnimator = AnimatorCompatHelper.emptyValueAnimator();
+ mValueAnimator.addUpdateListener(
+ new AnimatorUpdateListenerCompat() {
+ @Override
+ public void onAnimationUpdate(ValueAnimatorCompat animation) {
+ setFraction(animation.getAnimatedFraction());
+ }
+ });
+ mValueAnimator.setTarget(viewHolder.itemView);
+ mValueAnimator.addListener(this);
+ setFraction(0f);
+ }
+
+ public void setDuration(long duration) {
+ mValueAnimator.setDuration(duration);
+ }
+
+ public void start() {
+ mViewHolder.setIsRecyclable(false);
+ mValueAnimator.start();
+ }
+
+ public void cancel() {
+ mValueAnimator.cancel();
+ }
+
+ public void setFraction(float fraction) {
+ mFraction = fraction;
+ }
+
+ /**
+ * We run updates on onDraw method but use the fraction from animator callback.
+ * This way, we can sync translate x/y values w/ the animators to avoid one-off frames.
+ */
+ public void update() {
+ if (mStartDx == mTargetX) {
+ mX = ViewCompat.getTranslationX(mViewHolder.itemView);
+ } else {
+ mX = mStartDx + mFraction * (mTargetX - mStartDx);
+ }
+ if (mStartDy == mTargetY) {
+ mY = ViewCompat.getTranslationY(mViewHolder.itemView);
+ } else {
+ mY = mStartDy + mFraction * (mTargetY - mStartDy);
+ }
+ }
+
+ @Override
+ public void onAnimationStart(ValueAnimatorCompat animation) {
+
+ }
+
+ @Override
+ public void onAnimationEnd(ValueAnimatorCompat animation) {
+ mEnded = true;
+ }
+
+ @Override
+ public void onAnimationCancel(ValueAnimatorCompat animation) {
+ setFraction(1f); //make sure we recover the view's state.
+ }
+
+ @Override
+ public void onAnimationRepeat(ValueAnimatorCompat animation) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtil.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtil.java
new file mode 100644
index 000000000..22cb8061b
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtil.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 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.telegram.android.support.widget.helper;
+
+import android.graphics.Canvas;
+import android.view.View;
+
+import org.telegram.android.support.widget.RecyclerView;
+
+/**
+ * Utility class for {@link ItemTouchHelper} which handles item transformations for different
+ * API versions.
+ *
+ * This class has methods that map to {@link ItemTouchHelper.Callback}'s drawing methods. Default
+ * implementations in {@link ItemTouchHelper.Callback} call these methods with
+ * {@link RecyclerView.ViewHolder#itemView} and {@link ItemTouchUIUtil} makes necessary changes
+ * on the View depending on the API level. You can access the instance of {@link ItemTouchUIUtil}
+ * via {@link ItemTouchHelper.Callback#getDefaultUIUtil()} and call its methods with the children
+ * of ViewHolder that you want to apply default effects.
+ *
+ * @see ItemTouchHelper.Callback#getDefaultUIUtil()
+ */
+public interface ItemTouchUIUtil {
+
+ /**
+ * The default implementation for {@link ItemTouchHelper.Callback#onChildDraw(Canvas,
+ * RecyclerView, RecyclerView.ViewHolder, float, float, int, boolean)}
+ */
+ void onDraw(Canvas c, RecyclerView recyclerView, View view,
+ float dX, float dY, int actionState, boolean isCurrentlyActive);
+
+ /**
+ * The default implementation for {@link ItemTouchHelper.Callback#onChildDrawOver(Canvas,
+ * RecyclerView, RecyclerView.ViewHolder, float, float, int, boolean)}
+ */
+ void onDrawOver(Canvas c, RecyclerView recyclerView, View view,
+ float dX, float dY, int actionState, boolean isCurrentlyActive);
+
+ /**
+ * The default implementation for {@link ItemTouchHelper.Callback#clearView(RecyclerView,
+ * RecyclerView.ViewHolder)}
+ */
+ void clearView(View view);
+
+ /**
+ * The default implementation for {@link ItemTouchHelper.Callback#onSelectedChanged(
+ * RecyclerView.ViewHolder, int)}
+ */
+ void onSelected(View view);
+}
+
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtilImpl.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtilImpl.java
new file mode 100644
index 000000000..63a492beb
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/helper/ItemTouchUIUtilImpl.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 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.telegram.android.support.widget.helper;
+
+import android.graphics.Canvas;
+import android.support.v4.view.ViewCompat;
+import org.telegram.android.support.widget.RecyclerView;
+import android.view.View;
+
+
+/**
+ * Package private class to keep implementations. Putting them inside ItemTouchUIUtil makes them
+ * public API, which is not desired in this case.
+ */
+class ItemTouchUIUtilImpl {
+ final static int item_touch_helper_previous_elevation = 123;
+ static class Lollipop extends Honeycomb {
+ @Override
+ public void onDraw(Canvas c, RecyclerView recyclerView, View view,
+ float dX, float dY, int actionState, boolean isCurrentlyActive) {
+ if (isCurrentlyActive) {
+ Object originalElevation = view.getTag(item_touch_helper_previous_elevation);
+ if (originalElevation == null) {
+ originalElevation = ViewCompat.getElevation(view);
+ float newElevation = 1f + findMaxElevation(recyclerView, view);
+ ViewCompat.setElevation(view, newElevation);
+ view.setTag(item_touch_helper_previous_elevation, originalElevation);
+ }
+ }
+ super.onDraw(c, recyclerView, view, dX, dY, actionState, isCurrentlyActive);
+ }
+
+ private float findMaxElevation(RecyclerView recyclerView, View itemView) {
+ final int childCount = recyclerView.getChildCount();
+ float max = 0;
+ for (int i = 0; i < childCount; i++) {
+ final View child = recyclerView.getChildAt(i);
+ if (child == itemView) {
+ continue;
+ }
+ final float elevation = ViewCompat.getElevation(child);
+ if (elevation > max) {
+ max = elevation;
+ }
+ }
+ return max;
+ }
+
+ @Override
+ public void clearView(View view) {
+ final Object tag = view.getTag(item_touch_helper_previous_elevation);
+ if (tag != null && tag instanceof Float) {
+ ViewCompat.setElevation(view, (Float) tag);
+ }
+ view.setTag(item_touch_helper_previous_elevation, null);
+ super.clearView(view);
+ }
+ }
+
+ static class Honeycomb implements ItemTouchUIUtil {
+
+ @Override
+ public void clearView(View view) {
+ ViewCompat.setTranslationX(view, 0f);
+ ViewCompat.setTranslationY(view, 0f);
+ }
+
+ @Override
+ public void onSelected(View view) {
+
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView recyclerView, View view,
+ float dX, float dY, int actionState, boolean isCurrentlyActive) {
+ ViewCompat.setTranslationX(view, dX);
+ ViewCompat.setTranslationY(view, dY);
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView recyclerView,
+ View view, float dX, float dY, int actionState, boolean isCurrentlyActive) {
+
+ }
+ }
+
+ static class Gingerbread implements ItemTouchUIUtil {
+
+ private void draw(Canvas c, RecyclerView parent, View view,
+ float dX, float dY) {
+ c.save();
+ c.translate(dX, dY);
+ parent.drawChild(c, view, 0);
+ c.restore();
+ }
+
+ @Override
+ public void clearView(View view) {
+ view.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ public void onSelected(View view) {
+ view.setVisibility(View.INVISIBLE);
+ }
+
+ @Override
+ public void onDraw(Canvas c, RecyclerView recyclerView, View view,
+ float dX, float dY, int actionState, boolean isCurrentlyActive) {
+ if (actionState != ItemTouchHelper.ACTION_STATE_DRAG) {
+ draw(c, recyclerView, view, dX, dY);
+ }
+ }
+
+ @Override
+ public void onDrawOver(Canvas c, RecyclerView recyclerView,
+ View view, float dX, float dY,
+ int actionState, boolean isCurrentlyActive) {
+ if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
+ draw(c, recyclerView, view, dX, dY);
+ }
+ }
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/android/support/widget/util/SortedListAdapterCallback.java b/TMessagesProj/src/main/java/org/telegram/android/support/widget/util/SortedListAdapterCallback.java
index 44ddd667e..2457f4932 100644
--- a/TMessagesProj/src/main/java/org/telegram/android/support/widget/util/SortedListAdapterCallback.java
+++ b/TMessagesProj/src/main/java/org/telegram/android/support/widget/util/SortedListAdapterCallback.java
@@ -16,7 +16,7 @@
package org.telegram.android.support.widget.util;
-import android.support.v7.util.SortedList;
+import org.telegram.android.support.util.SortedList;
import org.telegram.android.support.widget.RecyclerView;
/**
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java
index c7b0937a6..575d1e217 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/ApplicationLoader.java
@@ -90,7 +90,6 @@ public class ApplicationLoader extends Application {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
int selectedBackground = preferences.getInt("selectedBackground", 1000001);
selectedColor = preferences.getInt("selectedColor", 0);
- int cacheColorHint = 0;
if (selectedColor == 0) {
if (selectedBackground == 1000001) {
cachedWallpaper = applicationContext.getResources().getDrawable(R.drawable.background_hd);
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java
index 928d5e572..3f1dafe5b 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/ConnectionsManager.java
@@ -363,7 +363,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
try {
SerializedData data = new SerializedData(configFile);
isTestBackend = data.readInt32(false);
- int version = data.readInt32(false);
+ data.readInt32(false);
sessionsToDestroy.clear();
int count = data.readInt32(false);
for (int a = 0; a < count; a++) {
@@ -2700,7 +2700,7 @@ public class ConnectionsManager implements Action.ActionDelegate, TcpConnection.
return;
}
- int messageLength = data.readInt32(false);
+ data.readInt32(false);
TLObject message = deserialize(getRequestWithMessageId(messageId), data, true);
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java
index 2a006d37b..e7268e2ba 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoadOperation.java
@@ -28,6 +28,7 @@ public class FileLoadOperation {
private final static int stateFinished = 3;
private final static int downloadChunkSize = 1024 * 32;
+ private final static int downloadChunkSizeBig = 1024 * 128;
private final static int maxDownloadRequests = 3;
private int datacenter_id;
@@ -38,6 +39,7 @@ public class FileLoadOperation {
private FileLoadOperationDelegate delegate;
private byte[] key;
private byte[] iv;
+ private int currentDownloadChunkSize;
private int nextDownloadOffset = 0;
private ArrayList requestInfos = new ArrayList<>(maxDownloadRequests);
@@ -165,6 +167,7 @@ public class FileLoadOperation {
if (state != stateIdle) {
return;
}
+ currentDownloadChunkSize = totalBytesCount >= 1024 * 1024 * 30 ? downloadChunkSizeBig : downloadChunkSize;
state = stateDownloading;
if (location == null) {
Utilities.stageQueue.postRunnable(new Runnable() {
@@ -175,7 +178,6 @@ public class FileLoadOperation {
});
return;
}
- Long mediaId = null;
String fileNameFinal;
String fileNameTemp;
String fileNameIv = null;
@@ -223,7 +225,7 @@ public class FileLoadOperation {
cacheFileTemp = new File(tempPath, fileNameTemp);
if (cacheFileTemp.exists()) {
downloadedBytes = (int)cacheFileTemp.length();
- nextDownloadOffset = downloadedBytes = downloadedBytes / 1024 * 1024;
+ nextDownloadOffset = downloadedBytes = downloadedBytes / currentDownloadChunkSize * currentDownloadChunkSize;
}
if (fileNameIv != null) {
cacheIvTemp = new File(tempPath, fileNameIv);
@@ -388,10 +390,10 @@ public class FileLoadOperation {
}
}
- if (currentBytesSize != downloadChunkSize) {
+ if (currentBytesSize != currentDownloadChunkSize) {
onFinishLoadingFile();
} else {
- if (totalBytesCount != downloadedBytes && downloadedBytes % downloadChunkSize == 0 || totalBytesCount > 0 && totalBytesCount > downloadedBytes) {
+ if (totalBytesCount != downloadedBytes && downloadedBytes % currentDownloadChunkSize == 0 || totalBytesCount > 0 && totalBytesCount > downloadedBytes) {
startDownloadRequest();
} else {
onFinishLoadingFile();
@@ -422,7 +424,7 @@ public class FileLoadOperation {
startDownloadRequest();
}
} else if (error.text.contains("OFFSET_INVALID")) {
- if (downloadedBytes % downloadChunkSize == 0) {
+ if (downloadedBytes % currentDownloadChunkSize == 0) {
try {
onFinishLoadingFile();
} catch (Exception e) {
@@ -460,12 +462,12 @@ public class FileLoadOperation {
if (totalBytesCount > 0 && nextDownloadOffset >= totalBytesCount) {
break;
}
- boolean isLast = totalBytesCount <= 0 || a == count - 1 || totalBytesCount > 0 && nextDownloadOffset + downloadChunkSize >= totalBytesCount;
+ boolean isLast = totalBytesCount <= 0 || a == count - 1 || totalBytesCount > 0 && nextDownloadOffset + currentDownloadChunkSize >= totalBytesCount;
TLRPC.TL_upload_getFile req = new TLRPC.TL_upload_getFile();
req.location = location;
req.offset = nextDownloadOffset;
- req.limit = downloadChunkSize;
- nextDownloadOffset += downloadChunkSize;
+ req.limit = currentDownloadChunkSize;
+ nextDownloadOffset += currentDownloadChunkSize;
final RequestInfo requestInfo = new RequestInfo();
requestInfos.add(requestInfo);
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java
index 2860c3cc9..19ebeba03 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/FileLoader.java
@@ -675,6 +675,15 @@ public class FileLoader {
return closestObject;
}
+ public static String getFileExtension(File file) {
+ String name = file.getName();
+ try {
+ return name.substring(name.lastIndexOf(".") + 1);
+ } catch (Exception e) {
+ return "";
+ }
+ }
+
public static String getDocumentFileName(TLRPC.Document document) {
if (document != null) {
if (document.file_name != null) {
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java b/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java
index 7043dca59..b99706fe0 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/HandshakeAction.java
@@ -637,7 +637,7 @@ public class HandshakeAction extends Action implements TcpConnection.TcpConnecti
FileLog.d("tmessages", String.format("===== Duplicate message id %d received, ignoring", messageId));
return;
}
- int messageLength = data.readInt32(false);
+ data.readInt32(false);
int constructor = data.readInt32(false);
TLObject object = TLClassStore.Instance().TLdeserialize(data, constructor, false);
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java
index 5de616dc4..954025cc1 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/TLRPC.java
@@ -11634,6 +11634,9 @@ public class TLRPC {
case 0x9eddf188:
result = new TL_inputMessagesFilterDocument();
break;
+ case 0x5afbf764:
+ result = new TL_inputMessagesFilterAudioDocuments();
+ break;
case 0x9fc00e65:
result = new TL_inputMessagesFilterVideo();
break;
@@ -11672,6 +11675,15 @@ public class TLRPC {
}
}
+ public static class TL_inputMessagesFilterAudioDocuments extends MessagesFilter {
+ public static int constructor = 0x5afbf764;
+
+
+ public void serializeToStream(AbsSerializedData stream) {
+ stream.writeInt32(constructor);
+ }
+ }
+
public static class TL_inputMessagesFilterVideo extends MessagesFilter {
public static int constructor = 0x9fc00e65;
diff --git a/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java b/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java
index 217e63fb1..417d5c4e5 100644
--- a/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java
+++ b/TMessagesProj/src/main/java/org/telegram/messenger/TcpConnection.java
@@ -143,7 +143,7 @@ public class TcpConnection extends ConnectionContext {
FileLog.e("tmessages", e2);
}
- FileLog.d("tmessages", String.format(TcpConnection.this + " Connecting (%s:%d)", hostAddress, hostPort));
+ FileLog.d("tmessages", String.format(TcpConnection.this + " Connecting (%s:%d), connection class %d", hostAddress, hostPort, transportRequestClass));
firstPacket = true;
if (restOfTheData != null) {
BuffersStorage.getInstance().reuseFreeBuffer(restOfTheData);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java
index 7ddad2ce3..358725c23 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBar.java
@@ -15,7 +15,6 @@ import android.os.Build;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
@@ -23,6 +22,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
+import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.R;
import org.telegram.ui.Components.LayoutHelper;
@@ -38,7 +38,6 @@ public class ActionBar extends FrameLayout {
}
}
- private FrameLayout titleFrameLayout;
private ImageView backButtonImageView;
private TextView titleTextView;
private TextView subTitleTextView;
@@ -60,116 +59,6 @@ public class ActionBar extends FrameLayout {
public ActionBar(Context context) {
super(context);
- titleFrameLayout = new FrameLayout(context);
- addView(titleFrameLayout);
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)titleFrameLayout.getLayoutParams();
- layoutParams.width = LayoutHelper.WRAP_CONTENT;
- layoutParams.height = LayoutHelper.MATCH_PARENT;
- layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
- titleFrameLayout.setLayoutParams(layoutParams);
- titleFrameLayout.setPadding(0, 0, AndroidUtilities.dp(4), 0);
- titleFrameLayout.setEnabled(false);
- }
-
- private void positionBackImage(int height) {
- if (backButtonImageView != null) {
- LayoutParams layoutParams = (LayoutParams)backButtonImageView.getLayoutParams();
- layoutParams.width = AndroidUtilities.dp(54);
- layoutParams.height = height;
- layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
- backButtonImageView.setLayoutParams(layoutParams);
- }
- }
-
- private void positionTitle(int width, int height) {
- int offset = AndroidUtilities.dp(2);
- if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- offset = AndroidUtilities.dp(1);
- }
- int maxTextWidth = 0;
-
- LayoutParams layoutParams;
-
- if (titleTextView != null && titleTextView.getVisibility() == VISIBLE) {
- if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
- } else {
- titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 20);
- }
-
- layoutParams = (LayoutParams) titleTextView.getLayoutParams();
- layoutParams.width = LayoutHelper.WRAP_CONTENT;
- layoutParams.height = LayoutHelper.WRAP_CONTENT;
- layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
- titleTextView.setLayoutParams(layoutParams);
- titleTextView.measure(width, height);
- maxTextWidth = titleTextView.getMeasuredWidth();
- }
- if (subTitleTextView != null && subTitleTextView.getVisibility() == VISIBLE) {
- if (!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
- subTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
- } else {
- subTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
- }
-
- layoutParams = (LayoutParams) subTitleTextView.getLayoutParams();
- layoutParams.width = LayoutHelper.WRAP_CONTENT;
- layoutParams.height = LayoutHelper.WRAP_CONTENT;
- layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
- subTitleTextView.setLayoutParams(layoutParams);
- subTitleTextView.measure(width, height);
- maxTextWidth = Math.max(maxTextWidth, subTitleTextView.getMeasuredWidth());
- }
-
- int x;
- if (backButtonImageView != null && backButtonImageView.getVisibility() == VISIBLE) {
- x = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 80 : 72);
- } else {
- x = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 26 : 18);
- }
-
- if (menu != null) {
- maxTextWidth = Math.min(maxTextWidth, width - menu.getMeasuredWidth() - AndroidUtilities.dp(16) - x);
- }
-
- if (titleTextView != null && titleTextView.getVisibility() == VISIBLE) {
- layoutParams = (LayoutParams) titleTextView.getLayoutParams();
- layoutParams.width = LayoutHelper.MATCH_PARENT;
- layoutParams.height = titleTextView.getMeasuredHeight();
- int y;
- if (subTitleTextView != null && subTitleTextView.getVisibility() == VISIBLE) {
- y = (height / 2 - titleTextView.getMeasuredHeight()) / 2 + offset;
- } else {
- y = (height - titleTextView.getMeasuredHeight()) / 2 - AndroidUtilities.dp(1);
- }
- layoutParams.setMargins(x, y, 0, 0);
- titleTextView.setLayoutParams(layoutParams);
- }
- if (subTitleTextView != null && subTitleTextView.getVisibility() == VISIBLE) {
- layoutParams = (LayoutParams) subTitleTextView.getLayoutParams();
- layoutParams.width = LayoutHelper.MATCH_PARENT;
- layoutParams.height = subTitleTextView.getMeasuredHeight();
- layoutParams.setMargins(x, height / 2 + (height / 2 - subTitleTextView.getMeasuredHeight()) / 2 - offset, 0, 0);
- subTitleTextView.setLayoutParams(layoutParams);
- }
-
- MarginLayoutParams layoutParams1 = (MarginLayoutParams) titleFrameLayout.getLayoutParams();
- layoutParams1.width = x + maxTextWidth + (isSearchFieldVisible ? 0 : AndroidUtilities.dp(6));
- layoutParams1.topMargin = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0;
- titleFrameLayout.setLayoutParams(layoutParams1);
- }
-
- public void positionMenu(int width, int height) {
- if (menu == null) {
- return;
- }
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)menu.getLayoutParams();
- layoutParams.width = isSearchFieldVisible ? LayoutHelper.MATCH_PARENT : LayoutHelper.WRAP_CONTENT;
- layoutParams.height = height;
- layoutParams.leftMargin = isSearchFieldVisible ? AndroidUtilities.dp(AndroidUtilities.isTablet() ? 74 : 66) : 0;
- layoutParams.topMargin = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0;
- menu.setLayoutParams(layoutParams);
- menu.measure(width, height);
}
private void createBackButtonImage() {
@@ -177,9 +66,10 @@ public class ActionBar extends FrameLayout {
return;
}
backButtonImageView = new ImageView(getContext());
- titleFrameLayout.addView(backButtonImageView);
backButtonImageView.setScaleType(ImageView.ScaleType.CENTER);
backButtonImageView.setBackgroundResource(itemsBackgroundResourceId);
+ addView(backButtonImageView, LayoutHelper.createFrame(54, 54, Gravity.LEFT | Gravity.TOP));
+
backButtonImageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
@@ -195,31 +85,19 @@ public class ActionBar extends FrameLayout {
}
public void setBackButtonDrawable(Drawable drawable) {
- boolean reposition = false;
if (backButtonImageView == null) {
createBackButtonImage();
- } else {
- reposition = true;
}
backButtonImageView.setVisibility(drawable == null ? GONE : VISIBLE);
backButtonImageView.setImageDrawable(drawable);
- if (reposition) {
- positionTitle(getMeasuredWidth(), getMeasuredHeight());
- }
}
public void setBackButtonImage(int resource) {
- boolean reposition = false;
if (backButtonImageView == null) {
createBackButtonImage();
- } else {
- reposition = true;
}
backButtonImageView.setVisibility(resource == 0 ? GONE : VISIBLE);
backButtonImageView.setImageResource(resource);
- if (reposition) {
- positionTitle(getMeasuredWidth(), getMeasuredHeight());
- }
}
private void createSubtitleTextView() {
@@ -227,13 +105,13 @@ public class ActionBar extends FrameLayout {
return;
}
subTitleTextView = new TextView(getContext());
- titleFrameLayout.addView(subTitleTextView);
subTitleTextView.setGravity(Gravity.LEFT);
subTitleTextView.setTextColor(0xffd7e8f7);
subTitleTextView.setSingleLine(true);
subTitleTextView.setLines(1);
subTitleTextView.setMaxLines(1);
subTitleTextView.setEllipsize(TextUtils.TruncateAt.END);
+ addView(subTitleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP));
}
public void setSubtitle(CharSequence value) {
@@ -243,22 +121,6 @@ public class ActionBar extends FrameLayout {
if (subTitleTextView != null) {
subTitleTextView.setVisibility(value != null && !isSearchFieldVisible ? VISIBLE : INVISIBLE);
subTitleTextView.setText(value);
- positionTitle(getMeasuredWidth(), getMeasuredHeight());
- }
- }
-
- public void setSubTitleIcon(int resourceId, Drawable drawable, int padding) {
- if ((resourceId != 0 || drawable != null) && subTitleTextView == null) {
- createSubtitleTextView();
- positionTitle(getMeasuredWidth(), getMeasuredHeight());
- }
- if (subTitleTextView != null) {
- if (drawable != null) {
- subTitleTextView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null);
- } else {
- subTitleTextView.setCompoundDrawablesWithIntrinsicBounds(resourceId, 0, 0, 0);
- }
- subTitleTextView.setCompoundDrawablePadding(padding);
}
}
@@ -268,39 +130,32 @@ public class ActionBar extends FrameLayout {
}
titleTextView = new TextView(getContext());
titleTextView.setGravity(Gravity.LEFT);
- titleTextView.setSingleLine(true);
titleTextView.setLines(1);
titleTextView.setMaxLines(1);
+ titleTextView.setSingleLine(true);
titleTextView.setEllipsize(TextUtils.TruncateAt.END);
- titleFrameLayout.addView(titleTextView);
titleTextView.setTextColor(0xffffffff);
titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
+ addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.LEFT | Gravity.TOP));
}
public void setTitle(CharSequence value) {
- boolean created = false;
if (value != null && titleTextView == null) {
createTitleTextView();
- created = true;
}
if (titleTextView != null) {
lastTitle = value;
titleTextView.setVisibility(value != null && !isSearchFieldVisible ? VISIBLE : INVISIBLE);
titleTextView.setText(value);
- positionTitle(getMeasuredWidth(), getMeasuredHeight());
- if (!created) {
- titleTextView.setText(value);
- }
}
}
- public void setTitleIcon(int resourceId, int padding) {
- if (resourceId != 0 && titleTextView == null) {
- createTitleTextView();
- positionTitle(getMeasuredWidth(), getMeasuredHeight());
- }
- titleTextView.setCompoundDrawablesWithIntrinsicBounds(resourceId, 0, 0, 0);
- titleTextView.setCompoundDrawablePadding(padding);
+ public TextView getSubTitleTextView() {
+ return subTitleTextView;
+ }
+
+ public TextView getTitleTextView() {
+ return titleTextView;
}
public Drawable getSubTitleIcon() {
@@ -332,17 +187,6 @@ public class ActionBar extends FrameLayout {
actionBarMenuOnItemClick = listener;
}
- public void setCustomView(int resourceId) {
- LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- View view = li.inflate(resourceId, null);
- addView(view);
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)view.getLayoutParams();
- layoutParams.width = LayoutHelper.MATCH_PARENT;
- layoutParams.height = LayoutHelper.MATCH_PARENT;
- layoutParams.topMargin = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0;
- view.setLayoutParams(layoutParams);
- }
-
public ActionBarMenu createActionMode() {
if (actionMode != null) {
return actionMode;
@@ -358,7 +202,7 @@ public class ActionBar extends FrameLayout {
actionMode.setLayoutParams(layoutParams);
actionMode.setVisibility(INVISIBLE);
- if (occupyStatusBar) {
+ if (occupyStatusBar && actionModeTop == null) {
actionModeTop = new View(getContext());
actionModeTop.setBackgroundColor(0x99000000);
addView(actionModeTop);
@@ -381,8 +225,14 @@ public class ActionBar extends FrameLayout {
if (occupyStatusBar && actionModeTop != null) {
actionModeTop.setVisibility(VISIBLE);
}
- if (titleFrameLayout != null) {
- titleFrameLayout.setVisibility(INVISIBLE);
+ if (titleTextView != null) {
+ titleTextView.setVisibility(INVISIBLE);
+ }
+ if (subTitleTextView != null) {
+ subTitleTextView.setVisibility(INVISIBLE);
+ }
+ if (backButtonImageView != null) {
+ backButtonImageView.setVisibility(INVISIBLE);
}
if (menu != null) {
menu.setVisibility(INVISIBLE);
@@ -397,14 +247,33 @@ public class ActionBar extends FrameLayout {
if (occupyStatusBar && actionModeTop != null) {
actionModeTop.setVisibility(INVISIBLE);
}
- if (titleFrameLayout != null) {
- titleFrameLayout.setVisibility(VISIBLE);
+ if (titleTextView != null) {
+ titleTextView.setVisibility(VISIBLE);
+ }
+ if (subTitleTextView != null) {
+ subTitleTextView.setVisibility(VISIBLE);
+ }
+ if (backButtonImageView != null) {
+ backButtonImageView.setVisibility(VISIBLE);
}
if (menu != null) {
menu.setVisibility(VISIBLE);
}
}
+ public void showActionModeTop() {
+ if (occupyStatusBar && actionModeTop == null) {
+ actionModeTop = new View(getContext());
+ actionModeTop.setBackgroundColor(0x99000000);
+ addView(actionModeTop);
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) actionModeTop.getLayoutParams();
+ layoutParams.height = AndroidUtilities.statusBarHeight;
+ layoutParams.width = LayoutHelper.MATCH_PARENT;
+ layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
+ actionModeTop.setLayoutParams(layoutParams);
+ }
+ }
+
public boolean isActionModeShowed() {
return actionMode != null && actionMode.getVisibility() == VISIBLE;
}
@@ -439,12 +308,136 @@ public class ActionBar extends FrameLayout {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int actionBarHeight = AndroidUtilities.getCurrentActionBarHeight();
- positionBackImage(actionBarHeight);
- positionMenu(MeasureSpec.getSize(widthMeasureSpec), actionBarHeight);
- positionTitle(MeasureSpec.getSize(widthMeasureSpec), actionBarHeight);
- actionBarHeight += occupyStatusBar ? AndroidUtilities.statusBarHeight : 0;
- super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(actionBarHeight + extraHeight, MeasureSpec.EXACTLY));
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+ int actionBarHeight = getCurrentActionBarHeight();
+ int actionBarHeightSpec = MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.EXACTLY);
+
+ setMeasuredDimension(width, actionBarHeight + extraHeight + (occupyStatusBar ? AndroidUtilities.statusBarHeight : 0));
+
+ int textLeft;
+ if (backButtonImageView != null && backButtonImageView.getVisibility() != GONE) {
+ backButtonImageView.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(54), MeasureSpec.EXACTLY), actionBarHeightSpec);
+ textLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 80 : 72);
+ } else {
+ textLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 26 : 18);
+ }
+
+ if (menu != null && menu.getVisibility() != GONE) {
+ int menuWidth;
+ if (isSearchFieldVisible) {
+ menuWidth = MeasureSpec.makeMeasureSpec(width - AndroidUtilities.dp(AndroidUtilities.isTablet() ? 74 : 66), MeasureSpec.EXACTLY);
+ } else {
+ menuWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST);
+ }
+ menu.measure(menuWidth, actionBarHeightSpec);
+ }
+
+ if (titleTextView != null && titleTextView.getVisibility() != GONE || subTitleTextView != null && subTitleTextView.getVisibility() != GONE) {
+ int availableWidth = width - (menu != null ? menu.getMeasuredWidth() : 0) - AndroidUtilities.dp(16) - textLeft;
+
+ if (titleTextView != null && titleTextView.getVisibility() != GONE) {
+ titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, !AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 18 : 20);
+ titleTextView.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.AT_MOST));
+
+ }
+ if (subTitleTextView != null && subTitleTextView.getVisibility() != GONE) {
+ subTitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, !AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 14 : 16);
+ subTitleTextView.measure(MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(actionBarHeight, MeasureSpec.AT_MOST));
+ }
+ }
+
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child.getVisibility() == GONE || child == titleTextView || child == subTitleTextView || child == menu || child == backButtonImageView) {
+ continue;
+ }
+ measureChildWithMargins(child, widthMeasureSpec, 0, MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY), 0);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ int additionalTop = occupyStatusBar ? AndroidUtilities.statusBarHeight : 0;
+
+ int textLeft;
+ if (backButtonImageView != null && backButtonImageView.getVisibility() != GONE) {
+ backButtonImageView.layout(0, additionalTop, backButtonImageView.getMeasuredWidth(), additionalTop + backButtonImageView.getMeasuredHeight());
+ textLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 80 : 72);
+ } else {
+ textLeft = AndroidUtilities.dp(AndroidUtilities.isTablet() ? 26 : 18);
+ }
+
+ if (menu != null && menu.getVisibility() != GONE) {
+ int menuLeft = isSearchFieldVisible ? AndroidUtilities.dp(AndroidUtilities.isTablet() ? 74 : 66) : (right - left) - menu.getMeasuredWidth();
+ menu.layout(menuLeft, additionalTop, menuLeft + menu.getMeasuredWidth(), additionalTop + menu.getMeasuredHeight());
+ }
+
+ int offset = AndroidUtilities.dp(!AndroidUtilities.isTablet() && getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE ? 1 : 2);
+ if (titleTextView != null && titleTextView.getVisibility() != GONE) {
+ int textTop;
+ if (subTitleTextView != null && subTitleTextView.getVisibility() != GONE) {
+ textTop = (getCurrentActionBarHeight() / 2 - titleTextView.getMeasuredHeight()) / 2 + offset;
+ } else {
+ textTop = (getCurrentActionBarHeight() - titleTextView.getMeasuredHeight()) / 2 - AndroidUtilities.dp(1);
+ }
+ titleTextView.layout(textLeft, additionalTop + textTop, textLeft + titleTextView.getMeasuredWidth(), additionalTop + textTop + titleTextView.getMeasuredHeight());
+ }
+ if (subTitleTextView != null && subTitleTextView.getVisibility() != GONE) {
+ int textTop = getCurrentActionBarHeight() / 2 + (getCurrentActionBarHeight() / 2 - subTitleTextView.getMeasuredHeight()) / 2 - offset;
+ subTitleTextView.layout(textLeft, additionalTop + textTop, textLeft + subTitleTextView.getMeasuredWidth(), additionalTop + textTop + subTitleTextView.getMeasuredHeight());
+ }
+
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ if (child.getVisibility() == GONE || child == titleTextView || child == subTitleTextView || child == menu || child == backButtonImageView) {
+ continue;
+ }
+
+ LayoutParams lp = (LayoutParams) child.getLayoutParams();
+
+ int width = child.getMeasuredWidth();
+ int height = child.getMeasuredHeight();
+ int childLeft;
+ int childTop;
+
+ int gravity = lp.gravity;
+ if (gravity == -1) {
+ gravity = Gravity.TOP | Gravity.LEFT;
+ }
+
+ final int absoluteGravity = gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
+ final int verticalGravity = gravity & Gravity.VERTICAL_GRAVITY_MASK;
+
+ switch (absoluteGravity & Gravity.HORIZONTAL_GRAVITY_MASK) {
+ case Gravity.CENTER_HORIZONTAL:
+ childLeft = (right - left - width) / 2 + lp.leftMargin - lp.rightMargin;
+ break;
+ case Gravity.RIGHT:
+ childLeft = right - width - lp.rightMargin;
+ break;
+ case Gravity.LEFT:
+ default:
+ childLeft = lp.leftMargin;
+ }
+
+ switch (verticalGravity) {
+ case Gravity.TOP:
+ childTop = lp.topMargin;
+ break;
+ case Gravity.CENTER_VERTICAL:
+ childTop = (bottom - top - height) / 2 + lp.topMargin - lp.bottomMargin;
+ break;
+ case Gravity.BOTTOM:
+ childTop = (bottom - top) - height - lp.bottomMargin;
+ break;
+ default:
+ childTop = lp.topMargin;
+ }
+ child.layout(childLeft, childTop, childLeft + width, childTop + height);
+ }
}
public void onMenuButtonPressed() {
@@ -474,10 +467,13 @@ public class ActionBar extends FrameLayout {
if (titleTextView != null) {
titleTextView.setVisibility(textToSet != null && !isSearchFieldVisible ? VISIBLE : INVISIBLE);
titleTextView.setText(textToSet);
- positionTitle(getMeasuredWidth(), getMeasuredHeight());
}
}
+ public boolean isSearchFieldVisible() {
+ return isSearchFieldVisible;
+ }
+
public void setExtraHeight(int value, boolean layout) {
extraHeight = value;
if (layout) {
@@ -520,4 +516,14 @@ public class ActionBar extends FrameLayout {
super.onTouchEvent(event);
return true;
}
+
+ public static int getCurrentActionBarHeight() {
+ if (AndroidUtilities.isTablet()) {
+ return AndroidUtilities.dp(64);
+ } else if (ApplicationLoader.applicationContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ return AndroidUtilities.dp(48);
+ } else {
+ return AndroidUtilities.dp(56);
+ }
+ }
}
\ No newline at end of file
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java
index 68b3b28be..f74d7c4d9 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarLayout.java
@@ -59,7 +59,7 @@ public class ActionBarLayout extends FrameLayout {
if (child instanceof ActionBar) {
return super.drawChild(canvas, child, drawingTime);
} else {
- boolean wasActionBar = false;
+ //boolean wasActionBar = false;
int actionBarHeight = 0;
int childCount = getChildCount();
for (int a = 0; a < childCount; a++) {
@@ -339,7 +339,7 @@ public class ActionBarLayout extends FrameLayout {
BaseFragment lastFragment = fragmentsStack.get(fragmentsStack.size() - 2);
View fragmentView = lastFragment.fragmentView;
if (fragmentView == null) {
- fragmentView = lastFragment.createView(parentActivity, parentActivity.getLayoutInflater());
+ fragmentView = lastFragment.createView(parentActivity);
} else {
ViewGroup parent = (ViewGroup) fragmentView.getParent();
if (parent != null) {
@@ -625,7 +625,7 @@ public class ActionBarLayout extends FrameLayout {
fragment.setParentLayout(this);
View fragmentView = fragment.fragmentView;
if (fragmentView == null) {
- fragmentView = fragment.createView(parentActivity, parentActivity.getLayoutInflater());
+ fragmentView = fragment.createView(parentActivity);
} else {
ViewGroup parent = (ViewGroup) fragmentView.getParent();
if (parent != null) {
@@ -829,7 +829,7 @@ public class ActionBarLayout extends FrameLayout {
previousFragment.setParentLayout(this);
View fragmentView = previousFragment.fragmentView;
if (fragmentView == null) {
- fragmentView = previousFragment.createView(parentActivity, parentActivity.getLayoutInflater());
+ fragmentView = previousFragment.createView(parentActivity);
} else {
ViewGroup parent = (ViewGroup) fragmentView.getParent();
if (parent != null) {
@@ -972,7 +972,7 @@ public class ActionBarLayout extends FrameLayout {
previousFragment.setParentLayout(this);
View fragmentView = previousFragment.fragmentView;
if (fragmentView == null) {
- fragmentView = previousFragment.createView(parentActivity, parentActivity.getLayoutInflater());
+ fragmentView = previousFragment.createView(parentActivity);
} else {
ViewGroup parent = (ViewGroup) fragmentView.getParent();
if (parent != null) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java
index 18ce670aa..2604eb466 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenu.java
@@ -36,7 +36,7 @@ public class ActionBarMenu extends LinearLayout {
View view = li.inflate(resourceId, null);
view.setTag(id);
addView(view);
- LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)view.getLayoutParams();
+ LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) view.getLayoutParams();
layoutParams.height = LayoutHelper.MATCH_PARENT;
view.setBackgroundResource(parentActionBar.itemsBackgroundResourceId);
view.setLayoutParams(layoutParams);
@@ -74,14 +74,14 @@ public class ActionBarMenu extends LinearLayout {
menuItem.iconView.setImageResource(icon);
}
addView(menuItem);
- LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)menuItem.getLayoutParams();
+ LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) menuItem.getLayoutParams();
layoutParams.height = LayoutHelper.MATCH_PARENT;
layoutParams.width = width;
menuItem.setLayoutParams(layoutParams);
menuItem.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
- ActionBarMenuItem item = (ActionBarMenuItem)view;
+ ActionBarMenuItem item = (ActionBarMenuItem) view;
if (item.hasSubMenu()) {
if (parentActionBar.actionBarMenuOnItemClick.canOpenMenu()) {
item.toggleSubMenu();
@@ -89,7 +89,7 @@ public class ActionBarMenu extends LinearLayout {
} else if (item.isSearchField()) {
parentActionBar.onSearchFieldVisibilityChanged(item.toggleSearch());
} else {
- onItemClick((Integer)view.getTag());
+ onItemClick((Integer) view.getTag());
}
}
});
@@ -100,7 +100,7 @@ public class ActionBarMenu extends LinearLayout {
for (int a = 0; a < getChildCount(); a++) {
View view = getChildAt(a);
if (view instanceof ActionBarMenuItem) {
- ((ActionBarMenuItem)view).closeSubMenu();
+ ((ActionBarMenuItem) view).closeSubMenu();
}
}
}
@@ -122,10 +122,16 @@ public class ActionBarMenu extends LinearLayout {
for (int a = 0; a < getChildCount(); a++) {
View view = getChildAt(a);
if (view instanceof ActionBarMenuItem) {
- ActionBarMenuItem item = (ActionBarMenuItem)view;
- if (item.hasSubMenu() && item.getVisibility() == VISIBLE) {
+ ActionBarMenuItem item = (ActionBarMenuItem) view;
+ if (item.getVisibility() != VISIBLE) {
+ continue;
+ }
+ if (item.hasSubMenu()) {
item.toggleSubMenu();
break;
+ } else if (item.overrideMenuClick) {
+ onItemClick((Integer) item.getTag());
+ break;
}
}
}
@@ -135,7 +141,7 @@ public class ActionBarMenu extends LinearLayout {
for (int a = 0; a < getChildCount(); a++) {
View view = getChildAt(a);
if (view instanceof ActionBarMenuItem) {
- ActionBarMenuItem item = (ActionBarMenuItem)view;
+ ActionBarMenuItem item = (ActionBarMenuItem) view;
if (item.isSearchField()) {
parentActionBar.onSearchFieldVisibilityChanged(item.toggleSearch());
break;
@@ -148,7 +154,7 @@ public class ActionBarMenu extends LinearLayout {
for (int a = 0; a < getChildCount(); a++) {
View view = getChildAt(a);
if (view instanceof ActionBarMenuItem) {
- ActionBarMenuItem item = (ActionBarMenuItem)view;
+ ActionBarMenuItem item = (ActionBarMenuItem) view;
if (item.isSearchField()) {
if (toggle) {
parentActionBar.onSearchFieldVisibilityChanged(item.toggleSearch());
@@ -164,7 +170,7 @@ public class ActionBarMenu extends LinearLayout {
public ActionBarMenuItem getItem(int id) {
View v = findViewWithTag(id);
if (v instanceof ActionBarMenuItem) {
- return (ActionBarMenuItem)v;
+ return (ActionBarMenuItem) v;
}
return null;
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java
index ad5fc1d9b..aa357e762 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarMenuItem.java
@@ -82,6 +82,8 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
private int subMenuOpenSide = 0;
private ActionBarMenuItemDelegate delegate;
private boolean allowCloseAnimation = true;
+ protected boolean overrideMenuClick;
+ private boolean processedPopupClick;
public ActionBarMenuItem(Context context, ActionBarMenu menu, int background) {
super(context);
@@ -129,21 +131,23 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
x -= location[0];
y -= location[1];
selectedMenuView = null;
- for (int a = 0; a < popupLayout.getChildCount(); a++) {
- View child = popupLayout.getChildAt(a);
+ for (int a = 0; a < popupLayout.getItemsCount(); a++) {
+ View child = popupLayout.getItemAt(a);
child.getHitRect(rect);
if ((Integer) child.getTag() < 100) {
if (!rect.contains((int) x, (int) y)) {
child.setPressed(false);
child.setSelected(false);
- if (Build.VERSION.SDK_INT >= 21) {
+ if (Build.VERSION.SDK_INT == 21) {
child.getBackground().setVisible(false, false);
}
} else {
child.setPressed(true);
child.setSelected(true);
if (Build.VERSION.SDK_INT >= 21) {
- child.getBackground().setVisible(true, false);
+ if (Build.VERSION.SDK_INT == 21) {
+ child.getBackground().setVisible(true, false);
+ }
child.drawableHotspotChanged(x, y - child.getTop());
}
selectedMenuView = child;
@@ -192,9 +196,6 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
rect = new Rect();
location = new int[2];
popupLayout = new ActionBarPopupWindow.ActionBarPopupWindowLayout(getContext());
- popupLayout.setOrientation(LinearLayout.VERTICAL);
- popupLayout.setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8));
- //popupLayout.setBackgroundResource(R.drawable.popup_fixed);
popupLayout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
@@ -252,6 +253,10 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
@Override
public void onClick(View view) {
if (popupWindow != null && popupWindow.isShowing()) {
+ if (processedPopupClick) {
+ return;
+ }
+ processedPopupClick = true;
popupWindow.dismiss(allowCloseAnimation);
}
if (parentMenu != null) {
@@ -306,6 +311,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
}
});
}
+ processedPopupClick = false;
popupWindow.setFocusable(true);
if (popupLayout.getMeasuredWidth() == 0) {
updateOrShowPopup(true, true);
@@ -367,6 +373,11 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
return setIsSearchField(value, true);
}
+ public ActionBarMenuItem setOverrideMenuClick(boolean value) {
+ overrideMenuClick = value;
+ return this;
+ }
+
public ActionBarMenuItem setIsSearchField(boolean value, boolean needClearButton) {
if (parentMenu == null) {
return this;
@@ -389,7 +400,8 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
searchField.setSingleLine(true);
searchField.setBackgroundResource(0);
searchField.setPadding(0, 0, 0, 0);
- searchField.setInputType(EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
+ int inputType = searchField.getInputType() | EditorInfo.TYPE_TEXT_FLAG_NO_SUGGESTIONS;
+ searchField.setInputType(inputType);
if (android.os.Build.VERSION.SDK_INT < 11) {
searchField.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
@@ -467,7 +479,7 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
layoutParams2.width = LayoutHelper.MATCH_PARENT;
layoutParams2.gravity = Gravity.CENTER_VERTICAL;
layoutParams2.height = AndroidUtilities.dp(36);
- layoutParams2.rightMargin = AndroidUtilities.dp(48);
+ layoutParams2.rightMargin = needClearButton ? AndroidUtilities.dp(48) : 0;
searchField.setLayoutParams(layoutParams2);
if (needClearButton) {
@@ -532,6 +544,10 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
}
}
+ if (show) {
+ popupLayout.scrollToTop();
+ }
+
if (subMenuOpenSide == 0) {
if (showFromBottom) {
if (show) {
@@ -574,10 +590,6 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
if (view != null) {
view.setVisibility(GONE);
}
- view = popupLayout.findViewWithTag(100 + id);
- if (view != null) {
- view.setVisibility(GONE);
- }
}
public void showSubItem(int id) {
@@ -585,9 +597,5 @@ public class ActionBarMenuItem extends FrameLayoutFixed {
if (view != null) {
view.setVisibility(VISIBLE);
}
- view = popupLayout.findViewWithTag(100 + id);
- if (view != null) {
- view.setVisibility(VISIBLE);
- }
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java
index 7d6816f25..ee42b1eb9 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/ActionBarPopupWindow.java
@@ -19,14 +19,18 @@ import android.graphics.drawable.Drawable;
import android.os.Build;
import android.view.KeyEvent;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
+import android.widget.ScrollView;
import org.telegram.android.AndroidUtilities;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
+import org.telegram.ui.Components.LayoutHelper;
import java.lang.reflect.Field;
import java.util.HashMap;
@@ -62,7 +66,7 @@ public class ActionBarPopupWindow extends PopupWindow {
void onDispatchKeyEvent(KeyEvent keyEvent);
}
- public static class ActionBarPopupWindowLayout extends LinearLayout {
+ public static class ActionBarPopupWindowLayout extends FrameLayout {
private OnDispatchKeyEventListener mOnDispatchKeyEventListener;
protected static Drawable backgroundDrawable;
@@ -73,13 +77,26 @@ public class ActionBarPopupWindow extends PopupWindow {
private boolean showedFromBotton;
private HashMap positions = new HashMap<>();
+ private ScrollView scrollView;
+ private LinearLayout linearLayout;
+
public ActionBarPopupWindowLayout(Context context) {
super(context);
- setWillNotDraw(false);
if (backgroundDrawable == null) {
backgroundDrawable = getResources().getDrawable(R.drawable.popup_fixed);
}
+
+ setPadding(AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8), AndroidUtilities.dp(8));
+ setWillNotDraw(false);
+
+ scrollView = new ScrollView(context);
+ scrollView.setVerticalScrollBarEnabled(false);
+ addView(scrollView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
+
+ linearLayout = new LinearLayout(context);
+ linearLayout.setOrientation(LinearLayout.VERTICAL);
+ scrollView.addView(linearLayout, new ScrollView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
}
public void setShowedFromBotton(boolean value) {
@@ -106,15 +123,15 @@ public class ActionBarPopupWindow extends PopupWindow {
public void setBackScaleY(float value) {
backScaleY = value;
if (animationEnabled) {
- int count = getChildCount();
+ int count = getItemsCount();
int visibleCount = 0;
for (int a = 0; a < count; a++) {
- visibleCount += getChildAt(a).getVisibility() == VISIBLE ? 1 : 0;
+ visibleCount += getItemAt(a).getVisibility() == VISIBLE ? 1 : 0;
}
int height = getMeasuredHeight() - AndroidUtilities.dp(16);
if (showedFromBotton) {
for (int a = lastStartedChild; a >= 0; a--) {
- View child = getChildAt(a);
+ View child = getItemAt(a);
if (child.getVisibility() != VISIBLE) {
continue;
}
@@ -127,7 +144,7 @@ public class ActionBarPopupWindow extends PopupWindow {
}
} else {
for (int a = lastStartedChild; a < count; a++) {
- View child = getChildAt(a);
+ View child = getItemAt(a);
if (child.getVisibility() != VISIBLE) {
continue;
}
@@ -155,6 +172,11 @@ public class ActionBarPopupWindow extends PopupWindow {
}
}
+ @Override
+ public void addView(View child) {
+ linearLayout.addView(child);
+ }
+
public float getBackScaleX() {
return backScaleX;
}
@@ -183,6 +205,18 @@ public class ActionBarPopupWindow extends PopupWindow {
backgroundDrawable.draw(canvas);
}
}
+
+ public int getItemsCount() {
+ return linearLayout.getChildCount();
+ }
+
+ public View getItemAt(int index) {
+ return linearLayout.getChildAt(index);
+ }
+
+ public void scrollToTop() {
+ scrollView.scrollTo(0, 0);
+ }
}
public ActionBarPopupWindow() {
@@ -269,11 +303,11 @@ public class ActionBarPopupWindow extends PopupWindow {
content.setAlpha(1.0f);
content.setPivotX(content.getMeasuredWidth());
content.setPivotY(0);
- int count = content.getChildCount();
+ int count = content.getItemsCount();
content.positions.clear();
int visibleCount = 0;
for (int a = 0; a < count; a++) {
- View child = content.getChildAt(a);
+ View child = content.getItemAt(a);
if (child.getVisibility() != View.VISIBLE) {
continue;
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java
index dad03f246..1138a158b 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BaseFragment.java
@@ -14,7 +14,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -44,7 +43,7 @@ public class BaseFragment {
classGuid = ConnectionsManager.getInstance().generateClassGuid();
}
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
return null;
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java
index dd00b928b..87ac403ba 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/BottomSheet.java
@@ -9,10 +9,18 @@
package org.telegram.ui.ActionBar;
import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
@@ -45,7 +53,7 @@ import java.util.ArrayList;
public class BottomSheet extends Dialog {
- private LinearLayout linearLayout;
+ private LinearLayout containerView;
private FrameLayout container;
private boolean dismissed;
@@ -57,24 +65,73 @@ public class BottomSheet extends Dialog {
private int[] itemIcons;
private View customView;
private CharSequence title;
- private boolean overrideTabletWidth = true;
+ private boolean fullWidth;
private boolean isGrid;
private ColorDrawable backgroundDrawable = new ColorDrawable(0xff000000);
+ private static Drawable shadowDrawable;
+ private Paint ciclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+
+ private static int backgroundPaddingTop;
+ private static int backgroundPaddingLeft;
+
+ private boolean useRevealAnimation;
+ private float revealRadius;
private int revealX;
private int revealY;
- private boolean useRevealAnimation;
+ private boolean applyTopPaddings = true;
private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();
private AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
private ArrayList itemViews = new ArrayList<>();
- private BottomSheetDelegate delegate;
+ private BottomSheetDelegateInterface delegate;
- public interface BottomSheetDelegate {
+ public interface BottomSheetDelegateInterface {
void onOpenAnimationStart();
+
void onOpenAnimationEnd();
+
+ void onRevealAnimationStart(boolean open);
+
+ void onRevealAnimationEnd(boolean open);
+
+ void onRevealAnimationProgress(boolean open, float radius, int x, int y);
+
+ View getRevealView();
+ }
+
+ public static class BottomSheetDelegate implements BottomSheetDelegateInterface {
+ @Override
+ public void onOpenAnimationStart() {
+
+ }
+
+ @Override
+ public void onOpenAnimationEnd() {
+
+ }
+
+ @Override
+ public void onRevealAnimationStart(boolean open) {
+
+ }
+
+ @Override
+ public void onRevealAnimationEnd(boolean open) {
+
+ }
+
+ @Override
+ public void onRevealAnimationProgress(boolean open, float radius, int x, int y) {
+
+ }
+
+ @Override
+ public View getRevealView() {
+ return null;
+ }
}
private static class BottomSheetCell extends FrameLayout {
@@ -139,7 +196,40 @@ public class BottomSheet extends Dialog {
public BottomSheet(Context context) {
super(context);
- container = new FrameLayout(getContext());
+ container = new FrameLayout(getContext()) {
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ int height = MeasureSpec.getSize(heightMeasureSpec);
+
+ setMeasuredDimension(width, height);
+ boolean isPortrait = width < height;
+
+ if (containerView != null) {
+ int left = useRevealAnimation && Build.VERSION.SDK_INT <= 19 ? 0 : backgroundPaddingLeft;
+ if (!fullWidth) {
+ if (AndroidUtilities.isTablet()) {
+ int side = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.8f);
+ containerView.measure(MeasureSpec.makeMeasureSpec(side + left * 2, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
+ } else {
+ int maxWidth = Math.min(AndroidUtilities.dp(480), width);
+ containerView.measure(isPortrait ? MeasureSpec.makeMeasureSpec(width + left * 2, MeasureSpec.EXACTLY) : MeasureSpec.makeMeasureSpec((int) Math.max(width * 0.8f, maxWidth) + left * 2, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
+ }
+ } else {
+ containerView.measure(MeasureSpec.makeMeasureSpec(width + left * 2, MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
+ }
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ if (containerView != null) {
+ int l = ((right - left) - containerView.getMeasuredWidth()) / 2;
+ int t = (bottom - top) - containerView.getMeasuredHeight();
+ containerView.layout(l, t, l + containerView.getMeasuredWidth(), t + getMeasuredHeight());
+ }
+ }
+ };
container.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
@@ -159,25 +249,37 @@ public class BottomSheet extends Dialog {
window.requestFeature(Window.FEATURE_NO_TITLE);
window.setWindowAnimations(R.style.DialogNoAnimation);
- setContentView(container);
-
- linearLayout = new LinearLayout(getContext());
- linearLayout.setOrientation(LinearLayout.VERTICAL);
- if (AndroidUtilities.isTablet() && !overrideTabletWidth) {
- container.addView(linearLayout, 0, LayoutHelper.createFrame(320, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL));
- } else {
- container.addView(linearLayout, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
+ if (shadowDrawable == null) {
+ Rect padding = new Rect();
+ shadowDrawable = getContext().getResources().getDrawable(R.drawable.sheet_shadow);
+ shadowDrawable.getPadding(padding);
+ backgroundPaddingLeft = padding.left;
+ backgroundPaddingTop = padding.top;
}
- View shadow = new View(getContext());
- shadow.setBackgroundResource(R.drawable.header_shadow_reverse);
- linearLayout.addView(shadow, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 3));
+ setContentView(container, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
- LinearLayout containerView = new LinearLayout(getContext());
- containerView.setBackgroundColor(0xffffffff);
+ ciclePaint.setColor(0xffffffff);
+
+ containerView = new LinearLayout(getContext()) {
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (useRevealAnimation && Build.VERSION.SDK_INT <= 19) {
+ canvas.drawCircle(revealX, revealY, revealRadius, ciclePaint);
+ //shadowDrawable.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
+ //shadowDrawable.draw(canvas);
+ }
+ }
+
+ @Override
+ protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
+ return super.drawChild(canvas, child, drawingTime);
+ }
+ };
+ containerView.setWillNotDraw(false);
containerView.setOrientation(LinearLayout.VERTICAL);
- containerView.setPadding(0, AndroidUtilities.dp(8), 0, AndroidUtilities.dp(isGrid ? 16 : 8));
- linearLayout.addView(containerView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
+ container.addView(containerView, 0, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
if (title != null) {
TextView titleView = new TextView(getContext());
@@ -273,104 +375,179 @@ public class BottomSheet extends Dialog {
setOnShowListener(new OnShowListener() {
@Override
public void onShow(DialogInterface dialog) {
- if (useRevealAnimation) {
- int finalRadius = Math.max(AndroidUtilities.displaySize.x, container.getHeight());
- Animator anim = ViewAnimationUtils.createCircularReveal(container, revealX, revealY, 0, finalRadius);
- anim.setDuration(400);
- anim.addListener(new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- if (delegate != null) {
- delegate.onOpenAnimationStart();
- }
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- if (delegate != null) {
- delegate.onOpenAnimationEnd();
- }
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
-
- }
-
- @Override
- public void onAnimationRepeat(Animator animation) {
-
- }
- });
- anim.start();
- } else {
- //startLayoutAnimation(true, true);
- ViewProxy.setTranslationY(linearLayout, linearLayout.getHeight());
- backgroundDrawable.setAlpha(0);
- AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy();
- animatorSetProxy.playTogether(
- ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", 0),
- ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 51));
- animatorSetProxy.setDuration(200);
- animatorSetProxy.setStartDelay(20);
- animatorSetProxy.setInterpolator(new DecelerateInterpolator());
- animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() {
- @Override
- public void onAnimationEnd(Object animation) {
- if (delegate != null) {
- delegate.onOpenAnimationEnd();
- }
- }
- });
- animatorSetProxy.start();
+ if (Build.VERSION.SDK_INT >= 21) {
+ startOpenAnimation();
}
}
});
}
- private float animationProgress;
- private long lastFrameTime;
- private void startLayoutAnimation(final boolean open, final boolean first) {
- if (first) {
- animationProgress = 0.0f;
- lastFrameTime = System.nanoTime() / 1000000;
- if (Build.VERSION.SDK_INT >= 11) {
- container.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ @Override
+ public void show() {
+ super.show();
+ dismissed = false;
+ if (Build.VERSION.SDK_INT >= 21 || !useRevealAnimation) {
+ containerView.setBackgroundDrawable(shadowDrawable);
+ } else {
+ containerView.setBackgroundDrawable(null);
+ }
+ int left = useRevealAnimation && Build.VERSION.SDK_INT <= 19 ? 0 : backgroundPaddingLeft;
+ int top = useRevealAnimation && Build.VERSION.SDK_INT <= 19 ? 0 : backgroundPaddingTop;
+ containerView.setPadding(left, (applyTopPaddings ? AndroidUtilities.dp(8) : 0) + top, left, (applyTopPaddings ? AndroidUtilities.dp(isGrid ? 16 : 8) : 0));
+ if (Build.VERSION.SDK_INT < 21) {
+ startOpenAnimation();
+ }
+ }
+
+ protected void setRevealRadius(float radius) {
+ revealRadius = radius;
+ delegate.onRevealAnimationProgress(!dismissed, radius, revealX, revealY);
+ if (Build.VERSION.SDK_INT <= 19) {
+ containerView.invalidate();
+ }
+ }
+
+ protected float getRevealRadius() {
+ return revealRadius;
+ }
+
+ @SuppressLint("NewApi")
+ private void startRevealAnimation(final boolean open) {
+
+ if (open) {
+ backgroundDrawable.setAlpha(0);
+ containerView.setVisibility(View.VISIBLE);
+ } else {
+ backgroundDrawable.setAlpha(51);
+ }
+ ViewProxy.setTranslationY(containerView, 0);
+
+ AnimatorSet animatorSet = new AnimatorSet();
+
+ View view = delegate.getRevealView();
+ if (view.getVisibility() == View.VISIBLE && ((ViewGroup) view.getParent()).getVisibility() == View.VISIBLE) {
+ final int coords[] = new int[2];
+ view.getLocationInWindow(coords);
+ float top;
+ if (Build.VERSION.SDK_INT <= 19) {
+ top = AndroidUtilities.displaySize.y - containerView.getMeasuredHeight() - AndroidUtilities.statusBarHeight;
+ } else {
+ top = containerView.getY();
+ }
+ revealX = coords[0] + view.getMeasuredWidth() / 2;
+ revealY = (int) (coords[1] + view.getMeasuredHeight() / 2 - top);
+ if (Build.VERSION.SDK_INT <= 19) {
+ revealY -= AndroidUtilities.statusBarHeight;
+ }
+ } else {
+ revealX = AndroidUtilities.displaySize.x / 2 + backgroundPaddingLeft;
+ revealY = (int) (AndroidUtilities.displaySize.y - containerView.getY());
+ }
+
+ int corners[][] = new int[][]{
+ {0, 0},
+ {0, containerView.getMeasuredHeight()},
+ {containerView.getMeasuredWidth(), 0},
+ {containerView.getMeasuredWidth(), containerView.getMeasuredHeight()}
+ };
+ int finalRevealRadius = 0;
+ for (int a = 0; a < 4; a++) {
+ finalRevealRadius = Math.max(finalRevealRadius, (int) Math.ceil(Math.sqrt((revealX - corners[a][0]) * (revealX - corners[a][0]) + (revealY - corners[a][1]) * (revealY - corners[a][1]))));
+ }
+
+ ArrayList animators = new ArrayList<>(3);
+ animators.add(ObjectAnimator.ofFloat(this, "revealRadius", open ? 0 : finalRevealRadius, open ? finalRevealRadius : 0));
+ animators.add(ObjectAnimator.ofInt(backgroundDrawable, "alpha", open ? 51 : 0));
+ if (Build.VERSION.SDK_INT >= 21) {
+ containerView.setElevation(AndroidUtilities.dp(10));
+ animators.add(ViewAnimationUtils.createCircularReveal(containerView, revealX <= containerView.getMeasuredWidth() ? revealX : containerView.getMeasuredWidth(), revealY, open ? 0 : finalRevealRadius, open ? finalRevealRadius : 0));
+ animatorSet.setDuration(300);
+ } else {
+ if (!open) {
+ animatorSet.setDuration(200);
+ containerView.setPivotX(revealX <= containerView.getMeasuredWidth() ? revealX : containerView.getMeasuredWidth());
+ containerView.setPivotY(revealY);
+ animators.add(ObjectAnimator.ofFloat(containerView, "scaleX", 0.0f));
+ animators.add(ObjectAnimator.ofFloat(containerView, "scaleY", 0.0f));
+ animators.add(ObjectAnimator.ofFloat(containerView, "alpha", 0.0f));
+ } else {
+ animatorSet.setDuration(250);
+ containerView.setScaleX(1);
+ containerView.setScaleY(1);
+ containerView.setAlpha(1);
+ if (Build.VERSION.SDK_INT <= 19) {
+ animatorSet.setStartDelay(20);
+ }
}
}
- AndroidUtilities.runOnUIThread(new Runnable() {
+ animatorSet.playTogether(animators);
+ animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
- public void run() {
- long newTime = System.nanoTime() / 1000000;
- long dt = newTime - lastFrameTime;
- FileLog.e("tmessages", "dt = " + dt);
- if (dt > 16) {
- dt = 16;
- }
- lastFrameTime = newTime;
- animationProgress += dt / 200.0f;
- if (animationProgress > 1.0f) {
- animationProgress = 1.0f;
+ public void onAnimationStart(Animator animation) {
+ if (delegate != null) {
+ delegate.onRevealAnimationStart(open);
}
+ }
- if (open) {
- float interpolated = decelerateInterpolator.getInterpolation(animationProgress);
- ViewProxy.setTranslationY(linearLayout, linearLayout.getHeight() * (1.0f - interpolated));
- backgroundDrawable.setAlpha((int) (51 * interpolated));
- } else {
- float interpolated = accelerateInterpolator.getInterpolation(animationProgress);
- ViewProxy.setTranslationY(linearLayout, linearLayout.getHeight() * interpolated);
- backgroundDrawable.setAlpha((int) (51 * (1.0f - interpolated)));
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (delegate != null) {
+ delegate.onRevealAnimationEnd(open);
}
- if (animationProgress < 1) {
- startLayoutAnimation(open, false);
- } else {
- if (open && delegate != null) {
- delegate.onOpenAnimationEnd();
+ containerView.invalidate();
+ if (Build.VERSION.SDK_INT >= 11) {
+ container.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ if (!open) {
+ containerView.setVisibility(View.INVISIBLE);
+ try {
+ BottomSheet.super.dismiss();
+ } catch (Exception e) {
+ FileLog.e("tmessages", e);
}
}
}
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ onAnimationEnd(animation);
+ }
});
+ animatorSet.start();
+ }
+
+ private void startOpenAnimation() {
+ if (Build.VERSION.SDK_INT >= 20) {
+ container.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ }
+ if (containerView.getMeasuredHeight() == 0) {
+ containerView.measure(View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.x, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(AndroidUtilities.displaySize.y, View.MeasureSpec.AT_MOST));
+ }
+ if (useRevealAnimation) {
+ startRevealAnimation(true);
+ } else {
+ ViewProxy.setTranslationY(containerView, containerView.getMeasuredHeight());
+ backgroundDrawable.setAlpha(0);
+ AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy();
+ animatorSetProxy.playTogether(
+ ObjectAnimatorProxy.ofFloat(containerView, "translationY", 0),
+ ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 51));
+ animatorSetProxy.setDuration(200);
+ animatorSetProxy.setStartDelay(20);
+ animatorSetProxy.setInterpolator(new DecelerateInterpolator());
+ animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() {
+ @Override
+ public void onAnimationEnd(Object animation) {
+ if (delegate != null) {
+ delegate.onOpenAnimationEnd();
+ }
+ if (Build.VERSION.SDK_INT >= 11) {
+ container.setLayerType(View.LAYER_TYPE_NONE, null);
+ }
+ }
+ });
+ animatorSetProxy.start();
+ }
}
public void setDelegate(BottomSheetDelegate delegate) {
@@ -382,7 +559,7 @@ public class BottomSheet extends Dialog {
}
public LinearLayout getSheetContainer() {
- return linearLayout;
+ return containerView;
}
public int getTag() {
@@ -397,13 +574,14 @@ public class BottomSheet extends Dialog {
cell.textView.setText(text);
}
- private void dismissWithButtonClick(final int item) {
+ public void dismissWithButtonClick(final int item) {
if (dismissed) {
return;
}
+ dismissed = true;
AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy();
animatorSetProxy.playTogether(
- ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", linearLayout.getHeight() + AndroidUtilities.dp(10)),
+ ObjectAnimatorProxy.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)),
ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 0)
);
animatorSetProxy.setDuration(180);
@@ -440,34 +618,38 @@ public class BottomSheet extends Dialog {
return;
}
dismissed = true;
- AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy();
- animatorSetProxy.playTogether(
- ObjectAnimatorProxy.ofFloat(linearLayout, "translationY", linearLayout.getHeight() + AndroidUtilities.dp(10)),
- ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 0)
- );
- animatorSetProxy.setDuration(180);
- animatorSetProxy.setInterpolator(new AccelerateInterpolator());
- animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() {
- @Override
- public void onAnimationEnd(Object animation) {
- AndroidUtilities.runOnUIThread(new Runnable() {
- @Override
- public void run() {
- try {
- BottomSheet.super.dismiss();
- } catch (Exception e) {
- FileLog.e("tmessages", e);
+ if (useRevealAnimation) {
+ startRevealAnimation(false);
+ } else {
+ AnimatorSetProxy animatorSetProxy = new AnimatorSetProxy();
+ animatorSetProxy.playTogether(
+ ObjectAnimatorProxy.ofFloat(containerView, "translationY", containerView.getMeasuredHeight() + AndroidUtilities.dp(10)),
+ ObjectAnimatorProxy.ofInt(backgroundDrawable, "alpha", 0)
+ );
+ animatorSetProxy.setDuration(180);
+ animatorSetProxy.setInterpolator(new AccelerateInterpolator());
+ animatorSetProxy.addListener(new AnimatorListenerAdapterProxy() {
+ @Override
+ public void onAnimationEnd(Object animation) {
+ AndroidUtilities.runOnUIThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ BottomSheet.super.dismiss();
+ } catch (Exception e) {
+ FileLog.e("tmessages", e);
+ }
}
- }
- });
- }
+ });
+ }
- @Override
- public void onAnimationCancel(Object animation) {
- onAnimationEnd(animation);
- }
- });
- animatorSetProxy.start();
+ @Override
+ public void onAnimationCancel(Object animation) {
+ onAnimationEnd(animation);
+ }
+ });
+ animatorSetProxy.start();
+ }
}
public static class Builder {
@@ -515,10 +697,10 @@ public class BottomSheet extends Dialog {
return this;
}
- public Builder setRevealAnimation(int x, int y) {
- bottomSheet.revealX = x;
- bottomSheet.revealY = y;
- bottomSheet.useRevealAnimation = true;
+ public Builder setUseRevealAnimation() {
+ if (Build.VERSION.SDK_INT >= 18 && !AndroidUtilities.isTablet()) {
+ bottomSheet.useRevealAnimation = true;
+ }
return this;
}
@@ -532,8 +714,13 @@ public class BottomSheet extends Dialog {
return this;
}
- public BottomSheet setOverrideTabletWidth(boolean value) {
- bottomSheet.overrideTabletWidth = value;
+ public Builder setApplyTopPaddings(boolean value) {
+ bottomSheet.applyTopPaddings = value;
+ return this;
+ }
+
+ public BottomSheet setUseFullWidth(boolean value) {
+ bottomSheet.fullWidth = value;
return bottomSheet;
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java
index ce43585cc..d9c26a0a2 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ActionBar/DrawerLayoutContainer.java
@@ -383,7 +383,6 @@ public class DrawerLayoutContainer extends FrameLayout {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
inLayout = true;
- final int width = r - l;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = getChildAt(i);
@@ -416,8 +415,6 @@ public class DrawerLayoutContainer extends FrameLayout {
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java
index 8c39b844a..8efc34296 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/CountrySearchAdapter.java
@@ -72,7 +72,6 @@ public class CountrySearchAdapter extends BaseFragmentAdapter {
updateSearchResults(new ArrayList());
return;
}
- long time = System.currentTimeMillis();
ArrayList resultArray = new ArrayList<>();
String n = query.substring(0, 1);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java
index d1f497b7b..102a170fc 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/PhotoAttachAdapter.java
@@ -19,7 +19,7 @@ import org.telegram.ui.Cells.PhotoAttachPhotoCell;
import java.util.HashMap;
-public class PhotoAttachAdapter extends RecyclerView.Adapter implements NotificationCenter.NotificationCenterDelegate {
+public class PhotoAttachAdapter extends RecyclerView.Adapter {
private Context mContext;
private PhotoAttachAdapterDelegate delegate;
@@ -38,14 +38,6 @@ public class PhotoAttachAdapter extends RecyclerView.Adapter implements Notifica
public PhotoAttachAdapter(Context context) {
mContext = context;
- NotificationCenter.getInstance().addObserver(this, NotificationCenter.albumsDidLoaded);
- if (MediaController.allPhotosAlbumEntry == null) {
- MediaController.loadGalleryPhotosAlbums(0);
- }
- }
-
- public void onDestroy() {
- NotificationCenter.getInstance().removeObserver(this, NotificationCenter.albumsDidLoaded);
}
public void clearSelectedPhotos() {
@@ -64,13 +56,6 @@ public class PhotoAttachAdapter extends RecyclerView.Adapter implements Notifica
delegate = photoAttachAdapterDelegate;
}
- @Override
- public void didReceivedNotification(int id, Object... args) {
- if (id == NotificationCenter.albumsDidLoaded) {
- notifyDataSetChanged();
- }
- }
-
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
//if (position != 0) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java
index 00206cf9b..28864d911 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Adapters/StickersAdapter.java
@@ -87,7 +87,7 @@ public class StickersAdapter extends RecyclerView.Adapter implements Notificatio
}
public void loadStikersForEmoji(CharSequence emoji) {
- boolean search = emoji != null && emoji.length() != 0 && emoji.length() <= 2;
+ boolean search = emoji != null && emoji.length() > 0 && emoji.length() <= 4;
if (search) {
lastSticker = emoji.toString();
HashMap> allStickers = StickersQuery.getAllStickers();
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java
new file mode 100644
index 000000000..99ff51b60
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/ui/AudioPlayerActivity.java
@@ -0,0 +1,464 @@
+/*
+ * This is the source code of Telegram for Android v. 2.x.x.
+ * It is licensed under GNU GPL v. 2 or later.
+ * You should have received a copy of the license in this archive (see LICENSE).
+ *
+ * Copyright Nikolai Kudashov, 2013-2015.
+ */
+
+package org.telegram.ui;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.telegram.android.AndroidUtilities;
+import org.telegram.android.ImageLoader;
+import org.telegram.android.MediaController;
+import org.telegram.android.MessageObject;
+import org.telegram.android.NotificationCenter;
+import org.telegram.android.audioinfo.AudioInfo;
+import org.telegram.messenger.FileLoader;
+import org.telegram.messenger.R;
+import org.telegram.messenger.TLRPC;
+import org.telegram.ui.ActionBar.ActionBar;
+import org.telegram.ui.ActionBar.BaseFragment;
+import org.telegram.ui.Components.LayoutHelper;
+import org.telegram.ui.Components.LineProgressView;
+
+import java.io.File;
+
+public class AudioPlayerActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, MediaController.FileDownloadProgressListener {
+
+ private MessageObject lastMessageObject;
+ private ImageView placeholder;
+ private ImageView playButton;
+ private ImageView nextButton;
+ private ImageView prevButton;
+ private ImageView shuffleButton;
+ private LineProgressView progressView;
+ private ImageView repeatButton;
+ private ImageView[] buttons = new ImageView[5];
+ private TextView durationTextView;
+ private TextView timeTextView;
+ private SeekBarView seekBarView;
+
+ private int TAG;
+
+ private String lastTimeString;
+
+ private class SeekBarView extends FrameLayout {
+
+ private Paint innerPaint1;
+ private Paint outerPaint1;
+ private int thumbWidth;
+ private int thumbHeight;
+ public int thumbX = 0;
+ public int thumbDX = 0;
+ private boolean pressed = false;
+
+ public SeekBarView(Context context) {
+ super(context);
+ setWillNotDraw(false);
+ innerPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
+ innerPaint1.setColor(0x19000000);
+
+ outerPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
+ outerPaint1.setColor(0xff23afef);
+
+ thumbWidth = AndroidUtilities.dp(24);
+ thumbHeight = AndroidUtilities.dp(24);
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
+ return onTouch(ev);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ return onTouch(event);
+ }
+
+ boolean onTouch(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ getParent().requestDisallowInterceptTouchEvent(true);
+ int additionWidth = (getMeasuredHeight() - thumbWidth) / 2;
+ if (thumbX - additionWidth <= ev.getX() && ev.getX() <= thumbX + thumbWidth + additionWidth && ev.getY() >= 0 && ev.getY() <= getMeasuredHeight()) {
+ pressed = true;
+ thumbDX = (int)(ev.getX() - thumbX);
+ invalidate();
+ return true;
+ }
+ } else if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) {
+ if (pressed) {
+ if (ev.getAction() == MotionEvent.ACTION_UP) {
+ onSeekBarDrag((float) thumbX / (float) (getMeasuredWidth() - thumbWidth));
+ }
+ pressed = false;
+ invalidate();
+ return true;
+ }
+ } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
+ if (pressed) {
+ thumbX = (int)(ev.getX() - thumbDX);
+ if (thumbX < 0) {
+ thumbX = 0;
+ } else if (thumbX > getMeasuredWidth() - thumbWidth) {
+ thumbX = getMeasuredWidth() - thumbWidth;
+ }
+ invalidate();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void setProgress(float progress) {
+ int newThumbX = (int)Math.ceil((getMeasuredWidth() - thumbWidth) * progress);
+ if (thumbX != newThumbX) {
+ thumbX = newThumbX;
+ if (thumbX < 0) {
+ thumbX = 0;
+ } else if (thumbX > getMeasuredWidth() - thumbWidth) {
+ thumbX = getMeasuredWidth() - thumbWidth;
+ }
+ invalidate();
+ }
+ }
+
+ public boolean isDragging() {
+ return pressed;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ int y = (getMeasuredHeight() - thumbHeight) / 2;
+ canvas.drawRect(thumbWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), getMeasuredWidth() - thumbWidth / 2, getMeasuredHeight() / 2 + AndroidUtilities.dp(1), innerPaint1);
+ canvas.drawRect(thumbWidth / 2, getMeasuredHeight() / 2 - AndroidUtilities.dp(1), thumbWidth / 2 + thumbX, getMeasuredHeight() / 2 + AndroidUtilities.dp(1), outerPaint1);
+ canvas.drawCircle(thumbX + thumbWidth / 2, y + thumbHeight / 2, AndroidUtilities.dp(pressed ? 8 : 6), outerPaint1);
+ }
+ }
+
+ @Override
+ public boolean onFragmentCreate() {
+ TAG = MediaController.getInstance().generateObserverTag();
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset);
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged);
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidStarted);
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioProgressDidChanged);
+ return super.onFragmentCreate();
+ }
+
+ @Override
+ public void onFragmentDestroy() {
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset);
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged);
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidStarted);
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioProgressDidChanged);
+ MediaController.getInstance().removeLoadingFileObserver(this);
+ super.onFragmentDestroy();
+ }
+
+ @Override
+ public View createView(Context context) {
+ FrameLayout frameLayout = new FrameLayout(context);
+ frameLayout.setBackgroundColor(0xfff0f0f0);
+ frameLayout.setOnTouchListener(new View.OnTouchListener() {
+ @Override
+ public boolean onTouch(View v, MotionEvent event) {
+ return true;
+ }
+ });
+ fragmentView = frameLayout;
+
+ actionBar.setBackgroundColor(0xffffffff);
+ actionBar.setBackButtonImage(R.drawable.pl_back);
+ actionBar.setItemsBackground(R.drawable.bar_selector_audio);
+ if (!AndroidUtilities.isTablet()) {
+ actionBar.showActionModeTop();
+ }
+ actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
+ @Override
+ public void onItemClick(int id) {
+ if (id == -1) {
+ finishFragment();
+ }
+ }
+ });
+
+ placeholder = new ImageView(context);
+ frameLayout.addView(placeholder, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 0, 0, 66));
+
+ View shadow = new View(context);
+ shadow.setBackgroundResource(R.drawable.header_shadow_reverse);
+ frameLayout.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 96));
+
+ FrameLayout seekBarContainer = new FrameLayout(context);
+ seekBarContainer.setBackgroundColor(0xe5ffffff);
+ frameLayout.addView(seekBarContainer, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 30, Gravity.BOTTOM | Gravity.LEFT, 0, 0, 0, 66));
+
+ timeTextView = new TextView(context);
+ timeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
+ timeTextView.setTextColor(0xff19a7e8);
+ timeTextView.setGravity(Gravity.CENTER);
+ timeTextView.setText("0:00");
+ seekBarContainer.addView(timeTextView, LayoutHelper.createFrame(44, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT));
+
+ durationTextView = new TextView(context);
+ durationTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12);
+ durationTextView.setTextColor(0xff8a8a8a);
+ durationTextView.setGravity(Gravity.CENTER);
+ durationTextView.setText("3:00");
+ seekBarContainer.addView(durationTextView, LayoutHelper.createFrame(44, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.RIGHT));
+
+ seekBarView = new SeekBarView(context);
+ seekBarContainer.addView(seekBarView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 32, 0, 32, 0));
+
+ progressView = new LineProgressView(context);
+ progressView.setVisibility(View.INVISIBLE);
+ progressView.setBackgroundColor(0x19000000);
+ progressView.setProgressColor(0xff23afef);
+ seekBarContainer.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 2, Gravity.CENTER_VERTICAL | Gravity.LEFT, 44, 0, 44, 0));
+
+ FrameLayout bottomView = new FrameLayout(context) {
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ int dist = ((right - left) - AndroidUtilities.dp(30 + 48 * 5)) / 4;
+ for (int a = 0; a < 5; a++) {
+ int l = AndroidUtilities.dp(15 + 48 * a) + dist * a;
+ int t = AndroidUtilities.dp(9);
+ buttons[a].layout(l, t, l + buttons[a].getMeasuredWidth(), t + buttons[a].getMeasuredHeight());
+ }
+ }
+ };
+ bottomView.setBackgroundColor(0xffffffff);
+ frameLayout.addView(bottomView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 66, Gravity.BOTTOM | Gravity.LEFT));
+
+ buttons[0] = repeatButton = new ImageView(context);
+ repeatButton.setScaleType(ImageView.ScaleType.CENTER);
+ bottomView.addView(repeatButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
+ repeatButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ MediaController.getInstance().toggleRepeatMode();
+ updateRepeatButton();
+ }
+ });
+
+ buttons[1] = prevButton = new ImageView(context);
+ prevButton.setScaleType(ImageView.ScaleType.CENTER);
+ prevButton.setImageResource(R.drawable.player_prev_states);
+ bottomView.addView(prevButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
+ prevButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ MediaController.getInstance().playPreviousMessage();
+ }
+ });
+
+ buttons[2] = playButton = new ImageView(context);
+ playButton.setScaleType(ImageView.ScaleType.CENTER);
+ playButton.setImageResource(R.drawable.player_play_states);
+ bottomView.addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
+ playButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (MediaController.getInstance().isDownloadingCurrentMessage()) {
+ return;
+ }
+ if (MediaController.getInstance().isAudioPaused()) {
+ MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject());
+ } else {
+ MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject());
+ }
+ }
+ });
+
+ buttons[3] = nextButton = new ImageView(context);
+ nextButton.setScaleType(ImageView.ScaleType.CENTER);
+ nextButton.setImageResource(R.drawable.player_next_states);
+ bottomView.addView(nextButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
+ nextButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ MediaController.getInstance().playNextMessage();
+ }
+ });
+
+ buttons[4] = shuffleButton = new ImageView(context);
+ shuffleButton.setScaleType(ImageView.ScaleType.CENTER);
+ bottomView.addView(shuffleButton, LayoutHelper.createFrame(48, 48, Gravity.LEFT | Gravity.TOP));
+ shuffleButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ MediaController.getInstance().toggleShuffleMusic();
+ updateShuffleButton();
+ }
+ });
+
+ updateTitle(false);
+ updateRepeatButton();
+ updateShuffleButton();
+
+ return frameLayout;
+ }
+
+ @Override
+ public void didReceivedNotification(int id, Object... args) {
+ if (id == NotificationCenter.audioDidStarted || id == NotificationCenter.audioPlayStateChanged || id == NotificationCenter.audioDidReset) {
+ updateTitle(id == NotificationCenter.audioDidReset && (Boolean) args[1]);
+ } else if (id == NotificationCenter.audioProgressDidChanged) {
+ MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
+
+ if (messageObject.isMusic()) {
+ updateProgress(messageObject);
+ }
+ }
+ }
+
+ @Override
+ public void onFailedDownload(String fileName) {
+
+ }
+
+ @Override
+ public void onSuccessDownload(String fileName) {
+
+ }
+
+ @Override
+ public void onProgressDownload(String fileName, float progress) {
+ progressView.setProgress(progress, true);
+ }
+
+ @Override
+ public void onProgressUpload(String fileName, float progress, boolean isEncrypted) {
+
+ }
+
+ @Override
+ public int getObserverTag() {
+ return TAG;
+ }
+
+ private void onSeekBarDrag(float progress) {
+ MediaController.getInstance().seekToProgress(MediaController.getInstance().getPlayingMessageObject(), progress);
+ }
+
+ private void updateShuffleButton() {
+ if (MediaController.getInstance().isShuffleMusic()) {
+ shuffleButton.setImageResource(R.drawable.pl_shuffle_active);
+ } else {
+ shuffleButton.setImageResource(R.drawable.pl_shuffle);
+ }
+ }
+
+ private void updateRepeatButton() {
+ int mode = MediaController.getInstance().getRepeatMode();
+ if (mode == 0) {
+ repeatButton.setImageResource(R.drawable.pl_repeat);
+ } else if (mode == 1) {
+ repeatButton.setImageResource(R.drawable.pl_repeat_active);
+ } else if (mode == 2) {
+ repeatButton.setImageResource(R.drawable.pl_repeat1_active);
+ }
+ }
+
+ private void updateProgress(MessageObject messageObject) {
+ if (seekBarView != null) {
+ if (!seekBarView.isDragging()) {
+ seekBarView.setProgress(messageObject.audioProgress);
+ }
+ String timeString = String.format("%d:%02d", messageObject.audioProgressSec / 60, messageObject.audioProgressSec % 60);
+ if (lastTimeString == null || lastTimeString != null && !lastTimeString.equals(timeString)) {
+ lastTimeString = timeString;
+ timeTextView.setText(timeString);
+ }
+ }
+ }
+
+ private void checkIfMusicDownloaded(MessageObject messageObject) {
+ File cacheFile = null;
+ if (messageObject.messageOwner.attachPath != null && messageObject.messageOwner.attachPath.length() > 0) {
+ cacheFile = new File(messageObject.messageOwner.attachPath);
+ if(!cacheFile.exists()) {
+ cacheFile = null;
+ }
+ }
+ if (cacheFile == null) {
+ cacheFile = FileLoader.getPathToMessage(messageObject.messageOwner);
+ }
+ if (!cacheFile.exists()) {
+ String fileName = messageObject.getFileName();
+ MediaController.getInstance().addLoadingFileObserver(fileName, this);
+ Float progress = ImageLoader.getInstance().getFileProgress(fileName);
+ progressView.setProgress(progress != null ? progress : 0, false);
+ progressView.setVisibility(View.VISIBLE);
+ seekBarView.setVisibility(View.INVISIBLE);
+ playButton.setEnabled(false);
+ } else {
+ MediaController.getInstance().removeLoadingFileObserver(this);
+ progressView.setVisibility(View.INVISIBLE);
+ seekBarView.setVisibility(View.VISIBLE);
+ playButton.setEnabled(true);
+ }
+ }
+
+ private void updateTitle(boolean shutdown) {
+ MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
+ if (messageObject == null && shutdown || messageObject != null && !messageObject.isMusic()) {
+ if (!parentLayout.fragmentsStack.isEmpty() && parentLayout.fragmentsStack.get(parentLayout.fragmentsStack.size() - 1) == this) {
+ finishFragment();
+ } else {
+ removeSelfFromStack();
+ }
+ } else {
+ if (messageObject == null) {
+ return;
+ }
+ checkIfMusicDownloaded(messageObject);
+ updateProgress(messageObject);
+
+ if (MediaController.getInstance().isAudioPaused()) {
+ playButton.setImageResource(R.drawable.player_play_states);
+ } else {
+ playButton.setImageResource(R.drawable.player_pause_states);
+ }
+ if (actionBar != null) {
+ actionBar.setTitle(messageObject.getMusicTitle());
+ actionBar.getTitleTextView().setTextColor(0xff212121);
+ actionBar.setSubtitle(messageObject.getMusicAuthor());
+ actionBar.getSubTitleTextView().setTextColor(0xff8a8a8a);
+ }
+ AudioInfo audioInfo = MediaController.getInstance().getAudioInfo();
+ if (audioInfo != null && audioInfo.getCover() != null) {
+ placeholder.setImageBitmap(audioInfo.getCover());
+ placeholder.setPadding(0, 0, 0, 0);
+ placeholder.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ } else {
+ placeholder.setImageResource(R.drawable.nocover);
+ placeholder.setPadding(0, 0, 0, AndroidUtilities.dp(30));
+ placeholder.setScaleType(ImageView.ScaleType.CENTER);
+ }
+
+ if (durationTextView != null) {
+ int duration = 0;
+ for (TLRPC.DocumentAttribute attribute : messageObject.messageOwner.media.document.attributes) {
+ if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
+ duration = attribute.duration;
+ break;
+ }
+ }
+ durationTextView.setText(duration != 0 ? String.format("%d:%02d", duration / 60, duration % 60) : "-:--");
+ }
+ }
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java
new file mode 100644
index 000000000..a663665bb
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/ui/AudioSelectActivity.java
@@ -0,0 +1,344 @@
+/*
+ * This is the source code of Telegram for Android v. 2.x.x.
+ * It is licensed under GNU GPL v. 2 or later.
+ * You should have received a copy of the license in this archive (see LICENSE).
+ *
+ * Copyright Nikolai Kudashov, 2013-2015.
+ */
+
+package org.telegram.ui;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.os.Build;
+import android.provider.MediaStore;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.FrameLayout;
+import android.widget.ListView;
+
+import org.telegram.android.AndroidUtilities;
+import org.telegram.android.LocaleController;
+import org.telegram.android.MediaController;
+import org.telegram.android.MessageObject;
+import org.telegram.android.NotificationCenter;
+import org.telegram.messenger.ApplicationLoader;
+import org.telegram.messenger.FileLoader;
+import org.telegram.messenger.FileLog;
+import org.telegram.messenger.R;
+import org.telegram.messenger.TLRPC;
+import org.telegram.messenger.UserConfig;
+import org.telegram.messenger.Utilities;
+import org.telegram.ui.ActionBar.ActionBar;
+import org.telegram.ui.ActionBar.BaseFragment;
+import org.telegram.ui.Adapters.BaseFragmentAdapter;
+import org.telegram.ui.Cells.AudioCell;
+import org.telegram.ui.Components.EmptyTextProgressView;
+import org.telegram.ui.Components.LayoutHelper;
+import org.telegram.ui.Components.PickerBottomLayout;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class AudioSelectActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
+
+ private ListAdapter listViewAdapter;
+ private EmptyTextProgressView progressView;
+ private PickerBottomLayout bottomLayout;
+
+ private boolean loadingAudio;
+
+ private ArrayList audioEntries = new ArrayList<>();
+ private HashMap selectedAudios = new HashMap<>();
+
+ private AudioSelectActivityDelegate delegate;
+
+ private MessageObject playingAudio;
+
+ public interface AudioSelectActivityDelegate {
+ void didSelectAudio(ArrayList audios);
+ }
+
+ @Override
+ public boolean onFragmentCreate() {
+ super.onFragmentCreate();
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.closeChats);
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset);
+ loadAudio();
+ return true;
+ }
+
+ @Override
+ public void onFragmentDestroy() {
+ super.onFragmentDestroy();
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.closeChats);
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset);
+ if (playingAudio != null && MediaController.getInstance().isPlayingAudio(playingAudio)) {
+ MediaController.getInstance().clenupPlayer(true, true);
+ }
+ }
+
+ @Override
+ public View createView(Context context) {
+ actionBar.setBackButtonImage(R.drawable.ic_ab_back);
+ actionBar.setAllowOverlayTitle(true);
+ actionBar.setTitle(LocaleController.getString("AttachAudio", R.string.AttachAudio));
+ actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
+ @Override
+ public void onItemClick(int id) {
+ if (id == -1) {
+ finishFragment();
+ }
+ }
+ });
+
+ fragmentView = new FrameLayout(context);
+ FrameLayout frameLayout = (FrameLayout) fragmentView;
+
+ progressView = new EmptyTextProgressView(context);
+ progressView.setText(LocaleController.getString("NoAudio", R.string.NoAudio));
+ frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
+
+ ListView listView = new ListView(context);
+ listView.setEmptyView(progressView);
+ listView.setVerticalScrollBarEnabled(false);
+ listView.setDivider(null);
+ listView.setDividerHeight(0);
+ listView.setAdapter(listViewAdapter = new ListAdapter(context));
+ if (Build.VERSION.SDK_INT >= 11) {
+ listView.setVerticalScrollbarPosition(LocaleController.isRTL ? ListView.SCROLLBAR_POSITION_LEFT : ListView.SCROLLBAR_POSITION_RIGHT);
+ }
+ frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 0, 0, 0, 48));
+
+ listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
+ AudioCell audioCell = (AudioCell) view;
+ MediaController.AudioEntry audioEntry = audioCell.getAudioEntry();
+ if (selectedAudios.containsKey(audioEntry.id)) {
+ selectedAudios.remove(audioEntry.id);
+ audioCell.setChecked(false);
+ } else {
+ selectedAudios.put(audioEntry.id, audioEntry);
+ audioCell.setChecked(true);
+ }
+ updateBottomLayoutCount();
+ }
+ });
+
+ bottomLayout = new PickerBottomLayout(context, false);
+ frameLayout.addView(bottomLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM));
+ bottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ finishFragment();
+ }
+ });
+ bottomLayout.doneButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (delegate != null) {
+ ArrayList audios = new ArrayList<>();
+ for (HashMap.Entry entry : selectedAudios.entrySet()) {
+ audios.add(entry.getValue().messageObject);
+ }
+ delegate.didSelectAudio(audios);
+ }
+ finishFragment();
+ }
+ });
+
+ View shadow = new View(context);
+ shadow.setBackgroundResource(R.drawable.header_shadow_reverse);
+ frameLayout.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.LEFT | Gravity.BOTTOM, 0, 0, 0, 48));
+
+ if (loadingAudio) {
+ progressView.showProgress();
+ } else {
+ progressView.showTextView();
+ }
+ updateBottomLayoutCount();
+ return fragmentView;
+ }
+
+ @Override
+ public void didReceivedNotification(int id, Object... args) {
+ if (id == NotificationCenter.closeChats) {
+ removeSelfFromStack();
+ } else if (id == NotificationCenter.audioDidReset) {
+ if (listViewAdapter != null) {
+ listViewAdapter.notifyDataSetChanged();
+ }
+ }
+ }
+
+ private void updateBottomLayoutCount() {
+ bottomLayout.updateSelectedCount(selectedAudios.size(), true);
+ }
+
+ public void setDelegate(AudioSelectActivityDelegate audioSelectActivityDelegate) {
+ delegate = audioSelectActivityDelegate;
+ }
+
+ private void loadAudio() {
+ loadingAudio = true;
+ if (progressView != null) {
+ progressView.showProgress();
+ }
+ Utilities.globalQueue.postRunnable(new Runnable() {
+ @Override
+ public void run() {
+ String[] projection = {
+ MediaStore.Audio.Media._ID,
+ MediaStore.Audio.Media.ARTIST,
+ MediaStore.Audio.Media.TITLE,
+ MediaStore.Audio.Media.DATA,
+ MediaStore.Audio.Media.DURATION,
+ MediaStore.Audio.Media.ALBUM
+ };
+
+ final ArrayList newAudioEntries = new ArrayList<>();
+ Cursor cursor = null;
+ try {
+ cursor = ApplicationLoader.applicationContext.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, projection, MediaStore.Audio.Media.IS_MUSIC + " != 0", null, null);
+ int id = -2000000000;
+ while (cursor.moveToNext()) {
+ MediaController.AudioEntry audioEntry = new MediaController.AudioEntry();
+ audioEntry.id = cursor.getInt(0);
+ audioEntry.author = cursor.getString(1);
+ audioEntry.title = cursor.getString(2);
+ audioEntry.path = cursor.getString(3);
+ audioEntry.duration = (int) (cursor.getLong(4) / 1000);
+ audioEntry.genre = cursor.getString(5);
+
+ File file = new File(audioEntry.path);
+
+ TLRPC.TL_message message = new TLRPC.TL_message();
+ message.flags = TLRPC.MESSAGE_FLAG_OUT;
+ message.id = id;
+ message.to_id = new TLRPC.TL_peerUser();
+ message.to_id.user_id = message.from_id = UserConfig.getClientUserId();
+ message.date = (int) (System.currentTimeMillis() / 1000);
+ message.message = "-1";
+ message.attachPath = audioEntry.path;
+ message.media = new TLRPC.TL_messageMediaDocument();
+ message.media.document = new TLRPC.TL_document();
+
+ String ext = FileLoader.getFileExtension(file);
+
+ message.media.document.id = 0;
+ message.media.document.access_hash = 0;
+ message.media.document.date = message.date;
+ message.media.document.mime_type = "audio/" + (ext.length() > 0 ? ext : "mp3");
+ message.media.document.size = (int) file.length();
+ message.media.document.thumb = new TLRPC.TL_photoSizeEmpty();
+ message.media.document.thumb.type = "s";
+ message.media.document.dc_id = 0;
+
+ TLRPC.TL_documentAttributeAudio attributeAudio = new TLRPC.TL_documentAttributeAudio();
+ attributeAudio.duration = audioEntry.duration;
+ attributeAudio.title = audioEntry.title;
+ attributeAudio.performer = audioEntry.author;
+ message.media.document.attributes.add(attributeAudio);
+
+ TLRPC.TL_documentAttributeFilename fileName = new TLRPC.TL_documentAttributeFilename();
+ fileName.file_name = file.getName();
+ message.media.document.attributes.add(fileName);
+
+ audioEntry.messageObject = new MessageObject(message, null, false);
+
+ newAudioEntries.add(audioEntry);
+ id--;
+ }
+ } catch (Exception e) {
+ FileLog.e("tmessages", e);
+ } finally {
+ if (cursor != null) {
+ cursor.close();
+ }
+ }
+ AndroidUtilities.runOnUIThread(new Runnable() {
+ @Override
+ public void run() {
+ audioEntries = newAudioEntries;
+ progressView.showTextView();
+ listViewAdapter.notifyDataSetChanged();
+ }
+ });
+ }
+ });
+ }
+
+ private class ListAdapter extends BaseFragmentAdapter {
+ private Context mContext;
+
+ public ListAdapter(Context context) {
+ mContext = context;
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isEnabled(int i) {
+ return true;
+ }
+
+ @Override
+ public int getCount() {
+ return audioEntries.size();
+ }
+
+ @Override
+ public Object getItem(int i) {
+ return audioEntries.get(i);
+ }
+
+ @Override
+ public long getItemId(int i) {
+ return i;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return false;
+ }
+
+ @Override
+ public View getView(int i, View view, ViewGroup viewGroup) {
+ int type = getItemViewType(i);
+ if (view == null) {
+ view = new AudioCell(mContext);
+ ((AudioCell) view).setDelegate(new AudioCell.AudioCellDelegate() {
+ @Override
+ public void startedPlayingAudio(MessageObject messageObject) {
+ playingAudio = messageObject;
+ }
+ });
+ }
+ MediaController.AudioEntry audioEntry = audioEntries.get(i);
+ ((AudioCell) view).setAudio(audioEntries.get(i), i != audioEntries.size() - 1, selectedAudios.containsKey(audioEntry.id));
+ return view;
+ }
+
+ @Override
+ public int getItemViewType(int i) {
+ return 0;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return audioEntries.isEmpty();
+ }
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java
index 1c1699d13..990286990 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/BlockedUsersActivity.java
@@ -14,7 +14,6 @@ import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -65,7 +64,7 @@ public class BlockedUsersActivity extends BaseFragment implements NotificationCe
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("BlockedUsers", R.string.BlockedUsers));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java
new file mode 100644
index 000000000..d2e9b0c1f
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/AudioCell.java
@@ -0,0 +1,169 @@
+/*
+ * This is the source code of Telegram for Android v. 2.x.x.
+ * It is licensed under GNU GPL v. 2 or later.
+ * You should have received a copy of the license in this archive (see LICENSE).
+ *
+ * Copyright Nikolai Kudashov, 2013-2015.
+ */
+
+package org.telegram.ui.Cells;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.text.TextUtils;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import org.telegram.android.AndroidUtilities;
+import org.telegram.android.LocaleController;
+import org.telegram.android.MediaController;
+import org.telegram.android.MessageObject;
+import org.telegram.messenger.R;
+import org.telegram.ui.Components.CheckBox;
+import org.telegram.ui.Components.LayoutHelper;
+
+import java.util.ArrayList;
+
+public class AudioCell extends FrameLayout {
+
+ private ImageView playButton;
+ private TextView titleTextView;
+ private TextView authorTextView;
+ private TextView genreTextView;
+ private TextView timeTextView;
+ private CheckBox checkBox;
+
+ private MediaController.AudioEntry audioEntry;
+ private boolean needDivider;
+ private static Paint paint;
+
+ private AudioCellDelegate delegate;
+
+ public interface AudioCellDelegate {
+ void startedPlayingAudio(MessageObject messageObject);
+ }
+
+ public AudioCell(Context context) {
+ super(context);
+
+ if (paint == null) {
+ paint = new Paint();
+ paint.setColor(0xffd9d9d9);
+ paint.setStrokeWidth(1);
+ }
+
+ playButton = new ImageView(context);
+ playButton.setScaleType(ImageView.ScaleType.CENTER);
+ addView(playButton, LayoutHelper.createFrame(46, 46, ((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP), LocaleController.isRTL ? 0 : 13, 13, LocaleController.isRTL ? 13 : 0, 0));
+ playButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (audioEntry != null) {
+ if (MediaController.getInstance().isPlayingAudio(audioEntry.messageObject) && !MediaController.getInstance().isAudioPaused()) {
+ MediaController.getInstance().pauseAudio(audioEntry.messageObject);
+ playButton.setImageResource(R.drawable.audiosend_play);
+ } else {
+ ArrayList arrayList = new ArrayList<>();
+ arrayList.add(audioEntry.messageObject);
+ if (MediaController.getInstance().setPlaylist(arrayList, audioEntry.messageObject)) {
+ playButton.setImageResource(R.drawable.audiosend_pause);
+ if (delegate != null) {
+ delegate.startedPlayingAudio(audioEntry.messageObject);
+ }
+ }
+ }
+ }
+ }
+ });
+
+ titleTextView = new TextView(context);
+ titleTextView.setTextColor(0xff212121);
+ titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
+ titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
+ titleTextView.setLines(1);
+ titleTextView.setMaxLines(1);
+ titleTextView.setSingleLine(true);
+ titleTextView.setEllipsize(TextUtils.TruncateAt.END);
+ titleTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
+ addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 50 : 72, 7, LocaleController.isRTL ? 72 : 50, 0));
+
+ genreTextView = new TextView(context);
+ genreTextView.setTextColor(0xff8a8a8a);
+ genreTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
+ genreTextView.setLines(1);
+ genreTextView.setMaxLines(1);
+ genreTextView.setSingleLine(true);
+ genreTextView.setEllipsize(TextUtils.TruncateAt.END);
+ genreTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
+ addView(genreTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 50 : 72, 28, LocaleController.isRTL ? 72 : 50, 0));
+
+ authorTextView = new TextView(context);
+ authorTextView.setTextColor(0xff8a8a8a);
+ authorTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
+ authorTextView.setLines(1);
+ authorTextView.setMaxLines(1);
+ authorTextView.setSingleLine(true);
+ authorTextView.setEllipsize(TextUtils.TruncateAt.END);
+ authorTextView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP);
+ addView(authorTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, LocaleController.isRTL ? 50 : 72, 44, LocaleController.isRTL ? 72 : 50, 0));
+
+ timeTextView = new TextView(context);
+ timeTextView.setTextColor(0xff999999);
+ timeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
+ timeTextView.setLines(1);
+ timeTextView.setMaxLines(1);
+ timeTextView.setSingleLine(true);
+ timeTextView.setEllipsize(TextUtils.TruncateAt.END);
+ timeTextView.setGravity((LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP);
+ addView(timeTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 18 : 0, 11, LocaleController.isRTL ? 0 : 18, 0));
+
+ checkBox = new CheckBox(context, R.drawable.round_check2);
+ checkBox.setVisibility(VISIBLE);
+ checkBox.setColor(0xff29b6f7);
+ addView(checkBox, LayoutHelper.createFrame(22, 22, (LocaleController.isRTL ? Gravity.LEFT : Gravity.RIGHT) | Gravity.TOP, LocaleController.isRTL ? 18 : 0, 39, LocaleController.isRTL ? 0 : 18, 0));
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(72) + (needDivider ? 1 : 0), MeasureSpec.EXACTLY));
+ }
+
+ public void setAudio(MediaController.AudioEntry entry, boolean divider, boolean checked) {
+ audioEntry = entry;
+
+ titleTextView.setText(audioEntry.title);
+ genreTextView.setText(audioEntry.genre);
+ authorTextView.setText(audioEntry.author);
+ timeTextView.setText(String.format("%d:%02d", audioEntry.duration / 60, audioEntry.duration % 60));
+ playButton.setImageResource(MediaController.getInstance().isPlayingAudio(audioEntry.messageObject) && !MediaController.getInstance().isAudioPaused() ? R.drawable.audiosend_pause : R.drawable.audiosend_play);
+
+ needDivider = divider;
+ setWillNotDraw(!divider);
+
+ checkBox.setChecked(checked, false);
+ }
+
+ public void setChecked(boolean value) {
+ checkBox.setChecked(value, true);
+ }
+
+ public void setDelegate(AudioCellDelegate audioCellDelegate) {
+ delegate = audioCellDelegate;
+ }
+
+ public MediaController.AudioEntry getAudioEntry() {
+ return audioEntry;
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ if (needDivider) {
+ canvas.drawLine(AndroidUtilities.dp(72), getHeight() - 1, getWidth(), getHeight() - 1, paint);
+ }
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java
index 6c05ae107..32d9c6baa 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java
@@ -42,6 +42,7 @@ public class BotHelpCell extends View {
private int height;
private int textX;
private int textY;
+ private int textXOffset;
private ClickableSpan pressedLink;
private LinkPath urlPath = new LinkPath();
@@ -101,7 +102,9 @@ public class BotHelpCell extends View {
width = 0;
height = textLayout.getHeight() + AndroidUtilities.dp(4 + 18);
int count = textLayout.getLineCount();
+ textXOffset = Integer.MAX_VALUE;
for (int a = 0; a < count; a++) {
+ textXOffset = (int) Math.ceil(Math.min(textXOffset, textLayout.getLineLeft(a)));
width = (int) Math.ceil(Math.max(width, textLayout.getLineWidth(a) - textLayout.getLineLeft(a)));
}
width += AndroidUtilities.dp(4 + 18);
@@ -113,7 +116,6 @@ public class BotHelpCell extends View {
float y = event.getY();
boolean result = false;
- int side = AndroidUtilities.dp(48);
if (textLayout != null) {
if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
@@ -186,7 +188,7 @@ public class BotHelpCell extends View {
ResourceLoader.backgroundMediaDrawableIn.setBounds(x, y, width + x, height + y);
ResourceLoader.backgroundMediaDrawableIn.draw(canvas);
canvas.save();
- canvas.translate(textX = AndroidUtilities.dp(2 + 9) + x, textY = AndroidUtilities.dp(2 + 9) + y);
+ canvas.translate(textX = AndroidUtilities.dp(2 + 9) + x - textXOffset, textY = AndroidUtilities.dp(2 + 9) + y);
if (pressedLink != null) {
canvas.drawPath(urlPath, urlPaint);
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java
index 12c749222..82ab4b730 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatActionCell.java
@@ -174,8 +174,8 @@ public class ChatActionCell extends BaseCell {
final int line = textLayout.getLineForVertical((int)y);
final int off = textLayout.getOffsetForHorizontal(line, x);
final float left = textLayout.getLineLeft(line);
- if (left <= x && left + textLayout.getLineWidth(line) >= x) {
- Spannable buffer = (Spannable)currentMessageObject.messageText;
+ if (left <= x && left + textLayout.getLineWidth(line) >= x && currentMessageObject.messageText instanceof Spannable) {
+ Spannable buffer = (Spannable) currentMessageObject.messageText;
URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
if (link.length != 0) {
@@ -226,7 +226,6 @@ public class ChatActionCell extends BaseCell {
int linesCount = textLayout.getLineCount();
for (int a = 0; a < linesCount; a++) {
float lineWidth;
- float lineLeft = 0;
try {
lineWidth = textLayout.getLineWidth(a);
textHeight = (int)Math.max(textHeight, Math.ceil(textLayout.getLineBottom(a)));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java
index 1b7a9db99..77f5069e2 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatAudioCell.java
@@ -21,10 +21,11 @@ import android.view.SoundEffectConstants;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.ImageLoader;
import org.telegram.android.MessagesController;
+import org.telegram.android.SendMessagesHelper;
import org.telegram.messenger.FileLoader;
import org.telegram.android.MediaController;
import org.telegram.android.MessageObject;
-import org.telegram.ui.Components.ProgressView;
+import org.telegram.ui.Components.RadialProgress;
import org.telegram.ui.Components.ResourceLoader;
import org.telegram.ui.Components.SeekBar;
@@ -36,10 +37,10 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
private static Paint circlePaint;
private SeekBar seekBar;
- private ProgressView progressView;
private int seekBarX;
private int seekBarY;
+ private RadialProgress radialProgress;
private int buttonState = 0;
private int buttonX;
private int buttonY;
@@ -58,7 +59,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
seekBar = new SeekBar(context);
seekBar.delegate = this;
- progressView = new ProgressView();
+ radialProgress = new RadialProgress(this);
drawForwardedName = true;
if (timePaint == null) {
@@ -78,7 +79,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
- updateButtonState();
+ updateButtonState(false);
}
@Override
@@ -131,21 +132,25 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
}
if (result) {
buttonState = 1;
+ radialProgress.setBackground(getDrawableForCurrentState(), false, false);
invalidate();
}
} else if (buttonState == 1) {
boolean result = MediaController.getInstance().pauseAudio(currentMessageObject);
if (result) {
buttonState = 0;
+ radialProgress.setBackground(getDrawableForCurrentState(), false, false);
invalidate();
}
} else if (buttonState == 2) {
FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.audio, true);
buttonState = 3;
+ radialProgress.setBackground(getDrawableForCurrentState(), true, false);
invalidate();
} else if (buttonState == 3) {
FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.audio);
buttonState = 2;
+ radialProgress.setBackground(getDrawableForCurrentState(), false, false);
invalidate();
} else if (buttonState == 4) {
if (currentMessageObject.isOut() && currentMessageObject.isSending()) {
@@ -173,6 +178,7 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
}
String timeString = String.format("%02d:%02d", duration / 60, duration % 60);
if (lastTimeString == null || lastTimeString != null && !lastTimeString.equals(timeString)) {
+ lastTimeString = timeString;
timeWidth = (int)Math.ceil(timePaint.measureText(timeString));
timeLayout = new StaticLayout(timeString, timePaint, timeWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
}
@@ -183,16 +189,23 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
if (buttonState == 2) {
FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.audio, true);
buttonState = 3;
- invalidate();
+ radialProgress.setBackground(getDrawableForCurrentState(), false, false);
}
}
- public void updateButtonState() {
+ public void updateButtonState(boolean animated) {
if (currentMessageObject == null) {
return;
}
if (currentMessageObject.isOut() && currentMessageObject.isSending()) {
+ MediaController.getInstance().addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this);
buttonState = 4;
+ radialProgress.setBackground(getDrawableForCurrentState(), true, animated);
+ Float progress = ImageLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath);
+ if (progress == null && SendMessagesHelper.getInstance().isSendingMessage(currentMessageObject.getId())) {
+ progress = 1.0f;
+ }
+ radialProgress.setProgress(progress != null ? progress : 0, false);
} else {
File cacheFile = null;
if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() > 0) {
@@ -212,21 +225,24 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
} else {
buttonState = 1;
}
- progressView.setProgress(0);
+ radialProgress.setProgress(0, animated);
+ radialProgress.setBackground(getDrawableForCurrentState(), false, animated);
} else {
String fileName = currentMessageObject.getFileName();
MediaController.getInstance().addLoadingFileObserver(fileName, this);
if (!FileLoader.getInstance().isLoadingFile(fileName)) {
buttonState = 2;
- progressView.setProgress(0);
+ radialProgress.setProgress(0, animated);
+ radialProgress.setBackground(getDrawableForCurrentState(), false, animated);
} else {
buttonState = 3;
Float progress = ImageLoader.getInstance().getFileProgress(fileName);
if (progress != null) {
- progressView.setProgress(progress);
+ radialProgress.setProgress(progress, animated);
} else {
- progressView.setProgress(0);
+ radialProgress.setProgress(0, animated);
}
+ radialProgress.setBackground(getDrawableForCurrentState(), true, animated);
}
}
}
@@ -235,26 +251,25 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
@Override
public void onFailedDownload(String fileName) {
- updateButtonState();
+ updateButtonState(true);
}
@Override
public void onSuccessDownload(String fileName) {
- updateButtonState();
+ updateButtonState(true);
}
@Override
public void onProgressDownload(String fileName, float progress) {
- progressView.setProgress(progress);
+ radialProgress.setProgress(progress, true);
if (buttonState != 3) {
- updateButtonState();
+ updateButtonState(false);
}
- invalidate();
}
@Override
public void onProgressUpload(String fileName, float progress, boolean isEncrypted) {
-
+ radialProgress.setProgress(progress, true);
}
@Override
@@ -299,17 +314,17 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
seekBar.width = backgroundWidth - AndroidUtilities.dp(70);
seekBar.height = AndroidUtilities.dp(30);
- progressView.width = backgroundWidth - AndroidUtilities.dp(94);
- progressView.height = AndroidUtilities.dp(30);
seekBarY = AndroidUtilities.dp(11) + namesOffset;
buttonY = AndroidUtilities.dp(13) + namesOffset;
+ radialProgress.setProgressRect(buttonX, buttonY, buttonX + AndroidUtilities.dp(40), buttonY + AndroidUtilities.dp(40));
updateProgress();
}
@Override
public void setMessageObject(MessageObject messageObject) {
- if (currentMessageObject != messageObject || isUserDataChanged()) {
+ boolean dataChanged = currentMessageObject == messageObject && isUserDataChanged();
+ if (currentMessageObject != messageObject || dataChanged) {
if (AndroidUtilities.isTablet()) {
backgroundWidth = Math.min(AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(isChat ? 102 : 50), AndroidUtilities.dp(300));
} else {
@@ -318,15 +333,20 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
if (messageObject.isOut()) {
seekBar.type = 0;
- progressView.setProgressColors(0xffb4e396, 0xff6ac453);
+ radialProgress.setProgressColor(0xff87bf78);
} else {
seekBar.type = 1;
- progressView.setProgressColors(0xffd9e2eb, 0xff86c5f8);
+ radialProgress.setProgressColor(0xffa2b5c7);
}
super.setMessageObject(messageObject);
}
- updateButtonState();
+ updateButtonState(dataChanged);
+ }
+
+ private Drawable getDrawableForCurrentState() {
+ return ResourceLoader.audioStatesDrawable[currentMessageObject.isOut() ? buttonState : buttonState + 5][0];
+ //buttonPressed ? 1 :
}
@Override
@@ -338,27 +358,18 @@ public class ChatAudioCell extends ChatBaseCell implements SeekBar.SeekBarDelega
}
canvas.save();
- if (buttonState == 0 || buttonState == 1) {
- canvas.translate(seekBarX, seekBarY);
- seekBar.draw(canvas);
- } else {
- canvas.translate(seekBarX + AndroidUtilities.dp(12), seekBarY);
- progressView.draw(canvas);
- }
+ canvas.translate(seekBarX, seekBarY);
+ seekBar.draw(canvas);
canvas.restore();
- int state = buttonState;
if (currentMessageObject.isOut()) {
timePaint.setColor(0xff70b15c);
circlePaint.setColor(0xff87bf78);
} else {
- state += 5;
timePaint.setColor(0xffa1aab3);
circlePaint.setColor(0xff4195e5);
}
- Drawable buttonDrawable = ResourceLoader.audioStatesDrawable[state][buttonPressed ? 1 : 0];
- setDrawableBounds(buttonDrawable, buttonX, buttonY);
- buttonDrawable.draw(canvas);
+ radialProgress.onDraw(canvas);
canvas.save();
canvas.translate(timeX, AndroidUtilities.dp(42) + namesOffset);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java
index 8e28d5163..dda180c9a 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatBaseCell.java
@@ -445,7 +445,7 @@ public class ChatBaseCell extends BaseCell {
mess = mess.substring(0, 150);
}
mess = mess.replace("\n", " ");
- stringFinalText = Emoji.replaceEmoji(mess, replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14));
+ stringFinalText = Emoji.replaceEmoji(mess, replyTextPaint.getFontMetricsInt(), AndroidUtilities.dp(14), false);
stringFinalText = TextUtils.ellipsize(stringFinalText, replyTextPaint, maxWidth - AndroidUtilities.dp(8), TextUtils.TruncateAt.END);
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java
index 129348b60..92c337c27 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatContactCell.java
@@ -108,7 +108,6 @@ public class ChatContactCell extends ChatBaseCell {
float y = event.getY();
boolean result = false;
- int side = AndroidUtilities.dp(36);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (x >= avatarImage.getImageX() && x <= avatarImage.getImageX() + namesWidth + AndroidUtilities.dp(42) && y >= avatarImage.getImageY() && y <= avatarImage.getImageY() + avatarImage.getImageHeight()) {
avatarPressed = true;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java
index 23f72ec76..0c704b956 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMediaCell.java
@@ -379,7 +379,6 @@ public class ChatMediaCell extends ChatBaseCell implements MediaController.FileD
private Drawable getDrawableForCurrentState() {
if (buttonState >= 0 && buttonState < 4) {
- Drawable currentButtonDrawable = null;
if (currentMessageObject.type == 9 && gifDrawable == null) {
if (buttonState == 1 && !currentMessageObject.isSending()) {
return ResourceLoader.buttonStatesDrawablesDoc[2][currentMessageObject.isOut() ? 1 : 0];
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java
index aac1b324d..14159564f 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMessageCell.java
@@ -193,7 +193,7 @@ public class ChatMessageCell extends ChatBaseCell {
pressedLink.onClick(this);
} else {
TLRPC.WebPage webPage = currentMessageObject.messageOwner.media.webpage;
- if (Build.VERSION.SDK_INT >= 16 && webPage.embed_url != null && webPage.embed_url.length() != 0) {
+ if (Build.VERSION.SDK_INT >= 19 && webPage.embed_url != null && webPage.embed_url.length() != 0) {
delegate.needOpenWebView(webPage.embed_url, webPage.site_name, webPage.url, webPage.embed_width, webPage.embed_height);
} else {
Uri uri = Uri.parse(webPage.url);
@@ -536,7 +536,7 @@ public class ChatMessageCell extends ChatBaseCell {
if (webPage.photo != null) {
boolean smallImage = webPage.type != null && (webPage.type.equals("app") || webPage.type.equals("profile") || webPage.type.equals("article"));
- if (smallImage && descriptionLayout != null && descriptionLayout.getLineCount() == 1) {
+ if (smallImage && (descriptionLayout == null || descriptionLayout != null && descriptionLayout.getLineCount() == 1)) {
smallImage = false;
isSmallImage = false;
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java
new file mode 100644
index 000000000..d85fe7747
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/ChatMusicCell.java
@@ -0,0 +1,428 @@
+/*
+ * This is the source code of Telegram for Android v. 2.x.x.
+ * It is licensed under GNU GPL v. 2 or later.
+ * You should have received a copy of the license in this archive (see LICENSE).
+ *
+ * Copyright Nikolai Kudashov, 2013-2015.
+ */
+
+package org.telegram.ui.Cells;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.drawable.Drawable;
+import android.text.Layout;
+import android.text.StaticLayout;
+import android.text.TextPaint;
+import android.text.TextUtils;
+import android.view.MotionEvent;
+import android.view.SoundEffectConstants;
+
+import org.telegram.android.AndroidUtilities;
+import org.telegram.android.ImageLoader;
+import org.telegram.android.MediaController;
+import org.telegram.android.MessageObject;
+import org.telegram.android.SendMessagesHelper;
+import org.telegram.messenger.FileLoader;
+import org.telegram.messenger.TLRPC;
+import org.telegram.ui.Components.RadialProgress;
+import org.telegram.ui.Components.ResourceLoader;
+import org.telegram.ui.Components.SeekBar;
+
+import java.io.File;
+
+public class ChatMusicCell extends ChatBaseCell implements SeekBar.SeekBarDelegate, MediaController.FileDownloadProgressListener {
+
+ public interface ChatMusicCellDelegate {
+ boolean needPlayMusic(MessageObject messageObject);
+ }
+
+ private static TextPaint timePaint;
+ private static TextPaint titlePaint;
+ private static TextPaint authorPaint;
+
+ private SeekBar seekBar;
+ private int seekBarX;
+ private int seekBarY;
+
+ private RadialProgress radialProgress;
+ private int buttonState = 0;
+ private int buttonX;
+ private int buttonY;
+ private boolean buttonPressed = false;
+
+ private StaticLayout timeLayout;
+ private int timeX;
+ private String lastTimeString = null;
+
+ private StaticLayout titleLayout;
+ private int titleX;
+
+ private StaticLayout authorLayout;
+ private int authorX;
+
+ private int TAG;
+
+ private ChatMusicCellDelegate musicDelegate;
+
+ public ChatMusicCell(Context context) {
+ super(context);
+ TAG = MediaController.getInstance().generateObserverTag();
+
+ seekBar = new SeekBar(context);
+ seekBar.delegate = this;
+ radialProgress = new RadialProgress(this);
+ drawForwardedName = false;
+
+ if (timePaint == null) {
+ timePaint = new TextPaint(TextPaint.ANTI_ALIAS_FLAG);
+ timePaint.setTextSize(AndroidUtilities.dp(13));
+
+ titlePaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
+ titlePaint.setTextSize(AndroidUtilities.dp(16));
+ titlePaint.setColor(0xff212121);
+ titlePaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
+
+ authorPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
+ authorPaint.setTextSize(AndroidUtilities.dp(15));
+ authorPaint.setColor(0xff212121);
+ }
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ MediaController.getInstance().removeLoadingFileObserver(this);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ updateButtonState(false);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ float x = event.getX();
+ float y = event.getY();
+ boolean result = seekBar.onTouch(event.getAction(), event.getX() - seekBarX, event.getY() - seekBarY);
+ if (result) {
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ getParent().requestDisallowInterceptTouchEvent(true);
+ }
+ invalidate();
+ } else {
+ int side = AndroidUtilities.dp(36);
+ if (event.getAction() == MotionEvent.ACTION_DOWN) {
+ if (x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side) {
+ buttonPressed = true;
+ invalidate();
+ result = true;
+ }
+ } else if (buttonPressed) {
+ if (event.getAction() == MotionEvent.ACTION_UP) {
+ buttonPressed = false;
+ playSoundEffect(SoundEffectConstants.CLICK);
+ didPressedButton();
+ invalidate();
+ } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
+ buttonPressed = false;
+ invalidate();
+ } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
+ if (!(x >= buttonX && x <= buttonX + side && y >= buttonY && y <= buttonY + side)) {
+ buttonPressed = false;
+ invalidate();
+ }
+ }
+ }
+ if (!result) {
+ result = super.onTouchEvent(event);
+ }
+ }
+
+ return result;
+ }
+
+ private void didPressedButton() {
+ if (buttonState == 0) {
+ if (musicDelegate != null) {
+ if (musicDelegate.needPlayMusic(currentMessageObject)) {
+ buttonState = 1;
+ radialProgress.setBackground(getDrawableForCurrentState(), false, false);
+ invalidate();
+ }
+ }
+ } else if (buttonState == 1) {
+ boolean result = MediaController.getInstance().pauseAudio(currentMessageObject);
+ if (result) {
+ buttonState = 0;
+ radialProgress.setBackground(getDrawableForCurrentState(), false, false);
+ invalidate();
+ }
+ } else if (buttonState == 2) {
+ FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true, false);
+ buttonState = 3;
+ radialProgress.setBackground(getDrawableForCurrentState(), true, false);
+ invalidate();
+ } else if (buttonState == 3) {
+ FileLoader.getInstance().cancelLoadFile(currentMessageObject.messageOwner.media.document);
+ buttonState = 2;
+ radialProgress.setBackground(getDrawableForCurrentState(), false, false);
+ invalidate();
+ } else if (buttonState == 4) {
+ if (currentMessageObject.isOut() && currentMessageObject.isSending()) {
+ if (delegate != null) {
+ delegate.didPressedCancelSendButton(this);
+ }
+ }
+ }
+ }
+
+ public void setMusicDelegate(ChatMusicCellDelegate delegate) {
+ musicDelegate = delegate;
+ }
+
+ public void updateProgress() {
+ if (currentMessageObject == null) {
+ return;
+ }
+
+ if (!seekBar.isDragging()) {
+ seekBar.setProgress(currentMessageObject.audioProgress);
+ }
+
+ int duration = 0;
+ int currentProgress = 0;
+ for (TLRPC.DocumentAttribute attribute : currentMessageObject.messageOwner.media.document.attributes) {
+ if (attribute instanceof TLRPC.TL_documentAttributeAudio) {
+ duration = attribute.duration;
+ break;
+ }
+ }
+ if (MediaController.getInstance().isPlayingAudio(currentMessageObject)) {
+ currentProgress = currentMessageObject.audioProgressSec;
+ }
+ String timeString = String.format("%d:%02d / %d:%02d", currentProgress / 60, currentProgress % 60, duration / 60, duration % 60);
+ if (lastTimeString == null || lastTimeString != null && !lastTimeString.equals(timeString)) {
+ lastTimeString = timeString;
+ int timeWidth = (int) Math.ceil(timePaint.measureText(timeString));
+ timeLayout = new StaticLayout(timeString, timePaint, timeWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
+ }
+ invalidate();
+ }
+
+ public void downloadAudioIfNeed() {
+ //if (buttonState == 2) {
+ //FileLoader.getInstance().loadFile(currentMessageObject.messageOwner.media.document, true, false);
+ // buttonState = 3;
+ // invalidate();
+ //}
+ }
+
+ public void updateButtonState(boolean animated) {
+ if (currentMessageObject == null) {
+ return;
+ }
+ if (currentMessageObject.isOut() && currentMessageObject.isSending()) {
+ MediaController.getInstance().addLoadingFileObserver(currentMessageObject.messageOwner.attachPath, this);
+ buttonState = 4;
+ radialProgress.setBackground(getDrawableForCurrentState(), true, animated);
+ Float progress = ImageLoader.getInstance().getFileProgress(currentMessageObject.messageOwner.attachPath);
+ if (progress == null && SendMessagesHelper.getInstance().isSendingMessage(currentMessageObject.getId())) {
+ progress = 1.0f;
+ }
+ radialProgress.setProgress(progress != null ? progress : 0, false);
+ } else {
+ File cacheFile = null;
+ if (currentMessageObject.messageOwner.attachPath != null && currentMessageObject.messageOwner.attachPath.length() > 0) {
+ cacheFile = new File(currentMessageObject.messageOwner.attachPath);
+ if(!cacheFile.exists()) {
+ cacheFile = null;
+ }
+ }
+ if (cacheFile == null) {
+ cacheFile = FileLoader.getPathToMessage(currentMessageObject.messageOwner);
+ }
+ if (cacheFile.exists()) {
+ MediaController.getInstance().removeLoadingFileObserver(this);
+ boolean playing = MediaController.getInstance().isPlayingAudio(currentMessageObject);
+ if (!playing || playing && MediaController.getInstance().isAudioPaused()) {
+ buttonState = 0;
+ } else {
+ buttonState = 1;
+ }
+ radialProgress.setProgress(0, animated);
+ radialProgress.setBackground(getDrawableForCurrentState(), false, animated);
+ } else {
+ String fileName = currentMessageObject.getFileName();
+ MediaController.getInstance().addLoadingFileObserver(fileName, this);
+ if (!FileLoader.getInstance().isLoadingFile(fileName)) {
+ buttonState = 2;
+ radialProgress.setProgress(0, animated);
+ radialProgress.setBackground(getDrawableForCurrentState(), false, animated);
+ } else {
+ buttonState = 3;
+ Float progress = ImageLoader.getInstance().getFileProgress(fileName);
+ if (progress != null) {
+ radialProgress.setProgress(progress, animated);
+ } else {
+ radialProgress.setProgress(0, animated);
+ }
+ radialProgress.setBackground(getDrawableForCurrentState(), true, animated);
+ }
+ }
+ }
+ updateProgress();
+ }
+
+ @Override
+ public void onFailedDownload(String fileName) {
+ updateButtonState(true);
+ }
+
+ @Override
+ public void onSuccessDownload(String fileName) {
+ updateButtonState(true);
+ }
+
+ @Override
+ public void onProgressDownload(String fileName, float progress) {
+ radialProgress.setProgress(progress, true);
+ if (buttonState != 3) {
+ updateButtonState(false);
+ }
+ }
+
+ @Override
+ public void onProgressUpload(String fileName, float progress, boolean isEncrypted) {
+ radialProgress.setProgress(progress, true);
+ }
+
+ @Override
+ public int getObserverTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onSeekBarDrag(float progress) {
+ if (currentMessageObject == null) {
+ return;
+ }
+ currentMessageObject.audioProgress = progress;
+ MediaController.getInstance().seekToProgress(currentMessageObject, progress);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ setMeasuredDimension(width, AndroidUtilities.dp(78) + namesOffset);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+
+ if (currentMessageObject.isOut()) {
+ seekBarX = layoutWidth - backgroundWidth + AndroidUtilities.dp(52);
+ buttonX = layoutWidth - backgroundWidth + AndroidUtilities.dp(13);
+ timeX = layoutWidth - backgroundWidth + AndroidUtilities.dp(63);
+ } else {
+ if (isChat) {
+ seekBarX = AndroidUtilities.dp(113);
+ buttonX = AndroidUtilities.dp(74);
+ timeX = AndroidUtilities.dp(124);
+ } else {
+ seekBarX = AndroidUtilities.dp(61);
+ buttonX = AndroidUtilities.dp(22);
+ timeX = AndroidUtilities.dp(72);
+ }
+ }
+
+ seekBar.width = backgroundWidth - AndroidUtilities.dp(67);
+ seekBar.height = AndroidUtilities.dp(30);
+ seekBarY = AndroidUtilities.dp(26) + namesOffset;
+ buttonY = AndroidUtilities.dp(13) + namesOffset;
+ radialProgress.setProgressRect(buttonX, buttonY, buttonX + AndroidUtilities.dp(40), buttonY + AndroidUtilities.dp(40));
+
+ updateProgress();
+ }
+
+ @Override
+ public void setMessageObject(MessageObject messageObject) {
+ boolean dataChanged = currentMessageObject == messageObject && isUserDataChanged();
+ if (currentMessageObject != messageObject || dataChanged) {
+ if (AndroidUtilities.isTablet()) {
+ backgroundWidth = Math.min(AndroidUtilities.getMinTabletSide() - AndroidUtilities.dp(isChat ? 102 : 50), AndroidUtilities.dp(300));
+ } else {
+ backgroundWidth = Math.min(AndroidUtilities.displaySize.x - AndroidUtilities.dp(isChat ? 102 : 50), AndroidUtilities.dp(300));
+ }
+
+ if (messageObject.isOut()) {
+ seekBar.type = 0;
+ radialProgress.setProgressColor(0xff87bf78);
+ } else {
+ seekBar.type = 1;
+ radialProgress.setProgressColor(0xffa2b5c7);
+ }
+
+ int maxWidth = backgroundWidth - AndroidUtilities.dp(86);
+
+ CharSequence stringFinal = TextUtils.ellipsize(messageObject.getMusicTitle().replace("\n", " "), titlePaint, maxWidth, TextUtils.TruncateAt.END);
+ titleLayout = new StaticLayout(stringFinal, titlePaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
+ if (titleLayout.getLineCount() > 0) {
+ titleX = (int) Math.ceil(titleLayout.getLineLeft(0));
+ }
+
+ stringFinal = TextUtils.ellipsize(messageObject.getMusicAuthor().replace("\n", " "), authorPaint, maxWidth, TextUtils.TruncateAt.END);
+ authorLayout = new StaticLayout(stringFinal, authorPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
+ if (authorLayout.getLineCount() > 0) {
+ authorX = (int) Math.ceil(authorLayout.getLineLeft(0));
+ }
+
+ super.setMessageObject(messageObject);
+ }
+ updateButtonState(dataChanged);
+ }
+
+ private Drawable getDrawableForCurrentState() {
+ return ResourceLoader.audioStatesDrawable[currentMessageObject.isOut() ? buttonState : buttonState + 5][0];
+ //buttonPressed ? 1 :
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (currentMessageObject == null) {
+ return;
+ }
+
+ if (currentMessageObject.isOut()) {
+ timePaint.setColor(0xff70b15c);
+ } else {
+ timePaint.setColor(0xffa1aab3);
+ }
+ radialProgress.onDraw(canvas);
+
+ canvas.save();
+ canvas.translate(timeX + titleX, AndroidUtilities.dp(12) + namesOffset);
+ titleLayout.draw(canvas);
+ canvas.restore();
+
+ canvas.save();
+ if (MediaController.getInstance().isPlayingAudio(currentMessageObject)) {
+ canvas.translate(seekBarX, seekBarY);
+ seekBar.draw(canvas);
+ } else {
+ canvas.translate(timeX + authorX, AndroidUtilities.dp(32) + namesOffset);
+ authorLayout.draw(canvas);
+ }
+ canvas.restore();
+
+ canvas.save();
+ canvas.translate(timeX, AndroidUtilities.dp(52) + namesOffset);
+ timeLayout.draw(canvas);
+ canvas.restore();
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java
index b163ec918..73ac7d063 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/DialogCell.java
@@ -356,15 +356,7 @@ public class DialogCell extends BaseCell {
if (message.isOut()) {
name = LocaleController.getString("FromYou", R.string.FromYou);
} else {
- if (UserObject.isDeleted(fromUser)) {
- name = "Deleted";
- } else {
- if (fromUser.first_name != null && fromUser.first_name.length() > 0) {
- name = fromUser.first_name;
- } else {
- name = fromUser.last_name;
- }
- }
+ name = UserObject.getFirstName(fromUser);
}
checkMessage = false;
if (message.caption != null) {
@@ -373,11 +365,11 @@ public class DialogCell extends BaseCell {
mess = mess.substring(0, 150);
}
mess = mess.replace("\n", " ");
- messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20));
+ messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
} else {
if (message.messageOwner.media != null && !message.isMediaEmpty()) {
currentMessagePaint = messagePrintingPaint;
- messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, message.messageText), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20));
+ messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, message.messageText), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
} else {
if (message.messageOwner.message != null) {
String mess = message.messageOwner.message;
@@ -385,7 +377,7 @@ public class DialogCell extends BaseCell {
mess = mess.substring(0, 150);
}
mess = mess.replace("\n", " ");
- messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20));
+ messageString = Emoji.replaceEmoji(AndroidUtilities.replaceTags(String.format("%s: %s", name, mess), AndroidUtilities.FLAG_TAG_COLOR), messagePaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
}
}
}
@@ -580,7 +572,7 @@ public class DialogCell extends BaseCell {
mess = mess.substring(0, 150);
}
mess = mess.replace("\n", " ");
- messageString = Emoji.replaceEmoji(mess, messagePaint.getFontMetricsInt(), AndroidUtilities.dp(17));
+ messageString = Emoji.replaceEmoji(mess, messagePaint.getFontMetricsInt(), AndroidUtilities.dp(17), false);
}
messageWidth = Math.max(AndroidUtilities.dp(12), messageWidth);
CharSequence messageStringFinal = TextUtils.ellipsize(messageString, currentMessagePaint, messageWidth - AndroidUtilities.dp(12), TextUtils.TruncateAt.END);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java
index 54414ebc2..c389b017d 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachCameraCell.java
@@ -13,7 +13,6 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import org.telegram.android.AndroidUtilities;
-import org.telegram.messenger.R;
import org.telegram.ui.Components.LayoutHelper;
public class PhotoAttachCameraCell extends FrameLayout {
@@ -23,7 +22,7 @@ public class PhotoAttachCameraCell extends FrameLayout {
ImageView imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER);
- imageView.setImageResource(R.drawable.ic_attach_photobig);
+ //imageView.setImageResource(R.drawable.ic_attach_photobig);
imageView.setBackgroundColor(0xff777777);
addView(imageView, LayoutHelper.createFrame(80, 80));
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java
index bf00964c4..9018a1623 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/PhotoAttachPhotoCell.java
@@ -81,5 +81,6 @@ public class PhotoAttachPhotoCell extends FrameLayout {
public void setOnCheckClickLisnener(OnClickListener onCheckClickLisnener) {
checkFrame.setOnClickListener(onCheckClickLisnener);
+ imageView.setOnClickListener(onCheckClickLisnener);
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java
index 7cc059b68..9d677bb44 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedDocumentCell.java
@@ -100,7 +100,7 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F
});
nameTextView = new TextView(context);
- nameTextView.setTextColor(0xff222222);
+ nameTextView.setTextColor(0xff212121);
nameTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16);
nameTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
nameTextView.setLines(1);
@@ -318,6 +318,9 @@ public class SharedDocumentCell extends FrameLayout implements MediaController.F
@Override
public void onProgressDownload(String fileName, float progress) {
+ if (progressView.getVisibility() != VISIBLE) {
+ updateFileExistIcon();
+ }
progressView.setProgress(progress, true);
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java
index 1646b509b..010b51a0c 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/SharedMediaSectionCell.java
@@ -28,7 +28,7 @@ public class SharedMediaSectionCell extends FrameLayout {
textView = new TextView(getContext());
textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
textView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
- textView.setTextColor(0xff222222);
+ textView.setTextColor(0xff212121);
textView.setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL);
addView(textView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP, 13, 0, 13, 0));
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java
index ce803d315..1f5c47eeb 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/StickerEmojiCell.java
@@ -63,14 +63,14 @@ public class StickerEmojiCell extends FrameLayout {
for (TLRPC.DocumentAttribute attribute : document.attributes) {
if (attribute instanceof TLRPC.TL_documentAttributeSticker) {
if (attribute.alt != null && attribute.alt.length() > 0) {
- emojiTextView.setText(Emoji.replaceEmoji(attribute.alt, emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16)));
+ emojiTextView.setText(Emoji.replaceEmoji(attribute.alt, emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16), false));
set = true;
}
break;
}
}
if (!set) {
- emojiTextView.setText(Emoji.replaceEmoji(StickersQuery.getEmojiForSticker(sticker.id), emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16)));
+ emojiTextView.setText(Emoji.replaceEmoji(StickersQuery.getEmojiForSticker(sticker.id), emojiTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16), false));
}
emojiTextView.setVisibility(VISIBLE);
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java
index 7889b7803..7cab5ae05 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Cells/TextDetailCell.java
@@ -36,7 +36,7 @@ public class TextDetailCell extends FrameLayout {
textView.setMaxLines(1);
textView.setSingleLine(true);
textView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
- addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 10, LocaleController.isRTL ? 16 : 71, 0));
+ addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 10, LocaleController.isRTL ? 71 : 16, 0));
valueTextView = new TextView(context);
valueTextView.setTextColor(0xff8a8a8a);
@@ -45,7 +45,7 @@ public class TextDetailCell extends FrameLayout {
valueTextView.setMaxLines(1);
valueTextView.setSingleLine(true);
valueTextView.setGravity(LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT);
- addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 35, LocaleController.isRTL ? 16 : 71, 0));
+ addView(valueTextView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, LocaleController.isRTL ? 16 : 71, 35, LocaleController.isRTL ? 71 : 16, 0));
imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java
index 8eb72c7e1..2addf5a7d 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeChatNameActivity.java
@@ -16,7 +16,6 @@ import android.text.InputType;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -57,7 +56,7 @@ public class ChangeChatNameActivity extends BaseFragment {
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("EditName", R.string.EditName));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java
index 5c0088490..a71dcc505 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeNameActivity.java
@@ -15,7 +15,6 @@ import android.text.InputType;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -50,7 +49,7 @@ public class ChangeNameActivity extends BaseFragment {
private final static int done_button = 1;
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("EditName", R.string.EditName));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java
index bc6040073..b06244418 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneActivity.java
@@ -24,7 +24,6 @@ import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.AccelerateDecelerateInterpolator;
@@ -102,7 +101,7 @@ public class ChangePhoneActivity extends BaseFragment {
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName));
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java
index e4077ef3b..5144dc26d 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangePhoneHelpActivity.java
@@ -13,7 +13,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
@@ -36,7 +35,7 @@ import org.telegram.ui.Components.LayoutHelper;
public class ChangePhoneHelpActivity extends BaseFragment {
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java
index 0e40b1a41..0f607ee9a 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChangeUsernameActivity.java
@@ -20,7 +20,6 @@ import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -62,7 +61,7 @@ public class ChangeUsernameActivity extends BaseFragment {
private final static int done_button = 1;
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("Username", R.string.Username));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java
index 8e59129c3..0077cde01 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ChatActivity.java
@@ -14,7 +14,6 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.database.Cursor;
@@ -32,7 +31,6 @@ import android.util.Base64;
import android.util.SparseArray;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -40,6 +38,7 @@ import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.webkit.MimeTypeMap;
import android.widget.AdapterView;
+import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -96,6 +95,7 @@ import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.ActionBarMenu;
import org.telegram.ui.ActionBar.ActionBarMenuItem;
import org.telegram.ui.Cells.ChatMessageCell;
+import org.telegram.ui.Cells.ChatMusicCell;
import org.telegram.ui.Cells.ChatUnreadCell;
import org.telegram.ui.Components.AlertsCreator;
import org.telegram.ui.Components.AvatarDrawable;
@@ -123,7 +123,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.concurrent.Semaphore;
-public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate,
+public class ChatActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.MessagesActivityDelegate,
PhotoViewer.PhotoViewerProvider {
protected TLRPC.Chat currentChat;
@@ -177,6 +177,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
private ListView mentionListView;
private AnimatorSetProxy mentionListAnimation;
private ChatAttachView chatAttachView;
+ private BottomSheet chatAttachViewSheet;
private boolean allowStickersPanel;
private AnimatorSetProxy runningAnimation;
@@ -455,6 +456,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
NotificationCenter.getInstance().addObserver(this, NotificationCenter.removeAllMessagesFromDialog);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioProgressDidChanged);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset);
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.screenshotTook);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.blockedUsersDidLoaded);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.FileNewChunkAvailable);
@@ -558,6 +560,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.botInfoDidLoaded);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.botKeyboardDidLoaded);
NotificationCenter.getInstance().removeObserver(this, NotificationCenter.chatSearchResultsAvailable);
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged);
if (AndroidUtilities.isTablet()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.openedChatChanged, dialog_id, true);
@@ -578,11 +581,14 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
chatAttachView.onDestroy();
}
AndroidUtilities.unlockOrientation(getParentActivity());
- MediaController.getInstance().stopAudio();
+ MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
+ if (messageObject != null && !messageObject.isMusic()) {
+ MediaController.getInstance().stopAudio();
+ }
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
for (int a = 0; a < 8; a++) {
chatMessageCellsCache.add(new ChatMessageCell(context));
@@ -595,6 +601,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
lastStatus = null;
hasOwnBackground = true;
chatAttachView = null;
+ chatAttachViewSheet = null;
ResourceLoader.loadRecources(context);
@@ -673,7 +680,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
Bundle args = new Bundle();
args.putBoolean("onlySelect", true);
args.putInt("dialogsType", 1);
- MessagesActivity fragment = new MessagesActivity(args);
+ DialogsActivity fragment = new DialogsActivity(args);
fragment.setDelegate(ChatActivity.this);
presentFragment(fragment);
} else if (id == chat_enc_timer) {
@@ -770,20 +777,19 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
selectedMessagesCanCopyIds.clear();
actionBar.hideActionMode();
updateVisibleRows();
- }/* else if (id == chat_menu_attach) {
+ } else if (id == chat_menu_attach) {
if (getParentActivity() == null) {
return;
}
- BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity());
+
if (chatAttachView == null) {
+ BottomSheet.Builder builder = new BottomSheet.Builder(getParentActivity());
chatAttachView = new ChatAttachView(getParentActivity());
chatAttachView.setDelegate(new ChatAttachView.ChatAttachViewDelegate() {
@Override
public void didPressedButton(int button) {
- if (visibleDialog != null) {
- visibleDialog.dismiss();
- }
if (button == 7) {
+ chatAttachViewSheet.dismiss();
HashMap selectedPhotos = chatAttachView.getSelectedPhotos();
if (!selectedPhotos.isEmpty()) {
ArrayList photos = new ArrayList<>();
@@ -796,31 +802,50 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
showReplyPanel(false, null, null, null, false, true);
}
return;
+ } else {
+ chatAttachViewSheet.dismissWithButtonClick(button);
}
processSelectedAttach(button);
}
});
+ builder.setDelegate(new BottomSheet.BottomSheetDelegate() {
+
+ @Override
+ public void onRevealAnimationStart(boolean open) {
+ chatAttachView.onRevealAnimationStart(open);
+ }
+
+ @Override
+ public void onRevealAnimationProgress(boolean open, float radius, int x, int y) {
+ chatAttachView.onRevealAnimationProgress(open, radius, x, y);
+ }
+
+ @Override
+ public void onRevealAnimationEnd(boolean open) {
+ chatAttachView.onRevealAnimationEnd(open);
+ }
+
+ @Override
+ public void onOpenAnimationEnd() {
+ chatAttachView.onRevealAnimationEnd(true);
+ }
+
+ @Override
+ public View getRevealView() {
+ return menuItem;
+ }
+ });
+ builder.setApplyTopPaddings(false);
+ builder.setUseRevealAnimation();
+ builder.setCustomView(chatAttachView);
+ chatAttachViewSheet = builder.create();
}
- builder.setCustomView(chatAttachView);
- final int coords[] = new int[2];
- menuItem.getLocationInWindow(coords);
- builder.setRevealAnimation(coords[0] + menuItem.getWidth() / 2, coords[1] + menuItem.getHeight() / 2);
- builder.setDelegate(new BottomSheet.BottomSheetDelegate() {
- @Override
- public void onOpenAnimationStart() {
- chatAttachView.startAnimations(coords[1] > AndroidUtilities.displaySize.y - AndroidUtilities.dp(100));
- }
- @Override
- public void onOpenAnimationEnd() {
-
- }
- });
chatAttachView.init(ChatActivity.this);
- showDialog(builder.create());
- }*/ else if (id == attach_gallery || id == attach_video || id == attach_document || id == attach_location || id == attach_photo || id == attach_audio || id == attach_contact) {
+ showDialog(chatAttachViewSheet);
+ }/* else if (id == attach_gallery || id == attach_video || id == attach_document || id == attach_location || id == attach_photo || id == attach_audio || id == attach_contact) {
processSelectedAttach(id);
- } else if (id == bot_help) {
+ } */else if (id == bot_help) {
SendMessagesHelper.getInstance().sendMessage("/help", dialog_id, null, null, false);
} else if (id == bot_settings) {
SendMessagesHelper.getInstance().sendMessage("/settings", dialog_id, null, null, false);
@@ -922,12 +947,26 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
ActionBarMenu menu = actionBar.createMenu();
if (currentEncryptedChat == null && !isBroadcast) {
- /*searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true, false).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() {
+ searchItem = menu.addItem(0, R.drawable.ic_ab_search).setIsSearchField(true, false).setActionBarMenuItemSearchListener(new ActionBarMenuItem.ActionBarMenuItemSearchListener() {
@Override
public void onSearchCollapse() {
avatarContainer.setVisibility(View.VISIBLE);
- headerItem.setVisibility(View.VISIBLE);
+ if (chatActivityEnterView.hasText()) {
+ if (headerItem != null) {
+ headerItem.setVisibility(View.GONE);
+ }
+ if (attachItem != null) {
+ attachItem.setVisibility(View.VISIBLE);
+ }
+ } else {
+ if (headerItem != null) {
+ headerItem.setVisibility(View.VISIBLE);
+ }
+ if (attachItem != null) {
+ attachItem.setVisibility(View.GONE);
+ }
+ }
searchItem.setVisibility(View.GONE);
//chatActivityEnterView.setVisibility(View.VISIBLE);
searchUpItem.clearAnimation();
@@ -945,7 +984,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
searchItem.getSearchField().requestFocus();
AndroidUtilities.showKeyboard(searchItem.getSearchField());
}
- }, 200); //TODO find a better way to open keyboard
+ }, 300); //TODO find a better way to open keyboard
}
@Override
@@ -960,7 +999,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
searchUpItem = menu.addItem(search_up, R.drawable.search_up);
searchUpItem.setVisibility(View.GONE);
searchDownItem = menu.addItem(search_down, R.drawable.search_down);
- searchDownItem.setVisibility(View.GONE);*/
+ searchDownItem.setVisibility(View.GONE);
}
headerItem = menu.addItem(0, R.drawable.ic_ab_other);
@@ -990,22 +1029,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
updateSubtitle();
updateTitleIcons();
- attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other).setAllowCloseAnimation(false);
- attachItem.addSubItem(attach_photo, LocaleController.getString("ChatTakePhoto", R.string.ChatTakePhoto), R.drawable.ic_attach_photo);
- attachItem.addSubItem(attach_gallery, LocaleController.getString("ChatGallery", R.string.ChatGallery), R.drawable.ic_attach_gallery);
- attachItem.addSubItem(attach_video, LocaleController.getString("ChatVideo", R.string.ChatVideo), R.drawable.ic_attach_video);
- attachItem.addSubItem(attach_document, LocaleController.getString("ChatDocument", R.string.ChatDocument), R.drawable.ic_ab_doc);
- attachItem.addSubItem(attach_location, LocaleController.getString("ChatLocation", R.string.ChatLocation), R.drawable.ic_attach_location);
+ attachItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_other).setOverrideMenuClick(true).setAllowCloseAnimation(false);
attachItem.setVisibility(View.GONE);
-
menuItem = menu.addItem(chat_menu_attach, R.drawable.ic_ab_attach).setAllowCloseAnimation(false);
- menuItem.addSubItem(attach_photo, LocaleController.getString("ChatTakePhoto", R.string.ChatTakePhoto), R.drawable.ic_attach_photo);
- menuItem.addSubItem(attach_gallery, LocaleController.getString("ChatGallery", R.string.ChatGallery), R.drawable.ic_attach_gallery);
- menuItem.addSubItem(attach_video, LocaleController.getString("ChatVideo", R.string.ChatVideo), R.drawable.ic_attach_video);
- menuItem.addSubItem(attach_document, LocaleController.getString("ChatDocument", R.string.ChatDocument), R.drawable.ic_ab_doc);
- menuItem.addSubItem(attach_location, LocaleController.getString("ChatLocation", R.string.ChatLocation), R.drawable.ic_attach_location);
- menuItem.setShowFromBottom(true);
-
menuItem.setBackgroundDrawable(null);
actionModeViews.clear();
@@ -1053,8 +1079,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
@@ -1067,14 +1091,10 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- if (child == chatActivityEnterView) {
- measureChildWithMargins(child, widthMeasureSpec, 0, heightMeasureSpec, 0);
- inputFieldHeight = child.getMeasuredHeight();
- break;
- }
- }
+
+ measureChildWithMargins(chatActivityEnterView, widthMeasureSpec, 0, heightMeasureSpec, 0);
+ inputFieldHeight = chatActivityEnterView.getMeasuredHeight();
+
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
if (child.getVisibility() == GONE || child == chatActivityEnterView) {
@@ -1660,6 +1680,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
public void onAttachButtonHidden() {
+ if (actionBar.isSearchFieldVisible()) {
+ return;
+ }
if (attachItem != null) {
attachItem.setVisibility(View.VISIBLE);
}
@@ -1670,6 +1693,9 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
public void onAttachButtonShow() {
+ if (actionBar.isSearchFieldVisible()) {
+ return;
+ }
if (attachItem != null) {
attachItem.setVisibility(View.GONE);
}
@@ -1680,7 +1706,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
@Override
public void onWindowSizeChanged(int size) {
- if (size < AndroidUtilities.dp(72) + AndroidUtilities.getCurrentActionBarHeight()) {
+ if (size < AndroidUtilities.dp(72) + ActionBar.getCurrentActionBarHeight()) {
allowStickersPanel = false;
if (stickersPanel.getVisibility() == View.VISIBLE) {
stickersPanel.clearAnimation();
@@ -2089,12 +2115,15 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
});
presentFragment(fragment);
} else if (which == attach_audio) {
- try {
- Intent intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
- startActivityForResult(intent, 32);
- } catch (Exception e) {
- FileLog.e("tmessages", e);
- }
+ AudioSelectActivity fragment = new AudioSelectActivity();
+ fragment.setDelegate(new AudioSelectActivity.AudioSelectActivityDelegate() {
+ @Override
+ public void didSelectAudio(ArrayList audios) {
+ SendMessagesHelper.prepareSendingAudioDocuments(audios, dialog_id, replyingMessageObject);
+ showReplyPanel(false, null, null, null, false, true);
+ }
+ });
+ presentFragment(fragment);
} else if (which == attach_contact) {
try {
Intent intent = new Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI);
@@ -2216,7 +2245,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
mess = mess.substring(0, 150);
}
mess = mess.replace("\n", " ");
- replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14)));
+ replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false));
}
} else if (messageObjects != null) {
if (messageObjects.isEmpty()) {
@@ -2277,7 +2306,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
mess = mess.substring(0, 150);
}
mess = mess.replace("\n", " ");
- replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14)));
+ replyObjectTextView.setText(Emoji.replaceEmoji(mess, replyObjectTextView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(14), false));
} else {
replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedMessage", messageObjects.size()));
}
@@ -2296,7 +2325,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
} else if (type == 12) {
replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedContact", messageObjects.size()));
- } else if (type == 2) {
+ } else if (type == 2 || type == 14) {
replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedAudio", messageObjects.size()));
} else if (type == 13) {
replyObjectTextView.setText(LocaleController.formatPluralString("ForwardedSticker", messageObjects.size()));
@@ -3221,22 +3250,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
FileLog.e("tmessages", e);
}
}
- } else if (requestCode == 32) {
- if (data == null || data.getData() == null) {
- showAttachmentError();
- return;
- }
- Uri uri = data.getData();
- String path = AndroidUtilities.getPath(uri);
- if (path != null) {
- TLRPC.TL_audio audio = new TLRPC.TL_audio();
- audio.dc_id = Integer.MIN_VALUE;
- audio.id = Integer.MIN_VALUE;
- audio.user_id = UserConfig.getClientUserId();
- audio.mime_type = "audio/mp3";
- SendMessagesHelper.getInstance().sendMessage(audio, path, dialog_id, replyingMessageObject);
- showReplyPanel(false, null, null, null, false, true);
- }
}
}
}
@@ -3587,7 +3600,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (currentEncryptedChat != null && obj.isOut() && obj.messageOwner.action != null && obj.messageOwner.action instanceof TLRPC.TL_messageEncryptedAction &&
obj.messageOwner.action.encryptedAction instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL && getParentActivity() != null) {
- TLRPC.TL_decryptedMessageActionSetMessageTTL action = (TLRPC.TL_decryptedMessageActionSetMessageTTL) obj.messageOwner.action.encryptedAction;
if (AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 17 && currentEncryptedChat.ttl > 0 && currentEncryptedChat.ttl <= 60) {
AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity());
builder.setTitle(LocaleController.getString("AppName", R.string.AppName));
@@ -4005,7 +4017,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
int encId = (Integer) args[0];
if (currentEncryptedChat != null && currentEncryptedChat.id == encId) {
int date = (Integer) args[1];
- boolean started = false;
for (MessageObject obj : messages) {
if (!obj.isOut()) {
continue;
@@ -4018,7 +4029,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
updateVisibleRows();
}
- } else if (id == NotificationCenter.audioDidReset) {
+ } else if (id == NotificationCenter.audioDidReset || id == NotificationCenter.audioPlayStateChanged) {
Integer mid = (Integer) args[0];
if (chatListView != null) {
int count = chatListView.getChildCount();
@@ -4027,7 +4038,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (view instanceof ChatAudioCell) {
ChatAudioCell cell = (ChatAudioCell) view;
if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) {
- cell.updateButtonState();
+ cell.updateButtonState(false);
+ break;
+ }
+ } else if (view instanceof ChatMusicCell) {
+ ChatMusicCell cell = (ChatMusicCell) view;
+ if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) {
+ cell.updateButtonState(false);
break;
}
}
@@ -4045,6 +4062,16 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
cell.updateProgress();
break;
}
+ } else if (view instanceof ChatMusicCell) {
+ ChatMusicCell cell = (ChatMusicCell) view;
+ if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) {
+ MessageObject playing = cell.getMessageObject();
+ MessageObject player = MediaController.getInstance().getPlayingMessageObject();
+ playing.audioProgress = player.audioProgress;
+ playing.audioProgressSec = player.audioProgressSec;
+ cell.updateProgress();
+ break;
+ }
}
}
}
@@ -4121,6 +4148,27 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
} else if (id == NotificationCenter.audioDidStarted) {
MessageObject messageObject = (MessageObject) args[0];
sendSecretMessageRead(messageObject);
+
+ int mid = messageObject.getId();
+ if (chatListView != null) {
+ int count = chatListView.getChildCount();
+ for (int a = 0; a < count; a++) {
+ View view = chatListView.getChildAt(a);
+ if (view instanceof ChatAudioCell) {
+ ChatAudioCell cell = (ChatAudioCell) view;
+ if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) {
+ cell.updateButtonState(false);
+ break;
+ }
+ } else if (view instanceof ChatMusicCell) {
+ ChatMusicCell cell = (ChatMusicCell) view;
+ if (cell.getMessageObject() != null && cell.getMessageObject().getId() == mid) {
+ cell.updateButtonState(false);
+ break;
+ }
+ }
+ }
+ }
} else if (id == NotificationCenter.updateMessageMedia) {
MessageObject messageObject = (MessageObject) args[0];
MessageObject existMessageObject = messagesDict.get(messageObject.getId());
@@ -4555,7 +4603,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
actionBar.setBackButtonImage(R.drawable.ic_close_white);
}
}
- int padding = (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2;
+ int padding = (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2;
avatarContainer.setPadding(avatarContainer.getPaddingLeft(), padding, avatarContainer.getPaddingRight(), padding);
FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) avatarContainer.getLayoutParams();
layoutParams.topMargin = (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0);
@@ -4629,7 +4677,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
options = new int[]{8, 2, 3, 1};
} else if (type == 4) {
if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
- items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
+ String saveString;
+ if (selectedObject.isMusic()) {
+ saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic);
+ } else {
+ saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads);
+ }
+ items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
options = new int[]{8, 10, 4, 2, 1};
} else {
items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
@@ -4639,7 +4693,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
options = new int[]{8, 5, 4, 2, 1};
} else if (type == 6) {
- items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
+ String saveString;
+ if (selectedObject.isMusic()) {
+ saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic);
+ } else {
+ saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads);
+ }
+ items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("SaveToGallery", R.string.SaveToGallery), saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
options = new int[]{8, 7, 10, 6, 2, 1};
} else if (type == 7) {
items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("AddToStickers", R.string.AddToStickers), LocaleController.getString("Delete", R.string.Delete)};
@@ -4654,7 +4714,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
options = new int[]{2, 3, 1};
} else if (type == 4) {
if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
- items = new CharSequence[]{LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
+ String saveString;
+ if (selectedObject.isMusic()) {
+ saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic);
+ } else {
+ saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads);
+ }
+ items = new CharSequence[]{saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
options = new int[]{10, 4, 2, 1};
} else {
items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
@@ -4664,7 +4730,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
items = new CharSequence[]{LocaleController.getString("ApplyLocalizationFile", R.string.ApplyLocalizationFile), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
options = new int[]{5, 4, 2, 1};
} else if (type == 6) {
- items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
+ String saveString;
+ if (selectedObject.isMusic()) {
+ saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic);
+ } else {
+ saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads);
+ }
+ items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("Delete", R.string.Delete)};
options = new int[]{7, 10, 6, 2, 1};
} else if (type == 7) {
items = new CharSequence[]{LocaleController.getString("Reply", R.string.Reply), LocaleController.getString("Forward", R.string.Forward), LocaleController.getString("AddToStickers", R.string.AddToStickers), LocaleController.getString("Delete", R.string.Delete)};
@@ -4680,7 +4752,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
options = new int[]{3, 1};
} else if (type == 4) {
if (selectedObject.messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
- items = new CharSequence[]{LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads), LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Delete", R.string.Delete)};
+ String saveString;
+ if (selectedObject.isMusic()) {
+ saveString = LocaleController.getString("SaveToMusic", R.string.SaveToMusic);
+ } else {
+ saveString = LocaleController.getString("SaveToDownloads", R.string.SaveToDownloads);
+ }
+ items = new CharSequence[]{saveString, LocaleController.getString("ShareFile", R.string.ShareFile), LocaleController.getString("Delete", R.string.Delete)};
options = new int[]{10, 4, 1};
} else {
items = new CharSequence[]{LocaleController.getString("SaveToGallery", R.string.SaveToGallery), LocaleController.getString("Delete", R.string.Delete)};
@@ -4770,7 +4848,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
Bundle args = new Bundle();
args.putBoolean("onlySelect", true);
args.putInt("dialogsType", 1);
- MessagesActivity fragment = new MessagesActivity(args);
+ DialogsActivity fragment = new DialogsActivity(args);
fragment.setDelegate(this);
presentFragment(fragment);
} else if (option == 3) {
@@ -4787,7 +4865,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
FileLog.e("tmessages", e);
}
} else if (option == 4) {
- String fileName = selectedObject.getFileName();
String path = selectedObject.messageOwner.attachPath;
if (path != null && path.length() > 0) {
File temp = new File(path);
@@ -4802,7 +4879,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
MediaController.saveFile(path, getParentActivity(), 1, null);
} else if (selectedObject.type == 1) {
MediaController.saveFile(path, getParentActivity(), 0, null);
- } else if (selectedObject.type == 8 || selectedObject.type == 9) {
+ } else if (selectedObject.type == 8 || selectedObject.type == 9 || selectedObject.type == 14) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType(selectedObject.messageOwner.media.document.mime_type);
intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(new File(path)));
@@ -4837,7 +4914,6 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
} else if (option == 6 || option == 7) {
- String fileName = selectedObject.getFileName();
String path = selectedObject.messageOwner.attachPath;
if (path != null && path.length() > 0) {
File temp = new File(path);
@@ -4848,7 +4924,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (path == null || path.length() == 0) {
path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString();
}
- if (selectedObject.type == 8 || selectedObject.type == 9) {
+ if (selectedObject.type == 8 || selectedObject.type == 9 || selectedObject.type == 14) {
if (option == 6) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType(selectedObject.messageOwner.media.document.mime_type);
@@ -4877,13 +4953,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (path == null || path.length() == 0) {
path = FileLoader.getPathToMessage(selectedObject.messageOwner).toString();
}
- MediaController.saveFile(path, getParentActivity(), 2, fileName);
+ MediaController.saveFile(path, getParentActivity(), selectedObject.isMusic() ? 3 : 2, fileName);
}
selectedObject = null;
}
@Override
- public void didSelectDialog(MessagesActivity activity, long did, boolean param) {
+ public void didSelectDialog(DialogsActivity activity, long did, boolean param) {
if (dialog_id != 0 && (forwaringMessage != null || !selectedMessagesIds.isEmpty())) {
ArrayList fmessages = new ArrayList<>();
if (forwaringMessage != null) {
@@ -4961,7 +5037,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
public boolean isGoogleMapsInstalled() {
try {
- ApplicationInfo info = ApplicationLoader.applicationContext.getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0);
+ ApplicationLoader.applicationContext.getPackageManager().getApplicationInfo("com.google.android.apps.maps", 0);
return true;
} catch (PackageManager.NameNotFoundException e) {
if (getParentActivity() == null) {
@@ -5213,7 +5289,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (url.startsWith("@")) {
MessagesController.openByUserName(url.substring(1), ChatActivity.this, 0);
} else if (url.startsWith("#")) {
- MessagesActivity fragment = new MessagesActivity(null);
+ DialogsActivity fragment = new DialogsActivity(null);
fragment.setSearchString(url);
presentFragment(fragment);
} else if (url.startsWith("/")) {
@@ -5221,6 +5297,8 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
}
}
});
+ } else if (viewType == 8) {
+ view = new ChatMusicCell(mContext);
}
if (view instanceof ChatBaseCell) {
@@ -5261,7 +5339,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
if (url.startsWith("@")) {
MessagesController.openByUserName(url.substring(1), ChatActivity.this, 0);
} else if (url.startsWith("#")) {
- MessagesActivity fragment = new MessagesActivity(null);
+ DialogsActivity fragment = new DialogsActivity(null);
fragment.setSearchString(url);
presentFragment(fragment);
} else if (url.startsWith("/")) {
@@ -5273,7 +5351,7 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
public void needOpenWebView(String url, String title, String originalUrl, int w, int h) {
BottomSheet.Builder builder = new BottomSheet.Builder(mContext);
builder.setCustomView(new WebFrameLayout(mContext, builder.create(), title, originalUrl, url, w, h));
- builder.setOverrideTabletWidth(true);
+ builder.setUseFullWidth(true);
showDialog(builder.create());
}
@@ -5434,6 +5512,13 @@ public class ChatActivity extends BaseFragment implements NotificationCenter.Not
showDialog(builder.create());
}
});
+ } else if (view instanceof ChatMusicCell) {
+ ((ChatMusicCell) view).setMusicDelegate(new ChatMusicCell.ChatMusicCellDelegate() {
+ @Override
+ public boolean needPlayMusic(MessageObject messageObject) {
+ return MediaController.getInstance().setPlaylist(messages, messageObject);
+ }
+ });
}
} else if (view instanceof ChatActionCell) {
((ChatActionCell) view).setDelegate(new ChatActionCell.ChatActionCellDelegate() {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java
index cb8164d78..a6d987748 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/BotKeyboardView.java
@@ -57,7 +57,7 @@ public class BotKeyboardView extends LinearLayout {
public void setPanelHeight(int height) {
panelHeight = height;
- if (isFullSize && botButtons != null) {
+ if (isFullSize && botButtons != null && botButtons.rows.size() != 0) {
buttonHeight = !isFullSize ? 42 : (int) Math.max(42, (panelHeight - AndroidUtilities.dp(30) - (botButtons.rows.size() - 1) * AndroidUtilities.dp(10)) / botButtons.rows.size() / AndroidUtilities.density);
int count = container.getChildCount();
int newHeight = AndroidUtilities.dp(buttonHeight);
@@ -87,7 +87,7 @@ public class BotKeyboardView extends LinearLayout {
container.removeAllViews();
buttonViews.clear();
- if (buttons != null) {
+ if (buttons != null && botButtons.rows.size() != 0) {
isFullSize = (buttons.flags & 1) == 0;
buttonHeight = !isFullSize ? 42 : (int) Math.max(42, (panelHeight - AndroidUtilities.dp(30) - (botButtons.rows.size() - 1) * AndroidUtilities.dp(10)) / botButtons.rows.size() / AndroidUtilities.density);
for (int a = 0; a < buttons.rows.size(); a++) {
@@ -106,7 +106,7 @@ public class BotKeyboardView extends LinearLayout {
textView.setGravity(Gravity.CENTER);
textView.setBackgroundResource(R.drawable.bot_keyboard_states);
textView.setPadding(AndroidUtilities.dp(4), 0, AndroidUtilities.dp(4), 0);
- textView.setText(Emoji.replaceEmoji(button.text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16)));
+ textView.setText(Emoji.replaceEmoji(button.text, textView.getPaint().getFontMetricsInt(), AndroidUtilities.dp(16), false));
layout.addView(textView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, weight, 0, 0, b != row.buttons.size() - 1 ? 10 : 0, 0));
textView.setOnClickListener(new OnClickListener() {
@Override
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java
index 6fc40e4a8..b939a3ec7 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatActivityEnterView.java
@@ -44,6 +44,7 @@ import org.telegram.android.NotificationCenter;
import org.telegram.messenger.R;
import org.telegram.messenger.TLRPC;
import org.telegram.messenger.UserConfig;
+import org.telegram.ui.ActionBar.ActionBar;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.android.AnimationCompat.AnimatorListenerAdapterProxy;
import org.telegram.android.AnimationCompat.AnimatorSetProxy;
@@ -117,6 +118,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
private BaseFragment parentFragment;
private long dialog_id;
private boolean ignoreTextChange;
+ private int innerTextChange;
private MessageObject replyingMessageObject;
private MessageObject botMessageObject;
private TLRPC.WebPage messageWebPage;
@@ -187,7 +189,16 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
}
});
- messageEditText = new EditText(context);
+ messageEditText = new EditText(context) {
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ if (isPopupShowing() && event.getAction() == MotionEvent.ACTION_DOWN) {
+ showPopup(AndroidUtilities.usingHardwareInput ? 0 : 2, 0);
+ openKeyboardInternal();
+ }
+ return super.onTouchEvent(event);
+ }
+ };
messageEditText.setHint(LocaleController.getString("TypeMessage", R.string.TypeMessage));
messageEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
messageEditText.setInputType(messageEditText.getInputType() | EditorInfo.TYPE_TEXT_FLAG_CAP_SENTENCES | EditorInfo.TYPE_TEXT_FLAG_MULTI_LINE);
@@ -216,14 +227,6 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
return false;
}
});
- messageEditText.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (isPopupShowing()) {
- showPopup(AndroidUtilities.usingHardwareInput ? 0 : 2, 0);
- }
- }
- });
messageEditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
@@ -240,6 +243,8 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
}
});
messageEditText.addTextChangedListener(new TextWatcher() {
+ boolean processChange = false;
+
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
@@ -247,16 +252,20 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
- String message = getTrimmedString(charSequence.toString());
+ if (innerTextChange == 1) {
+ return;
+ }
checkSendButton(true);
-
+ String message = getTrimmedString(charSequence.toString());
if (delegate != null) {
if (count > 2 || charSequence == null || charSequence.length() == 0) {
messageWebPageSearch = true;
}
delegate.onTextChanged(charSequence, before > count + 1 || (count - before) > 2);
}
-
+ if (innerTextChange != 2 && before != count && (count - before) > 1) {
+ processChange = true;
+ }
if (message.length() != 0 && lastTypingTimeSend < System.currentTimeMillis() - 5000 && !ignoreTextChange) {
int currentTime = ConnectionsManager.getInstance().getCurrentTime();
TLRPC.User currentUser = null;
@@ -275,19 +284,19 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
@Override
public void afterTextChanged(Editable editable) {
+ if (innerTextChange != 0) {
+ return;
+ }
if (sendByEnter && editable.length() > 0 && editable.charAt(editable.length() - 1) == '\n') {
sendMessage();
}
- int i = 0;
- ImageSpan[] arrayOfImageSpan = editable.getSpans(0, editable.length(), ImageSpan.class);
- int j = arrayOfImageSpan.length;
- while (true) {
- if (i >= j) {
- Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20));
- return;
+ if (processChange) {
+ ImageSpan[] spans = editable.getSpans(0, editable.length(), ImageSpan.class);
+ for (int i = 0; i < spans.length; i++) {
+ editable.removeSpan(spans[i]);
}
- editable.removeSpan(arrayOfImageSpan[i]);
- i++;
+ Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
+ processChange = false;
}
}
});
@@ -590,7 +599,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
delegate.onWindowSizeChanged(size);
}
if (topView != null) {
- if (size < AndroidUtilities.dp(72) + AndroidUtilities.getCurrentActionBarHeight()) {
+ if (size < AndroidUtilities.dp(72) + ActionBar.getCurrentActionBarHeight()) {
if (allowShowTopView) {
allowShowTopView = false;
if (needShowTopView) {
@@ -773,11 +782,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
});
runningAnimation2.start();
- if (messageEditText != null) {
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams();
- layoutParams.rightMargin = AndroidUtilities.dp(0);
- messageEditText.setLayoutParams(layoutParams);
- }
+ updateFieldRight(0);
delegate.onAttachButtonHidden();
}
@@ -823,9 +828,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
attachButton.setVisibility(View.GONE);
attachButton.clearAnimation();
delegate.onAttachButtonHidden();
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams();
- layoutParams.rightMargin = AndroidUtilities.dp(0);
- messageEditText.setLayoutParams(layoutParams);
+ updateFieldRight(0);
}
}
}
@@ -854,11 +857,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
runningAnimation2.setDuration(100);
runningAnimation2.start();
- if (messageEditText != null) {
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams();
- layoutParams.rightMargin = AndroidUtilities.dp(50);
- messageEditText.setLayoutParams(layoutParams);
- }
+ updateFieldRight(1);
delegate.onAttachButtonShow();
}
@@ -903,14 +902,37 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
if (attachButton != null) {
delegate.onAttachButtonShow();
attachButton.setVisibility(View.VISIBLE);
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams();
- layoutParams.rightMargin = AndroidUtilities.dp(50);
- messageEditText.setLayoutParams(layoutParams);
+ updateFieldRight(1);
}
}
}
}
+ private void updateFieldRight(int attachVisible) {
+ if (messageEditText == null) {
+ return;
+ }
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) messageEditText.getLayoutParams();
+ if (attachVisible == 1) {
+ if (botButton != null && botButton.getVisibility() == VISIBLE) {
+ layoutParams.rightMargin = AndroidUtilities.dp(98);
+ } else {
+ layoutParams.rightMargin = AndroidUtilities.dp(50);
+ }
+ } else if (attachVisible == 2) {
+ if (layoutParams.rightMargin != AndroidUtilities.dp(2)) {
+ if (botButton != null && botButton.getVisibility() == VISIBLE) {
+ layoutParams.rightMargin = AndroidUtilities.dp(98);
+ } else {
+ layoutParams.rightMargin = AndroidUtilities.dp(50);
+ }
+ }
+ } else {
+ layoutParams.rightMargin = AndroidUtilities.dp(2);
+ }
+ messageEditText.setLayoutParams(layoutParams);
+ }
+
private void updateAudioRecordIntefrace() {
if (recordingAudio) {
if (audioInterfaceState == 1) {
@@ -1108,6 +1130,7 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
} else {
botButton.setVisibility(GONE);
}
+ updateFieldRight(2);
ViewProxy.setPivotX(attachButton, AndroidUtilities.dp(botButton.getVisibility() == GONE ? 48 : 96));
attachButton.clearAnimation();
}
@@ -1209,12 +1232,15 @@ public class ChatActivityEnterView extends FrameLayoutFixed implements Notificat
i = 0;
}
try {
- CharSequence localCharSequence = Emoji.replaceEmoji(symbol/* + "\uFE0F"*/, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20));
+ innerTextChange = 2;
+ CharSequence localCharSequence = Emoji.replaceEmoji(symbol/* + "\uFE0F"*/, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
messageEditText.setText(messageEditText.getText().insert(i, localCharSequence));
int j = i + localCharSequence.length();
messageEditText.setSelection(j, j);
} catch (Exception e) {
FileLog.e("tmessages", e);
+ } finally {
+ innerTextChange = 0;
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java
index 461e32f9b..3b175e09a 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ChatAttachView.java
@@ -8,8 +8,11 @@
package org.telegram.ui.Components;
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Build;
import android.text.TextUtils;
@@ -18,6 +21,7 @@ import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
@@ -25,14 +29,16 @@ import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.android.MediaController;
+import org.telegram.android.NotificationCenter;
import org.telegram.android.support.widget.LinearLayoutManager;
import org.telegram.messenger.R;
import org.telegram.ui.Adapters.PhotoAttachAdapter;
import org.telegram.ui.ChatActivity;
+import java.util.ArrayList;
import java.util.HashMap;
-public class ChatAttachView extends FrameLayout {
+public class ChatAttachView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
public interface ChatAttachViewDelegate {
void didPressedButton(int button);
@@ -42,7 +48,16 @@ public class ChatAttachView extends FrameLayout {
private PhotoAttachAdapter photoAttachAdapter;
private ChatActivity baseFragment;
private AttachButton sendPhotosButton;
- private AttachButton buttons[] = new AttachButton[8];
+ private View views[] = new View[20];
+ private RecyclerListView attachPhotoRecyclerView;
+ private View lineView;
+ private EmptyTextProgressView progressView;
+
+ private float[] distCache = new float[20];
+
+ private DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator();
+
+ private boolean loading;
private ChatAttachViewDelegate delegate;
@@ -56,7 +71,6 @@ public class ChatAttachView extends FrameLayout {
imageView = new ImageView(context);
imageView.setScaleType(ImageView.ScaleType.CENTER);
- //imageView.setColorFilter(0x33000000);
addView(imageView, LayoutHelper.createFrame(64, 64, Gravity.CENTER_HORIZONTAL | Gravity.TOP));
textView = new TextView(context);
@@ -83,10 +97,15 @@ public class ChatAttachView extends FrameLayout {
public ChatAttachView(Context context) {
super(context);
- RecyclerListView attachPhotoRecyclerView = new RecyclerListView(context);
- if (photoAttachAdapter != null) {
- photoAttachAdapter.onDestroy();
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.albumsDidLoaded);
+ if (MediaController.allPhotosAlbumEntry == null) {
+ if (Build.VERSION.SDK_INT >= 21) {
+ MediaController.loadGalleryPhotosAlbums(0);
+ }
+ loading = true;
}
+
+ views[8] = attachPhotoRecyclerView = new RecyclerListView(context);
attachPhotoRecyclerView.setVerticalScrollBarEnabled(true);
attachPhotoRecyclerView.setAdapter(photoAttachAdapter = new PhotoAttachAdapter(context));
attachPhotoRecyclerView.setClipToPadding(false);
@@ -112,11 +131,14 @@ public class ChatAttachView extends FrameLayout {
}
});
- View lineView = new View(getContext());
+ views[9] = progressView = new EmptyTextProgressView(context);
+ progressView.setText(LocaleController.getString("NoPhotos", R.string.NoPhotos));
+ addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 80));
+ attachPhotoRecyclerView.setEmptyView(progressView);
+
+ views[10] = lineView = new View(getContext());
lineView.setBackgroundColor(0xffd2d2d2);
- FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1, Gravity.TOP | Gravity.LEFT);
- layoutParams.topMargin = AndroidUtilities.dp(88);
- addView(lineView, layoutParams);
+ addView(lineView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 1, Gravity.TOP | Gravity.LEFT));
CharSequence[] items = new CharSequence[]{
LocaleController.getString("ChatCamera", R.string.ChatCamera),
LocaleController.getString("ChatGallery", R.string.ChatGallery),
@@ -128,23 +150,21 @@ public class ChatAttachView extends FrameLayout {
""
};
int itemIcons[] = new int[] {
- R.drawable.ic_attach_photo_big,
- R.drawable.ic_attach_gallery_big,
- R.drawable.ic_attach_video_big,
- R.drawable.ic_attach_music_big,
- R.drawable.ic_attach_file_big,
- R.drawable.ic_attach_contact_big,
- R.drawable.ic_attach_location_big,
- R.drawable.ic_attach_hide_big,
+ R.drawable.attach_camera_states,
+ R.drawable.attach_gallery_states,
+ R.drawable.attach_video_states,
+ R.drawable.attach_audio_states,
+ R.drawable.attach_file_states,
+ R.drawable.attach_contact_states,
+ R.drawable.attach_location_states,
+ R.drawable.attach_hide_states,
};
for (int a = 0; a < 8; a++) {
AttachButton attachButton = new AttachButton(context);
attachButton.setTextAndIcon(items[a], itemIcons[a]);
- int y = 97 + 95 * (a / 4);
- int x = 10 + (a % 4) * 85;
- addView(attachButton, LayoutHelper.createFrame(85, 90, Gravity.LEFT | Gravity.TOP, x, y, 0, 0));
+ addView(attachButton, LayoutHelper.createFrame(85, 90, Gravity.LEFT | Gravity.TOP));
attachButton.setTag(a);
- buttons[a] = attachButton;
+ views[a] = attachButton;
if (a == 7) {
sendPhotosButton = attachButton;
sendPhotosButton.imageView.setPadding(0, AndroidUtilities.dp(4), 0, 0);
@@ -164,24 +184,58 @@ public class ChatAttachView extends FrameLayout {
return true;
}
});
+
+ if (loading) {
+ progressView.showProgress();
+ } else {
+ progressView.showTextView();
+ }
+ }
+
+ @Override
+ public void didReceivedNotification(int id, Object... args) {
+ if (id == NotificationCenter.albumsDidLoaded) {
+ if (photoAttachAdapter != null) {
+ loading = false;
+ progressView.showTextView();
+ photoAttachAdapter.notifyDataSetChanged();
+ }
+ }
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
- super.onMeasure(widthSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(278), MeasureSpec.EXACTLY));
+ super.onMeasure(widthSpec, MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(294), MeasureSpec.EXACTLY));
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ int width = right - left;
+
+ int t = AndroidUtilities.dp(8);
+ attachPhotoRecyclerView.layout(0, t, width, t + attachPhotoRecyclerView.getMeasuredHeight());
+ progressView.layout(0, t, width, t + progressView.getMeasuredHeight());
+ lineView.layout(0, AndroidUtilities.dp(96), width, AndroidUtilities.dp(96) + lineView.getMeasuredHeight());
+
+ int diff = (width - AndroidUtilities.dp(85 * 4 + 20)) / 3;
+ for (int a = 0; a < 8; a++) {
+ int y = AndroidUtilities.dp(105 + 95 * (a / 4));
+ int x = AndroidUtilities.dp(10) + (a % 4) * (AndroidUtilities.dp(85) + diff);
+ views[a].layout(x, y, x + views[a].getMeasuredWidth(), y + views[a].getMeasuredHeight());
+ }
}
public void updatePhotosButton() {
int count = photoAttachAdapter.getSelectedPhotos().size();
if (count == 0) {
sendPhotosButton.imageView.setPadding(0, AndroidUtilities.dp(4), 0, 0);
- sendPhotosButton.imageView.setBackgroundResource(R.drawable.ic_attach_hide_big);
- sendPhotosButton.imageView.setImageResource(R.drawable.ic_attach_hide_big_icon);
+ sendPhotosButton.imageView.setBackgroundResource(R.drawable.attach_hide_states);
+ sendPhotosButton.imageView.setImageResource(R.drawable.attach_hide2);
sendPhotosButton.textView.setText("");
} else {
sendPhotosButton.imageView.setPadding(AndroidUtilities.dp(2), 0, 0, 0);
- sendPhotosButton.imageView.setBackgroundResource(R.drawable.ic_attach_send_big);
- sendPhotosButton.imageView.setImageResource(R.drawable.ic_attach_send_big_icon);
+ sendPhotosButton.imageView.setBackgroundResource(R.drawable.attach_send_states);
+ sendPhotosButton.imageView.setImageResource(R.drawable.attach_send2);
sendPhotosButton.textView.setText(LocaleController.formatString("SendItems", R.string.SendItems, String.format("(%d)", count)));
}
}
@@ -190,22 +244,83 @@ public class ChatAttachView extends FrameLayout {
delegate = chatAttachViewDelegate;
}
- public void startAnimations(boolean up) {
- for (int a = 0; a < 4; a++) {
- //buttons[a].setTranslationY(AndroidUtilities.dp(up ? 20 : -20));
- //buttons[a + 4].setTranslationY(AndroidUtilities.dp(up ? 20 : -20));
- buttons[a].setScaleX(0.8f);
- buttons[a].setScaleY(0.8f);
- buttons[a + 4].setScaleX(0.8f);
- buttons[a + 4].setScaleY(0.8f);
- AnimatorSet animatorSet = new AnimatorSet();
- animatorSet.playTogether(ObjectAnimator.ofFloat(buttons[a], "scaleX", 1),
- ObjectAnimator.ofFloat(buttons[a + 4], "scaleX", 1),
- ObjectAnimator.ofFloat(buttons[a], "scaleY", 1),
- ObjectAnimator.ofFloat(buttons[a + 4], "scaleY", 1));
- animatorSet.setDuration(150);
- animatorSet.setStartDelay((3 - a) * 40);
- animatorSet.start();
+ public void onRevealAnimationEnd(boolean open) {
+ if (open && Build.VERSION.SDK_INT <= 19 && MediaController.allPhotosAlbumEntry == null) {
+ MediaController.loadGalleryPhotosAlbums(0);
+ }
+ }
+
+ @SuppressLint("NewApi")
+ public void onRevealAnimationStart(boolean open) {
+ if (!open) {
+ return;
+ }
+ int count = Build.VERSION.SDK_INT <= 19 ? 11 : 8;
+ for (int a = 0; a < count; a++) {
+ if (Build.VERSION.SDK_INT <= 19) {
+ if (a < 8) {
+ views[a].setScaleX(0.1f);
+ views[a].setScaleY(0.1f);
+ }
+ views[a].setAlpha(0.0f);
+ } else {
+ views[a].setScaleX(0.7f);
+ views[a].setScaleY(0.7f);
+ }
+ views[a].setTag(R.string.AppName, null);
+ distCache[a] = 0;
+ }
+ }
+
+ @SuppressLint("NewApi")
+ public void onRevealAnimationProgress(boolean open, float radius, int x, int y) {
+ if (!open) {
+ return;
+ }
+ int count = Build.VERSION.SDK_INT <= 19 ? 11 : 8;
+ for (int a = 0; a < count; a++) {
+ if (views[a].getTag(R.string.AppName) == null) {
+ if (distCache[a] == 0) {
+ int buttonX = views[a].getLeft() + views[a].getMeasuredWidth() / 2;
+ int buttonY = views[a].getTop() + views[a].getMeasuredHeight() / 2;
+ distCache[a] = (float) Math.sqrt((x - buttonX) * (x - buttonX) + (y - buttonY) * (y - buttonY));
+ float vecX = (x - buttonX) / distCache[a];
+ float vecY = (y - buttonY) / distCache[a];
+ views[a].setPivotX(views[a].getMeasuredWidth() / 2 + vecX * AndroidUtilities.dp(20));
+ views[a].setPivotY(views[a].getMeasuredHeight() / 2 + vecY * AndroidUtilities.dp(20));
+ }
+ if (distCache[a] > radius + AndroidUtilities.dp(27)) {
+ continue;
+ }
+
+ views[a].setTag(R.string.AppName, 1);
+ final ArrayList animators = new ArrayList<>();
+ final ArrayList animators2 = new ArrayList<>();
+ if (a < 8) {
+ animators.add(ObjectAnimator.ofFloat(views[a], "scaleX", 0.7f, 1.05f));
+ animators.add(ObjectAnimator.ofFloat(views[a], "scaleY", 0.7f, 1.05f));
+ animators2.add(ObjectAnimator.ofFloat(views[a], "scaleX", 1.0f));
+ animators2.add(ObjectAnimator.ofFloat(views[a], "scaleY", 1.0f));
+ }
+ if (Build.VERSION.SDK_INT <= 19) {
+ animators.add(ObjectAnimator.ofFloat(views[a], "alpha", 1.0f));
+ }
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(animators);
+ animatorSet.setDuration(150);
+ animatorSet.setInterpolator(decelerateInterpolator);
+ animatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ AnimatorSet animatorSet = new AnimatorSet();
+ animatorSet.playTogether(animators2);
+ animatorSet.setDuration(100);
+ animatorSet.setInterpolator(decelerateInterpolator);
+ animatorSet.start();
+ }
+ });
+ animatorSet.start();
+ }
}
}
@@ -221,7 +336,7 @@ public class ChatAttachView extends FrameLayout {
}
public void onDestroy() {
- photoAttachAdapter.onDestroy();
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.albumsDidLoaded);
baseFragment = null;
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java
new file mode 100644
index 000000000..3e39df2e0
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/DrawerPlayerView.java
@@ -0,0 +1,130 @@
+/*
+ * This is the source code of Telegram for Android v. 2.x.x.
+ * It is licensed under GNU GPL v. 2 or later.
+ * You should have received a copy of the license in this archive (see LICENSE).
+ *
+ * Copyright Nikolai Kudashov, 2013-2015.
+ */
+
+package org.telegram.ui.Components;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import org.telegram.android.AndroidUtilities;
+import org.telegram.android.MediaController;
+import org.telegram.android.MessageObject;
+import org.telegram.android.NotificationCenter;
+import org.telegram.messenger.R;
+
+public class DrawerPlayerView extends FrameLayout implements NotificationCenter.NotificationCenterDelegate {
+
+ private ImageView playButton;
+ private TextView titleTextView;
+ private ListView parentListView;
+ private MessageObject lastMessageObject;
+
+ public DrawerPlayerView(Context context, ListView listView) {
+ super(context);
+ parentListView = listView;
+
+ View shadow = new View(context);
+ shadow.setBackgroundResource(R.drawable.header_shadow_reverse);
+ addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3));
+
+ FrameLayout frameLayout = new FrameLayout(context);
+ frameLayout.setBackgroundColor(0xffffffff);
+ addView(frameLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, 0, 3, 0, 0));
+
+ playButton = new ImageView(context);
+ playButton.setScaleType(ImageView.ScaleType.CENTER);
+ addView(playButton, LayoutHelper.createFrame(48, 48, Gravity.TOP | Gravity.LEFT, 2, 3, 0, 0));
+ playButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (MediaController.getInstance().isAudioPaused()) {
+ MediaController.getInstance().playAudio(MediaController.getInstance().getPlayingMessageObject());
+ } else {
+ MediaController.getInstance().pauseAudio(MediaController.getInstance().getPlayingMessageObject());
+ }
+ }
+ });
+
+ titleTextView = new TextView(context);
+ titleTextView.setTextColor(0xff15a5ed);
+ titleTextView.setMaxLines(1);
+ titleTextView.setLines(1);
+ titleTextView.setSingleLine(true);
+ titleTextView.setEllipsize(TextUtils.TruncateAt.END);
+ titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 15);
+ titleTextView.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
+ titleTextView.setGravity(Gravity.CENTER_VERTICAL);
+ addView(titleTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP, 72, 3, 8, 0));
+
+ checkPlayer();
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidReset);
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioPlayStateChanged);
+ NotificationCenter.getInstance().removeObserver(this, NotificationCenter.audioDidStarted);
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidReset);
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioPlayStateChanged);
+ NotificationCenter.getInstance().addObserver(this, NotificationCenter.audioDidStarted);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, AndroidUtilities.dp(51));
+ }
+
+ @Override
+ public void didReceivedNotification(int id, Object... args) {
+ if (id == NotificationCenter.audioDidStarted || id == NotificationCenter.audioPlayStateChanged || id == NotificationCenter.audioDidReset) {
+ checkPlayer();
+ }
+ }
+
+ private void checkPlayer() {
+ MessageObject messageObject = MediaController.getInstance().getPlayingMessageObject();
+ if (messageObject == null || !messageObject.isMusic()) {
+ lastMessageObject = null;
+ if (getVisibility() != GONE) {
+ setVisibility(GONE);
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) parentListView.getLayoutParams();
+ layoutParams.bottomMargin = 0;
+ parentListView.setLayoutParams(layoutParams);
+ }
+ } else {
+ if (getVisibility() != VISIBLE) {
+ setVisibility(VISIBLE);
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) parentListView.getLayoutParams();
+ layoutParams.bottomMargin = AndroidUtilities.dp(48);
+ parentListView.setLayoutParams(layoutParams);
+ }
+ if (MediaController.getInstance().isAudioPaused()) {
+ playButton.setImageResource(R.drawable.menu_play);
+ } else {
+ playButton.setImageResource(R.drawable.menu_pause);
+ }
+ if (lastMessageObject != messageObject) {
+ lastMessageObject = messageObject;
+ titleTextView.setText(String.format("%s - %s", messageObject.getMusicAuthor(), messageObject.getMusicTitle()));
+ }
+ }
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java
index 076a91869..683ad8e31 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmojiView.java
@@ -196,6 +196,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
scrollSlidingTabStrip.setUnderlineHeight(AndroidUtilities.dp(1));
scrollSlidingTabStrip.setIndicatorColor(0xffe2e5e7);
scrollSlidingTabStrip.setUnderlineColor(0xffe2e5e7);
+ scrollSlidingTabStrip.setVisibility(INVISIBLE);
addView(scrollSlidingTabStrip, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.LEFT | Gravity.TOP));
ViewProxy.setTranslationX(scrollSlidingTabStrip, AndroidUtilities.displaySize.x);
updateStickerTabs();
@@ -360,6 +361,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
if (ViewProxy.getTranslationX(pagerSlidingTabStripContainer) != margin) {
ViewProxy.setTranslationX(pagerSlidingTabStripContainer, margin);
ViewProxy.setTranslationX(scrollSlidingTabStrip, width + margin);
+ scrollSlidingTabStrip.setVisibility(margin < 0 ? VISIBLE : INVISIBLE);
if (Build.VERSION.SDK_INT < 11) {
if (margin <= -width) {
pagerSlidingTabStripContainer.clearAnimation();
@@ -449,7 +451,7 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
stringBuilder.append("=");
stringBuilder.append(entry.getValue());
}
- getContext().getSharedPreferences("emoji", 0).edit().putString("stickers", stringBuilder.toString()).commit();
+ preferences.edit().putString("stickers", stringBuilder.toString()).commit();
}
private void sortStickers() {
@@ -565,10 +567,12 @@ public class EmojiView extends FrameLayout implements NotificationCenter.Notific
layoutParams.width = View.MeasureSpec.getSize(widthMeasureSpec);
if (scrollSlidingTabStrip != null) {
layoutParams1 = (FrameLayout.LayoutParams) scrollSlidingTabStrip.getLayoutParams();
- layoutParams1.width = layoutParams.width;
+ if (layoutParams1 != null) {
+ layoutParams1.width = layoutParams.width;
+ }
}
if (layoutParams.width != oldWidth) {
- if (scrollSlidingTabStrip != null) {
+ if (scrollSlidingTabStrip != null && layoutParams1 != null) {
onPageScrolled(pager.getCurrentItem(), layoutParams.width, 0);
scrollSlidingTabStrip.setLayoutParams(layoutParams1);
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java
index 0e38769e6..3bd67919d 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/EmptyTextProgressView.java
@@ -17,6 +17,7 @@ import android.widget.FrameLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
+import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.messenger.R;
@@ -39,6 +40,7 @@ public class EmptyTextProgressView extends FrameLayout {
textView.setTextColor(0xff808080);
textView.setGravity(Gravity.CENTER);
textView.setVisibility(INVISIBLE);
+ textView.setPadding(AndroidUtilities.dp(20), 0, AndroidUtilities.dp(20), 0);
textView.setText(LocaleController.getString("NoResult", R.string.NoResult));
addView(textView, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
@@ -81,7 +83,6 @@ public class EmptyTextProgressView extends FrameLayout {
continue;
}
- LayoutParams lp = (LayoutParams) child.getLayoutParams();
int x = (width - child.getMeasuredWidth()) / 2;
int y;
if (showAtCenter) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java
index aedc5bcd6..9ac490ad4 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LetterSectionsListView.java
@@ -113,7 +113,7 @@ public class LetterSectionsListView extends ListView implements AbsListView.OnSc
header.setTag(-header.getHeight());
} else if (pos == count - 2) {
View child = getChildAt(itemNum - firstVisibleItem);
- int headerTop = 0;
+ int headerTop;
if (child != null) {
headerTop = child.getTop();
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java
index 60c2522eb..74f4168a5 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/LineProgressView.java
@@ -25,6 +25,9 @@ public class LineProgressView extends View {
private float animatedProgressValue = 0;
private float animatedAlphaValue = 1.0f;
+ private int backColor;
+ private int progressColor = 0xff36a2ee;
+
private static DecelerateInterpolator decelerateInterpolator = null;
private static Paint progressPaint = null;
@@ -37,7 +40,6 @@ public class LineProgressView extends View {
progressPaint.setStyle(Paint.Style.STROKE);
progressPaint.setStrokeCap(Paint.Cap.ROUND);
progressPaint.setStrokeWidth(AndroidUtilities.dp(2));
- progressPaint.setColor(0xff36a2ee);
}
}
@@ -70,7 +72,11 @@ public class LineProgressView extends View {
}
public void setProgressColor(int color) {
- progressPaint.setColor(color);
+ progressColor = color;
+ }
+
+ public void setBackColor(int color) {
+ backColor = color;
}
public void setProgress(float value, boolean animated) {
@@ -91,6 +97,14 @@ public class LineProgressView extends View {
}
public void onDraw(Canvas canvas) {
+ if (backColor != 0 && animatedProgressValue != 1) {
+ progressPaint.setColor(backColor);
+ progressPaint.setAlpha((int) (255 * animatedAlphaValue));
+ int start = (int) (getWidth() * animatedProgressValue);
+ canvas.drawRect(start, 0, getWidth(), getHeight(), progressPaint);
+ }
+
+ progressPaint.setColor(progressColor);
progressPaint.setAlpha((int)(255 * animatedAlphaValue));
canvas.drawRect(0, 0, getWidth() * animatedProgressValue, getHeight(), progressPaint);
updateAnimation();
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java
index e87f71c0c..10b9309ae 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/NumberPicker.java
@@ -533,7 +533,6 @@ public class NumberPicker extends LinearLayout {
}
maxTextWidth = (int) (numberOfDigits * maxDigitWidth);
} else {
- final int valueCount = mDisplayedValues.length;
for (String mDisplayedValue : mDisplayedValues) {
final float textWidth = mSelectorWheelPaint.measureText(mDisplayedValue);
if (textWidth > maxTextWidth) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java
index 6321efc63..b4d408792 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PagerSlidingTabStrip.java
@@ -15,7 +15,6 @@ import android.graphics.Paint.Style;
import android.os.Build;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
-import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.FrameLayout;
@@ -70,8 +69,6 @@ public class PagerSlidingTabStrip extends HorizontalScrollView {
tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
addView(tabsContainer);
- DisplayMetrics dm = getResources().getDisplayMetrics();
-
rectPaint = new Paint();
rectPaint.setAntiAlias(true);
rectPaint.setStyle(Style.FILL);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java
index 22f7a4326..1834f9cf4 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PasscodeView.java
@@ -671,7 +671,6 @@ public class PasscodeView extends FrameLayout {
@Override
public void onClick(View v) {
int tag = (Integer) v.getTag();
- int key = KeyEvent.KEYCODE_DEL;
switch (tag) {
case 0:
passwordEditText2.appendCharacter("0");
@@ -845,7 +844,6 @@ public class PasscodeView extends FrameLayout {
}
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("mainconfig", Activity.MODE_PRIVATE);
int selectedBackground = preferences.getInt("selectedBackground", 1000001);
- boolean customTheme = false;
if (selectedBackground == 1000001) {
backgroundFrameLayout.setBackgroundColor(0xff517c9e);
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java
index ced235b6a..d2de9216e 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoFilterView.java
@@ -11,9 +11,7 @@ package org.telegram.ui.Components;
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.Matrix;
-import android.graphics.Paint;
import android.graphics.SurfaceTexture;
import android.opengl.GLES20;
import android.opengl.GLUtils;
@@ -1205,28 +1203,29 @@ public class PhotoFilterView extends FrameLayout {
}
private Bitmap createBitmap(Bitmap bitmap, int w, int h, float scale) {
- Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(result);
- Paint paint = new Paint();
- paint.setFilterBitmap(true);
+ //Bitmap result = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
+ //Canvas canvas = new Canvas(result);
+ //Paint paint = new Paint();
+ //paint.setFilterBitmap(true);
Matrix matrix = new Matrix();
matrix.setScale(scale, scale);
- matrix.postTranslate(-bitmap.getWidth() / 2, -bitmap.getHeight() / 2);
+ //matrix.postTranslate(-bitmap.getWidth() / 2, -bitmap.getHeight() / 2);
matrix.postRotate(orientation);
- if (orientation == 90 || orientation == 270) {
+ /*if (orientation == 90 || orientation == 270) {
matrix.postTranslate(bitmap.getHeight() / 2, bitmap.getWidth() / 2);
} else {
matrix.postTranslate(bitmap.getWidth() / 2, bitmap.getHeight() / 2);
- }
- canvas.drawBitmap(bitmap, matrix, paint);
- try {
- canvas.setBitmap(null);
- } catch (Exception e) {
+ }*/
+ //canvas.drawBitmap(bitmap, matrix, paint);
+ //try {
+ // canvas.setBitmap(null);
+ //} catch (Exception e) {
//don't promt, this will crash on 2.x
- }
+ //}
+ return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
- return result;
+ //return result;
}
private void loadTexture(Bitmap bitmap) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java
index fcff6ef23..4f0051ce5 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoViewerCaptionEnterView.java
@@ -62,6 +62,8 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not
private boolean keyboardVisible;
private int emojiPadding;
+ private boolean innerTextChange;
+
private PhotoViewerCaptionEnterViewDelegate delegate;
public PhotoViewerCaptionEnterView(Context context, SizeNotifierFrameLayoutPhoto parent) {
@@ -149,6 +151,8 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not
}
});
messageEditText.addTextChangedListener(new TextWatcher() {
+ boolean processChange = false;
+
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i2, int i3) {
@@ -156,23 +160,31 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
+ if (innerTextChange) {
+ return;
+ }
+
if (delegate != null) {
delegate.onTextChanged(charSequence);
}
+
+ if (before != count && (count - before) > 1) {
+ processChange = true;
+ }
}
@Override
public void afterTextChanged(Editable editable) {
- int i = 0;
- ImageSpan[] arrayOfImageSpan = editable.getSpans(0, editable.length(), ImageSpan.class);
- int j = arrayOfImageSpan.length;
- while (true) {
- if (i >= j) {
- Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20));
- return;
+ if (innerTextChange) {
+ return;
+ }
+ if (processChange) {
+ ImageSpan[] spans = editable.getSpans(0, editable.length(), ImageSpan.class);
+ for (int i = 0; i < spans.length; i++) {
+ editable.removeSpan(spans[i]);
}
- editable.removeSpan(arrayOfImageSpan[i]);
- i++;
+ Emoji.replaceEmoji(editable, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
+ processChange = false;
}
}
});
@@ -299,12 +311,15 @@ public class PhotoViewerCaptionEnterView extends FrameLayoutFixed implements Not
i = 0;
}
try {
- CharSequence localCharSequence = Emoji.replaceEmoji(symbol, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20));
+ innerTextChange = true;
+ CharSequence localCharSequence = Emoji.replaceEmoji(symbol/* + "\uFE0F"*/, messageEditText.getPaint().getFontMetricsInt(), AndroidUtilities.dp(20), false);
messageEditText.setText(messageEditText.getText().insert(i, localCharSequence));
int j = i + localCharSequence.length();
messageEditText.setSelection(j, j);
} catch (Exception e) {
FileLog.e("tmessages", e);
+ } finally {
+ innerTextChange = false;
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPickerBottomLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java
similarity index 81%
rename from TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPickerBottomLayout.java
rename to TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java
index 67c72c127..657566273 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PhotoPickerBottomLayout.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PickerBottomLayout.java
@@ -20,22 +20,30 @@ import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
import org.telegram.messenger.R;
-public class PhotoPickerBottomLayout extends FrameLayout {
+public class PickerBottomLayout extends FrameLayout {
public LinearLayout doneButton;
public TextView cancelButton;
public TextView doneButtonTextView;
public TextView doneButtonBadgeTextView;
- public PhotoPickerBottomLayout(Context context) {
+ private boolean isDarkTheme;
+
+ public PickerBottomLayout(Context context) {
+ this(context, true);
+ }
+
+ public PickerBottomLayout(Context context, boolean darkTheme) {
super(context);
- setBackgroundColor(0xff1a1a1a);
+ isDarkTheme = darkTheme;
+
+ setBackgroundColor(isDarkTheme ? 0xff1a1a1a : 0xffffffff);
cancelButton = new TextView(context);
cancelButton.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
- cancelButton.setTextColor(0xffffffff);
+ cancelButton.setTextColor(isDarkTheme ? 0xffffffff : 0xff19a7e8);
cancelButton.setGravity(Gravity.CENTER);
- cancelButton.setBackgroundResource(R.drawable.bar_selector_picker);
+ cancelButton.setBackgroundResource(isDarkTheme ? R.drawable.bar_selector_picker : R.drawable.bar_selector_audio);
cancelButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0);
cancelButton.setText(LocaleController.getString("Cancel", R.string.Cancel).toUpperCase());
cancelButton.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));
@@ -48,7 +56,7 @@ public class PhotoPickerBottomLayout extends FrameLayout {
doneButton = new LinearLayout(context);
doneButton.setOrientation(LinearLayout.HORIZONTAL);
- doneButton.setBackgroundResource(R.drawable.bar_selector_picker);
+ doneButton.setBackgroundResource(isDarkTheme ? R.drawable.bar_selector_picker : R.drawable.bar_selector_audio);
doneButton.setPadding(AndroidUtilities.dp(29), 0, AndroidUtilities.dp(29), 0);
addView(doneButton);
layoutParams = (LayoutParams) doneButton.getLayoutParams();
@@ -62,7 +70,7 @@ public class PhotoPickerBottomLayout extends FrameLayout {
doneButtonBadgeTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 13);
doneButtonBadgeTextView.setTextColor(0xffffffff);
doneButtonBadgeTextView.setGravity(Gravity.CENTER);
- doneButtonBadgeTextView.setBackgroundResource(R.drawable.photobadge);
+ doneButtonBadgeTextView.setBackgroundResource(isDarkTheme ? R.drawable.photobadge : R.drawable.bluecounter);
doneButtonBadgeTextView.setMinWidth(AndroidUtilities.dp(23));
doneButtonBadgeTextView.setPadding(AndroidUtilities.dp(8), 0, AndroidUtilities.dp(8), AndroidUtilities.dp(1));
doneButton.addView(doneButtonBadgeTextView);
@@ -75,7 +83,7 @@ public class PhotoPickerBottomLayout extends FrameLayout {
doneButtonTextView = new TextView(context);
doneButtonTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 14);
- doneButtonTextView.setTextColor(0xffffffff);
+ doneButtonTextView.setTextColor(isDarkTheme ? 0xffffffff : 0xff19a7e8);
doneButtonTextView.setGravity(Gravity.CENTER);
doneButtonTextView.setCompoundDrawablePadding(AndroidUtilities.dp(8));
doneButtonTextView.setText(LocaleController.getString("Send", R.string.Send).toUpperCase());
@@ -96,18 +104,16 @@ public class PhotoPickerBottomLayout extends FrameLayout {
doneButtonTextView.setTextColor(0xff999999);
doneButton.setEnabled(false);
} else {
- doneButtonTextView.setTextColor(0xffffffff);
+ doneButtonTextView.setTextColor(isDarkTheme ? 0xffffffff : 0xff19a7e8);
}
} else {
doneButtonTextView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
doneButtonBadgeTextView.setVisibility(View.VISIBLE);
doneButtonBadgeTextView.setText(String.format("%d", count));
+ doneButtonTextView.setTextColor(isDarkTheme ? 0xffffffff : 0xff19a7e8);
if (disable) {
- doneButtonTextView.setTextColor(0xffffffff);
doneButton.setEnabled(true);
- } else {
- doneButtonTextView.setTextColor(0xffffffff);
}
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java
index c6f7bb038..d145ca2f6 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/PopupAudioView.java
@@ -90,11 +90,6 @@ public class PopupAudioView extends BaseCell implements SeekBar.SeekBarDelegate,
public void setMessageObject(MessageObject messageObject) {
if (currentMessageObject != messageObject) {
- int uid = messageObject.messageOwner.media.audio.user_id;
- if (uid == 0) {
- uid = messageObject.messageOwner.from_id;
- }
-
seekBar.type = 1;
progressView.setProgressColors(0xffd9e2eb, 0xff86c5f8);
@@ -269,7 +264,7 @@ public class PopupAudioView extends BaseCell implements SeekBar.SeekBarDelegate,
seekBar.setProgress(currentMessageObject.audioProgress);
}
- int duration = 0;
+ int duration;
if (!MediaController.getInstance().isPlayingAudio(currentMessageObject)) {
duration = currentMessageObject.messageOwner.media.audio.duration;
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java
index af86334cd..8826b64a2 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RadialProgress.java
@@ -35,6 +35,7 @@ public class RadialProgress {
private Drawable currentDrawable;
private Drawable previousDrawable;
private boolean hideCurrentDrawable;
+ private int progressColor = 0xffffffff;
private static DecelerateInterpolator decelerateInterpolator = null;
private static Paint progressPaint = null;
@@ -46,7 +47,6 @@ public class RadialProgress {
progressPaint.setStyle(Paint.Style.STROKE);
progressPaint.setStrokeCap(Paint.Cap.ROUND);
progressPaint.setStrokeWidth(AndroidUtilities.dp(2));
- progressPaint.setColor(0xffffffff);
}
parent = parentView;
}
@@ -86,7 +86,7 @@ public class RadialProgress {
}
public void setProgressColor(int color) {
- progressPaint.setColor(color);
+ progressColor = color;
}
public void setHideCurrentDrawable(boolean value) {
@@ -154,6 +154,7 @@ public class RadialProgress {
if (currentWithRound || previousWithRound) {
int diff = AndroidUtilities.dp(1);
+ progressPaint.setColor(progressColor);
if (previousWithRound) {
progressPaint.setAlpha((int)(255 * animatedAlphaValue));
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java
index b356c7196..f503341e1 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/RecyclerListView.java
@@ -161,6 +161,11 @@ public class RecyclerListView extends RecyclerView {
public void onTouchEvent(RecyclerView view, MotionEvent e) {
}
+
+ @Override
+ public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
+
+ }
}
private AdapterDataObserver observer = new AdapterDataObserver() {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java
index a5b56b4d3..9b4ce1c41 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/ScrollSlidingTabStrip.java
@@ -12,7 +12,6 @@ import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
-import android.util.DisplayMetrics;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
@@ -61,8 +60,6 @@ public class ScrollSlidingTabStrip extends HorizontalScrollView {
tabsContainer.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
addView(tabsContainer);
- DisplayMetrics dm = getResources().getDisplayMetrics();
-
rectPaint = new Paint();
rectPaint.setAntiAlias(true);
rectPaint.setStyle(Style.FILL);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java
index bc15136a0..727b3bacb 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SeekBar.java
@@ -11,11 +11,9 @@ package org.telegram.ui.Components;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
-import android.graphics.drawable.Drawable;
import android.view.MotionEvent;
import org.telegram.android.AndroidUtilities;
-import org.telegram.messenger.R;
public class SeekBar {
@@ -23,14 +21,10 @@ public class SeekBar {
void onSeekBarDrag(float progress);
}
- private static Drawable thumbDrawable1;
- private static Drawable thumbDrawablePressed1;
- private static Drawable thumbDrawable2;
- private static Drawable thumbDrawablePressed2;
- private static Paint innerPaint1 = new Paint();
- private static Paint outerPaint1 = new Paint();
- private static Paint innerPaint2 = new Paint();
- private static Paint outerPaint2 = new Paint();
+ private static Paint innerPaint1;
+ private static Paint outerPaint1;
+ private static Paint innerPaint2;
+ private static Paint outerPaint2;
private static int thumbWidth;
private static int thumbHeight;
public int type;
@@ -42,17 +36,21 @@ public class SeekBar {
public SeekBarDelegate delegate;
public SeekBar(Context context) {
- if (thumbDrawable1 == null) {
- thumbDrawable1 = context.getResources().getDrawable(R.drawable.player1);
- thumbDrawablePressed1 = context.getResources().getDrawable(R.drawable.player1_pressed);
- thumbDrawable2 = context.getResources().getDrawable(R.drawable.player2);
- thumbDrawablePressed2 = context.getResources().getDrawable(R.drawable.player2_pressed);
- innerPaint1.setColor(0xffb4e396);
- outerPaint1.setColor(0xff6ac453);
- innerPaint2.setColor(0xffd9e2eb);
- outerPaint2.setColor(0xff86c5f8);
- thumbWidth = thumbDrawable1.getIntrinsicWidth();
- thumbHeight = thumbDrawable1.getIntrinsicHeight();
+ if (innerPaint1 == null) {
+ innerPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
+ innerPaint1.setColor(0xffc3e3ab);
+
+ outerPaint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
+ outerPaint1.setColor(0xff87bf78);
+
+ innerPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
+ innerPaint2.setColor(0xffe4eaf0);
+
+ outerPaint2 = new Paint(Paint.ANTI_ALIAS_FLAG);
+ outerPaint2.setColor(0xff4195e5);
+
+ thumbWidth = AndroidUtilities.dp(24);
+ thumbHeight = AndroidUtilities.dp(24);
}
}
@@ -100,30 +98,18 @@ public class SeekBar {
}
public void draw(Canvas canvas) {
- Drawable thumb = null;
Paint inner = null;
Paint outer = null;
if (type == 0) {
- if (!pressed) {
- thumb = thumbDrawable1;
- } else {
- thumb = thumbDrawablePressed1;
- }
inner = innerPaint1;
outer = outerPaint1;
} else if (type == 1) {
- if (!pressed) {
- thumb = thumbDrawable2;
- } else {
- thumb = thumbDrawablePressed2;
- }
inner = innerPaint2;
outer = outerPaint2;
}
int y = (height - thumbHeight) / 2;
canvas.drawRect(thumbWidth / 2, height / 2 - AndroidUtilities.dp(1), width - thumbWidth / 2, height / 2 + AndroidUtilities.dp(1), inner);
canvas.drawRect(thumbWidth / 2, height / 2 - AndroidUtilities.dp(1), thumbWidth / 2 + thumbX, height / 2 + AndroidUtilities.dp(1), outer);
- thumb.setBounds(thumbX, y, thumbX + thumbWidth, y + thumbHeight);
- thumb.draw(canvas);
+ canvas.drawCircle(thumbX + thumbWidth / 2, y + thumbHeight / 2, AndroidUtilities.dp(pressed ? 8 : 6), outer);
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java
new file mode 100644
index 000000000..c64b07616
--- /dev/null
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/SpannableStringLight.java
@@ -0,0 +1,88 @@
+/*
+ * This is the source code of Telegram for Android v. 2.x.x.
+ * It is licensed under GNU GPL v. 2 or later.
+ * You should have received a copy of the license in this archive (see LICENSE).
+ *
+ * Copyright Nikolai Kudashov, 2013-2015.
+ */
+
+package org.telegram.ui.Components;
+
+import android.text.SpannableString;
+
+import org.telegram.messenger.FileLog;
+
+import java.lang.reflect.Field;
+
+public class SpannableStringLight extends SpannableString {
+
+ private static Field mSpansField;
+ private static Field mSpanDataField;
+ private static Field mSpanCountField;
+ private static boolean fieldsAvailable;
+
+ private Object[] mSpansOverride;
+ private int[] mSpanDataOverride;
+ private int mSpanCountOverride;
+ private int num;
+
+ public SpannableStringLight(CharSequence source) {
+ super(source);
+
+ try {
+ mSpansOverride = (Object[]) mSpansField.get(this);
+ mSpanDataOverride = (int[]) mSpanDataField.get(this);
+ mSpanCountOverride = (int) mSpanCountField.get(this);
+ } catch (Throwable e) {
+ FileLog.e("tmessages", e);
+ }
+ }
+
+ public void setSpansCount(int count) {
+ count += mSpanCountOverride;
+ mSpansOverride = new Object[count];
+ mSpanDataOverride = new int[count * 3];
+ num = mSpanCountOverride;
+ mSpanCountOverride = count;
+
+ try {
+ mSpansField.set(this, mSpansOverride);
+ mSpanDataField.set(this, mSpanDataOverride);
+ mSpanCountField.set(this, mSpanCountOverride);
+ } catch (Throwable e) {
+ FileLog.e("tmessages", e);
+ }
+ }
+
+ public static boolean isFieldsAvailable() {
+ if (!fieldsAvailable && mSpansField == null) {
+ try {
+ mSpansField = SpannableString.class.getSuperclass().getDeclaredField("mSpans");
+ mSpansField.setAccessible(true);
+
+ mSpanDataField = SpannableString.class.getSuperclass().getDeclaredField("mSpanData");
+ mSpanDataField.setAccessible(true);
+
+ mSpanCountField = SpannableString.class.getSuperclass().getDeclaredField("mSpanCount");
+ mSpanCountField.setAccessible(true);
+ } catch (Throwable e) {
+ FileLog.e("tmessages", e);
+ }
+ fieldsAvailable = true;
+ }
+ return mSpansField != null;
+ }
+
+ public void setSpanLight(Object what, int start, int end, int flags) {
+ mSpansOverride[num] = what;
+ mSpanDataOverride[num * 3] = start;
+ mSpanDataOverride[num * 3 + 1] = end;
+ mSpanDataOverride[num * 3 + 2] = flags;
+ num++;
+ }
+
+ @Override
+ public void removeSpan(Object what) {
+ super.removeSpan(what);
+ }
+}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java
index fa6740a9d..b57b21894 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/Switch.java
@@ -555,8 +555,6 @@ public class Switch extends CompoundButton {
final int switchTop = mSwitchTop;
final int switchBottom = mSwitchBottom;
- final int switchInnerTop = switchTop + padding.top;
- final int switchInnerBottom = switchBottom - padding.bottom;
final Drawable thumbDrawable = mThumbDrawable;
if (trackDrawable != null) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java
index 7bfd47999..1aae15996 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TimerDrawable.java
@@ -45,7 +45,7 @@ public class TimerDrawable extends Drawable {
public void setTime(int value) {
time = value;
- String timeString = null;
+ String timeString;
if (time >= 1 && time < 60) {
timeString = "" + value;
if (timeString.length() < 2) {
@@ -91,7 +91,7 @@ public class TimerDrawable extends Drawable {
public void draw(Canvas canvas) {
int width = timerDrawable.getIntrinsicWidth();
int height = timerDrawable.getIntrinsicHeight();
- Drawable drawable = null;
+ Drawable drawable;
if (time == 0) {
drawable = timerDrawable;
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java
index d644d7d6d..f26e450f8 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/TypingDotsDrawable.java
@@ -88,7 +88,7 @@ public class TypingDotsDrawable extends Drawable {
@Override
public void draw(Canvas canvas) {
- int y = 0;
+ int y;
if (isChat) {
y = AndroidUtilities.dp(6);
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java
index d562cc6bb..980237dfc 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/VideoTimelineView.java
@@ -202,7 +202,6 @@ public class VideoTimelineView extends View {
int h = (int) (bitmap.getHeight() * scale);
Rect srcRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Rect destRect = new Rect((frameWidth - w) / 2, (frameHeight - h) / 2, w, h);
- Paint paint = new Paint();
canvas.drawBitmap(bitmap, srcRect, destRect, null);
bitmap.recycle();
bitmap = result;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java
index d794f29db..e42fe5ae4 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/Components/WebFrameLayout.java
@@ -59,6 +59,10 @@ public class WebFrameLayout extends FrameLayout {
openUrl = originalUrl;
width = w;
height = h;
+ if (width == 0 || height == 0) {
+ width = AndroidUtilities.displaySize.x;
+ height = AndroidUtilities.displaySize.y / 2;
+ }
dialog = parentDialog;
fullscreenVideoContainer = new FrameLayout(context);
@@ -211,10 +215,6 @@ public class WebFrameLayout extends FrameLayout {
});
parentDialog.setDelegate(new BottomSheet.BottomSheetDelegate() {
- @Override
- public void onOpenAnimationStart() {
-
- }
@Override
public void onOpenAnimationEnd() {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java
index c09173f9d..f57e4f9bc 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactAddActivity.java
@@ -17,7 +17,6 @@ import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
@@ -79,7 +78,7 @@ public class ContactAddActivity extends BaseFragment implements NotificationCent
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
if (addContact) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java
index 6a6695aeb..88ce8849b 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ContactsActivity.java
@@ -20,7 +20,6 @@ import android.text.InputType;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -125,7 +124,7 @@ public class ContactsActivity extends BaseFragment implements NotificationCenter
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
searching = false;
searchWas = false;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java
index 3058d6912..16e710294 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/CountrySelectActivity.java
@@ -11,7 +11,6 @@ package org.telegram.ui;
import android.content.Context;
import android.os.Build;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
@@ -62,7 +61,7 @@ public class CountrySelectActivity extends BaseFragment {
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("ChooseCountry", R.string.ChooseCountry));
@@ -185,7 +184,7 @@ public class CountrySelectActivity extends BaseFragment {
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, int i, long l) {
- Country country = null;
+ Country country;
if (searching && searchWas) {
country = searchListViewAdapter.getItem(i);
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java
similarity index 98%
rename from TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java
rename to TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java
index 53ec757da..3362c6714 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/MessagesActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/DialogsActivity.java
@@ -20,7 +20,6 @@ import android.os.Build;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewOutlineProvider;
@@ -67,7 +66,7 @@ import org.telegram.ui.Components.ResourceLoader;
import java.util.ArrayList;
-public class MessagesActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
+public class DialogsActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate {
private RecyclerListView listView;
private LinearLayoutManager layoutManager;
@@ -101,10 +100,10 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
private MessagesActivityDelegate delegate;
public interface MessagesActivityDelegate {
- void didSelectDialog(MessagesActivity fragment, long dialog_id, boolean param);
+ void didSelectDialog(DialogsActivity fragment, long dialog_id, boolean param);
}
- public MessagesActivity(Bundle args) {
+ public DialogsActivity(Bundle args) {
super(args);
}
@@ -165,7 +164,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
}
@Override
- public View createView(final Context context, LayoutInflater inflater) {
+ public View createView(final Context context) {
searching = false;
searchWas = false;
@@ -887,7 +886,7 @@ public class MessagesActivity extends BaseFragment implements NotificationCenter
showDialog(builder.create());
} else {
if (delegate != null) {
- delegate.didSelectDialog(MessagesActivity.this, dialog_id, param);
+ delegate.didSelectDialog(DialogsActivity.this, dialog_id, param);
delegate = null;
} else {
finishFragment();
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java
index 260092182..cee01daf9 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/DocumentSelectActivity.java
@@ -19,7 +19,6 @@ import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -126,7 +125,7 @@ public class DocumentSelectActivity extends BaseFragment {
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
if (!receiverRegistered) {
receiverRegistered = true;
IntentFilter filter = new IntentFilter();
@@ -194,7 +193,7 @@ public class DocumentSelectActivity extends BaseFragment {
actionModeViews.add(actionMode.addItem(done, R.drawable.ic_ab_done_gray, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54)));
- fragmentView = inflater.inflate(R.layout.document_select_layout, null, false);
+ fragmentView = getParentActivity().getLayoutInflater().inflate(R.layout.document_select_layout, null, false);
listAdapter = new ListAdapter(context);
emptyView = (TextView) fragmentView.findViewById(R.id.searchEmptyView);
emptyView.setOnTouchListener(new View.OnTouchListener() {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java
index 2639f756a..a5142a02a 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateActivity.java
@@ -142,7 +142,7 @@ public class GroupCreateActivity extends BaseFragment implements NotificationCen
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
searching = false;
searchWas = false;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java
index 93aaffa07..5684bc3fb 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupCreateFinalActivity.java
@@ -19,7 +19,6 @@ import android.text.InputType;
import android.text.TextWatcher;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
@@ -139,7 +138,7 @@ public class GroupCreateFinalActivity extends BaseFragment implements Notificati
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
if (isBroadcast) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java
index 1ea12de42..3677a8ee9 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/GroupInviteActivity.java
@@ -14,7 +14,6 @@ import android.content.DialogInterface;
import android.content.Intent;
import android.os.Build;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -88,7 +87,7 @@ public class GroupInviteActivity extends BaseFragment implements NotificationCen
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("InviteLink", R.string.InviteLink));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java
index fea96db4c..b75c2d366 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/IdenticonActivity.java
@@ -10,7 +10,6 @@ package org.telegram.ui;
import android.content.Context;
import android.os.Bundle;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
@@ -44,7 +43,7 @@ public class IdenticonActivity extends BaseFragment {
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("EncryptionKey", R.string.EncryptionKey));
@@ -58,7 +57,7 @@ public class IdenticonActivity extends BaseFragment {
}
});
- fragmentView = inflater.inflate(R.layout.identicon_layout, null, false);
+ fragmentView = getParentActivity().getLayoutInflater().inflate(R.layout.identicon_layout, null, false);
ImageView identiconView = (ImageView) fragmentView.findViewById(R.id.identicon_view);
TextView textView = (TextView) fragmentView.findViewById(R.id.identicon_text);
TLRPC.EncryptedChat encryptedChat = MessagesController.getInstance().getEncryptedChat(chat_id);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java
index 96fc7648f..be68ecf57 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/LanguageSelectActivity.java
@@ -12,7 +12,6 @@ import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -53,7 +52,7 @@ public class LanguageSelectActivity extends BaseFragment {
public ArrayList searchResult;
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
searching = false;
searchWas = false;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java
index 1b1f81c04..2ac98eb9f 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenActivity.java
@@ -18,7 +18,6 @@ import android.os.Bundle;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -100,7 +99,7 @@ public class LastSeenActivity extends BaseFragment implements NotificationCenter
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("PrivacyLastSeen", R.string.PrivacyLastSeen));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java
index b476860fc..7b5950b6f 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/LastSeenUsersActivity.java
@@ -14,7 +14,6 @@ import android.content.DialogInterface;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -76,7 +75,7 @@ public class LastSeenUsersActivity extends BaseFragment implements NotificationC
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
if (isAlwaysShare) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java
index e77c865dc..7e9980499 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/LaunchActivity.java
@@ -24,6 +24,7 @@ import android.os.Bundle;
import android.os.Parcelable;
import android.provider.ContactsContract;
import android.view.ActionMode;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
@@ -61,6 +62,7 @@ import org.telegram.ui.Adapters.DrawerLayoutAdapter;
import org.telegram.ui.ActionBar.ActionBarLayout;
import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.ActionBar.DrawerLayoutContainer;
+import org.telegram.ui.Components.DrawerPlayerView;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.PasscodeView;
@@ -70,7 +72,7 @@ import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Map;
-public class LaunchActivity extends Activity implements ActionBarLayout.ActionBarLayoutDelegate, NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate {
+public class LaunchActivity extends Activity implements ActionBarLayout.ActionBarLayoutDelegate, NotificationCenter.NotificationCenterDelegate, DialogsActivity.MessagesActivityDelegate {
private boolean finished;
private String videoPath;
@@ -253,20 +255,22 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
drawerLayoutContainer.addView(actionBarLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
}
- ListView listView = new ListView(this);
- listView.setAdapter(drawerLayoutAdapter = new DrawerLayoutAdapter(this));
- drawerLayoutContainer.setDrawerLayout(listView);
- listView.setBackgroundColor(0xffffffff);
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams)listView.getLayoutParams();
+ FrameLayout listViewContainer = new FrameLayout(this);
+ listViewContainer.setBackgroundColor(0xffffffff);
+ drawerLayoutContainer.setDrawerLayout(listViewContainer);
+ FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) listViewContainer.getLayoutParams();
Point screenSize = AndroidUtilities.getRealScreenSize();
layoutParams.width = AndroidUtilities.isTablet() ? AndroidUtilities.dp(320) : Math.min(screenSize.x, screenSize.y) - AndroidUtilities.dp(56);
layoutParams.height = LayoutHelper.MATCH_PARENT;
- listView.setPadding(0, 0, 0, 0);
+ listViewContainer.setLayoutParams(layoutParams);
+
+ ListView listView = new ListView(this);
+ listView.setAdapter(drawerLayoutAdapter = new DrawerLayoutAdapter(this));
listView.setChoiceMode(AbsListView.CHOICE_MODE_SINGLE);
listView.setDivider(null);
listView.setDividerHeight(0);
- listView.setLayoutParams(layoutParams);
listView.setVerticalScrollBarEnabled(false);
+ listViewContainer.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
@@ -320,6 +324,16 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
}
});
+ DrawerPlayerView drawerPlayerView = new DrawerPlayerView(this, listView);
+ listViewContainer.addView(drawerPlayerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 51, Gravity.LEFT | Gravity.BOTTOM));
+ drawerPlayerView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ actionBarLayout.presentFragment(new AudioPlayerActivity());
+ drawerLayoutContainer.closeDrawer(false);
+ }
+ });
+
drawerLayoutContainer.setParentActionBarLayout(actionBarLayout);
actionBarLayout.setDrawerLayoutContainer(drawerLayoutContainer);
actionBarLayout.init(mainFragmentsStack);
@@ -350,7 +364,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
actionBarLayout.addFragmentToStack(new LoginActivity());
drawerLayoutContainer.setAllowOpenDrawer(false, false);
} else {
- actionBarLayout.addFragmentToStack(new MessagesActivity(null));
+ actionBarLayout.addFragmentToStack(new DialogsActivity(null));
drawerLayoutContainer.setAllowOpenDrawer(true, false);
}
@@ -469,6 +483,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
Integer push_enc_id = 0;
Integer open_settings = 0;
boolean showDialogsList = false;
+ boolean showPlayer = false;
photoPathsArray = null;
videoPath = null;
@@ -589,7 +604,6 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
}
Uri uri = (Uri) parcelable;
if (uri != null && (type != null && type.startsWith("image/") || uri.toString().toLowerCase().endsWith(".jpg"))) {
- String tempPath = AndroidUtilities.getPath(uri);
if (photoPathsArray == null) {
photoPathsArray = new ArrayList<>();
}
@@ -762,6 +776,8 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
} else {
showDialogsList = true;
}
+ } else if (intent.getAction().equals("com.tmessages.openplayer")) {
+ showPlayer = true;
}
}
}
@@ -801,6 +817,30 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
}
pushOpened = false;
isNew = false;
+ } else if (showPlayer) {
+ if (AndroidUtilities.isTablet()) {
+ for (int a = 0; a < layersActionBarLayout.fragmentsStack.size(); a++) {
+ BaseFragment fragment = layersActionBarLayout.fragmentsStack.get(a);
+ if (fragment instanceof AudioPlayerActivity) {
+ layersActionBarLayout.removeFragmentFromStack(fragment);
+ break;
+ }
+ }
+ actionBarLayout.showLastFragment();
+ rightActionBarLayout.showLastFragment();
+ drawerLayoutContainer.setAllowOpenDrawer(false, false);
+ } else {
+ for (int a = 0; a < actionBarLayout.fragmentsStack.size(); a++) {
+ BaseFragment fragment = actionBarLayout.fragmentsStack.get(a);
+ if (fragment instanceof AudioPlayerActivity) {
+ actionBarLayout.removeFragmentFromStack(fragment);
+ break;
+ }
+ }
+ drawerLayoutContainer.setAllowOpenDrawer(true, false);
+ }
+ actionBarLayout.presentFragment(new AudioPlayerActivity(), false, true, true);
+ pushOpened = true;
} else if (videoPath != null || photoPathsArray != null || sendingText != null || documentsPathsArray != null || contactsToSend != null || documentsUrisArray != null) {
if (!AndroidUtilities.isTablet()) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
@@ -809,13 +849,13 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
args.putBoolean("onlySelect", true);
args.putString("selectAlertString", LocaleController.getString("SendMessagesTo", R.string.SendMessagesTo));
args.putString("selectAlertStringGroup", LocaleController.getString("SendMessagesToGroup", R.string.SendMessagesToGroup));
- MessagesActivity fragment = new MessagesActivity(args);
+ DialogsActivity fragment = new DialogsActivity(args);
fragment.setDelegate(this);
boolean removeLast;
if (AndroidUtilities.isTablet()) {
- removeLast = layersActionBarLayout.fragmentsStack.size() > 0 && layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1) instanceof MessagesActivity;
+ removeLast = layersActionBarLayout.fragmentsStack.size() > 0 && layersActionBarLayout.fragmentsStack.get(layersActionBarLayout.fragmentsStack.size() - 1) instanceof DialogsActivity;
} else {
- removeLast = actionBarLayout.fragmentsStack.size() > 1 && actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1) instanceof MessagesActivity;
+ removeLast = actionBarLayout.fragmentsStack.size() > 1 && actionBarLayout.fragmentsStack.get(actionBarLayout.fragmentsStack.size() - 1) instanceof DialogsActivity;
}
actionBarLayout.presentFragment(fragment, removeLast, true, true);
pushOpened = true;
@@ -851,7 +891,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
}
} else {
if (actionBarLayout.fragmentsStack.isEmpty()) {
- actionBarLayout.addFragmentToStack(new MessagesActivity(null));
+ actionBarLayout.addFragmentToStack(new DialogsActivity(null));
drawerLayoutContainer.setAllowOpenDrawer(true, false);
}
}
@@ -861,7 +901,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
actionBarLayout.addFragmentToStack(new LoginActivity());
drawerLayoutContainer.setAllowOpenDrawer(false, false);
} else {
- actionBarLayout.addFragmentToStack(new MessagesActivity(null));
+ actionBarLayout.addFragmentToStack(new DialogsActivity(null));
drawerLayoutContainer.setAllowOpenDrawer(true, false);
}
}
@@ -920,10 +960,10 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
args.putBoolean("onlySelect", true);
args.putInt("dialogsType", 2);
args.putString("addToGroupAlertString", LocaleController.formatString("AddToTheGroupTitle", R.string.AddToTheGroupTitle, UserObject.getUserName(user), "%1$s"));
- MessagesActivity fragment = new MessagesActivity(args);
- fragment.setDelegate(new MessagesActivity.MessagesActivityDelegate() {
+ DialogsActivity fragment = new DialogsActivity(args);
+ fragment.setDelegate(new DialogsActivity.MessagesActivityDelegate() {
@Override
- public void didSelectDialog(MessagesActivity fragment, long did, boolean param) {
+ public void didSelectDialog(DialogsActivity fragment, long did, boolean param) {
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
MessagesController.getInstance().addUserToChat(-(int) did, user, null, 0, botChat);
Bundle args = new Bundle();
@@ -1113,7 +1153,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
}
@Override
- public void didSelectDialog(MessagesActivity messageFragment, long dialog_id, boolean param) {
+ public void didSelectDialog(DialogsActivity messageFragment, long dialog_id, boolean param) {
if (dialog_id != 0) {
int lower_part = (int)dialog_id;
int high_id = (int)(dialog_id >> 32);
@@ -1637,9 +1677,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
public boolean needPresentFragment(BaseFragment fragment, boolean removeLast, boolean forceWithoutAnimation, ActionBarLayout layout) {
if (AndroidUtilities.isTablet()) {
drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity || fragment instanceof CountrySelectActivity) && layersActionBarLayout.getVisibility() != View.VISIBLE, true);
- if (fragment instanceof MessagesActivity) {
- MessagesActivity messagesActivity = (MessagesActivity)fragment;
- if (messagesActivity.isMainDialogList() && layout != actionBarLayout) {
+ if (fragment instanceof DialogsActivity) {
+ DialogsActivity dialogsActivity = (DialogsActivity)fragment;
+ if (dialogsActivity.isMainDialogList() && layout != actionBarLayout) {
actionBarLayout.removeAllFragments();
actionBarLayout.presentFragment(fragment, removeLast, forceWithoutAnimation, false);
layersActionBarLayout.removeAllFragments();
@@ -1726,9 +1766,9 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
public boolean needAddFragmentToStack(BaseFragment fragment, ActionBarLayout layout) {
if (AndroidUtilities.isTablet()) {
drawerLayoutContainer.setAllowOpenDrawer(!(fragment instanceof LoginActivity || fragment instanceof CountrySelectActivity) && layersActionBarLayout.getVisibility() != View.VISIBLE, true);
- if (fragment instanceof MessagesActivity) {
- MessagesActivity messagesActivity = (MessagesActivity)fragment;
- if (messagesActivity.isMainDialogList() && layout != actionBarLayout) {
+ if (fragment instanceof DialogsActivity) {
+ DialogsActivity dialogsActivity = (DialogsActivity)fragment;
+ if (dialogsActivity.isMainDialogList() && layout != actionBarLayout) {
actionBarLayout.removeAllFragments();
actionBarLayout.addFragmentToStack(fragment);
layersActionBarLayout.removeAllFragments();
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java
index 9907ecccb..36cec820e 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/LocationActivity.java
@@ -21,7 +21,6 @@ import android.os.Build;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -107,7 +106,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter
private CircleOptions circleOptions;
private LocationActivityDelegate delegate;
- private int overScrollHeight = AndroidUtilities.displaySize.x - AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(66);
+ private int overScrollHeight = AndroidUtilities.displaySize.x - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(66);
private int halfHeight;
private final static int share = 1;
@@ -152,7 +151,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
if (AndroidUtilities.isTablet()) {
@@ -501,7 +500,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter
View shadow = new View(context);
shadow.setBackgroundResource(R.drawable.header_shadow_reverse);
- mapViewClip.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, AndroidUtilities.dp(3), Gravity.LEFT | Gravity.BOTTOM));
+ mapViewClip.addView(shadow, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 3, Gravity.LEFT | Gravity.BOTTOM));
markerImageView = new ImageView(context);
markerImageView.setImageResource(R.drawable.map_pin);
@@ -696,7 +695,7 @@ public class LocationActivity extends BaseFragment implements NotificationCenter
private void fixLayoutInternal(final boolean resume) {
if (listView != null) {
- int height = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight();
+ int height = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight();
int viewHeight = fragmentView.getMeasuredHeight();
if (viewHeight == 0) {
return;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java
index dfe8b5867..1d8bddab0 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/LoginActivity.java
@@ -34,7 +34,6 @@ import android.text.method.PasswordTransformationMethod;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.AccelerateDecelerateInterpolator;
@@ -109,7 +108,7 @@ public class LoginActivity extends BaseFragment {
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setTitle(LocaleController.getString("AppName", R.string.AppName));
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
@@ -395,7 +394,7 @@ public class LoginActivity extends BaseFragment {
public void needFinishActivity() {
clearCurrentState();
- presentFragment(new MessagesActivity(null), true);
+ presentFragment(new DialogsActivity(null), true);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mainUserInfoChanged);
}
@@ -724,11 +723,9 @@ public class LoginActivity extends BaseFragment {
if (!codeText.equals(resultCode)) {
phone = PhoneFormat.getInstance().format(phoneField.getText().toString()).trim();
phoneField.setText(phone);
- int len = phoneField.length();
phoneField.setSelection(phoneField.length());
} else {
phoneField.setText(phone.substring(idx).trim());
- int len = phoneField.length();
phoneField.setSelection(phoneField.length());
}
} else {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java
index fb10c8d0e..b52d4b1ad 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/MediaActivity.java
@@ -21,7 +21,6 @@ import android.os.Bundle;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
@@ -40,6 +39,7 @@ import android.widget.TextView;
import org.telegram.android.AndroidUtilities;
import org.telegram.android.LocaleController;
+import org.telegram.android.MediaController;
import org.telegram.android.MessagesController;
import org.telegram.android.query.SharedMediaQuery;
import org.telegram.messenger.ApplicationLoader;
@@ -217,7 +217,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setTitle("");
actionBar.setAllowOverlayTitle(false);
@@ -284,10 +284,10 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
Bundle args = new Bundle();
args.putBoolean("onlySelect", true);
args.putInt("dialogsType", 1);
- MessagesActivity fragment = new MessagesActivity(args);
- fragment.setDelegate(new MessagesActivity.MessagesActivityDelegate() {
+ DialogsActivity fragment = new DialogsActivity(args);
+ fragment.setDelegate(new DialogsActivity.MessagesActivityDelegate() {
@Override
- public void didSelectDialog(MessagesActivity fragment, long did, boolean param) {
+ public void didSelectDialog(DialogsActivity fragment, long did, boolean param) {
int lower_part = (int) did;
if (lower_part != 0) {
Bundle args = new Bundle();
@@ -374,14 +374,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
dropDownContainer.setSubMenuOpenSide(1);
dropDownContainer.addSubItem(shared_media_item, LocaleController.getString("SharedMediaTitle", R.string.SharedMediaTitle), 0);
dropDownContainer.addSubItem(files_item, LocaleController.getString("DocumentsTitle", R.string.DocumentsTitle), 0);
- actionBar.addView(dropDownContainer);
- FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) dropDownContainer.getLayoutParams();
- layoutParams.height = LayoutHelper.MATCH_PARENT;
- layoutParams.width = LayoutHelper.WRAP_CONTENT;
- layoutParams.rightMargin = AndroidUtilities.dp(40);
- layoutParams.leftMargin = AndroidUtilities.isTablet() ? AndroidUtilities.dp(64) : AndroidUtilities.dp(56);
- layoutParams.gravity = Gravity.TOP | Gravity.LEFT;
- dropDownContainer.setLayoutParams(layoutParams);
+ actionBar.addView(dropDownContainer, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.MATCH_PARENT, Gravity.TOP | Gravity.LEFT, AndroidUtilities.isTablet() ? 64 : 56, 0, 40, 0));
dropDownContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
@@ -400,13 +393,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
dropDown.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_arrow_drop_down, 0);
dropDown.setCompoundDrawablePadding(AndroidUtilities.dp(4));
dropDown.setPadding(0, 0, AndroidUtilities.dp(10), 0);
- dropDownContainer.addView(dropDown);
- layoutParams = (FrameLayout.LayoutParams) dropDown.getLayoutParams();
- layoutParams.width = LayoutHelper.WRAP_CONTENT;
- layoutParams.height = LayoutHelper.WRAP_CONTENT;
- layoutParams.leftMargin = AndroidUtilities.dp(16);
- layoutParams.gravity = Gravity.CENTER_VERTICAL;
- dropDown.setLayoutParams(layoutParams);
+ dropDownContainer.addView(dropDown, LayoutHelper.createFrame(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER_VERTICAL, 16, 0, 0, 0));
final ActionBarMenu actionMode = actionBar.createActionMode();
actionModeViews.add(actionMode.addItem(-2, R.drawable.ic_ab_back_grey, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54)));
@@ -426,12 +413,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
return true;
}
});
- actionMode.addView(selectedMessagesCountTextView);
- LinearLayout.LayoutParams layoutParams1 = (LinearLayout.LayoutParams) selectedMessagesCountTextView.getLayoutParams();
- layoutParams1.weight = 1;
- layoutParams1.width = 0;
- layoutParams1.height = LayoutHelper.MATCH_PARENT;
- selectedMessagesCountTextView.setLayoutParams(layoutParams1);
+ actionMode.addView(selectedMessagesCountTextView, LayoutHelper.createLinear(0, LayoutHelper.MATCH_PARENT, 1.0f));
if ((int) dialog_id != 0) {
actionModeViews.add(actionMode.addItem(forward, R.drawable.ic_ab_fwd_forward, R.drawable.bar_selector_mode, null, AndroidUtilities.dp(54)));
@@ -450,12 +432,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
listView.setDividerHeight(0);
listView.setDrawSelectorOnTop(true);
listView.setClipToPadding(false);
- frameLayout.addView(listView);
- layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams();
- layoutParams.width = LayoutHelper.MATCH_PARENT;
- layoutParams.height = LayoutHelper.MATCH_PARENT;
- layoutParams.gravity = Gravity.TOP;
- listView.setLayoutParams(layoutParams);
+ frameLayout.addView(listView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> adapterView, View view, final int i, long l) {
@@ -515,11 +492,7 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
emptyView.setGravity(Gravity.CENTER);
emptyView.setVisibility(View.GONE);
emptyView.setBackgroundColor(0xfff0f0f0);
- frameLayout.addView(emptyView);
- layoutParams = (FrameLayout.LayoutParams) emptyView.getLayoutParams();
- layoutParams.width = LayoutHelper.MATCH_PARENT;
- layoutParams.height = LayoutHelper.MATCH_PARENT;
- emptyView.setLayoutParams(layoutParams);
+ frameLayout.addView(emptyView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
emptyView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
@@ -528,42 +501,24 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
});
emptyImageView = new ImageView(context);
- emptyView.addView(emptyImageView);
- layoutParams1 = (LinearLayout.LayoutParams) emptyImageView.getLayoutParams();
- layoutParams1.width = LayoutHelper.WRAP_CONTENT;
- layoutParams1.height = LayoutHelper.WRAP_CONTENT;
- emptyImageView.setLayoutParams(layoutParams1);
+ emptyView.addView(emptyImageView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
emptyTextView = new TextView(context);
emptyTextView.setTextColor(0xff8a8a8a);
emptyTextView.setGravity(Gravity.CENTER);
emptyTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 17);
emptyTextView.setPadding(AndroidUtilities.dp(40), 0, AndroidUtilities.dp(40), AndroidUtilities.dp(128));
- emptyView.addView(emptyTextView);
- layoutParams1 = (LinearLayout.LayoutParams) emptyTextView.getLayoutParams();
- layoutParams1.topMargin = AndroidUtilities.dp(24);
- layoutParams1.width = LayoutHelper.WRAP_CONTENT;
- layoutParams1.height = LayoutHelper.WRAP_CONTENT;
- layoutParams1.gravity = Gravity.CENTER;
- emptyTextView.setLayoutParams(layoutParams1);
+ emptyView.addView(emptyTextView, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT, Gravity.CENTER, 0, 24, 0, 0));
progressView = new LinearLayout(context);
progressView.setGravity(Gravity.CENTER);
progressView.setOrientation(LinearLayout.VERTICAL);
progressView.setVisibility(View.GONE);
progressView.setBackgroundColor(0xfff0f0f0);
- frameLayout.addView(progressView);
- layoutParams = (FrameLayout.LayoutParams) progressView.getLayoutParams();
- layoutParams.width = LayoutHelper.MATCH_PARENT;
- layoutParams.height = LayoutHelper.MATCH_PARENT;
- progressView.setLayoutParams(layoutParams);
+ frameLayout.addView(progressView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT));
ProgressBar progressBar = new ProgressBar(context);
- progressView.addView(progressBar);
- layoutParams1 = (LinearLayout.LayoutParams) progressBar.getLayoutParams();
- layoutParams1.width = LayoutHelper.WRAP_CONTENT;
- layoutParams1.height = LayoutHelper.WRAP_CONTENT;
- progressBar.setLayoutParams(layoutParams1);
+ progressView.addView(progressBar, LayoutHelper.createLinear(LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT));
switchToCurrentSelectedMode();
@@ -639,7 +594,6 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
} else if (id == NotificationCenter.didReceivedNewMessages) {
long uid = (Long) args[0];
if (uid == dialog_id) {
- boolean markAsRead = false;
ArrayList arr = (ArrayList) args[1];
boolean enc = ((int) dialog_id) == 0;
boolean updated = false;
@@ -804,7 +758,6 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
} else if (selectedMode == 1) {
listView.setAdapter(documentsAdapter);
dropDown.setText(LocaleController.getString("DocumentsTitle", R.string.DocumentsTitle));
- int lower_id = (int) dialog_id;
emptyImageView.setImageResource(R.drawable.tip2);
emptyTextView.setText(LocaleController.getString("NoSharedFiles", R.string.NoSharedFiles));
searchItem.setVisibility(!sharedMediaData[1].messages.isEmpty() ? View.VISIBLE : View.GONE);
@@ -887,6 +840,11 @@ public class MediaActivity extends BaseFragment implements NotificationCenter.No
if (view instanceof SharedDocumentCell) {
SharedDocumentCell cell = (SharedDocumentCell) view;
if (cell.isLoaded()) {
+ if (message.isMusic()) {
+ if (MediaController.getInstance().setPlaylist(sharedMediaData[1].messages, message)) {
+ return;
+ }
+ }
File f = null;
String fileName = FileLoader.getAttachFileName(message.messageOwner.media.document);
if (message.messageOwner.attachPath != null && message.messageOwner.attachPath.length() != 0) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java
index a2ad12143..84ae277c6 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/NotificationsSettingsActivity.java
@@ -20,7 +20,6 @@ import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -88,7 +87,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
private int otherSectionRow2;
private int otherSectionRow;
private int badgeNumberRow;
- private int pebbleAlertRow;
private int androidAutoAlertRow;
private int repeatRow;
private int resetSectionRow2;
@@ -143,7 +141,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
otherSectionRow = rowCount++;
badgeNumberRow = rowCount++;
androidAutoAlertRow = -1;
- pebbleAlertRow = rowCount++;
repeatRow = rowCount++;
resetSectionRow2 = rowCount++;
resetSectionRow = rowCount++;
@@ -161,7 +158,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds));
@@ -321,12 +318,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
MessagesController.getInstance().enableJoined = !enabled;
editor.putBoolean("EnableContactJoined", !enabled);
editor.commit();
- } else if (i == pebbleAlertRow) {
- SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
- SharedPreferences.Editor editor = preferences.edit();
- enabled = preferences.getBoolean("EnablePebbleNotifications", false);
- editor.putBoolean("EnablePebbleNotifications", !enabled);
- editor.commit();
} else if (i == androidAutoAlertRow) {
SharedPreferences preferences = ApplicationLoader.applicationContext.getSharedPreferences("Notifications", Activity.MODE_PRIVATE);
SharedPreferences.Editor editor = preferences.edit();
@@ -448,7 +439,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
builder.setTitle(LocaleController.getString("Vibrate", R.string.Vibrate));
builder.setItems(new CharSequence[]{
LocaleController.getString("VibrationDisabled", R.string.VibrationDisabled),
- LocaleController.getString("Default", R.string.Default),
+ LocaleController.getString("VibrationDefault", R.string.VibrationDefault),
LocaleController.getString("Short", R.string.Short),
LocaleController.getString("Long", R.string.Long),
LocaleController.getString("OnlyIfSilent", R.string.OnlyIfSilent)
@@ -708,8 +699,6 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
checkCell.setTextAndCheck(LocaleController.getString("NotificationsPriority", R.string.NotificationsPriority), preferences.getBoolean("EnableInAppPriority", false), false);
} else if (i == contactJoinedRow) {
checkCell.setTextAndCheck(LocaleController.getString("ContactJoined", R.string.ContactJoined), preferences.getBoolean("EnableContactJoined", true), false);
- } else if (i == pebbleAlertRow) {
- checkCell.setTextAndCheck(LocaleController.getString("Pebble", R.string.Pebble), preferences.getBoolean("EnablePebbleNotifications", false), true);
} else if (i == androidAutoAlertRow) {
checkCell.setTextAndCheck("Android Auto", preferences.getBoolean("EnableAutoNotifications", false), true);
} else if (i == notificationsServiceRow) {
@@ -771,7 +760,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
value = preferences.getInt("vibrate_group", 0);
}
if (value == 0) {
- textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Default", R.string.Default), true);
+ textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("VibrationDefault", R.string.VibrationDefault), true);
} else if (value == 1) {
textCell.setTextAndValue(LocaleController.getString("Vibrate", R.string.Vibrate), LocaleController.getString("Short", R.string.Short), true);
} else if (value == 2) {
@@ -837,7 +826,7 @@ public class NotificationsSettingsActivity extends BaseFragment implements Notif
return 0;
} else if (i == messageAlertRow || i == messagePreviewRow || i == groupAlertRow ||
i == groupPreviewRow || i == inappSoundRow || i == inappVibrateRow ||
- i == inappPreviewRow || i == contactJoinedRow || i == pebbleAlertRow ||
+ i == inappPreviewRow || i == contactJoinedRow ||
i == notificationsServiceRow || i == badgeNumberRow || i == inappPriorityRow ||
i == inchatSoundRow || i == androidAutoAlertRow) {
return 1;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java
index 677837b97..c48cc65aa 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PasscodeActivity.java
@@ -27,7 +27,6 @@ import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -108,7 +107,7 @@ public class PasscodeActivity extends BaseFragment implements NotificationCenter
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
if (type != 3) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java
index 74b2b80f6..303bc9f85 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoAlbumPickerActivity.java
@@ -15,7 +15,6 @@ import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.text.TextUtils;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.View;
@@ -42,7 +41,7 @@ import org.telegram.ui.Adapters.BaseFragmentAdapter;
import org.telegram.ui.Cells.PhotoPickerAlbumsCell;
import org.telegram.ui.Cells.PhotoPickerSearchCell;
import org.telegram.ui.Components.LayoutHelper;
-import org.telegram.ui.Components.PhotoPickerBottomLayout;
+import org.telegram.ui.Components.PickerBottomLayout;
import java.util.ArrayList;
import java.util.HashMap;
@@ -72,7 +71,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati
private TextView emptyView;
private TextView dropDown;
private ActionBarMenuItem dropDownContainer;
- private PhotoPickerBottomLayout photoPickerBottomLayout;
+ private PickerBottomLayout pickerBottomLayout;
private boolean sendPressed = false;
private boolean singlePhoto = false;
private int selectedMode;
@@ -109,7 +108,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati
@SuppressWarnings("unchecked")
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackgroundColor(0xff333333);
actionBar.setItemsBackground(R.drawable.bar_selector_picker);
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
@@ -256,20 +255,20 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati
layoutParams.gravity = Gravity.CENTER;
progressView.setLayoutParams(layoutParams);
- photoPickerBottomLayout = new PhotoPickerBottomLayout(context);
- frameLayout.addView(photoPickerBottomLayout);
- layoutParams = (FrameLayout.LayoutParams) photoPickerBottomLayout.getLayoutParams();
+ pickerBottomLayout = new PickerBottomLayout(context);
+ frameLayout.addView(pickerBottomLayout);
+ layoutParams = (FrameLayout.LayoutParams) pickerBottomLayout.getLayoutParams();
layoutParams.width = LayoutHelper.MATCH_PARENT;
layoutParams.height = AndroidUtilities.dp(48);
layoutParams.gravity = Gravity.BOTTOM;
- photoPickerBottomLayout.setLayoutParams(layoutParams);
- photoPickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() {
+ pickerBottomLayout.setLayoutParams(layoutParams);
+ pickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finishFragment();
}
});
- photoPickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() {
+ pickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendSelectedPhotos();
@@ -284,7 +283,7 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati
progressView.setVisibility(View.GONE);
listView.setEmptyView(emptyView);
}
- photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
+ pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
return fragmentView;
}
@@ -464,8 +463,8 @@ public class PhotoAlbumPickerActivity extends BaseFragment implements Notificati
fragment.setDelegate(new PhotoPickerActivity.PhotoPickerActivityDelegate() {
@Override
public void selectedPhotosChanged() {
- if (photoPickerBottomLayout != null) {
- photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
+ if (pickerBottomLayout != null) {
+ pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
}
}
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java
index fd947b253..db5fba6ec 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoCropActivity.java
@@ -16,7 +16,6 @@ import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Bundle;
import android.util.AttributeSet;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
@@ -400,7 +399,7 @@ public class PhotoCropActivity extends BaseFragment {
return false;
}
}
- int size = 0;
+ int size;
if (AndroidUtilities.isTablet()) {
size = AndroidUtilities.dp(520);
} else {
@@ -432,7 +431,7 @@ public class PhotoCropActivity extends BaseFragment {
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackgroundColor(0xff333333);
actionBar.setItemsBackground(R.drawable.bar_selector_picker);
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java
index a9f420e8c..4c0f327a4 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoPickerActivity.java
@@ -61,7 +61,7 @@ import org.telegram.ui.ActionBar.BaseFragment;
import org.telegram.ui.Cells.PhotoPickerPhotoCell;
import org.telegram.ui.Components.BackupImageView;
import org.telegram.ui.Components.LayoutHelper;
-import org.telegram.ui.Components.PhotoPickerBottomLayout;
+import org.telegram.ui.Components.PickerBottomLayout;
import java.net.URLEncoder;
import java.util.ArrayList;
@@ -98,7 +98,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
private GridView listView;
private ListAdapter listAdapter;
- private PhotoPickerBottomLayout photoPickerBottomLayout;
+ private PickerBottomLayout pickerBottomLayout;
private FrameLayout progressView;
private TextView emptyView;
private ActionBarMenuItem searchItem;
@@ -150,7 +150,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
@SuppressWarnings("unchecked")
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackgroundColor(0xff333333);
actionBar.setItemsBackground(R.drawable.bar_selector_picker);
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
@@ -395,32 +395,32 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
updateSearchInterface();
}
- photoPickerBottomLayout = new PhotoPickerBottomLayout(context);
- frameLayout.addView(photoPickerBottomLayout);
- layoutParams = (FrameLayout.LayoutParams) photoPickerBottomLayout.getLayoutParams();
+ pickerBottomLayout = new PickerBottomLayout(context);
+ frameLayout.addView(pickerBottomLayout);
+ layoutParams = (FrameLayout.LayoutParams) pickerBottomLayout.getLayoutParams();
layoutParams.width = LayoutHelper.MATCH_PARENT;
layoutParams.height = AndroidUtilities.dp(48);
layoutParams.gravity = Gravity.BOTTOM;
- photoPickerBottomLayout.setLayoutParams(layoutParams);
- photoPickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() {
+ pickerBottomLayout.setLayoutParams(layoutParams);
+ pickerBottomLayout.cancelButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
delegate.actionButtonPressed(true);
finishFragment();
}
});
- photoPickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() {
+ pickerBottomLayout.doneButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
sendSelectedPhotos();
}
});
if (singlePhoto) {
- photoPickerBottomLayout.setVisibility(View.GONE);
+ pickerBottomLayout.setVisibility(View.GONE);
}
listView.setEmptyView(emptyView);
- photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
+ pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
return fragmentView;
}
@@ -650,7 +650,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
break;
}
}
- photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
+ pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
delegate.selectedPhotosChanged();
}
@@ -935,7 +935,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
listView.setSelection(position);
if (selectedAlbum == null) {
- emptyView.setPadding(0, 0, 0, (int)((AndroidUtilities.displaySize.y - AndroidUtilities.getCurrentActionBarHeight()) * 0.4f));
+ emptyView.setPadding(0, 0, 0, (int)((AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight()) * 0.4f));
}
}
@@ -1033,7 +1033,7 @@ public class PhotoPickerActivity extends BaseFragment implements NotificationCen
}
((PhotoPickerPhotoCell) v.getParent()).checkBox.setChecked(selectedWebPhotos.containsKey(photoEntry.id), true);
}
- photoPickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
+ pickerBottomLayout.updateSelectedCount(selectedPhotos.size() + selectedWebPhotos.size(), true);
delegate.selectedPhotosChanged();
}
});
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java
index 2816c6257..bffc3f51a 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PhotoViewer.java
@@ -78,7 +78,7 @@ import org.telegram.ui.Components.GifDrawable;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.PhotoCropView;
import org.telegram.ui.Components.PhotoFilterView;
-import org.telegram.ui.Components.PhotoPickerBottomLayout;
+import org.telegram.ui.Components.PickerBottomLayout;
import org.telegram.ui.Components.PhotoViewerCaptionEnterView;
import org.telegram.ui.Components.SizeNotifierFrameLayoutPhoto;
@@ -114,8 +114,8 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
private ImageView shareButton;
private BackgroundDrawable backgroundDrawable = new BackgroundDrawable(0xff000000);
private CheckBox checkImageView;
- private PhotoPickerBottomLayout pickerView;
- private PhotoPickerBottomLayout editorDoneLayout;
+ private PickerBottomLayout pickerView;
+ private PickerBottomLayout editorDoneLayout;
private RadialProgressView radialProgressViews[] = new RadialProgressView[3];
private GifDrawable gifDrawable;
private ActionBarMenuItem cropItem;
@@ -522,8 +522,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int widthMode = MeasureSpec.getMode(widthMeasureSpec);
- int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
@@ -1209,7 +1207,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
dateTextView.setGravity(Gravity.LEFT);
bottomLayout.addView(dateTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.TOP | Gravity.LEFT, 16, 25, 50, 0));
- pickerView = new PhotoPickerBottomLayout(parentActivity);
+ pickerView = new PickerBottomLayout(parentActivity);
pickerView.setBackgroundColor(0x7f000000);
containerView.addView(pickerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, Gravity.BOTTOM | Gravity.LEFT));
pickerView.cancelButton.setOnClickListener(new View.OnClickListener() {
@@ -1231,7 +1229,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
});
- editorDoneLayout = new PhotoPickerBottomLayout(parentActivity);
+ editorDoneLayout = new PickerBottomLayout(parentActivity);
editorDoneLayout.setBackgroundColor(0x7f000000);
editorDoneLayout.updateSelectedCount(0, false);
editorDoneLayout.setVisibility(View.GONE);
@@ -1310,7 +1308,7 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
@Override
public void onWindowSizeChanged(int size) {
int height = AndroidUtilities.dp(36 * Math.min(3, mentionsAdapter.getCount()) + (mentionsAdapter.getCount() > 3 ? 18 : 0));
- if (size - AndroidUtilities.getCurrentActionBarHeight() * 2 < height) {
+ if (size - ActionBar.getCurrentActionBarHeight() * 2 < height) {
allowMentions = false;
if (mentionListView != null && mentionListView.getVisibility() == View.VISIBLE) {
mentionListView.clearAnimation();
@@ -1613,8 +1611,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
float newScaleY = (float) getContainerViewHeight(0) / (float) bitmapHeight;
float scale = scaleX > scaleY ? scaleY : scaleX;
float newScale = newScaleX > newScaleY ? newScaleY : newScaleX;
- int width = (int) (bitmapWidth * scale);
- int height = (int) (bitmapHeight * scale);
animateToScale = newScale / scale;
animateToX = 0;
@@ -1767,8 +1763,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
float newScaleY = (float) getContainerViewHeight(1) / (float) bitmapHeight;
float scale = scaleX > scaleY ? scaleY : scaleX;
float newScale = newScaleX > newScaleY ? newScaleY : newScaleX;
- int width = (int) (bitmapWidth * scale);
- int height = (int) (bitmapHeight * scale);
animateToScale = newScale / scale;
animateToX = 0;
@@ -1887,8 +1881,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
float newScaleY = (float) getContainerViewHeight(2) / (float) bitmapHeight;
float scale = scaleX > scaleY ? scaleY : scaleX;
float newScale = newScaleX > newScaleY ? newScaleY : newScaleX;
- int width = (int) (bitmapWidth * scale);
- int height = (int) (bitmapHeight * scale);
animateToScale = newScale / scale;
animateToX = 0;
@@ -2557,7 +2549,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
captionTextViewNew = captionTextView;
captionItem.setIcon(R.drawable.photo_text2);
- CharSequence oldText = captionTextView.getText();
captionTextView.setTag(caption);
captionTextView.setText(caption);
ViewProxy.setAlpha(captionTextView, bottomLayout.getVisibility() == View.VISIBLE || pickerView.getVisibility() == View.VISIBLE ? 1.0f : 0.0f);
@@ -3055,7 +3046,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
if (animated) {
animationInProgress = 1;
- int visibility = animatingImageView.getVisibility();
animatingImageView.setVisibility(View.VISIBLE);
containerView.invalidate();
@@ -3739,7 +3729,6 @@ public class PhotoViewer implements NotificationCenter.NotificationCenterDelegat
}
ImageReceiver sideImage = null;
- Bitmap bitmap;
if (currentEditMode == 0) {
if (scale >= 1.0f && !zoomAnimation && !zooming) {
if (currentTranslationX > maxX + AndroidUtilities.dp(5)) {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java
index f5d4a8828..0404394b7 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PopupNotificationActivity.java
@@ -153,6 +153,12 @@ public class PopupNotificationActivity extends Activity implements NotificationC
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+
+ int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
+ if (resourceId > 0) {
+ AndroidUtilities.statusBarHeight = getResources().getDimensionPixelSize(resourceId);
+ }
+
classGuid = ConnectionsManager.getInstance().generateClassGuid();
NotificationCenter.getInstance().addObserver(this, NotificationCenter.appDidLogout);
NotificationCenter.getInstance().addObserver(this, NotificationCenter.pushMessagesUpdated);
@@ -822,7 +828,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
if (avatarContainer != null) {
avatarContainer.getViewTreeObserver().removeOnPreDrawListener(this);
}
- int padding = (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2;
+ int padding = (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(48)) / 2;
avatarContainer.setPadding(avatarContainer.getPaddingLeft(), padding, avatarContainer.getPaddingRight(), padding);
return true;
}
@@ -835,7 +841,7 @@ public class PopupNotificationActivity extends Activity implements NotificationC
messageContainer.getViewTreeObserver().removeOnPreDrawListener(this);
if (!checkTransitionAnimation() && !startedMoving) {
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) messageContainer.getLayoutParams();
- layoutParams.topMargin = AndroidUtilities.getCurrentActionBarHeight();
+ layoutParams.topMargin = ActionBar.getCurrentActionBarHeight();
layoutParams.bottomMargin = AndroidUtilities.dp(48);
layoutParams.width = ViewGroup.MarginLayoutParams.MATCH_PARENT;
layoutParams.height = ViewGroup.MarginLayoutParams.MATCH_PARENT;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java
index 6b6449365..78159d5bc 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/PrivacySettingsActivity.java
@@ -12,7 +12,6 @@ import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -90,7 +89,7 @@ public class PrivacySettingsActivity extends BaseFragment implements Notificatio
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("PrivacySettings", R.string.PrivacySettings));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java
index 07f415931..ecc42b868 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileActivity.java
@@ -25,7 +25,6 @@ import android.os.Bundle;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewOutlineProvider;
@@ -87,7 +86,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.concurrent.Semaphore;
-public class ProfileActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, MessagesActivity.MessagesActivityDelegate, PhotoViewer.PhotoViewerProvider {
+public class ProfileActivity extends BaseFragment implements NotificationCenter.NotificationCenterDelegate, DialogsActivity.MessagesActivityDelegate, PhotoViewer.PhotoViewerProvider {
private ListView listView;
private ListAdapter listAdapter;
@@ -245,7 +244,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(user_id != 0 ? 5 : chat_id));
actionBar.setItemsBackground(AvatarDrawable.getButtonColorForId(user_id != 0 ? 5 : chat_id));
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
@@ -290,7 +289,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
Bundle args = new Bundle();
args.putBoolean("onlySelect", true);
args.putInt("dialogsType", 1);
- MessagesActivity fragment = new MessagesActivity(args);
+ DialogsActivity fragment = new DialogsActivity(args);
fragment.setDelegate(ProfileActivity.this);
presentFragment(fragment);
} else if (id == edit_contact) {
@@ -342,10 +341,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
args.putBoolean("onlySelect", true);
args.putInt("dialogsType", 2);
args.putString("addToGroupAlertString", LocaleController.formatString("AddToTheGroupTitle", R.string.AddToTheGroupTitle, UserObject.getUserName(user), "%1$s"));
- MessagesActivity fragment = new MessagesActivity(args);
- fragment.setDelegate(new MessagesActivity.MessagesActivityDelegate() {
+ DialogsActivity fragment = new DialogsActivity(args);
+ fragment.setDelegate(new DialogsActivity.MessagesActivityDelegate() {
@Override
- public void didSelectDialog(MessagesActivity fragment, long did, boolean param) {
+ public void didSelectDialog(DialogsActivity fragment, long did, boolean param) {
NotificationCenter.getInstance().removeObserver(ProfileActivity.this, NotificationCenter.closeChats);
NotificationCenter.getInstance().postNotificationName(NotificationCenter.closeChats);
MessagesController.getInstance().addUserToChat(-(int) did, user, null, 0, null);
@@ -689,7 +688,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
- int action = 0;
if (i == 0) {
avatarUpdater.openCamera();
} else if (i == 1) {
@@ -796,7 +794,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
FrameLayout.LayoutParams layoutParams;
if (listView != null) {
layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams();
- layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight();
+ layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight();
listView.setLayoutParams(layoutParams);
}
@@ -806,7 +804,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
int avatarSize = 42 + (int)(18 * diff);
int avatarX = 17 + (int)(47 * diffm);
- int avatarY = AndroidUtilities.dp(22) - (int)((AndroidUtilities.dp(22) - (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff));
+ int avatarY = AndroidUtilities.dp(22) - (int)((AndroidUtilities.dp(22) - (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff));
int nameX = 97 + (int)(21 * diffm);
int nameEndX = 16 + (int)(32 * diffm);
int nameY = avatarY + AndroidUtilities.dp(29 - 10 * diffm);
@@ -815,7 +813,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
if (writeButton != null) {
layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams();
- layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f);
+ layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f);
writeButton.setLayoutParams(layoutParams);
/*ViewProxy.setAlpha(writeButton, diff);
writeButton.setVisibility(diff <= 0.02 ? View.GONE : View.VISIBLE);
@@ -1240,7 +1238,6 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
emptyRowChat2 = rowCount++;
rowCount += info.participants.size();
membersEndRow = rowCount;
- int maxCount = chat_id > 0 ? MessagesController.getInstance().maxGroupCount : MessagesController.getInstance().maxBroadcastCount;
addMemberRow = rowCount++;
} else {
membersEndRow = -1;
@@ -1358,7 +1355,7 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
}
@Override
- public void didSelectDialog(MessagesActivity messageFragment, long dialog_id, boolean param) {
+ public void didSelectDialog(DialogsActivity messageFragment, long dialog_id, boolean param) {
if (dialog_id != 0) {
Bundle args = new Bundle();
args.putBoolean("scrollToTopOnResume", true);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java
index 103ac0c18..401dbfe86 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/ProfileNotificationsActivity.java
@@ -22,7 +22,6 @@ import android.os.Bundle;
import android.provider.Settings;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -98,7 +97,7 @@ public class ProfileNotificationsActivity extends BaseFragment implements Notifi
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("NotificationsAndSounds", R.string.NotificationsAndSounds));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java
index a7185bc3d..7e89a3458 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/SessionsActivity.java
@@ -15,7 +15,6 @@ import android.content.DialogInterface;
import android.os.Build;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -86,7 +85,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("SessionsTitle", R.string.SessionsTitle));
@@ -109,7 +108,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
emptyLayout.setOrientation(LinearLayout.VERTICAL);
emptyLayout.setGravity(Gravity.CENTER);
emptyLayout.setBackgroundResource(R.drawable.greydivider_bottom);
- emptyLayout.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AndroidUtilities.displaySize.y - AndroidUtilities.getCurrentActionBarHeight()));
+ emptyLayout.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight()));
ImageView imageView = new ImageView(context);
imageView.setImageResource(R.drawable.devices);
@@ -433,7 +432,7 @@ public class SessionsActivity extends BaseFragment implements NotificationCenter
} else if (type == 3) {
ViewGroup.LayoutParams layoutParams = emptyLayout.getLayoutParams();
if (layoutParams != null) {
- layoutParams.height = Math.max(AndroidUtilities.dp(220), AndroidUtilities.displaySize.y - AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(128) - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0));
+ layoutParams.height = Math.max(AndroidUtilities.dp(220), AndroidUtilities.displaySize.y - ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(128) - (Build.VERSION.SDK_INT >= 21 ? AndroidUtilities.statusBarHeight : 0));
emptyLayout.setLayoutParams(layoutParams);
}
return emptyLayout;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java
index 9c0be40e4..119f3dcd6 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/SettingsActivity.java
@@ -33,7 +33,6 @@ import android.text.method.LinkMovementMethod;
import android.util.Base64;
import android.util.TypedValue;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -278,7 +277,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackgroundColor(AvatarDrawable.getProfileBackColorForId(5));
actionBar.setItemsBackground(AvatarDrawable.getButtonColorForId(5));
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
@@ -896,7 +895,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
FrameLayout.LayoutParams layoutParams;
if (listView != null) {
layoutParams = (FrameLayout.LayoutParams) listView.getLayoutParams();
- layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight();
+ layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight();
listView.setLayoutParams(layoutParams);
}
@@ -906,7 +905,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
int avatarSize = 42 + (int) (18 * diff);
int avatarX = 17 + (int) (47 * diffm);
- int avatarY = AndroidUtilities.dp(22) - (int) ((AndroidUtilities.dp(22) - (AndroidUtilities.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff));
+ int avatarY = AndroidUtilities.dp(22) - (int) ((AndroidUtilities.dp(22) - (ActionBar.getCurrentActionBarHeight() - AndroidUtilities.dp(42)) / 2) * (1.0f - diff));
int nameX = 97 + (int) (21 * diffm);
int nameEndX = 16 + (int) (32 * diffm);
int nameY = avatarY + AndroidUtilities.dp(29 - 13 * diffm);
@@ -914,7 +913,7 @@ public class SettingsActivity extends BaseFragment implements NotificationCenter
float scale = 1.0f - 0.12f * diffm;
layoutParams = (FrameLayout.LayoutParams) writeButton.getLayoutParams();
- layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + AndroidUtilities.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f);
+ layoutParams.topMargin = (actionBar.getOccupyStatusBar() ? AndroidUtilities.statusBarHeight : 0) + ActionBar.getCurrentActionBarHeight() + actionBar.getExtraHeight() - AndroidUtilities.dp(29.5f);
writeButton.setLayoutParams(layoutParams);
//ViewProxy.setScaleX(writeButton, diff > 0.2f ? 1.0f : diff / 0.2f);
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java
index 0fd9958b1..897b521cb 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/StickersActivity.java
@@ -16,7 +16,6 @@ import android.os.Build;
import android.os.Message;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
-import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
@@ -69,7 +68,7 @@ public class StickersActivity extends BaseFragment implements NotificationCenter
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("Stickers", R.string.Stickers));
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java
index 079bf6926..d6d39f973 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/TwoStepVerificationActivity.java
@@ -22,7 +22,6 @@ import android.view.ActionMode;
import android.view.ContextMenu;
import android.view.Gravity;
import android.view.KeyEvent;
-import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
@@ -144,7 +143,7 @@ public class TwoStepVerificationActivity extends BaseFragment implements Notific
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(false);
actionBar.setActionBarMenuOnItemClick(new ActionBar.ActionBarMenuOnItemClick() {
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java
index 37fa05bf4..f5f02e4fd 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/VideoEditorActivity.java
@@ -19,7 +19,6 @@ import android.media.MediaPlayer;
import android.os.Build;
import android.os.Bundle;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
@@ -224,7 +223,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackgroundColor(0xff333333);
actionBar.setItemsBackground(R.drawable.bar_selector_white);
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
@@ -261,7 +260,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
ActionBarMenu menu = actionBar.createMenu();
menu.addItemWithWidth(1, R.drawable.ic_done, AndroidUtilities.dp(56));
- fragmentView = inflater.inflate(R.layout.video_editor_layout, null, false);
+ fragmentView = getParentActivity().getLayoutInflater().inflate(R.layout.video_editor_layout, null, false);
originalSizeTextView = (TextView) fragmentView.findViewById(R.id.original_size);
editedSizeTextView = (TextView) fragmentView.findViewById(R.id.edited_size);
videoContainerView = fragmentView.findViewById(R.id.video_container);
@@ -539,7 +538,7 @@ public class VideoEditorActivity extends BaseFragment implements TextureView.Sur
if (AndroidUtilities.isTablet()) {
viewHeight = AndroidUtilities.dp(472);
} else {
- viewHeight = AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - AndroidUtilities.getCurrentActionBarHeight();
+ viewHeight = AndroidUtilities.displaySize.y - AndroidUtilities.statusBarHeight - ActionBar.getCurrentActionBarHeight();
}
int width;
diff --git a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java
index 1689a0e62..060dbf839 100644
--- a/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java
+++ b/TMessagesProj/src/main/java/org/telegram/ui/WallpapersActivity.java
@@ -21,7 +21,6 @@ import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.Gravity;
-import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
@@ -102,7 +101,7 @@ public class WallpapersActivity extends BaseFragment implements NotificationCent
}
@Override
- public View createView(Context context, LayoutInflater inflater) {
+ public View createView(Context context) {
actionBar.setBackButtonImage(R.drawable.ic_ab_back);
actionBar.setAllowOverlayTitle(true);
actionBar.setTitle(LocaleController.getString("ChatBackground", R.string.ChatBackground));
diff --git a/TMessagesProj/src/main/res/anim/no_animation.xml b/TMessagesProj/src/main/res/anim/no_animation.xml
new file mode 100644
index 000000000..bfaa5cfba
--- /dev/null
+++ b/TMessagesProj/src/main/res/anim/no_animation.xml
@@ -0,0 +1,3 @@
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_audio.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_audio.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_audio_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_audio_pressed.png
new file mode 100755
index 000000000..f29f74faa
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_audio_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photo_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_camera.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photo_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_camera.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_camera_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_camera_pressed.png
new file mode 100755
index 000000000..c44d38bcd
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_camera_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_contact.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_contact.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_contact_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_contact_pressed.png
new file mode 100755
index 000000000..8c38efd61
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_contact_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_file_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_file.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_file_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_file.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_file_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_file_pressed.png
new file mode 100755
index 000000000..4859f01cb
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_file_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_gallery.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery_pressed.png
new file mode 100755
index 000000000..354e4617b
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_gallery_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_hide_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_hide1.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_hide_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_hide1.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_hide1_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_hide1_pressed.png
new file mode 100755
index 000000000..ac5912686
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_hide1_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_hide_big_icon.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_hide2.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_hide_big_icon.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_hide2.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_location.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_location.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_location_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_location_pressed.png
new file mode 100755
index 000000000..bc2f11844
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_location_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_send_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_send1.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_send_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_send1.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_send1_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_send1_pressed.png
new file mode 100755
index 000000000..86dafab4a
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_send1_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_send_big_icon.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_send2.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_send_big_icon.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_send2.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_video_big.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_video.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-hdpi/ic_attach_video_big.png
rename to TMessagesProj/src/main/res/drawable-hdpi/attach_video.png
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/attach_video_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/attach_video_pressed.png
new file mode 100755
index 000000000..db40e51ce
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/attach_video_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_pause.png
new file mode 100755
index 000000000..3900d8151
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png
new file mode 100755
index 000000000..4b13c02e6
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/audiosend_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png
new file mode 100644
index 000000000..afafbee3b
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/bluecounter.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_action_next.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_next.png
new file mode 100755
index 000000000..4eaf7caab
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_next.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_action_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_pause.png
new file mode 100755
index 000000000..da17d12ba
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_action_play.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_play.png
new file mode 100755
index 000000000..0cd5cb61a
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_action_previous.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_previous.png
new file mode 100755
index 000000000..e59dedb62
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/ic_action_previous.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact.png
deleted file mode 100755
index 671f56f99..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_contact.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery.png
deleted file mode 100755
index 1c60351cb..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_gallery.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location.png
deleted file mode 100755
index 52bf60516..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_location.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music.png
deleted file mode 100755
index 5a8f5cf4e..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_music.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photo.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photo.png
deleted file mode 100755
index b2b0caaa5..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photo.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photobig.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photobig.png
deleted file mode 100755
index ca397177e..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_photobig.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_video.png b/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_video.png
deleted file mode 100755
index 193373521..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/ic_attach_video.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_pause.png
new file mode 100644
index 000000000..9643e6522
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-hdpi/menu_play.png
new file mode 100644
index 000000000..8b4bb5712
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/menu_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/nocover.png b/TMessagesProj/src/main/res/drawable-hdpi/nocover.png
new file mode 100644
index 000000000..4c0748a94
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/nocover.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png
new file mode 100644
index 000000000..7b02d9e1c
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/nocover_big.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-hdpi/nocover_small.9.png
new file mode 100644
index 000000000..8e5d60b8a
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/nocover_small.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_back.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_back.png
new file mode 100644
index 000000000..8eb567adc
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_back.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png
new file mode 100644
index 000000000..c65818124
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_next.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_next_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_next_pressed.png
new file mode 100644
index 000000000..5a01fac92
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_next_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_pause.png
new file mode 100644
index 000000000..c3cbab416
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_pause_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_pause_pressed.png
new file mode 100644
index 000000000..4ec1ead1a
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_pause_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png
new file mode 100644
index 000000000..434039be9
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_play_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_play_pressed.png
new file mode 100644
index 000000000..836f92d59
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_play_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png
new file mode 100644
index 000000000..b9d678725
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_previous.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_previous_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_previous_pressed.png
new file mode 100644
index 000000000..4ef7d468b
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_previous_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png
new file mode 100644
index 000000000..492637b71
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1_active.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1_active.png
new file mode 100644
index 000000000..4379bbd2c
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat1_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat_active.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat_active.png
new file mode 100644
index 000000000..432f02870
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_repeat_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png
new file mode 100644
index 000000000..0389f00b9
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle_active.png b/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle_active.png
new file mode 100644
index 000000000..c1c5ab850
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/pl_shuffle_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player.png b/TMessagesProj/src/main/res/drawable-hdpi/player.png
new file mode 100644
index 000000000..a62ef59b8
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/player.png differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player1.png b/TMessagesProj/src/main/res/drawable-hdpi/player1.png
deleted file mode 100755
index 6ec1a5d28..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/player1.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player1_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/player1_pressed.png
deleted file mode 100755
index f5698eb11..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/player1_pressed.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player2.png b/TMessagesProj/src/main/res/drawable-hdpi/player2.png
deleted file mode 100755
index cb9f570bb..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/player2.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/player2_pressed.png b/TMessagesProj/src/main/res/drawable-hdpi/player2_pressed.png
deleted file mode 100755
index 879278c30..000000000
Binary files a/TMessagesProj/src/main/res/drawable-hdpi/player2_pressed.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow.9.png
new file mode 100644
index 000000000..dccf34feb
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-hdpi/sheet_shadow.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_audio.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_audio.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_audio_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_audio_pressed.png
new file mode 100755
index 000000000..1ca2ee2b6
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_audio_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_camera.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_camera.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_camera_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_camera_pressed.png
new file mode 100755
index 000000000..0acb5a385
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_camera_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_contact_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_contact.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_contact_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_contact.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_contact_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_contact_pressed.png
new file mode 100755
index 000000000..0546d8d70
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_contact_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_file_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_file.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_file_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_file.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_file_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_file_pressed.png
new file mode 100755
index 000000000..4075c3baf
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_file_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_gallery.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery_pressed.png
new file mode 100755
index 000000000..5dcdcf076
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_gallery_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_hide_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_hide1.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_hide_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_hide1.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_hide1_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_hide1_pressed.png
new file mode 100755
index 000000000..8439f1f5e
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_hide1_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_hide_big_icon.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_hide2.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_hide_big_icon.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_hide2.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_location.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_location.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_location_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_location_pressed.png
new file mode 100755
index 000000000..1c3917fe0
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_location_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_send_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_send1.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_send_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_send1.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_send1_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_send1_pressed.png
new file mode 100755
index 000000000..d8f4bed39
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_send1_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_send_big_icon.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_send2.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_send_big_icon.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_send2.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_video_big.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_video.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-mdpi/ic_attach_video_big.png
rename to TMessagesProj/src/main/res/drawable-mdpi/attach_video.png
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/attach_video_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/attach_video_pressed.png
new file mode 100755
index 000000000..b814908bc
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/attach_video_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png
new file mode 100755
index 000000000..df9cc8f14
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png
new file mode 100755
index 000000000..b2352c30a
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/audiosend_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-mdpi/bluecounter.9.png
new file mode 100644
index 000000000..b683c0cea
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/bluecounter.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_action_next.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_next.png
new file mode 100755
index 000000000..936cdd77d
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_next.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_action_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_pause.png
new file mode 100755
index 000000000..b4bdbb558
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_action_play.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_play.png
new file mode 100755
index 000000000..164385d04
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_action_previous.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_previous.png
new file mode 100755
index 000000000..97970e08f
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/ic_action_previous.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_contact.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_contact.png
deleted file mode 100755
index b7ca453f5..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_contact.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery.png
deleted file mode 100755
index a53056967..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_gallery.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location.png
deleted file mode 100755
index 193306974..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_location.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music.png
deleted file mode 100755
index 3440214d1..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_music.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo.png
deleted file mode 100755
index 9a70e6b58..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photo.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photobig.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photobig.png
deleted file mode 100755
index f4a9297d4..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_photobig.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_video.png b/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_video.png
deleted file mode 100755
index b6ebbb60a..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/ic_attach_video.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png
new file mode 100644
index 000000000..befe821c8
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-mdpi/menu_play.png
new file mode 100644
index 000000000..6d2ad6b3f
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/menu_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nocover.png b/TMessagesProj/src/main/res/drawable-mdpi/nocover.png
new file mode 100644
index 000000000..abbedfc21
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/nocover.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png
new file mode 100644
index 000000000..017c16f16
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/nocover_big.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-mdpi/nocover_small.9.png
new file mode 100644
index 000000000..6c5b5e65f
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/nocover_small.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_back.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_back.png
new file mode 100644
index 000000000..6702c4be6
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_back.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png
new file mode 100644
index 000000000..08df043ef
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_next.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_next_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_next_pressed.png
new file mode 100644
index 000000000..fc645c147
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_next_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png
new file mode 100644
index 000000000..1bf3d4abf
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_pause_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_pause_pressed.png
new file mode 100644
index 000000000..b8e61746f
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_pause_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png
new file mode 100644
index 000000000..31fce9bc1
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_play_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_play_pressed.png
new file mode 100644
index 000000000..d8ca3eb74
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_play_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png
new file mode 100644
index 000000000..1b52aca08
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_previous.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_previous_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_previous_pressed.png
new file mode 100644
index 000000000..1b34ae6fe
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_previous_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png
new file mode 100644
index 000000000..c62fb6c85
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1_active.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1_active.png
new file mode 100644
index 000000000..0b1a47433
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat1_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat_active.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat_active.png
new file mode 100644
index 000000000..140c797bf
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_repeat_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle.png
new file mode 100644
index 000000000..c22ab8e3f
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle_active.png b/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle_active.png
new file mode 100644
index 000000000..8e3888ddc
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/pl_shuffle_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player.png b/TMessagesProj/src/main/res/drawable-mdpi/player.png
new file mode 100644
index 000000000..1a26651ce
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/player.png differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player1.png b/TMessagesProj/src/main/res/drawable-mdpi/player1.png
deleted file mode 100755
index ff66a1aa5..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/player1.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player1_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/player1_pressed.png
deleted file mode 100755
index 4bc5b5735..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/player1_pressed.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player2.png b/TMessagesProj/src/main/res/drawable-mdpi/player2.png
deleted file mode 100755
index 9d3caac8d..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/player2.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/player2_pressed.png b/TMessagesProj/src/main/res/drawable-mdpi/player2_pressed.png
deleted file mode 100755
index 946cf59d7..000000000
Binary files a/TMessagesProj/src/main/res/drawable-mdpi/player2_pressed.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow.9.png
new file mode 100644
index 000000000..58be559f8
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-mdpi/sheet_shadow.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-v21/bar_selector_audio.xml b/TMessagesProj/src/main/res/drawable-v21/bar_selector_audio.xml
new file mode 100644
index 000000000..fc4dddc7f
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable-v21/bar_selector_audio.xml
@@ -0,0 +1,4 @@
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_audio.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio_pressed.png
new file mode 100755
index 000000000..4d058f53d
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_audio_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photo_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_camera.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photo_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_camera.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_camera_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_camera_pressed.png
new file mode 100755
index 000000000..ba0d86273
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_camera_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_contact_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_contact_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_contact.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact_pressed.png
new file mode 100755
index 000000000..bada4c266
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_contact_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_file_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_file.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_file_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_file.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_file_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_file_pressed.png
new file mode 100755
index 000000000..491efc190
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_file_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery_pressed.png
new file mode 100755
index 000000000..e9e735211
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_gallery_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_hide_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_hide_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1_pressed.png
new file mode 100755
index 000000000..1fabe1da5
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_hide1_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_hide_big_icon.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_hide2.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_hide_big_icon.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_hide2.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_location_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_location.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_location_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_location.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_location_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_location_pressed.png
new file mode 100755
index 000000000..50e92b498
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_location_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_send_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send1.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_send_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_send1.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_send1_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send1_pressed.png
new file mode 100755
index 000000000..4a107c6b4
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send1_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_send_big_icon.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_send2.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_send_big_icon.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_send2.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_video_big.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_video.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_video_big.png
rename to TMessagesProj/src/main/res/drawable-xhdpi/attach_video.png
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/attach_video_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/attach_video_pressed.png
new file mode 100755
index 000000000..d251fd69c
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/attach_video_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_pause.png
new file mode 100755
index 000000000..8078779df
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_play.png
new file mode 100755
index 000000000..bfd90992e
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/audiosend_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/bluecounter.9.png
new file mode 100644
index 000000000..2087fd181
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/bluecounter.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_next.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_next.png
new file mode 100755
index 000000000..f282b9245
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_next.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_pause.png
new file mode 100755
index 000000000..72dfa9fa6
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_play.png
new file mode 100755
index 000000000..043acd808
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_previous.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_previous.png
new file mode 100755
index 000000000..2522877df
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/ic_action_previous.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_contact.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_contact.png
deleted file mode 100755
index 6fdc58b0b..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_contact.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery.png
deleted file mode 100755
index 4227122dc..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_gallery.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_location.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_location.png
deleted file mode 100755
index 3e27c97e7..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_location.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music.png
deleted file mode 100755
index 12336bf80..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_music.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photo.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photo.png
deleted file mode 100755
index 25f0d3c81..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photo.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photobig.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photobig.png
deleted file mode 100755
index 67a9bf2ea..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_photobig.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_video.png b/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_video.png
deleted file mode 100755
index 49f6685e0..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/ic_attach_video.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png
new file mode 100644
index 000000000..54f0f7bcd
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png
new file mode 100644
index 000000000..718da7c4e
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/menu_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png b/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png
new file mode 100644
index 000000000..0e916f376
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/nocover.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png
new file mode 100644
index 000000000..7026a671f
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_big.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_small.9.png
new file mode 100644
index 000000000..5e135bde6
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/nocover_small.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_back.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_back.png
new file mode 100644
index 000000000..5be0d0c96
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_back.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png
new file mode 100644
index 000000000..a9b7bb559
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_next.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_next_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_next_pressed.png
new file mode 100644
index 000000000..adfa91502
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_next_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png
new file mode 100644
index 000000000..88901a49e
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause_pressed.png
new file mode 100644
index 000000000..95d5b1224
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_pause_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png
new file mode 100644
index 000000000..337bf8a37
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_play_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_play_pressed.png
new file mode 100644
index 000000000..adc3c6fe0
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_play_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous.png
new file mode 100644
index 000000000..1dbd201bd
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous_pressed.png
new file mode 100644
index 000000000..6979d0dd2
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_previous_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png
new file mode 100644
index 000000000..f0ebf4987
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat1_active.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat1_active.png
new file mode 100644
index 000000000..9b37d2dd3
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat1_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat_active.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat_active.png
new file mode 100644
index 000000000..da9e63bc1
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_repeat_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle.png
new file mode 100644
index 000000000..00293fad0
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle_active.png b/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle_active.png
new file mode 100644
index 000000000..1cba5d2f5
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/pl_shuffle_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/player.png b/TMessagesProj/src/main/res/drawable-xhdpi/player.png
new file mode 100644
index 000000000..c236f57a6
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/player.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/player1.png b/TMessagesProj/src/main/res/drawable-xhdpi/player1.png
deleted file mode 100755
index 2a11310e6..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/player1.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/player1_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/player1_pressed.png
deleted file mode 100755
index e3ebd1b5e..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/player1_pressed.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/player2.png b/TMessagesProj/src/main/res/drawable-xhdpi/player2.png
deleted file mode 100755
index 57bc079af..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/player2.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/player2_pressed.png b/TMessagesProj/src/main/res/drawable-xhdpi/player2_pressed.png
deleted file mode 100755
index 03723d55b..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xhdpi/player2_pressed.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow.9.png
new file mode 100644
index 000000000..171a4d54e
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xhdpi/sheet_shadow.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_music_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_music_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio_pressed.png
new file mode 100755
index 000000000..28f865b76
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_audio_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera_pressed.png
new file mode 100755
index 000000000..b9e2a0088
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_camera_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_contact_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_contact_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact_pressed.png
new file mode 100755
index 000000000..d8824727d
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_contact_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_file_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_file_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_file.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file_pressed.png
new file mode 100755
index 000000000..ff36de726
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_file_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery_pressed.png
new file mode 100755
index 000000000..7ae2a56ad
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_gallery_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_hide_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_hide_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1_pressed.png
new file mode 100755
index 000000000..4e3cc02a7
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide1_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_hide_big_icon.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide2.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_hide_big_icon.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_hide2.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_location_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_location.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_location_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_location.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_location_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_location_pressed.png
new file mode 100755
index 000000000..cfa436dd1
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_location_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_send_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_send_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1_pressed.png
new file mode 100755
index 000000000..750e47fc3
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send1_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_send_big_icon.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_send2.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_send_big_icon.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_send2.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video_big.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video.png
similarity index 100%
rename from TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video_big.png
rename to TMessagesProj/src/main/res/drawable-xxhdpi/attach_video.png
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video_pressed.png
new file mode 100755
index 000000000..292a0c3d5
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/attach_video_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png
new file mode 100755
index 000000000..6a227efc2
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_play.png
new file mode 100755
index 000000000..40478b917
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/audiosend_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/bluecounter.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/bluecounter.9.png
new file mode 100644
index 000000000..113537b7f
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/bluecounter.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_next.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_next.png
new file mode 100755
index 000000000..4fe60888b
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_next.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_pause.png
new file mode 100755
index 000000000..76833ff7d
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_play.png
new file mode 100755
index 000000000..fe7ea25cc
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_previous.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_previous.png
new file mode 100755
index 000000000..2c9310af9
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_action_previous.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_contact.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_contact.png
deleted file mode 100755
index cf1a4bbd6..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_contact.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery.png
deleted file mode 100755
index 4f8d40750..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_gallery.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_location.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_location.png
deleted file mode 100755
index b6bd6ca9a..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_location.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_music.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_music.png
deleted file mode 100755
index 7317d7295..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_music.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo.png
deleted file mode 100755
index ccf61d696..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photo.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photobig.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photobig.png
deleted file mode 100755
index db8c53ae1..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_photobig.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video.png b/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video.png
deleted file mode 100755
index 66843485e..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/ic_attach_video.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png
new file mode 100644
index 000000000..7bb5c4539
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png
new file mode 100644
index 000000000..3279b876b
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/menu_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png
new file mode 100644
index 000000000..61aab196a
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_big.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_big.9.png
new file mode 100644
index 000000000..eacbc19f7
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_big.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png
new file mode 100644
index 000000000..012386f97
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/nocover_small.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_back.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_back.png
new file mode 100644
index 000000000..10fcfc173
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_back.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next.png
new file mode 100644
index 000000000..7895ed90f
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next_pressed.png
new file mode 100644
index 000000000..fa5646ca3
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_next_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause.png
new file mode 100644
index 000000000..10dac92ff
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause_pressed.png
new file mode 100644
index 000000000..1eb9c4eb4
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_pause_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png
new file mode 100644
index 000000000..41d57747c
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play_pressed.png
new file mode 100644
index 000000000..bc1b06969
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_play_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png
new file mode 100644
index 000000000..6d45e33ca
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous_pressed.png
new file mode 100644
index 000000000..92baf19cd
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_previous_pressed.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png
new file mode 100644
index 000000000..a0404007d
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat1_active.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat1_active.png
new file mode 100644
index 000000000..49caea600
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat1_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat_active.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat_active.png
new file mode 100644
index 000000000..38266b9d1
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_repeat_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png
new file mode 100644
index 000000000..59108a061
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle_active.png b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle_active.png
new file mode 100644
index 000000000..1ca88b2e7
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/pl_shuffle_active.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/player.png b/TMessagesProj/src/main/res/drawable-xxhdpi/player.png
new file mode 100644
index 000000000..21217b2c1
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/player.png differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/player1.png b/TMessagesProj/src/main/res/drawable-xxhdpi/player1.png
deleted file mode 100755
index 6eee90a8e..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/player1.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/player1_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/player1_pressed.png
deleted file mode 100755
index f1af60fcc..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/player1_pressed.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/player2.png b/TMessagesProj/src/main/res/drawable-xxhdpi/player2.png
deleted file mode 100755
index 7a099f7cb..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/player2.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/player2_pressed.png b/TMessagesProj/src/main/res/drawable-xxhdpi/player2_pressed.png
deleted file mode 100755
index 8fb075f6f..000000000
Binary files a/TMessagesProj/src/main/res/drawable-xxhdpi/player2_pressed.png and /dev/null differ
diff --git a/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png b/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png
new file mode 100644
index 000000000..13c556455
Binary files /dev/null and b/TMessagesProj/src/main/res/drawable-xxhdpi/sheet_shadow.9.png differ
diff --git a/TMessagesProj/src/main/res/drawable/attach_audio_states.xml b/TMessagesProj/src/main/res/drawable/attach_audio_states.xml
new file mode 100644
index 000000000..881a09d0d
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_audio_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/attach_camera_states.xml b/TMessagesProj/src/main/res/drawable/attach_camera_states.xml
new file mode 100644
index 000000000..3b437c248
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_camera_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/attach_contact_states.xml b/TMessagesProj/src/main/res/drawable/attach_contact_states.xml
new file mode 100644
index 000000000..f8dbdd4ef
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_contact_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/attach_file_states.xml b/TMessagesProj/src/main/res/drawable/attach_file_states.xml
new file mode 100644
index 000000000..c5604e3a2
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_file_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/attach_gallery_states.xml b/TMessagesProj/src/main/res/drawable/attach_gallery_states.xml
new file mode 100644
index 000000000..40a9cf0f5
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_gallery_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/attach_hide_states.xml b/TMessagesProj/src/main/res/drawable/attach_hide_states.xml
new file mode 100644
index 000000000..6fb0453d7
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_hide_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/attach_location_states.xml b/TMessagesProj/src/main/res/drawable/attach_location_states.xml
new file mode 100644
index 000000000..942b7063d
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_location_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/attach_send_states.xml b/TMessagesProj/src/main/res/drawable/attach_send_states.xml
new file mode 100644
index 000000000..9377186e9
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_send_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/attach_video_states.xml b/TMessagesProj/src/main/res/drawable/attach_video_states.xml
new file mode 100644
index 000000000..93eb90089
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/attach_video_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/bar_selector_audio.xml b/TMessagesProj/src/main/res/drawable/bar_selector_audio.xml
new file mode 100644
index 000000000..f311824b8
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/bar_selector_audio.xml
@@ -0,0 +1,19 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/floating_states.xml b/TMessagesProj/src/main/res/drawable/floating_states.xml
index c2c53d129..55cb84eb4 100644
--- a/TMessagesProj/src/main/res/drawable/floating_states.xml
+++ b/TMessagesProj/src/main/res/drawable/floating_states.xml
@@ -1,13 +1,4 @@
-
-
-
diff --git a/TMessagesProj/src/main/res/drawable/player_next_states.xml b/TMessagesProj/src/main/res/drawable/player_next_states.xml
new file mode 100644
index 000000000..b3fe03129
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/player_next_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/player_pause_states.xml b/TMessagesProj/src/main/res/drawable/player_pause_states.xml
new file mode 100644
index 000000000..713cd0bc3
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/player_pause_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/player_play_states.xml b/TMessagesProj/src/main/res/drawable/player_play_states.xml
new file mode 100644
index 000000000..92447f398
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/player_play_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/player_prev_states.xml b/TMessagesProj/src/main/res/drawable/player_prev_states.xml
new file mode 100644
index 000000000..e34bbba26
--- /dev/null
+++ b/TMessagesProj/src/main/res/drawable/player_prev_states.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/drawable/search_dark_states.xml b/TMessagesProj/src/main/res/drawable/search_dark_states.xml
deleted file mode 100644
index d1d4b4594..000000000
--- a/TMessagesProj/src/main/res/drawable/search_dark_states.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/TMessagesProj/src/main/res/drawable/search_light_states.xml b/TMessagesProj/src/main/res/drawable/search_light_states.xml
deleted file mode 100644
index d1d4b4594..000000000
--- a/TMessagesProj/src/main/res/drawable/search_light_states.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
diff --git a/TMessagesProj/src/main/res/layout/player_big_notification.xml b/TMessagesProj/src/main/res/layout/player_big_notification.xml
new file mode 100755
index 000000000..98c7f0bd2
--- /dev/null
+++ b/TMessagesProj/src/main/res/layout/player_big_notification.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/layout/player_small_notification.xml b/TMessagesProj/src/main/res/layout/player_small_notification.xml
new file mode 100755
index 000000000..43c2b9d32
--- /dev/null
+++ b/TMessagesProj/src/main/res/layout/player_small_notification.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values-ar/strings.xml b/TMessagesProj/src/main/res/values-ar/strings.xml
index 8cbb7ef3a..5562767b2 100644
--- a/TMessagesProj/src/main/res/values-ar/strings.xml
+++ b/TMessagesProj/src/main/res/values-ar/strings.xml
@@ -65,6 +65,11 @@
أنت قمت بإنشاء قائمة رسالة جماعية
إضافة مستلم
إزالة من قائمة الرسالة الجماعية
+
+ فضلًا قم بإضافة ملفات لمكتبتك الموسيقية على جهازك لتتمكن من مشاهدتها هنا.
+ موسيقى
+ الفنان غير معروف
+ العنوان غير معروف
اختر ملف
متاح %1$s من %2$s
@@ -121,6 +126,7 @@
حذف هذه الدردشة
قم بالسحب للإلغاء
حفظ في الجهاز
+ احفظ في الموسيقى
مشاركة
تطبيق ملف التعريب
المرفق غير مدعوم
@@ -347,6 +353,7 @@
إيقاف
الأصوات داخل المحادثات
افتراضي
+ تلقائي
إشعارات ذكية
تعطيل
أعلى صوت %1$s خلال %2$s
@@ -827,6 +834,6 @@
h:mm a
%1$s الساعة %2$s
- تيليجرام نسخة الأندرويد تم تحديثه. الجديد في نسخة ٣.٠:\n\n- أقسام مخصصة خاصة ومرتبة لكل لحزم الملصقات. يمكنك إضافة حزم الملصقات كهذه https://telegram.me/addstickers/Animals\n- واجهة برمجية خاصة جديدة بالبوت، مجانًا للجميع. إذا كنت مبرمج، اصنع البوت الخاص بك مثل @quiz_bot و @hot_or_bot باستخدام حساب @botfather. للإستزادة، فضلًا اطلع على https://telegram.org/blog/bot-revolution
- 551
+ تم تحديث تيليجرام نسخة الأندرويد. الجديد في النسخة رقم 3.1:\n\n- بحث عن الرسائل داخل محادثات محددة. \n- إعادة تصميم كاملة لشاشة ارفاق الملفات. إرسال جهات اتصال وملفات صوتية مباشرة من خيار المرفقات. \n- تطوير لتشغيل الوسائط داخل التطبيق (يوتيوب, ڤيميو, ساوندكلاود وغيرها.),.\n\nللاستزادة، اطلع هنا:\nhttps://telegram.org/blog/search-and-media
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values-de/strings.xml b/TMessagesProj/src/main/res/values-de/strings.xml
index df5390eb6..d171f0ee5 100644
--- a/TMessagesProj/src/main/res/values-de/strings.xml
+++ b/TMessagesProj/src/main/res/values-de/strings.xml
@@ -65,6 +65,11 @@
Du hast eine Broadcast Liste erstellt
Empfänger hinzufügen
Aus Broadcast Liste entfernen
+
+ Bitte füge Musikdateien einfach deiner Android Musikbibliothek hinzu, um sie hier zu sehen.
+ Musik
+ Unbekannter Künstler
+ Unbekannter Titel
Datei auswählen
Freier Speicher: %1$s von %2$s
@@ -121,6 +126,7 @@
Diesen Chat löschen
WISCHEN UM ABZUBRECHEN
In Downloads speichern
+ Musik speichern
Teilen
Sprachdatei benutzen
Nicht unterstützte Datei
@@ -208,7 +214,7 @@
Geteilte Medien
Einstellungen
Mitglied hinzufügen
- Gruppe löschen und verlassen
+ Löschen und Gruppe verlassen
Mitteilungen
Aus der Gruppe entfernen
@@ -347,6 +353,7 @@
Aus
In-Chat-Töne
Standard
+ Standard
Intelligente Benachrichtigungen
Deaktiviert
Höchstens %1$s innerhalb von %2$s
@@ -827,6 +834,6 @@
h:mm a
%1$s um %2$s
- Telegram für Android wurde aktualisiert. Neu in Version 3.0:\n\n- Neue Tabs im Sticker Panel für alle deine eigenen Sticker-Pakete. Füge neue Sticker wie beispielsweise https://telegram.me/addstickers/Animals hinzu.\n- Neue Bot API, für alle kostenlos verfügbar. Kannst du programmieren? Erstelle deine eigenen Bots für Spiele, Dienste oder Integrationen. Mehr dazu unter https://telegram.org/blog/bot-revolution
- 551
+ Telegram für Android wurde aktualisiert. Neu in Version 3.1:\n\n- Direkte Suche in Chats.\n- In Chats versteckt sich ein komplett neues Menü hinter der Büroklammer. Nun kann man dort auch Musik und Kontakte versenden.\n- In-App Medienwiedergabe für YouTube, Vimeo, SoundCloud, etc. optimiert und neuer Player für Audiodateien.\n\nMehr dazu unter:\nhttps://telegram.org/blog/search-and-media
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values-es/strings.xml b/TMessagesProj/src/main/res/values-es/strings.xml
index 8cc0c49f4..3c328ef1b 100644
--- a/TMessagesProj/src/main/res/values-es/strings.xml
+++ b/TMessagesProj/src/main/res/values-es/strings.xml
@@ -65,6 +65,11 @@
Creaste una lista de difusión
Añadir destinatario
Quitar de la lista de difusión
+
+ Por favor, añade archivos a la carpeta de música en tu dispositivo para verlos aquí.
+ Música
+ Artista desconocido
+ Título desconocido
Elegir archivo
%1$s de %2$s libres
@@ -121,6 +126,7 @@
Eliminar este chat
DESLIZA PARA CANCELAR
Guardar en descargas
+ Guardar en música
Compartir
Aplicar traducción
Adjunto no soportado
@@ -347,6 +353,7 @@
Apagado
Sonidos en el chat
Por defecto
+ Por defecto
Notificaciones inteligentes
Desactivadas
Sonar como máximo %1$s en %2$s
@@ -827,6 +834,6 @@
h:mm a
%1$s a las %2$s
- Telegram para Android fue actualizada. Novedades en la versión 3.0:\n\n- Pestañas dedicadas para cada uno de tus packs de stickers personalizados en el panel de stickers. Añade stickers personalizados como: https://telegram.me/addstickers/Animals\n- Nueva API para bots, gratis para todos. Si eres un ingeniero, crea tus propios bots para juegos, servicios o integraciones. Conoce más en: https://telegram.org/blog/bot-revolution
- 551
+ Telegram para Android fue actualizada. Novedades en la versión 3.1:\n\n- Busca mensajes dentro de un chat en específico.\n- Menú para adjuntar completamente rediseñado. Envía contactos y archivos de audio directamente desde el menú para adjuntar.\n- Reproducción de multimedia dentro de la aplicación mejorada (YouTube, Vimeo, SoundCloud etc.), nuevo reproductor para archivos de audio largos.\n\nMás sobre esta actualización:\nhttps://telegram.org/blog/search-and-media
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values-it/strings.xml b/TMessagesProj/src/main/res/values-it/strings.xml
index 8b5e8022f..d826f248b 100644
--- a/TMessagesProj/src/main/res/values-it/strings.xml
+++ b/TMessagesProj/src/main/res/values-it/strings.xml
@@ -65,6 +65,11 @@
Hai creato una lista broadcast
Aggiungi destinatario
Rimuovi dalla lista broadcast
+
+ Aggiungi file nella libreria musicale del tuo dispositivo per vederli qui.
+ Musica
+ Artista sconosciuto
+ Titolo sconosciuto
Seleziona file
Liberi %1$s di %2$s
@@ -121,6 +126,7 @@
Elimina questa chat
ANNULLA
Salva nei download
+ Salva nella musica
Condividi
Applica traduzione
Allegato non supportato
@@ -284,7 +290,7 @@
Utenti bloccati
Disconnetti
Nessun suono
- Predefinita
+ Predefinite
Supporto
Solo se silenzioso
Sfondo chat
@@ -295,7 +301,7 @@
Un contatto si è unito a Telegram
PEBBLE
Lingua
- Nota che il supporto di Telegram è fornito da volontari. Proviamo a rispondere non appena possibile, ma potrebbe volerci un pò.
]]>Dai un\'occhiata alle FAQdi Telegram]]>: troverai risposte alla maggior parte delle domande e suggerimenti importanti per l\'individuazione del problema]]>
+ Nota che il supporto di Telegram è fornito da volontari. Proviamo a rispondere non appena possibile, ma potrebbe volerci un pò.
]]>Dai un\'occhiata alle FAQ di Telegram]]>: troverai risposte alla maggior parte delle domande e suggerimenti importanti per l\'individuazione del problema]]>
Chiedi a un volontario
FAQ di Telegram
https://telegram.org/faq/it
@@ -347,6 +353,7 @@
No
Suoni in-chat
Predefinito
+ Predefinita
Notifiche intelligenti
Disabilitate
Suona al massimo %1$s in %2$s
@@ -452,12 +459,12 @@
Reinserisci la tua password
E-mail di recupero
La tua e-mail
- Per favore inserisci un\'e-mail valida. È l\'unico modo di recuperare una password dimenticata.
+ Inserisci un\'e-mail valida. È l\'unico modo di recuperare una password dimenticata.
Salta
Attenzione
No, seriamente.\n\nSe dimentichi la tua password, perderai l\'accesso al tuo account Telegram. Non ci sarà modo di ripristinarlo.
Ci siamo quasi!
- Per favore controlla la tua e-mail (anche lo spam) per completare la configurazione della verifica in due passaggi.
+ Controlla la tua e-mail (anche lo spam) per completare la configurazione della verifica in due passaggi.
Fatto!
La password per la verifica in due passaggi è ora attiva.
Cambia password
@@ -466,16 +473,16 @@
Cambia e-mail di recupero
Sei sicuro di voler disabilitare la tua password?
Suggerimento password
- Per favore crea un suggerimento per la tua password
+ Crea un suggerimento per la tua password
Le password non corrispondono
Annulla configurazione della verifica in due passaggi
- Per favore segui questi step per completare la configurazione della verifica in due passaggi:\n\n1. Controlla la tua e-mail (anche lo spam)\n%1$s\n\n2. Clicca sul link di conferma.
+ Segui questi step per completare la configurazione della verifica in due passaggi:\n\n1. Controlla la tua e-mail (anche lo spam)\n%1$s\n\n2. Clicca sul link di conferma.
Il suggerimento deve essere diverso dalla password
E-mail non valida
Scusa
Siccome non hai fornito un\'email di recupero quando hai impostato la tua password, non ti resta che ricordarti la password o ripristinare il tuo account.
Abbiamo inviato un codice di ripristino alla e-mail che ci hai fornito:\n\n%1$s
- Per favore controlla la tua e-mail e inserisci il codice a 6 cifre che ti abbiamo inviato.
+ Controlla la tua e-mail e inserisci il codice a 6 cifre che ti abbiamo inviato.
Hai problemi ad accedere alla tua e-mail %1$s?
Se non puoi ripristinare l\'accesso alla tua e-mail, non ti resta che ricordarti la password o ripristinare il tuo account.
RIPRISTINA IL MIO ACCOUNT
@@ -508,10 +515,10 @@
Se lontano per
Se non ti connetti almeno una volta in questo periodo, il tuo account verrà eliminato insieme a tutti i gruppi, messaggi e contatti.
Eliminare il tuo account?
- Cambia chi può vedere il tuo Ultimo Accesso.
- Chi può vedere il tuo Ultimo Accesso?
+ Cambia chi può vedere il tuo ultimo accesso.
+ Chi può vedere il tuo ultimo accesso?
Aggiungi eccezioni
- Importante: non sarai in grado di vedere l\'Ultimo Accesso delle persone con le quali non condividi l\'Ultimo Accesso. Verrà mostrato un orario approssimativo (di recente, entro una settimana, entro un mese).
+ Importante: non sarai in grado di vedere l\'ultimo accesso delle persone con le quali non condividi l\'ultimo accesso. Verrà mostrato un orario approssimativo (di recente, entro una settimana, entro un mese).
Condividi con
Non condividere con
Queste impostazioni annulleranno i valori precedenti.
@@ -519,7 +526,7 @@
Condividi con gli utenti...
Non condividere
Non condividere con gli utenti...
- Aggiungi Utenti
+ Aggiungi utenti
Ci spiace, troppe richieste. Impossibile cambiare le impostazioni di privacy ora, attendi.
Disconnette tutti i dispositivi tranne questo.
Tieni premuto sull\'utente per eliminarlo.
@@ -682,12 +689,12 @@
%1$d oggetti
%1$d oggetti
%1$d oggetti
- in nessuna chat
- in %1$d chat
- in %1$d chat
- in %1$d chat
- in %1$d chat
- in %1$d chat
+ da nessuna chat
+ da %1$d chat
+ da %1$d chat
+ da %1$d chat
+ da %1$d chat
+ da %1$d chat
%1$d secondi
%1$d secondo
%1$d secondi
@@ -827,6 +834,6 @@
h:mm a
%1$s alle %2$s
- Telegram per Android è stato aggiornato. Nuovo nella versione 3.0:\n\n- Pagine dedicate per ognuno dei tuoi pacchetti sticker nel pannello sticker. Aggiunti sticker personalizzati come https://telegram.me/addstickers/Animals\n- Nuova API per i bot, gratis per tutti. Se sei un ingegnere, crea i tuoi bot per giochi, servizi o integrazioni. Scopri di più su https://telegram.org/blog/bot-revolution
- 551
+ Telegram per Android si è aggiornato. Nuovo nella versione 3.1:\n\n- Cerca messaggi all\'interno di una specifica chat.\n- Menu degli allegati completamente ridisegnato. Invia contatti e audio direttamente dal menu degli allegati.\n- Riproduzione in-app migliorata (YouTube, Vimeo, SoundCloud etc.), nuovo player per i file audio.\n\nMaggiori informazioni su questo aggiornamento:\nhttps://telegram.org/blog/search-and-media
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values-ko/strings.xml b/TMessagesProj/src/main/res/values-ko/strings.xml
index f4eec4eeb..f2fc30ddf 100644
--- a/TMessagesProj/src/main/res/values-ko/strings.xml
+++ b/TMessagesProj/src/main/res/values-ko/strings.xml
@@ -65,6 +65,11 @@
단체 메시지 리스트를 만들었습니다
받는 사람 추가
리스트에서 제외
+
+ 음악 라이브러리에 파일을 추가하셔야지만 볼 수 있습니다.
+ 음악
+ 알수 없는 아티스트
+ 알 수 없는 제목
파일 선택
%2$s 중 %1$s 남음
@@ -121,6 +126,7 @@
이 채팅방 삭제
밀어서 취소
다운로드 폴더에 저장
+ 음악으로 저장
공유
언어 파일 적용
지원하지 않는 형식입니다
@@ -347,6 +353,7 @@
끔
채팅중 소리 설정
기본값
+ 기본값
스마트 알림
비활성화됨
최대 %1$s번, %2$s번 이내 알림
@@ -827,6 +834,6 @@
a h:mm
%1$s %2$s
- 텔레그램 안드로이드 버전이 업데이트 되었습니다. 새로운 버전은 3.0 입니다:\n\n- 스티커 패널에 커스텀 스티커별 탭 지원. https://telegram.me/addstickers/Animals 와 같은 커스텀 스티커 추가 기능\n- 신규 봇 API를 무료로 공개합니다. 개발자라면 누구나 게임, 서비스나 통합 봇등 개발이 가능합니다. https://telegram.org/blog/bot-revolution 에서 자세한 사항을 알아보세요.
- 551
+ 텔레그램 안드로이드 버전이 업데이트 되었습니다. 새로운 버전은 3.1 입니다:\n\n- 특정 대화창에서 검색. \n- 첨부 메뉴 개선. 해당 메뉴에서 바로 연락처, 오디오를 전송 가능. \n- 인앱 미디어 재생 기능 향상 (YouTube, Vimeo, SoundCloud etc). 대용량 오디오 파일 별도 플레이어 기능. \n\nhttps://telegram.org/blog/search-and-media에서 자세한 사항을 알아보세요.
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values-nl/strings.xml b/TMessagesProj/src/main/res/values-nl/strings.xml
index 49562999d..487122018 100644
--- a/TMessagesProj/src/main/res/values-nl/strings.xml
+++ b/TMessagesProj/src/main/res/values-nl/strings.xml
@@ -65,6 +65,11 @@
Je hebt een verzendlijst gemaakt
Ontvanger toevoegen
Verwijder van verzendlijst
+
+ Voeg bestanden toe aan de muziekbibliotheek op je apparaat om ze hier te zien.
+ Muziek
+ Onbekende artiest
+ Onbekende titel
Kies een bestand
Vrij: %1$s van %2$s
@@ -121,6 +126,7 @@
Chat verwijderen
SLEEP OM TE ANNULEREN
Opslaan in Downloads
+ Opslaan in muziek
Delen
Vertaling toepassen
Bestandstype niet ondersteund
@@ -347,6 +353,7 @@
Uit
Chatgeluiden
Standaard
+ Standaard
Slimme meldingen
Uitgeschakeld
Geluid maximaal %1$s per %2$s
@@ -827,6 +834,6 @@
h:mm a
%1$s om %2$s
- Telegram voor Android is geüpdatet. Nieuw in versie 3.0:\n\n- Tabbladen voor al je eigen stickerbundels in het stickerpaneel. Voeg stickerbundels zoals: https://telegram.me/addstickers/Animals toe.\n- Nieuwe bot-API, gratis voor iedereen. Handig met programmeren? Maak dan je eigen bots voor spelletjes, diensten of integraties. Meer weten? kijk op: https://telegram.org/blog/bot-revolution
- 551
+ Telegram voor Android is bijgewerkt. Nieuw in versie 3.1:\n\n- Zoek naar berichten in een specifieke chat.\n- Volledig opnieuw ontworpen bijlagemenu. Verstuur contacten en audiobestanden rechtstreeks vanuit het bijlagemenu.\n- Afspelen van media in de app verbeterd (YouTube, Vimeo, SoundCloud, etc.), nieuwe speler voor grote audiobestanden.\n\nMeer weten? Kijk op:\nhttps://telegram.org/blog/search-and-media
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml
index 4b4e6d254..d9e826d5b 100644
--- a/TMessagesProj/src/main/res/values-pt-rBR/strings.xml
+++ b/TMessagesProj/src/main/res/values-pt-rBR/strings.xml
@@ -65,6 +65,11 @@
Você criou uma lista de transmissão
Adicionar destinatário
Remover da lista de transmissão
+
+ Por favor, adicione arquivos à biblioteca de música de seu dispositivo para vê-los aqui.
+ Música
+ Artista desconhecido
+ Título desconhecido
Selecione um Arquivo
Disponível %1$s de %2$s
@@ -121,6 +126,7 @@
Apagar este chat
DESLIZE PARA CANCELAR
Salvar em downloads
+ Salvar em músicas
Compartilhar
Aplicar arquivo de localização
Anexo não suportado
@@ -347,6 +353,7 @@
Desativado
Sons no Chat
Padrão
+ Padrão
Notificações Inteligentes
Desativado
Tocar no máximo %1$s a cada %2$s
@@ -827,6 +834,6 @@
h:mm a
%1$s às %2$s
- Seu Telegram para Android acaba de ser atualizado. Novo na versão 3.0:\n\n- Abas dedicadas para cada um dos pacotes customizados de stickers no painel de stickers. Adicione stickers customizados como https://telegram.me/addstickers/Animals\n- Nova API de bots, gratuita para todos. Se você for um engenheiro, crie seus próprios bots como @quiz_bot ou @hot_or_bot usando o @botfather. Leia mais em https://telegram.org/blog/bot-revolution
- 551
+ Telegram para Android foi atualizado. Novo na versão 3.1:\n\n- Busca por mensagens dentro de um chat específico.\n-Menu de anexo totalmente redesenhado. Envie contatos e arquivos de áudio diretamente do menu de anexo.\n- Reprodução melhorada de mídia dentro do aplicativo (YouTube, Vimeo, SoundCloud, etc.), novo player para grandes arquivos de áudio.\n\nMais sobre a atualização:\nhttps://telegram.org/blog/search-and-media
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml
index a544d799b..02883ee2d 100644
--- a/TMessagesProj/src/main/res/values-pt-rPT/strings.xml
+++ b/TMessagesProj/src/main/res/values-pt-rPT/strings.xml
@@ -65,6 +65,11 @@
Você criou uma lista de transmissão
Adicionar destinatário
Remover da lista de transmissão
+
+ Por favor, adicione arquivos à biblioteca de música de seu dispositivo para vê-los aqui.
+ Música
+ Artista desconhecido
+ Título desconhecido
Selecione um Arquivo
Disponível %1$s de %2$s
@@ -121,6 +126,7 @@
Apagar este chat
DESLIZE PARA CANCELAR
Salvar em downloads
+ Salvar em músicas
Compartilhar
Aplicar arquivo de localização
Anexo não suportado
@@ -347,6 +353,7 @@
Desativado
Sons no Chat
Padrão
+ Padrão
Notificações Inteligentes
Desativado
Tocar no máximo %1$s a cada %2$s
@@ -827,6 +834,6 @@
h:mm a
%1$s às %2$s
- Seu Telegram para Android acaba de ser atualizado. Novo na versão 3.0:\n\n- Abas dedicadas para cada um dos pacotes customizados de stickers no painel de stickers. Adicione stickers customizados como https://telegram.me/addstickers/Animals\n- Nova API de bots, gratuita para todos. Se você for um engenheiro, crie seus próprios bots como @quiz_bot ou @hot_or_bot usando o @botfather. Leia mais em https://telegram.org/blog/bot-revolution
- 551
+ Telegram para Android foi atualizado. Novo na versão 3.1:\n\n- Busca por mensagens dentro de um chat específico.\n-Menu de anexo totalmente redesenhado. Envie contatos e arquivos de áudio diretamente do menu de anexo.\n- Reprodução melhorada de mídia dentro do aplicativo (YouTube, Vimeo, SoundCloud, etc.), novo player para grandes arquivos de áudio.\n\nMais sobre a atualização:\nhttps://telegram.org/blog/search-and-media
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values/strings.xml b/TMessagesProj/src/main/res/values/strings.xml
index 903c5d2cd..782c27627 100644
--- a/TMessagesProj/src/main/res/values/strings.xml
+++ b/TMessagesProj/src/main/res/values/strings.xml
@@ -1,6 +1,7 @@
+
Telegram
English
@@ -64,6 +65,11 @@
You created a broadcast list
Add recipient
Remove from broadcast list
+
+ Please add files to the music library on your device to see them here.
+ Music
+ Unknown artist
+ Unknown title
Select File
Free %1$s of %2$s
@@ -120,6 +126,7 @@
Delete this chat
SLIDE TO CANCEL
Save to downloads
+ Save to music
Share
Apply localization file
Unsupported attachment
@@ -346,6 +353,7 @@
Off
In-Chat Sounds
Default
+ Default
Smart Notifications
Disabled
Sound at most %1$s within %2$s
@@ -826,6 +834,6 @@
h:mm a
%1$s at %2$s
- Telegram for Android has been updated. New in version 3.0:\n\n- Dedicated tabs for each one of your custom sticker sets in the sticker panel. Add custom stickers like https://telegram.me/addstickers/Animals\n- New bot API, free for everyone. If you\'re an engineer, create your own bots for games, services or integrations. Learn more at https://telegram.org/blog/bot-revolution
- 551
+ Telegram for Android has been updated. New in version 3.1:\n\n- Search for messages inside a specific chat.\n- Fully redesigned attachment menu. Send contacts and audio files straight from the attachment menu.\n- Improved in-app media playback (YouTube, Vimeo, SoundCloud etc.), new player for large audio files.\n\nMore about this update:\nhttps://telegram.org/blog/search-and-media
+ 577
\ No newline at end of file
diff --git a/TMessagesProj/src/main/res/values/styles.xml b/TMessagesProj/src/main/res/values/styles.xml
index 56449ed43..444570aed 100644
--- a/TMessagesProj/src/main/res/values/styles.xml
+++ b/TMessagesProj/src/main/res/values/styles.xml
@@ -73,8 +73,8 @@
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 27fd29715..89ecdcf96 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-all.zip