Make removal of queued items undoable
This commit is contained in:
parent
4707139def
commit
a66d225b9f
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 963 B |
|
@ -0,0 +1,22 @@
|
|||
<!--
|
||||
|
||||
Copyright 2012 Roman Nurik
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/undobar_button_pressed" android:state_pressed="true"/>
|
||||
<item android:drawable="@drawable/undobar_button_focused" android:state_focused="true"/>
|
||||
<item android:drawable="@android:color/transparent"/>
|
||||
</selector>
|
|
@ -32,4 +32,9 @@
|
|||
android:gravity="center"
|
||||
android:text="@string/no_items_label" />
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout android:id="@+id/undobar" style="@style/UndoBar">
|
||||
<TextView android:id="@+id/undobar_message" style="@style/UndoBarMessage" />
|
||||
<Button android:id="@+id/undobar_button" style="@style/UndoBarButton" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<integer name="undobar_hide_delay">5000</integer>
|
||||
</resources>
|
|
@ -122,6 +122,8 @@
|
|||
<!-- Queue operations -->
|
||||
<string name="clear_queue_label">Clear queue</string>
|
||||
<string name="organize_queue_label">Organize queue</string>
|
||||
<string name="undo">Undo</string>
|
||||
<string name="removed_from_queue">Item removed</string>
|
||||
|
||||
<!-- Flattr -->
|
||||
<string name="flattr_auth_label">Flattr sign-in</string>
|
||||
|
@ -239,4 +241,4 @@
|
|||
<string name="folder_not_empty_dialog_msg">The folder you have selected is not empty. Media downloads and other files will be placed directly in this folder. Continue anyway?</string>
|
||||
<string name="set_to_default_folder">Choose default folder</string>
|
||||
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -92,4 +92,42 @@
|
|||
<item name="android:textColor">#FFFFFF</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
<style name="UndoBar">
|
||||
<item name="android:layout_width">match_parent</item>
|
||||
<item name="android:layout_height">48dp</item>
|
||||
<item name="android:layout_gravity">bottom</item>
|
||||
<item name="android:layout_marginLeft">8dp</item>
|
||||
<item name="android:layout_marginRight">8dp</item>
|
||||
<item name="android:layout_marginBottom">16dp</item>
|
||||
<item name="android:orientation">horizontal</item>
|
||||
<item name="android:background">@drawable/undobar</item>
|
||||
<item name="android:clickable">true</item>
|
||||
<item name="android:showDividers">middle</item>
|
||||
<item name="android:divider">@drawable/undobar_divider</item>
|
||||
<item name="android:dividerPadding">10dp</item>
|
||||
</style>
|
||||
<style name="UndoBarMessage">
|
||||
<item name="android:layout_width">0dp</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_marginLeft">16dp</item>
|
||||
<item name="android:layout_gravity">center_vertical</item>
|
||||
<item name="android:layout_marginRight">16dp</item>
|
||||
<item name="android:textAppearance">?android:textAppearanceMedium</item>
|
||||
<item name="android:textColor">#fff</item>
|
||||
</style>
|
||||
<style name="UndoBarButton">
|
||||
<item name="android:layout_width">wrap_content</item>
|
||||
<item name="android:layout_height">match_parent</item>
|
||||
<item name="android:paddingLeft">16dp</item>
|
||||
<item name="android:paddingRight">16dp</item>
|
||||
<item name="android:background">@drawable/undobar_button</item>
|
||||
<item name="android:drawableLeft">@drawable/ic_undobar_undo</item>
|
||||
<item name="android:drawablePadding">12dp</item>
|
||||
<item name="android:textAppearance">?android:textAppearanceSmall</item>
|
||||
<item name="android:textAllCaps">true</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:textColor">#fff</item>
|
||||
<item name="android:text">@string/undo</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
|
|
@ -3,6 +3,8 @@ package de.danoeh.antennapod.activity;
|
|||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
@ -21,13 +23,15 @@ import de.danoeh.antennapod.feed.EventDistributor;
|
|||
import de.danoeh.antennapod.feed.FeedItem;
|
||||
import de.danoeh.antennapod.feed.FeedManager;
|
||||
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.util.UndoBarController;
|
||||
|
||||
public class OrganizeQueueActivity extends SherlockListActivity {
|
||||
public class OrganizeQueueActivity extends SherlockListActivity implements UndoBarController.UndoListener {
|
||||
private static final String TAG = "OrganizeQueueActivity";
|
||||
|
||||
private static final int MENU_ID_ACCEPT = 2;
|
||||
|
||||
private OrganizeAdapter adapter;
|
||||
private UndoBarController undoBarController;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
|
@ -41,6 +45,8 @@ public class OrganizeQueueActivity extends SherlockListActivity {
|
|||
|
||||
adapter = new OrganizeAdapter(this);
|
||||
setListAdapter(adapter);
|
||||
|
||||
undoBarController = new UndoBarController(findViewById(R.id.undobar), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -82,8 +88,10 @@ public class OrganizeQueueActivity extends SherlockListActivity {
|
|||
@Override
|
||||
public void remove(int which) {
|
||||
FeedManager manager = FeedManager.getInstance();
|
||||
manager.removeQueueItem(OrganizeQueueActivity.this,
|
||||
(FeedItem) getListAdapter().getItem(which));
|
||||
FeedItem item = (FeedItem) getListAdapter().getItem(which);
|
||||
manager.removeQueueItem(OrganizeQueueActivity.this, item);
|
||||
undoBarController.showUndoBar(false, getString(R.string.removed_from_queue),
|
||||
new UndoItem(item, which));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -110,6 +118,17 @@ public class OrganizeQueueActivity extends SherlockListActivity {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUndo(Parcelable token) {
|
||||
// Perform the undo
|
||||
UndoItem undoItem = (UndoItem) token;
|
||||
FeedItem feedItem = undoItem.getFeedItem();
|
||||
int position = undoItem.getPosition();
|
||||
|
||||
FeedManager manager = FeedManager.getInstance();
|
||||
manager.addQueueItemAt(OrganizeQueueActivity.this, feedItem, position, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* WARNING: If the PlaybackService is playing an episode from the queue,
|
||||
* this list adapter will ignore the first item in the list to make sure
|
||||
|
@ -185,4 +204,53 @@ public class OrganizeQueueActivity extends SherlockListActivity {
|
|||
|
||||
}
|
||||
|
||||
private static class UndoItem implements Parcelable {
|
||||
private long itemId;
|
||||
private long feedId;
|
||||
private int position;
|
||||
|
||||
public UndoItem(FeedItem item, int position) {
|
||||
FeedManager manager = FeedManager.getInstance();
|
||||
this.itemId = item.getId();
|
||||
this.feedId = item.getFeed().getId();
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
private UndoItem(Parcel in) {
|
||||
itemId = in.readLong();
|
||||
feedId = in.readLong();
|
||||
position = in.readInt();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<UndoItem> CREATOR
|
||||
= new Parcelable.Creator<UndoItem>() {
|
||||
public UndoItem createFromParcel(Parcel in) {
|
||||
return new UndoItem(in);
|
||||
}
|
||||
|
||||
public UndoItem[] newArray(int size) {
|
||||
return new UndoItem[size];
|
||||
}
|
||||
};
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeLong(itemId);
|
||||
out.writeLong(feedId);
|
||||
out.writeInt(position);
|
||||
}
|
||||
|
||||
public FeedItem getFeedItem() {
|
||||
FeedManager manager = FeedManager.getInstance();
|
||||
return manager.getFeedItem(itemId, feedId);
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* Copyright 2012 Roman Nurik
|
||||
*
|
||||
* 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 de.danoeh.antennapod.util;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
import android.widget.TextView;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
|
||||
public class UndoBarController {
|
||||
private View mBarView;
|
||||
private TextView mMessageView;
|
||||
private ViewPropertyAnimator mBarAnimator;
|
||||
private Handler mHideHandler = new Handler();
|
||||
|
||||
private UndoListener mUndoListener;
|
||||
|
||||
// State objects
|
||||
private Parcelable mUndoToken;
|
||||
private CharSequence mUndoMessage;
|
||||
|
||||
public interface UndoListener {
|
||||
void onUndo(Parcelable token);
|
||||
}
|
||||
|
||||
public UndoBarController(View undoBarView, UndoListener undoListener) {
|
||||
mBarView = undoBarView;
|
||||
mBarAnimator = mBarView.animate();
|
||||
mUndoListener = undoListener;
|
||||
|
||||
mMessageView = (TextView) mBarView.findViewById(R.id.undobar_message);
|
||||
mBarView.findViewById(R.id.undobar_button)
|
||||
.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
hideUndoBar(false);
|
||||
mUndoListener.onUndo(mUndoToken);
|
||||
}
|
||||
});
|
||||
|
||||
hideUndoBar(true);
|
||||
}
|
||||
|
||||
public void showUndoBar(boolean immediate, CharSequence message, Parcelable undoToken) {
|
||||
mUndoToken = undoToken;
|
||||
mUndoMessage = message;
|
||||
mMessageView.setText(mUndoMessage);
|
||||
|
||||
mHideHandler.removeCallbacks(mHideRunnable);
|
||||
mHideHandler.postDelayed(mHideRunnable,
|
||||
mBarView.getResources().getInteger(R.integer.undobar_hide_delay));
|
||||
|
||||
mBarView.setVisibility(View.VISIBLE);
|
||||
if (immediate) {
|
||||
mBarView.setAlpha(1);
|
||||
} else {
|
||||
mBarAnimator.cancel();
|
||||
mBarAnimator
|
||||
.alpha(1)
|
||||
.setDuration(
|
||||
mBarView.getResources()
|
||||
.getInteger(android.R.integer.config_shortAnimTime))
|
||||
.setListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void hideUndoBar(boolean immediate) {
|
||||
mHideHandler.removeCallbacks(mHideRunnable);
|
||||
if (immediate) {
|
||||
mBarView.setVisibility(View.GONE);
|
||||
mBarView.setAlpha(0);
|
||||
mUndoMessage = null;
|
||||
mUndoToken = null;
|
||||
|
||||
} else {
|
||||
mBarAnimator.cancel();
|
||||
mBarAnimator
|
||||
.alpha(0)
|
||||
.setDuration(mBarView.getResources()
|
||||
.getInteger(android.R.integer.config_shortAnimTime))
|
||||
.setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
mBarView.setVisibility(View.GONE);
|
||||
mUndoMessage = null;
|
||||
mUndoToken = null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putCharSequence("undo_message", mUndoMessage);
|
||||
outState.putParcelable("undo_token", mUndoToken);
|
||||
}
|
||||
|
||||
public void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
if (savedInstanceState != null) {
|
||||
mUndoMessage = savedInstanceState.getCharSequence("undo_message");
|
||||
mUndoToken = savedInstanceState.getParcelable("undo_token");
|
||||
|
||||
if (mUndoToken != null || !TextUtils.isEmpty(mUndoMessage)) {
|
||||
showUndoBar(true, mUndoMessage, mUndoToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Runnable mHideRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
hideUndoBar(false);
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue