diff options
-rw-r--r-- | res/layout/swipe_leavebehind.xml | 44 | ||||
-rw-r--r-- | res/values/strings.xml | 1 | ||||
-rw-r--r-- | src/com/android/mail/browse/ConversationCursor.java | 2 | ||||
-rw-r--r-- | src/com/android/mail/browse/ConversationItemView.java | 16 | ||||
-rw-r--r-- | src/com/android/mail/ui/AnimatedAdapter.java | 66 | ||||
-rw-r--r-- | src/com/android/mail/ui/ConversationListFragment.java | 8 | ||||
-rw-r--r-- | src/com/android/mail/ui/LeaveBehindItem.java | 106 | ||||
-rw-r--r-- | src/com/android/mail/ui/SwipeHelper.java | 52 | ||||
-rw-r--r-- | src/com/android/mail/ui/SwipeableItemView.java | 31 | ||||
-rw-r--r-- | src/com/android/mail/ui/SwipeableListView.java | 102 |
10 files changed, 351 insertions, 77 deletions
diff --git a/res/layout/swipe_leavebehind.xml b/res/layout/swipe_leavebehind.xml new file mode 100644 index 000000000..763c8baec --- /dev/null +++ b/res/layout/swipe_leavebehind.xml @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + Copyright (C) 2011 Google Inc. + Licensed to 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. +--> + +<!-- This layout is used as a template to create custom view CanvasConversationHeaderView + in normal mode. To be able to get the correct measurements, every source field should + be populated with data here. E.g: + - Text View should set text to a random long string (android:text="@string/long_string") + - Image View should set source to a specific asset --> +<com.android.mail.ui.LeaveBehindItem + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:minHeight="@dimen/conversation_item_height" + android:background="@android:color/black" + android:layout_gravity="center_vertical" + android:gravity="center_vertical"> + <Button android:id="@+id/undo_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:text="@string/undo"/> + <TextView android:id="@+id/undo_description" + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:layout_alignParentLeft="true" + android:textAppearance="?android:attr/textAppearanceMedium" + android:layout_marginLeft="16dip" + android:clickable="true"/> +</com.android.mail.ui.LeaveBehindItem>
\ No newline at end of file diff --git a/res/values/strings.xml b/res/values/strings.xml index 33f183871..ec316ee36 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -318,6 +318,7 @@ <string name="no_conversations">No conversations.</string> <!-- Menu item: undo latest action [CHAR LIMIT=12]--> <string name="undo">Undo</string> + <!-- Undo Strings: The following are shown in a dialog while we're waiting for the operation to complete --><skip /> <plurals name="conversation_marking_read"> <!-- Displayed while marking one conversation read --> diff --git a/src/com/android/mail/browse/ConversationCursor.java b/src/com/android/mail/browse/ConversationCursor.java index 4299bc354..bc5a964fb 100644 --- a/src/com/android/mail/browse/ConversationCursor.java +++ b/src/com/android/mail/browse/ConversationCursor.java @@ -1456,4 +1456,4 @@ public final class ConversationCursor implements Cursor { public boolean requery() { return true; } -} +}
\ No newline at end of file diff --git a/src/com/android/mail/browse/ConversationItemView.java b/src/com/android/mail/browse/ConversationItemView.java index 646f0a225..2de074b15 100644 --- a/src/com/android/mail/browse/ConversationItemView.java +++ b/src/com/android/mail/browse/ConversationItemView.java @@ -68,10 +68,11 @@ import com.android.mail.providers.UIProvider.ConversationColumns; import com.android.mail.ui.ConversationSelectionSet; import com.android.mail.ui.DragListener; import com.android.mail.ui.FolderDisplayer; +import com.android.mail.ui.SwipeableItemView; import com.android.mail.ui.ViewMode; import com.android.mail.utils.Utils; -public class ConversationItemView extends View { +public class ConversationItemView extends View implements SwipeableItemView { // Timer. private static int sLayoutCount = 0; private static Timer sTimer; // Create the sTimer here if you need to do perf analysis. @@ -1207,10 +1208,10 @@ public class ConversationItemView extends View { Animator fadeAnimator = ObjectAnimator.ofFloat(this, "itemAlpha", 0, 1.0f); mAnimatedHeight = start; undoAnimator.setInterpolator(new DecelerateInterpolator(2.0f)); + undoAnimator.addListener(listener); undoAnimator.setDuration(sUndoAnimationDuration); AnimatorSet transitionSet = new AnimatorSet(); transitionSet.playTogether(undoAnimator, fadeAnimator); - transitionSet.addListener(listener); transitionSet.start(); } @@ -1245,6 +1246,17 @@ public class ConversationItemView extends View { } } + @Override + public boolean canSwipe() { + return mSelectedConversationSet.isEmpty() + || (!mSelectedConversationSet.isEmpty() && isChecked()); + } + + @Override + public View getView() { + return this; + } + /** * With two pane mode and mailboxes in one pane (tablet), add the conversation to the selected * set and start drag mode. diff --git a/src/com/android/mail/ui/AnimatedAdapter.java b/src/com/android/mail/ui/AnimatedAdapter.java index 5182a6c03..205efc5b7 100644 --- a/src/com/android/mail/ui/AnimatedAdapter.java +++ b/src/com/android/mail/ui/AnimatedAdapter.java @@ -21,10 +21,12 @@ import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.Context; import android.database.Cursor; +import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.SimpleCursorAdapter; +import com.android.mail.R; import com.android.mail.browse.ConversationCursor; import com.android.mail.browse.ConversationItemView; import com.android.mail.providers.Account; @@ -32,11 +34,14 @@ import com.android.mail.providers.Conversation; import com.android.mail.providers.Folder; import com.android.mail.providers.Settings; import com.android.mail.providers.UIProvider; +import com.android.mail.ui.SwipeableListView.SwipeCompleteListener; import com.android.mail.ui.UndoBarView.OnUndoCancelListener; import com.android.mail.utils.LogUtils; +import com.google.common.collect.ImmutableList; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; public class AnimatedAdapter extends SimpleCursorAdapter implements @@ -45,6 +50,7 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements private final static int TYPE_VIEW_DELETING = 1; private final static int TYPE_VIEW_UNDOING = 2; private final static int TYPE_VIEW_FOOTER = 3; + private final static int TYPE_VIEW_LEAVEBEHIND = 4; private HashSet<Integer> mDeletingItems = new HashSet<Integer>(); private HashSet<Integer> mUndoingItems = new HashSet<Integer>(); private Account mSelectedAccount; @@ -61,6 +67,7 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements private Settings mCachedSettings; private boolean mSwipeEnabled; private DragListener mDragListener; + private HashMap<Long, UndoOperation> mLeaveBehindItems = new HashMap<Long, UndoOperation>(); /** * Used only for debugging. @@ -92,9 +99,8 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements return mShowFooter ? count + 1 : count; } - public void setUndo(boolean state) { - mUndo = state; - if (mUndo) { + public void setUndo(boolean undo) { + if (undo) { mUndoingItems.addAll(mLastDeletingItems); mLastDeletingItems.clear(); // Start animation @@ -132,8 +138,8 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements @Override public int getViewTypeCount() { // TYPE_VIEW_CONVERSATION, TYPE_VIEW_DELETING, TYPE_VIEW_UNDOING, and - // TYPE_VIEW_FOOTER. - return 4; + // TYPE_VIEW_FOOTER, TYPE_VIEW_LEAVEBEHIND. + return 5; } @Override @@ -145,6 +151,9 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements if (isPositionUndoing(position)) { return TYPE_VIEW_UNDOING; } + if (isPositionLeaveBehind(position)) { + return TYPE_VIEW_LEAVEBEHIND; + } if (mShowFooter && position == super.getCount()) { return TYPE_VIEW_FOOTER; } @@ -218,6 +227,12 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements } else if (isPositionDeleting(position)) { return getDeletingView(position, convertView, parent); } + if (hasLeaveBehinds()) { + Conversation conv = new Conversation((ConversationCursor) getItem(position)); + if(isPositionLeaveBehind(conv)) { + return getLeaveBehindItem(position, conv); + } + } // TODO: do this in the swipe helper? // If this view gets recycled, we need to reset things set by the // animation. @@ -232,6 +247,23 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements return super.getView(position, convertView, parent); } + private boolean hasLeaveBehinds() { + return !mLeaveBehindItems.isEmpty(); + } + + public void setupLeaveBehind(Conversation target, UndoOperation undoOp, int deletedRow) { + mLeaveBehindItems.put(target.id, undoOp); + mLastDeletingItems.add(deletedRow); + } + + private LeaveBehindItem getLeaveBehindItem(int position, Conversation target) { + LeaveBehindItem leaveBehind = (LeaveBehindItem) LayoutInflater.from(mContext).inflate( + R.layout.swipe_leavebehind, null); + leaveBehind.bindOperations(mSelectedAccount, this, mLeaveBehindItems.get(target.id), + target); + return leaveBehind; + } + @Override public long getItemId(int position) { if (mShowFooter && position == super.getCount()) { @@ -292,12 +324,24 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements return mUndoingItems.contains(position); } + private boolean isPositionLeaveBehind(Conversation conv) { + return mLeaveBehindItems.containsKey(conv.id) && conv.isMostlyDead(); + } + + private boolean isPositionLeaveBehind(int position) { + if (hasLeaveBehinds()) { + Conversation conv = new Conversation((ConversationCursor) getItem(position)); + return mLeaveBehindItems.containsKey(conv.id) && conv.isMostlyDead(); + } else { + return false; + } + } + @Override public void onAnimationStart(Animator animation) { - if (mUndo) { + if (!mUndoingItems.isEmpty()) { mDeletingItems.clear(); mLastDeletingItems.clear(); - mUndo = false; } else { mUndoingItems.clear(); } @@ -305,7 +349,7 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements @Override public void onAnimationEnd(Animator animation) { - if (mUndo && !mUndoingItems.isEmpty()) { + if (!mUndoingItems.isEmpty()) { // See if we have received all the animations we expected; if // so, call the listener and reset it. final int position = ((ConversationItemView) ((ObjectAnimator) animation).getTarget()) @@ -316,7 +360,6 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements mActionCompleteListener.onActionComplete(); mActionCompleteListener = null; } - mUndo = false; } } else if (!mDeletingItems.isEmpty()) { // See if we have received all the animations we expected; if @@ -382,4 +425,9 @@ public class AnimatedAdapter extends SimpleCursorAdapter implements public void setFolder(Folder folder) { mFolder = folder; } + + public void clearLeaveBehind(Conversation item) { + mLeaveBehindItems.remove(item.id); + notifyDataSetChanged(); + } } diff --git a/src/com/android/mail/ui/ConversationListFragment.java b/src/com/android/mail/ui/ConversationListFragment.java index 5541f22b6..305932691 100644 --- a/src/com/android/mail/ui/ConversationListFragment.java +++ b/src/com/android/mail/ui/ConversationListFragment.java @@ -219,7 +219,6 @@ public final class ConversationListFragment extends ListFragment implements mListView.setAdapter(mListAdapter); mListView.setSelectionSet(mActivity.getSelectedSet()); mListAdapter.hideFooter(); - mListView.setSwipeCompleteListener(this); // Don't need to add ourselves to our own set observer. // mActivity.getBatchConversations().addObserver(this); mActivity.setViewModeListener(this); @@ -281,9 +280,10 @@ public final class ConversationListFragment extends ListFragment implements mListView.setHeaderDividersEnabled(false); mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE); mListView.setOnItemLongClickListener(this); - mListView.enableSwipe( - mAccount.supportsCapability(UIProvider.AccountCapabilities.ARCHIVE)); - + mListView.enableSwipe(mAccount.supportsCapability(UIProvider.AccountCapabilities.UNDO)); + mListView.setSwipeAction(mAccount + .supportsCapability(UIProvider.AccountCapabilities.ARCHIVE) ? R.id.archive + : R.id.delete); // Note - we manually save/restore the listview state. mListView.setSaveEnabled(false); diff --git a/src/com/android/mail/ui/LeaveBehindItem.java b/src/com/android/mail/ui/LeaveBehindItem.java new file mode 100644 index 000000000..5790b6cdd --- /dev/null +++ b/src/com/android/mail/ui/LeaveBehindItem.java @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2012 Google Inc. + * Licensed to 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 com.android.mail.ui; + +import android.content.Context; +import android.text.Html; +import android.util.AttributeSet; +import android.widget.Button; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.view.View; +import android.view.View.OnClickListener; + +import com.android.mail.R; +import com.android.mail.providers.Account; +import com.android.mail.providers.Conversation; +import com.android.mail.ui.SwipeableListView.SwipeCompleteListener; +import com.google.common.collect.ImmutableList; + +import java.util.ArrayList; +import java.util.Collection; + +public class LeaveBehindItem extends RelativeLayout implements OnClickListener, SwipeableItemView { + + private UndoOperation mUndoOp; + private Account mAccount; + private AnimatedAdapter mAdapter; + private Conversation mConversation; + + public LeaveBehindItem(Context context) { + this(context, null); + } + + public LeaveBehindItem(Context context, AttributeSet attrs) { + this(context, attrs, -1); + } + + public LeaveBehindItem(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + switch (id) { + case R.id.undo_button: + if (mAccount.undoUri != null) { + // NOTE: We might want undo to return the messages affected, + // in which case + // the resulting cursor might be interesting... + // TODO: Use UIProvider.SEQUENCE_QUERY_PARAMETER to indicate + // the set of + // commands to undo + mAdapter.clearLeaveBehind(mConversation); + mAdapter.setUndo(true); + Conversation.undo(getContext(), mAccount.undoUri); + } + break; + } + } + + public void bindOperations(Account account, AnimatedAdapter adapter, UndoOperation undoOp, + Conversation target) { + mUndoOp = undoOp; + mAccount = account; + mAdapter = adapter; + mConversation = target; + ((TextView) findViewById(R.id.undo_description)).setText(Html.fromHtml(mUndoOp + .getDescription(getContext()))); + ((Button) findViewById(R.id.undo_button)).setOnClickListener(this); + } + + public void commit() { + Conversation.delete(getContext(), ImmutableList.of(mConversation)); + mAdapter.clearLeaveBehind(mConversation); + } + + public boolean canSwipe() { + return true; + } + + @Override + public View getView() { + return this; + } + + @Override + public void cancelTap() { + // Do nothing. + } +} diff --git a/src/com/android/mail/ui/SwipeHelper.java b/src/com/android/mail/ui/SwipeHelper.java index 9b1331e1d..cbb1a466b 100644 --- a/src/com/android/mail/ui/SwipeHelper.java +++ b/src/com/android/mail/ui/SwipeHelper.java @@ -68,7 +68,7 @@ public class SwipeHelper { private float mInitialTouchPosX; private boolean mDragging; - private ConversationItemView mCurrView; + private SwipeableItemView mCurrView; private View mCurrAnimView; private boolean mCanCurrViewBeDimissed; private float mDensityScale; @@ -190,12 +190,12 @@ public class SwipeHelper { mLastY = ev.getY(); mDragging = false; View view = mCallback.getChildAtPosition(ev); - if (view instanceof ConversationItemView) { - mCurrView = (ConversationItemView) view; + if (view instanceof SwipeableItemView) { + mCurrView = (SwipeableItemView) view; } mVelocityTracker.clear(); if (mCurrView != null) { - mCurrAnimView = mCallback.getChildContentView(mCurrView); + mCurrAnimView = mCurrView.getView(); mCanCurrViewBeDimissed = mCallback.canChildBeDismissed(mCurrView); mVelocityTracker.addMovement(ev); mInitialTouchPosX = ev.getX(); @@ -217,10 +217,8 @@ public class SwipeHelper { float pos = ev.getX(); float delta = pos - mInitialTouchPosX; if (Math.abs(delta) > mPagingTouchSlop) { - if (mCallback.getSelectionSet().isEmpty() - || (!mCallback.getSelectionSet().isEmpty() - && mCurrView.isChecked())) { - mCallback.onBeginDrag(mCurrView); + if (mCurrView.canSwipe()) { + mCallback.onBeginDrag(mCurrView.getView()); mDragging = true; mInitialTouchPosX = ev.getX() - mCurrAnimView.getTranslationX(); mInitialTouchPosY = ev.getY(); @@ -254,9 +252,9 @@ public class SwipeHelper { * @param velocity The desired pixels/second speed at which the view should * move */ - private void dismissChild(final View view, float velocity) { - final View animView = mCurrView; - final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(animView); + private void dismissChild(final SwipeableItemView view, float velocity) { + final View animView = mCurrView.getView(); + final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); float newPos = determinePos(animView, velocity); int duration = determineDuration(animView, newPos, velocity); @@ -265,8 +263,8 @@ public class SwipeHelper { anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mCallback.onChildDismissed(view); - mCurrView.setLayerType(View.LAYER_TYPE_NONE, null); + mCallback.onChildDismissed(mCurrView); + animView.setLayerType(View.LAYER_TYPE_NONE, null); } }); anim.addUpdateListener(new AnimatorUpdateListener() { @@ -285,8 +283,8 @@ public class SwipeHelper { AnimatorListenerAdapter listener = new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - mCallback.onChildrenDismissed(views); - mCurrView.setLayerType(View.LAYER_TYPE_NONE, null); + mCallback.onChildrenDismissed(mCurrView, views); + mCurrView.getView().setLayerType(View.LAYER_TYPE_NONE, null); } }; dismissChildren(views, velocity, listener); @@ -294,8 +292,8 @@ public class SwipeHelper { private void dismissChildren(final Collection<ConversationItemView> views, float velocity, AnimatorListenerAdapter listener) { - final View animView = mCurrView; - final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(animView); + final View animView = mCurrView.getView(); + final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(mCurrView); float newPos = determinePos(animView, velocity); int duration = determineDuration(animView, newPos, velocity); ArrayList<Animator> animations = new ArrayList<Animator>(); @@ -351,9 +349,9 @@ public class SwipeHelper { return newPos; } - public void snapChild(final View view, float velocity) { - final View animView = mCallback.getChildContentView(view); - final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(animView); + public void snapChild(final SwipeableItemView view, float velocity) { + final View animView = view.getView(); + final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view); ObjectAnimator anim = createTranslationAnimation(animView, 0); int duration = SNAP_ANIM_LEN; anim.setDuration(duration); @@ -426,7 +424,7 @@ public class SwipeHelper { mCurrAnimView.setAlpha(getAlphaForOffset(mCurrAnimView)); } } - invalidateGlobalRegion(mCurrView); + invalidateGlobalRegion(mCurrView.getView()); } break; case MotionEvent.ACTION_UP: @@ -473,7 +471,7 @@ public class SwipeHelper { mCallback.onDragCancelled(mCurrView); if (mAssociatedViews != null && mAssociatedViews.size() > 1) { - for (View v : mAssociatedViews) { + for (SwipeableItemView v : mAssociatedViews) { snapChild(v, velocity); } } else { @@ -489,17 +487,15 @@ public class SwipeHelper { public interface Callback { View getChildAtPosition(MotionEvent ev); - View getChildContentView(View v); - - boolean canChildBeDismissed(View v); + boolean canChildBeDismissed(SwipeableItemView v); void onBeginDrag(View v); - void onChildDismissed(View v); + void onChildDismissed(SwipeableItemView v); - void onChildrenDismissed(Collection<ConversationItemView> v); + void onChildrenDismissed(SwipeableItemView target, Collection<ConversationItemView> v); - void onDragCancelled(View v); + void onDragCancelled(SwipeableItemView v); ConversationSelectionSet getSelectionSet(); } diff --git a/src/com/android/mail/ui/SwipeableItemView.java b/src/com/android/mail/ui/SwipeableItemView.java new file mode 100644 index 000000000..f50a8caec --- /dev/null +++ b/src/com/android/mail/ui/SwipeableItemView.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2012 Google Inc. + * Licensed to 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 com.android.mail.ui; + +import android.view.View; + +/** + * Represents an item that can be dismissed by the SwipeableListView. + */ +public interface SwipeableItemView { + public View getView(); + + public boolean canSwipe(); + + public void cancelTap(); +} diff --git a/src/com/android/mail/ui/SwipeableListView.java b/src/com/android/mail/ui/SwipeableListView.java index 06b1f8936..45baebfc2 100644 --- a/src/com/android/mail/ui/SwipeableListView.java +++ b/src/com/android/mail/ui/SwipeableListView.java @@ -41,7 +41,6 @@ import java.util.Collection; public class SwipeableListView extends ListView implements Callback{ private SwipeHelper mSwipeHelper; - private SwipeCompleteListener mSwipeCompleteListener; private boolean mEnableSwipe = false; private ListAdapter mDebugAdapter; private int mDebugLastCount; @@ -52,6 +51,7 @@ public class SwipeableListView extends ListView implements Callback{ public static final String LOG_TAG = new LogUtils().getLogTag(); private ConversationSelectionSet mConvSelectionSet; + private int mSwipeAction; public SwipeableListView(Context context) { this(context, null); @@ -93,8 +93,8 @@ public class SwipeableListView extends ListView implements Callback{ return mEnableSwipe; } - public void setSwipeCompleteListener(SwipeCompleteListener listener) { - mSwipeCompleteListener = listener; + public void setSwipeAction(int action) { + mSwipeAction = action; } public void setSelectionSet(ConversationSelectionSet set) { @@ -175,46 +175,82 @@ public class SwipeableListView extends ListView implements Callback{ } @Override - public View getChildContentView(View v) { - return v; + public boolean canChildBeDismissed(SwipeableItemView v) { + View view = v.getView(); + return view instanceof ConversationItemView || view instanceof LeaveBehindItem; } @Override - public boolean canChildBeDismissed(View v) { - return v instanceof ConversationItemView; + public void onChildDismissed(SwipeableItemView v) { + View view = v.getView(); + if (view instanceof ConversationItemView) { + dismissChildren((ConversationItemView) v, null); + } else if (view instanceof LeaveBehindItem) { + ((LeaveBehindItem)view).commit(); + } } @Override - public void onChildDismissed(View v) { - dismissChildren(ImmutableList.of(getConversation(v))); + public void onChildrenDismissed(SwipeableItemView target, + Collection<ConversationItemView> views) { + assert(target instanceof ConversationItemView); + dismissChildren((ConversationItemView) target.getView(), views); } - @Override - public void onChildrenDismissed(Collection<ConversationItemView> views) { - final ArrayList<Conversation> conversations = new ArrayList<Conversation>(); - for (ConversationItemView view : views) { - conversations.add(getConversation(view)); + private void dismissChildren(final ConversationItemView target, + final Collection<ConversationItemView> conversationViews) { + final Context context = getContext(); + final AnimatedAdapter adapter = ((AnimatedAdapter) getAdapter()); + final UndoOperation undoOp; + if (conversationViews != null) { + final ArrayList<Conversation> conversations = new ArrayList<Conversation>( + conversationViews.size()); + for (ConversationItemView view : conversationViews) { + if (view.getConversation().id != target.getConversation().id) { + conversations.add(view.getConversation()); + } + } + undoOp = new UndoOperation( + conversationViews != null ? (conversations.size() + 1) : 1, mSwipeAction); + handleLeaveBehind(target, undoOp, context); + adapter.delete(conversations, new ActionCompleteListener() { + public void onActionComplete() { + switch (mSwipeAction) { + case R.id.archive: + Conversation.archive(context, conversations); + break; + case R.id.delete: + Conversation.delete(context, conversations); + break; + } + } + }); + } else { + undoOp = new UndoOperation(1, mSwipeAction); + target.getConversation().position = getPositionForView(target); + handleLeaveBehind(target, undoOp, context); } - dismissChildren(conversations); } - private Conversation getConversation(View view) { - Conversation c = ((ConversationItemView) view).getConversation(); - if (view.getParent() == null) { - return c; + private void handleLeaveBehind(ConversationItemView target, UndoOperation undoOp, + Context context) { + Conversation conv = target.getConversation(); + final AnimatedAdapter adapter = ((AnimatedAdapter) getAdapter()); + adapter.setupLeaveBehind(conv, undoOp, conv.position); + switch (mSwipeAction) { + case R.id.archive: + Conversation.mostlyArchive(context, + ImmutableList.of(target.getConversation())); + break; + case R.id.delete: + Conversation.mostlyDelete(context, + ImmutableList.of(target.getConversation())); + break; + } + adapter.notifyDataSetChanged(); + if (!mConvSelectionSet.isEmpty()) { + mConvSelectionSet.clear(); } - c.position = getPositionForView(view); - return c; - } - - private void dismissChildren(final Collection<Conversation> conversations) { - AnimatedAdapter adapter = ((AnimatedAdapter) getAdapter()); - adapter.delete(conversations, new ActionCompleteListener() { - @Override - public void onActionComplete() { - mSwipeCompleteListener.onSwipeComplete(conversations); - } - }); } @Override @@ -231,7 +267,7 @@ public class SwipeableListView extends ListView implements Callback{ } @Override - public void onDragCancelled(View v) { + public void onDragCancelled(SwipeableItemView v) { mSwipeHelper.setAssociatedViews(null); } @@ -258,4 +294,4 @@ public class SwipeableListView extends ListView implements Callback{ public interface SwipeCompleteListener { public void onSwipeComplete(Collection<Conversation> conversations); } -} +}
\ No newline at end of file |