Added queue fragment
BIN
res/drawable-hdpi/ic_drag_handle.png
Executable file
After Width: | Height: | Size: 220 B |
BIN
res/drawable-hdpi/ic_drag_handle_dark.png
Executable file
After Width: | Height: | Size: 204 B |
BIN
res/drawable-mdpi/ic_drag_handle.png
Executable file
After Width: | Height: | Size: 175 B |
BIN
res/drawable-mdpi/ic_drag_handle_dark.png
Executable file
After Width: | Height: | Size: 159 B |
BIN
res/drawable-xhdpi/ic_drag_handle.png
Executable file
After Width: | Height: | Size: 234 B |
BIN
res/drawable-xhdpi/ic_drag_handle_dark.png
Executable file
After Width: | Height: | Size: 216 B |
BIN
res/drawable-xxhdpi/ic_drag_handle.png
Executable file
After Width: | Height: | Size: 290 B |
BIN
res/drawable-xxhdpi/ic_drag_handle_dark.png
Executable file
After Width: | Height: | Size: 265 B |
@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:dslv="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:dslv="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.mobeta.android.dslv.DragSortListView
|
||||
android:id="@android:id/list"
|
||||
@ -24,7 +24,7 @@
|
||||
dslv:sort_enabled="false"
|
||||
dslv:track_drag_sort="false"
|
||||
dslv:float_background_color="?attr/dragview_float_background"
|
||||
dslv:use_default_controller="true" />
|
||||
dslv:use_default_controller="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
@ -32,13 +32,14 @@
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:text="@string/no_items_label" />
|
||||
android:text="@string/no_items_label"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progLoading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminateOnly="true" />
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
</FrameLayout>
|
58
res/layout/queue_fragment.xml
Normal file
@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:dslv="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.mobeta.android.dslv.DragSortListView
|
||||
android:id="@android:id/list"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
dslv:collapsed_height="2dp"
|
||||
dslv:drag_enabled="true"
|
||||
dslv:drag_handle_id="@id/drag_handle"
|
||||
dslv:drag_scroll_start="0.33"
|
||||
dslv:float_alpha="0.6"
|
||||
dslv:max_drag_scroll_speed="0.5"
|
||||
dslv:remove_enabled="true"
|
||||
dslv:remove_mode="flingRemove"
|
||||
dslv:slide_shuffle_speed="0.3"
|
||||
dslv:sort_enabled="true"
|
||||
dslv:track_drag_sort="true"
|
||||
dslv:float_background_color="?attr/dragview_float_background"
|
||||
dslv:use_default_controller="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:gravity="center"
|
||||
android:text="@string/no_items_label"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progLoading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<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>
|
||||
|
||||
</FrameLayout>
|
130
res/layout/queue_listitem.xml
Normal file
@ -0,0 +1,130 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="match_parent"
|
||||
android:id="@+id/drag_handle"
|
||||
android:src="?attr/dragview_background"
|
||||
android:scaleType="center"
|
||||
android:layout_margin="8dp"
|
||||
android:contentDescription="@string/drag_handle_content_description"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginRight="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvImage"
|
||||
android:contentDescription="@string/cover_label"
|
||||
android:layout_width="@dimen/thumbnail_length_itemlist"
|
||||
android:layout_height="@dimen/thumbnail_length_itemlist"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:scaleType="centerCrop"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/statusPlaying"
|
||||
android:contentDescription="@string/status_playing_label"
|
||||
android:layout_width="@dimen/status_indicator_width"
|
||||
android:layout_height="18dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="@color/status_playing"
|
||||
android:gravity="center"
|
||||
android:padding="2dp"
|
||||
android:src="@drawable/av_play_dark"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPublished"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toRightOf="@id/imgvImage"
|
||||
android:layout_toLeftOf="@id/statusPlaying"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorTertiary"
|
||||
android:textSize="@dimen/text_size_micro"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/txtvPublished"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:layout_toRightOf="@id/imgvImage"
|
||||
android:layout_toLeftOf="@id/statusPlaying"
|
||||
android:ellipsize="end"
|
||||
android:lines="2"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_toRightOf="@id/imgvImage"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/bottom_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbar_download_progress"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:max="100"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_alignParentLeft="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvDuration"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:textColor="?android:attr/textColorTertiary"
|
||||
android:textSize="@dimen/text_size_micro"/>
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/vertical_divider"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butSecondaryAction"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:layout_width="@dimen/listview_secondary_button_width"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/borderless_button"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
</LinearLayout>
|
@ -362,6 +362,7 @@
|
||||
<string name="in_queue_label">Episode is in the queue</string>
|
||||
<string name="new_episodes_count_label">Number of new episodes</string>
|
||||
<string name="in_progress_episodes_count_label">Number of episodes you have started listening to</string>
|
||||
<string name="drag_handle_content_description">Drag to change the position of this item</string>
|
||||
|
||||
<!-- AntennaPodSP -->
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
<item name="attr/overlay_background">@color/overlay_light</item>
|
||||
<item name="attr/spinner_button">@drawable/spinner_button</item>
|
||||
<item name="attr/overlay_drawable">@drawable/overlay_drawable</item>
|
||||
<item name="attr/dragview_background">@drawable/dragview_background</item>
|
||||
<item name="attr/dragview_background">@drawable/ic_drag_handle</item>
|
||||
<item name="attr/dragview_float_background">@color/white</item>
|
||||
<item name="attr/nav_drawer_background">@color/white</item>
|
||||
<item name="attr/nav_drawer_toggle">@drawable/ic_drawer</item>
|
||||
@ -71,7 +71,7 @@
|
||||
<item name="attr/overlay_background">@color/overlay_dark</item>
|
||||
<item name="attr/spinner_button">@drawable/spinner_button_dark</item>
|
||||
<item name="attr/overlay_drawable">@drawable/overlay_drawable_dark</item>
|
||||
<item name="attr/dragview_background">@drawable/dragview_background_dark</item>
|
||||
<item name="attr/dragview_background">@drawable/ic_drag_handle_dark</item>
|
||||
<item name="attr/dragview_float_background">@color/black</item>
|
||||
<item name="attr/nav_drawer_background">#3B3B3B</item>
|
||||
<item name="attr/nav_drawer_toggle">@drawable/ic_drawer_dark</item>
|
||||
|
@ -26,10 +26,7 @@ import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.asynctask.ImageLoader;
|
||||
import de.danoeh.antennapod.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.feed.Feed;
|
||||
import de.danoeh.antennapod.fragment.EpisodesFragment;
|
||||
import de.danoeh.antennapod.fragment.ExternalPlayerFragment;
|
||||
import de.danoeh.antennapod.fragment.ItemlistFragment;
|
||||
import de.danoeh.antennapod.fragment.NewEpisodesFragment;
|
||||
import de.danoeh.antennapod.fragment.*;
|
||||
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.storage.DBReader;
|
||||
import de.danoeh.antennapod.util.StorageUtils;
|
||||
@ -126,8 +123,15 @@ public class MainActivity extends ActionBarActivity {
|
||||
FragmentTransaction fT = fragmentManager.beginTransaction();
|
||||
Fragment fragment = null;
|
||||
if (viewType == NavListAdapter.VIEW_TYPE_NAV) {
|
||||
switch (relPos) {
|
||||
case 0:
|
||||
fragment = new NewEpisodesFragment();
|
||||
break;
|
||||
case 1:
|
||||
fragment = new QueueFragment();
|
||||
break;
|
||||
}
|
||||
currentTitle = getString(NavListAdapter.NAV_TITLES[relPos]);
|
||||
fragment = new NewEpisodesFragment();
|
||||
|
||||
} else if (viewType == NavListAdapter.VIEW_TYPE_SUBSCRIPTION) {
|
||||
Feed feed = itemAccess.getItem(relPos);
|
||||
@ -145,13 +149,13 @@ public class MainActivity extends ActionBarActivity {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
int viewType = parent.getAdapter().getItemViewType(position);
|
||||
if (viewType != NavListAdapter.VIEW_TYPE_SECTION_DIVIDER) {
|
||||
if (viewType != NavListAdapter.VIEW_TYPE_SECTION_DIVIDER && position != selectedNavListIndex) {
|
||||
int relPos = (viewType == NavListAdapter.VIEW_TYPE_NAV) ? position : position - NavListAdapter.SUBSCRIPTION_OFFSET;
|
||||
loadFragment(viewType, relPos);
|
||||
drawerLayout.closeDrawer(navList);
|
||||
selectedNavListIndex = position;
|
||||
navAdapter.notifyDataSetChanged();
|
||||
}
|
||||
drawerLayout.closeDrawer(navList);
|
||||
}
|
||||
};
|
||||
|
||||
@ -164,6 +168,7 @@ public class MainActivity extends ActionBarActivity {
|
||||
if (!drawerLayout.isDrawerOpen(navList)) {
|
||||
getSupportActionBar().setTitle(currentTitle);
|
||||
}
|
||||
selectedNavListIndex = savedInstanceState.getInt("selectedNavIndex");
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,6 +182,7 @@ public class MainActivity extends ActionBarActivity {
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString("title", currentTitle.toString());
|
||||
outState.putInt("selectedNavIndex", selectedNavListIndex);
|
||||
|
||||
}
|
||||
|
||||
|
176
src/de/danoeh/antennapod/adapter/QueueListAdapter.java
Normal file
@ -0,0 +1,176 @@
|
||||
package de.danoeh.antennapod.adapter;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.*;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.asynctask.ImageLoader;
|
||||
import de.danoeh.antennapod.feed.FeedItem;
|
||||
import de.danoeh.antennapod.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.util.Converter;
|
||||
|
||||
/**
|
||||
* List adapter for the queue.
|
||||
*/
|
||||
public class QueueListAdapter extends BaseAdapter {
|
||||
|
||||
|
||||
private final Context context;
|
||||
private final ItemAccess itemAccess;
|
||||
private final TypedArray drawables;
|
||||
private final int[] labels;
|
||||
|
||||
public QueueListAdapter(Context context, ItemAccess itemAccess) {
|
||||
super();
|
||||
this.context = context;
|
||||
this.itemAccess = itemAccess;
|
||||
drawables = context.obtainStyledAttributes(new int[]{
|
||||
R.attr.av_play, R.attr.navigation_cancel, R.attr.av_download});
|
||||
labels = new int[]{R.string.play_label, R.string.cancel_download_label, R.string.download_label};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return itemAccess.getCount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return itemAccess.getItem(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
Holder holder;
|
||||
final FeedItem item = (FeedItem) getItem(position);
|
||||
if (item == null) return null;
|
||||
|
||||
if (convertView == null) {
|
||||
holder = new Holder();
|
||||
LayoutInflater inflater = (LayoutInflater) context
|
||||
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
convertView = inflater.inflate(R.layout.queue_listitem,
|
||||
null);
|
||||
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
|
||||
holder.pubDate = (TextView) convertView
|
||||
.findViewById(R.id.txtvPublished);
|
||||
holder.butSecondary = (ImageButton) convertView
|
||||
.findViewById(R.id.butSecondaryAction);
|
||||
holder.statusPlaying = (ImageView) convertView
|
||||
.findViewById(R.id.statusPlaying);
|
||||
holder.downloadProgress = (ProgressBar) convertView
|
||||
.findViewById(R.id.pbar_download_progress);
|
||||
holder.imageView = (ImageView) convertView.findViewById(R.id.imgvImage);
|
||||
holder.txtvDuration = (TextView) convertView.findViewById(R.id.txtvDuration);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (Holder) convertView.getTag();
|
||||
}
|
||||
|
||||
holder.title.setText(item.getTitle());
|
||||
holder.pubDate.setText(DateUtils.formatDateTime(context, item.getPubDate().getTime(), DateUtils.FORMAT_SHOW_DATE));
|
||||
FeedItem.State state = item.getState();
|
||||
|
||||
if (state == FeedItem.State.PLAYING) {
|
||||
holder.statusPlaying.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
holder.statusPlaying.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media != null) {
|
||||
final boolean isDownloadingMedia = DownloadRequester.getInstance().isDownloadingFile(media);
|
||||
|
||||
if (media.getDuration() > 0) {
|
||||
holder.txtvDuration.setText(Converter.getDurationStringLong(media.getDuration()));
|
||||
} else {
|
||||
holder.txtvDuration.setText("");
|
||||
}
|
||||
|
||||
if (isDownloadingMedia) {
|
||||
holder.downloadProgress.setVisibility(View.VISIBLE);
|
||||
holder.txtvDuration.setVisibility(View.GONE);
|
||||
} else {
|
||||
holder.txtvDuration.setVisibility(View.VISIBLE);
|
||||
holder.downloadProgress.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
if (!media.isDownloaded()) {
|
||||
if (isDownloadingMedia) {
|
||||
// item is being downloaded
|
||||
holder.butSecondary.setVisibility(View.VISIBLE);
|
||||
holder.butSecondary.setImageDrawable(drawables
|
||||
.getDrawable(1));
|
||||
holder.butSecondary.setContentDescription(context.getString(labels[1]));
|
||||
|
||||
holder.downloadProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
|
||||
} else {
|
||||
// item is not downloaded and not being downloaded
|
||||
holder.butSecondary.setVisibility(View.VISIBLE);
|
||||
holder.butSecondary.setImageDrawable(drawables.getDrawable(2));
|
||||
holder.butSecondary.setContentDescription(context.getString(labels[2]));
|
||||
}
|
||||
} else {
|
||||
// item is not being downloaded
|
||||
holder.butSecondary.setVisibility(View.VISIBLE);
|
||||
holder.butSecondary
|
||||
.setImageDrawable(drawables.getDrawable(0));
|
||||
holder.butSecondary.setContentDescription(context.getString(labels[0]));
|
||||
}
|
||||
} else {
|
||||
holder.butSecondary.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
holder.butSecondary.setFocusable(false);
|
||||
holder.butSecondary.setTag(item);
|
||||
holder.butSecondary.setOnClickListener(secondaryActionListener);
|
||||
|
||||
|
||||
ImageLoader.getInstance().loadThumbnailBitmap(
|
||||
item,
|
||||
holder.imageView,
|
||||
(int) convertView.getResources().getDimension(
|
||||
R.dimen.thumbnail_length)
|
||||
);
|
||||
return convertView;
|
||||
}
|
||||
|
||||
private View.OnClickListener secondaryActionListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
FeedItem item = (FeedItem) v.getTag();
|
||||
itemAccess.onFeedItemSecondaryAction(item);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
static class Holder {
|
||||
TextView title;
|
||||
TextView pubDate;
|
||||
ImageView imageView;
|
||||
ImageView statusPlaying;
|
||||
ProgressBar downloadProgress;
|
||||
TextView txtvDuration;
|
||||
ImageButton butSecondary;
|
||||
}
|
||||
|
||||
public interface ItemAccess {
|
||||
int getCount();
|
||||
|
||||
FeedItem getItem(int position);
|
||||
|
||||
int getItemDownloadProgressPercent(FeedItem item);
|
||||
|
||||
void onFeedItemSecondaryAction(FeedItem item);
|
||||
}
|
||||
}
|
@ -111,6 +111,10 @@ public class NewEpisodesFragment extends Fragment {
|
||||
txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
|
||||
progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
|
||||
|
||||
if (!itemsLoaded) {
|
||||
progLoading.setVisibility(View.VISIBLE);
|
||||
txtvEmpty.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
viewsCreated = true;
|
||||
|
||||
|
282
src/de/danoeh/antennapod/fragment/QueueFragment.java
Normal file
@ -0,0 +1,282 @@
|
||||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import com.mobeta.android.dslv.DragSortListView;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.QueueListAdapter;
|
||||
import de.danoeh.antennapod.asynctask.DownloadObserver;
|
||||
import de.danoeh.antennapod.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.feed.FeedItem;
|
||||
import de.danoeh.antennapod.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.service.download.Downloader;
|
||||
import de.danoeh.antennapod.storage.DBReader;
|
||||
import de.danoeh.antennapod.storage.DBWriter;
|
||||
import de.danoeh.antennapod.util.UndoBarController;
|
||||
import de.danoeh.antennapod.util.gui.FeedItemUndoToken;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Shows all items in the queue
|
||||
*/
|
||||
public class QueueFragment extends Fragment {
|
||||
private static final String TAG = "QueueFragment";
|
||||
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
|
||||
EventDistributor.DOWNLOAD_QUEUED |
|
||||
EventDistributor.QUEUE_UPDATE;
|
||||
|
||||
private DragSortListView listView;
|
||||
private QueueListAdapter listAdapter;
|
||||
private TextView txtvEmpty;
|
||||
private ProgressBar progLoading;
|
||||
private UndoBarController undoBarController;
|
||||
|
||||
private List<FeedItem> queue;
|
||||
private List<Downloader> downloaderList;
|
||||
|
||||
private boolean itemsLoaded = false;
|
||||
private boolean viewsCreated = false;
|
||||
|
||||
private AtomicReference<Activity> activity = new AtomicReference<Activity>();
|
||||
|
||||
private DownloadObserver downloadObserver = null;
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
|
||||
startItemLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
EventDistributor.getInstance().register(contentUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
EventDistributor.getInstance().unregister(contentUpdate);
|
||||
stopItemLoader();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
this.activity.set((MainActivity) activity);
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.setActivity(activity);
|
||||
downloadObserver.onResume();
|
||||
}
|
||||
if (viewsCreated && itemsLoaded) {
|
||||
onFragmentLoaded();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
listAdapter = null;
|
||||
undoBarController = null;
|
||||
activity.set(null);
|
||||
viewsCreated = false;
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.onPause();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View root = inflater.inflate(R.layout.queue_fragment, container, false);
|
||||
listView = (DragSortListView) root.findViewById(android.R.id.list);
|
||||
txtvEmpty = (TextView) root.findViewById(android.R.id.empty);
|
||||
progLoading = (ProgressBar) root.findViewById(R.id.progLoading);
|
||||
listView.setEmptyView(txtvEmpty);
|
||||
|
||||
listView.setDropListener(new DragSortListView.DropListener() {
|
||||
@Override
|
||||
public void drop(int from, int to) {
|
||||
stopItemLoader();
|
||||
final FeedItem item = queue.remove(from);
|
||||
queue.add(to, item);
|
||||
listAdapter.notifyDataSetChanged();
|
||||
DBWriter.moveQueueItem(getActivity(), from, to, true);
|
||||
}
|
||||
});
|
||||
|
||||
listView.setRemoveListener(new DragSortListView.RemoveListener() {
|
||||
@Override
|
||||
public void remove(int which) {
|
||||
stopItemLoader();
|
||||
FeedItem item = (FeedItem) listView.getAdapter().getItem(which);
|
||||
DBWriter.removeQueueItem(getActivity(), item.getId(), true);
|
||||
undoBarController.showUndoBar(false,
|
||||
getString(R.string.removed_from_queue), new FeedItemUndoToken(item,
|
||||
which));
|
||||
}
|
||||
});
|
||||
|
||||
undoBarController = new UndoBarController(root.findViewById(R.id.undobar), new UndoBarController.UndoListener() {
|
||||
@Override
|
||||
public void onUndo(Parcelable token) {
|
||||
// Perform the undo
|
||||
FeedItemUndoToken undoToken = (FeedItemUndoToken) token;
|
||||
if (token != null) {
|
||||
long itemId = undoToken.getFeedItemId();
|
||||
int position = undoToken.getPosition();
|
||||
DBWriter.addQueueItemAt(getActivity(), itemId, position, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!itemsLoaded) {
|
||||
progLoading.setVisibility(View.VISIBLE);
|
||||
txtvEmpty.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
viewsCreated = true;
|
||||
|
||||
if (itemsLoaded && activity.get() != null) {
|
||||
onFragmentLoaded();
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void onFragmentLoaded() {
|
||||
if (listAdapter == null) {
|
||||
listAdapter = new QueueListAdapter(activity.get(), itemAccess);
|
||||
listView.setAdapter(listAdapter);
|
||||
downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
|
||||
downloadObserver.onResume();
|
||||
}
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
if (listAdapter != null) {
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadDataAvailable(List<Downloader> downloaderList) {
|
||||
QueueFragment.this.downloaderList = downloaderList;
|
||||
if (listAdapter != null) {
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private QueueListAdapter.ItemAccess itemAccess = new QueueListAdapter.ItemAccess() {
|
||||
@Override
|
||||
public int getCount() {
|
||||
return (itemsLoaded) ? queue.size() : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeedItem getItem(int position) {
|
||||
return (itemsLoaded) ? queue.get(position) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemDownloadProgressPercent(FeedItem item) {
|
||||
if (downloaderList != null) {
|
||||
for (Downloader downloader : downloaderList) {
|
||||
if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
|
||||
&& downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
|
||||
return downloader.getDownloadRequest().getProgressPercent();
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFeedItemSecondaryAction(FeedItem item) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & EVENTS) != 0) {
|
||||
startItemLoader();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private ItemLoader itemLoader;
|
||||
|
||||
private void startItemLoader() {
|
||||
if (itemLoader != null) {
|
||||
itemLoader.cancel(true);
|
||||
}
|
||||
itemLoader = new ItemLoader();
|
||||
itemLoader.execute();
|
||||
}
|
||||
|
||||
private void stopItemLoader() {
|
||||
if (itemLoader != null) {
|
||||
itemLoader.cancel(true);
|
||||
}
|
||||
}
|
||||
|
||||
private class ItemLoader extends AsyncTask<Void, Void, List<FeedItem>> {
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
super.onPreExecute();
|
||||
if (viewsCreated && !itemsLoaded) {
|
||||
listView.setVisibility(View.GONE);
|
||||
txtvEmpty.setVisibility(View.GONE);
|
||||
progLoading.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(List<FeedItem> feedItems) {
|
||||
super.onPostExecute(feedItems);
|
||||
listView.setVisibility(View.VISIBLE);
|
||||
progLoading.setVisibility(View.GONE);
|
||||
|
||||
if (feedItems != null) {
|
||||
queue = feedItems;
|
||||
itemsLoaded = true;
|
||||
if (viewsCreated && activity.get() != null) {
|
||||
onFragmentLoaded();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<FeedItem> doInBackground(Void... params) {
|
||||
Context context = activity.get();
|
||||
if (context != null) {
|
||||
return DBReader.getQueue(context);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
55
src/de/danoeh/antennapod/util/gui/FeedItemUndoToken.java
Normal file
@ -0,0 +1,55 @@
|
||||
package de.danoeh.antennapod.util.gui;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import de.danoeh.antennapod.feed.FeedItem;
|
||||
|
||||
/**
|
||||
* Used by an UndoBarController for saving a removed FeedItem
|
||||
*/
|
||||
public class FeedItemUndoToken implements Parcelable {
|
||||
private long itemId;
|
||||
private long feedId;
|
||||
private int position;
|
||||
|
||||
public FeedItemUndoToken(FeedItem item, int position) {
|
||||
this.itemId = item.getId();
|
||||
this.feedId = item.getFeed().getId();
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
private FeedItemUndoToken(Parcel in) {
|
||||
itemId = in.readLong();
|
||||
feedId = in.readLong();
|
||||
position = in.readInt();
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<FeedItemUndoToken> CREATOR = new Parcelable.Creator<FeedItemUndoToken>() {
|
||||
public FeedItemUndoToken createFromParcel(Parcel in) {
|
||||
return new FeedItemUndoToken(in);
|
||||
}
|
||||
|
||||
public FeedItemUndoToken[] newArray(int size) {
|
||||
return new FeedItemUndoToken[size];
|
||||
}
|
||||
};
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeLong(itemId);
|
||||
out.writeLong(feedId);
|
||||
out.writeInt(position);
|
||||
}
|
||||
|
||||
public long getFeedItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return position;
|
||||
}
|
||||
}
|
||||
|