Added navigation drawer + new episodes fragment

This commit is contained in:
daniel oeh 2014-04-01 22:53:18 +02:00
parent 9abf27ca2f
commit c37b67172e
26 changed files with 1261 additions and 252 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 B

View File

@ -1,21 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main_view"
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/playerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true" />
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_above="@id/playerFragment"
android:layout_alignParentTop="true" >
</android.support.v4.view.ViewPager>
</RelativeLayout>
<FrameLayout
android:id="@+id/playerFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
<FrameLayout
android:id="@+id/main_view"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_alignParentTop="true"
android:layout_above="@id/playerFragment"/>
</RelativeLayout>
<ListView
android:id="@+id/nav_list"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:background="?attr/nav_drawer_background"
android:scrollbarStyle="outsideOverlay"
android:paddingLeft="8dp"
android:paddingRight="8dp"/>
</android.support.v4.widget.DrawerLayout>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imgvCover"
android:contentDescription="@string/cover_label"
android:layout_width="@dimen/thumbnail_length_navlist"
android:layout_height="@dimen/thumbnail_length_navlist"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:adjustViewBounds="true"
android:cropToPadding="true"
android:scaleType="fitXY"
android:layout_marginTop="6dp"
android:layout_marginBottom="6dp"/>
<TextView
android:id="@+id/txtvTitle"
android:lines="1"
android:ellipsize="end"
android:layout_centerVertical="true"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/text_size_navdrawer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="12dp"
android:layout_marginTop="14dp"
android:layout_marginBottom="14dp"
android:layout_marginRight="48dp"
android:layout_toRightOf="@id/imgvCover"
/>
</RelativeLayout>

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/txtvTitle"
android:lines="1"
android:ellipsize="end"
android:layout_centerVertical="true"
android:textColor="?android:attr/textColorPrimary"
android:textSize="@dimen/text_size_navdrawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_marginTop="28dp"
android:layout_marginBottom="28dp"/>
</RelativeLayout>

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/transparent">
<TextView
android:id="@+id/txtvTitle"
android:textColor="?android:attr/textColorTertiary"
android:textSize="@dimen/text_size_small"
android:typeface="sans"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:layout_marginTop="16dp"
android:paddingBottom="4dp"/>
<View
android:layout_width="match_parent"
android:layout_height="2dp"
android:layout_alignParentBottom="true"
android:background="@color/gray"/>
</RelativeLayout>

View File

@ -0,0 +1,44 @@
<?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">
<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="false"
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="false"
dslv:track_drag_sort="false"
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" />
</LinearLayout>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:padding="12dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/text_size_large"
android:textColor="@color/bright_blue"
android:textAllCaps="true"
android:textStyle="italic"
android:text="@string/recently_published_episodes_label"/>
</LinearLayout>

View File

@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<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_margin="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">
<ImageView
android:id="@+id/imgvDownloadStatus"
android:layout_width="@dimen/enc_icons_size"
android:layout_height="@dimen/enc_icons_size"
android:layout_alignParentRight="true"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="8dp"
tools:ignore="ContentDescription"/>
<ImageView
android:id="@id/imgvInPlaylist"
android:contentDescription="@string/in_queue_label"
android:layout_width="@dimen/enc_icons_size"
android:layout_height="@dimen/enc_icons_size"
android:layout_toLeftOf="@+id/imgvDownloadStatus"
android:src="?attr/stat_playlist"/>
<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_toLeftOf="@id/imgvInPlaylist"
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_toLeftOf="@id/imgvDownloadStatus"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_alignParentLeft="true"
android:textColor="?android:attr/textColorTertiary"
android:textSize="@dimen/text_size_micro"/>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -1,39 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/all_feed_refresh"
android:title="@string/refresh_label"
android:icon="?attr/navigation_refresh"
custom:showAsAction="ifRoom|collapseActionView">
</item>
<item
android:id="@+id/add_feed"
android:title="@string/add_feed_label"
android:icon="?attr/content_new"
custom:showAsAction="ifRoom|collapseActionView">
</item>
<item
android:id="@id/search_item"
android:icon="?attr/action_search"
android:title="@string/search_label"
custom:showAsAction="ifRoom|collapseActionView"
android:actionViewClass="android.support.v7.widget.SearchView"/>
<item
android:id="@+id/show_player"
android:title="@string/show_player_label"
android:icon="@drawable/av_play"
custom:showAsAction="collapseActionView"/>
<item
android:id="@+id/show_playback_history"
android:title="@string/playback_history_label"
custom:showAsAction="collapseActionView"/>
<item
android:id="@+id/show_downloads"
android:title="@string/downloads_label"
android:icon="@drawable/av_download"
custom:showAsAction="collapseActionView">
</item>
<item
android:id="@+id/show_preferences"
android:title="@string/settings_label"

View File

@ -36,4 +36,6 @@
<attr name="non_transparent_background" format="reference" />
<attr name="overlay_background" format="color" />
<attr name="nav_drawer_background" format="color"/>
<attr name="nav_drawer_toggle" format="reference"/>
</resources>

View File

@ -8,9 +8,11 @@
<dimen name="enc_icons_size">20dp</dimen>
<dimen name="text_size_micro">12sp</dimen>
<dimen name="text_size_small">14sp</dimen>
<dimen name="text_size_navdrawer">16sp</dimen>
<dimen name="text_size_medium">18sp</dimen>
<dimen name="text_size_large">22sp</dimen>
<dimen name="status_indicator_width">36dp</dimen>
<dimen name="thumbnail_length_itemlist">80dp</dimen>
<dimen name="thumbnail_length_onlinefeedview">110dp</dimen>
<dimen name="thumbnail_length_navlist">42dp</dimen>
</resources>

View File

@ -9,6 +9,7 @@
<string name="feeds_label">Feeds</string>
<string name="podcasts_label">PODCASTS</string>
<string name="episodes_label">EPISODES</string>
<string name="new_episodes_label">New episodes</string>
<string name="new_label">New</string>
<string name="waiting_list_label">Waiting list</string>
<string name="settings_label">Settings</string>
@ -20,6 +21,13 @@
<string name="gpodnet_main_label">gpodder.net</string>
<string name="gpodnet_auth_label">gpodder.net login</string>
<!-- New episodes fragment -->
<string name="recently_published_episodes_label">Recently published</string>
<!-- Main activity -->
<string name="drawer_open">Open menu</string>
<string name="drawer_close">Close menu</string>
<!-- Webview actions -->
<string name="open_in_browser_label">Open in browser</string>
<string name="copy_url_label">Copy URL</string>
@ -349,6 +357,7 @@
<string name="status_playing_label">Episode is being played</string>
<string name="status_downloading_label">Episode is being downloaded</string>
<string name="status_downloaded_label">Episode is downloaded</string>
<string name="status_not_downloaded_label">Episode has not been downloaded yet</string>
<string name="status_unread_label">Item is new</string>
<string name="in_queue_label">Episode is in the queue</string>
<string name="new_episodes_count_label">Number of new episodes</string>

View File

@ -35,6 +35,8 @@
<item name="attr/overlay_drawable">@drawable/overlay_drawable</item>
<item name="attr/dragview_background">@drawable/dragview_background</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>
</style>
<style name="Theme.AntennaPod.Dark" parent="@style/Theme.AppCompat">
@ -71,6 +73,8 @@
<item name="attr/overlay_drawable">@drawable/overlay_drawable_dark</item>
<item name="attr/dragview_background">@drawable/dragview_background_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>
</style>
<style name="UndoBar">

View File

@ -4,183 +4,229 @@ import android.app.SearchManager;
import android.app.SearchableInfo;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.media.AudioManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBar;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.Window;
import android.view.*;
import android.widget.*;
import de.danoeh.antennapod.BuildConfig;
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.FeedlistFragment;
import de.danoeh.antennapod.fragment.ItemlistFragment;
import de.danoeh.antennapod.fragment.NewEpisodesFragment;
import de.danoeh.antennapod.preferences.UserPreferences;
import de.danoeh.antennapod.service.download.DownloadService;
import de.danoeh.antennapod.service.playback.PlaybackService;
import de.danoeh.antennapod.storage.DBReader;
import de.danoeh.antennapod.storage.DBTasks;
import de.danoeh.antennapod.storage.DownloadRequester;
import de.danoeh.antennapod.util.StorageUtils;
import de.danoeh.antennapod.util.ThemeUtils;
import java.util.ArrayList;
import java.util.List;
/** The activity that is shown when the user launches the app. */
/**
* The activity that is shown when the user launches the app.
*/
public class MainActivity extends ActionBarActivity {
private static final String TAG = "MainActivity";
private static final String TAG = "MainActivity";
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED
| EventDistributor.DOWNLOAD_QUEUED
| EventDistributor.FEED_LIST_UPDATE
| EventDistributor.UNREAD_ITEMS_UPDATE;
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED
| EventDistributor.DOWNLOAD_QUEUED;
private ExternalPlayerFragment externalPlayerFragment;
private DrawerLayout drawerLayout;
private ViewPager viewpager;
private TabsAdapter pagerAdapter;
private ExternalPlayerFragment externalPlayerFragment;
private ListView navList;
private NavListAdapter navAdapter;
private static boolean appLaunched = false;
private ActionBarDrawerToggle drawerToogle;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
StorageUtils.checkStorageAvailability(this);
requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
setContentView(R.layout.main);
private CharSequence drawerTitle;
private CharSequence currentTitle;
@Override
public void onCreate(Bundle savedInstanceState) {
setTheme(UserPreferences.getTheme());
super.onCreate(savedInstanceState);
StorageUtils.checkStorageAvailability(this);
setContentView(R.layout.main);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
drawerTitle = currentTitle = getTitle();
viewpager = (ViewPager) findViewById(R.id.viewpager);
pagerAdapter = new TabsAdapter(this, viewpager);
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
navList = (ListView) findViewById(R.id.nav_list);
viewpager.setAdapter(pagerAdapter);
TypedArray typedArray = obtainStyledAttributes(new int[]{R.attr.nav_drawer_toggle});
drawerToogle = new ActionBarDrawerToggle(this, drawerLayout, typedArray.getResourceId(0, 0), R.string.drawer_open, R.string.drawer_close) {
@Override
public void onDrawerOpened(View drawerView) {
super.onDrawerOpened(drawerView);
getSupportActionBar().setTitle(drawerTitle);
supportInvalidateOptionsMenu();
}
ActionBar.Tab feedsTab = getSupportActionBar().newTab();
feedsTab.setText(R.string.podcasts_label);
ActionBar.Tab episodesTab = getSupportActionBar().newTab();
episodesTab.setText(R.string.episodes_label);
@Override
public void onDrawerClosed(View drawerView) {
super.onDrawerClosed(drawerView);
getSupportActionBar().setTitle(currentTitle);
supportInvalidateOptionsMenu();
pagerAdapter.addTab(feedsTab, FeedlistFragment.class, null);
pagerAdapter.addTab(episodesTab, EpisodesFragment.class, null);
}
};
typedArray.recycle();
FragmentTransaction transaction = getSupportFragmentManager()
.beginTransaction();
externalPlayerFragment = new ExternalPlayerFragment();
transaction.replace(R.id.playerFragment, externalPlayerFragment);
transaction.commit();
drawerLayout.setDrawerListener(drawerToogle);
FragmentManager fm = getSupportFragmentManager();
FragmentTransaction transaction = fm.beginTransaction();
externalPlayerFragment = new ExternalPlayerFragment();
transaction.replace(R.id.playerFragment, externalPlayerFragment);
// executed on application start
if (!appLaunched && getIntent().getAction() != null
&& getIntent().getAction().equals(Intent.ACTION_MAIN)) {
appLaunched = true;
if (DBReader.getNumberOfUnreadItems(this) > 0) {
// select 'episodes' tab
getSupportActionBar().setSelectedNavigationItem(1);
}
}
if (savedInstanceState != null) {
getSupportActionBar().setSelectedNavigationItem(
savedInstanceState.getInt("tab", 0));
}
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getSupportActionBar()
.getSelectedNavigationIndex());
}
@Override
protected void onPause() {
super.onPause();
EventDistributor.getInstance().unregister(contentUpdate);
}
transaction.commit();
@Override
protected void onResume() {
super.onResume();
StorageUtils.checkStorageAvailability(this);
updateProgressBarVisibility();
EventDistributor.getInstance().register(contentUpdate);
Fragment mainFragment = fm.findFragmentByTag("main");
if (mainFragment != null) {
transaction = fm.beginTransaction();
transaction.replace(R.id.main_view, mainFragment);
transaction.commit();
} else {
loadFragment(NavListAdapter.VIEW_TYPE_NAV, 0);
}
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
navAdapter = new NavListAdapter(itemAccess, this);
navList.setAdapter(navAdapter);
navList.setOnItemClickListener(navListClickListener);
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((EVENTS & arg) != 0) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Received contentUpdate Intent.");
updateProgressBarVisibility();
}
}
};
loadData();
private void updateProgressBarVisibility() {
if (DownloadService.isRunning
&& DownloadRequester.getInstance().isDownloadingFeeds()) {
setSupportProgressBarIndeterminateVisibility(true);
} else {
setSupportProgressBarIndeterminateVisibility(false);
}
supportInvalidateOptionsMenu();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.add_feed:
startActivity(new Intent(this, AddFeedActivity.class));
return true;
case R.id.all_feed_refresh:
DBTasks.refreshAllFeeds(this, null);
return true;
case R.id.show_downloads:
startActivity(new Intent(this, DownloadActivity.class));
return true;
case R.id.show_preferences:
startActivity(new Intent(this, PreferenceActivity.class));
return true;
case R.id.show_player:
startActivity(PlaybackService.getPlayerActivityIntent(this));
return true;
case R.id.show_playback_history:
startActivity(new Intent(this, PlaybackHistoryActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void loadFragment(int viewType, int relPos) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fT = fragmentManager.beginTransaction();
Fragment fragment = null;
if (viewType == NavListAdapter.VIEW_TYPE_NAV) {
currentTitle = getString(NavListAdapter.NAV_TITLES[relPos]);
fragment = new NewEpisodesFragment();
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
} else if (viewType == NavListAdapter.VIEW_TYPE_SUBSCRIPTION) {
Feed feed = itemAccess.getItem(relPos);
currentTitle = feed.getTitle();
fragment = ItemlistFragment.newInstance(feed.getId());
}
if (fragment != null) {
fT.replace(R.id.main_view, fragment, "main");
}
fT.commit();
}
private AdapterView.OnItemClickListener navListClickListener = new AdapterView.OnItemClickListener() {
@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) {
int relPos = (viewType == NavListAdapter.VIEW_TYPE_NAV) ? position : position - NavListAdapter.SUBSCRIPTION_OFFSET;
loadFragment(viewType, relPos);
drawerLayout.closeDrawer(navList);
selectedNavListIndex = position;
navAdapter.notifyDataSetChanged();
}
}
};
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
drawerToogle.syncState();
if (savedInstanceState != null) {
currentTitle = savedInstanceState.getString("title");
if (!drawerLayout.isDrawerOpen(navList)) {
getSupportActionBar().setTitle(currentTitle);
}
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
drawerToogle.onConfigurationChanged(newConfig);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("title", currentTitle.toString());
}
@Override
protected void onPause() {
super.onPause();
}
@Override
protected void onResume() {
super.onResume();
StorageUtils.checkStorageAvailability(this);
EventDistributor.getInstance().register(contentUpdate);
}
@Override
protected void onStop() {
super.onStop();
cancelLoadTask();
EventDistributor.getInstance().unregister(contentUpdate);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (drawerToogle.onOptionsItemSelected(item)) {
return true;
}
switch (item.getItemId()) {
case R.id.show_preferences:
startActivity(new Intent(this, PreferenceActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
MenuItem refreshAll = menu.findItem(R.id.all_feed_refresh);
if (DownloadService.isRunning
&& DownloadRequester.getInstance().isDownloadingFeeds()) {
refreshAll.setVisible(false);
} else {
refreshAll.setVisible(true);
}
return true;
}
boolean drawerOpen = drawerLayout.isDrawerOpen(navList);
menu.findItem(R.id.search_item).setVisible(!drawerOpen);
@Override
public boolean onCreateOptionsMenu(Menu menu) {
return true;
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
SearchManager searchManager =
(SearchManager) getSystemService(Context.SEARCH_SERVICE);
@ -196,89 +242,242 @@ public class MainActivity extends ActionBarActivity {
searchView.setSearchableInfo(
searchManager.getSearchableInfo(getComponentName()));
return true;
}
}
public static class TabsAdapter extends FragmentPagerAdapter implements
ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
private List<Feed> feeds;
private AsyncTask<Void, Void, List<Feed>> loadTask;
private int selectedNavListIndex = 0;
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
private ItemAccess itemAccess = new ItemAccess() {
@Override
public int getCount() {
if (feeds != null) {
return feeds.size();
} else {
return 0;
}
}
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
@Override
public Feed getItem(int position) {
if (feeds != null && position < feeds.size()) {
return feeds.get(position);
} else {
return null;
}
}
public TabsAdapter(MainActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
@Override
public int getSelectedItemIndex() {
return selectedNavListIndex;
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
@Override
public int getCount() {
return mTabs.size();
}
};
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(),
info.args);
}
private void loadData() {
loadTask = new AsyncTask<Void, Void, List<Feed>>() {
@Override
protected List<Feed> doInBackground(Void... params) {
return DBReader.getFeedList(MainActivity.this);
}
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
}
@Override
protected void onPostExecute(List<Feed> result) {
super.onPostExecute(result);
feeds = result;
navAdapter.notifyDataSetChanged();
}
};
loadTask.execute();
}
@Override
public void onPageSelected(int position) {
mActionBar.setSelectedNavigationItem(position);
}
private void cancelLoadTask() {
if (loadTask != null) {
loadTask.cancel(true);
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
@Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i = 0; i < mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
}
@Override
public void update(EventDistributor eventDistributor, Integer arg) {
if ((EVENTS & arg) != 0) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Received contentUpdate Intent.");
loadData();
}
}
};
@Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) {
private static class NavListAdapter extends BaseAdapter {
}
static final int VIEW_TYPE_COUNT = 3;
static final int VIEW_TYPE_NAV = 0;
static final int VIEW_TYPE_SECTION_DIVIDER = 1;
static final int VIEW_TYPE_SUBSCRIPTION = 2;
@Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) {
}
}
static final int[] NAV_TITLES = {R.string.new_episodes_label, R.string.queue_label, R.string.downloads_label, R.string.playback_history_label, R.string.add_feed_label};
static final int SUBSCRIPTION_OFFSET = 1 + NAV_TITLES.length;
private ItemAccess itemAccess;
private Context context;
private NavListAdapter(ItemAccess itemAccess, Context context) {
this.itemAccess = itemAccess;
this.context = context;
}
@Override
public int getCount() {
return NAV_TITLES.length + 1 + itemAccess.getCount();
}
@Override
public Object getItem(int position) {
int viewType = getItemViewType(position);
if (viewType == VIEW_TYPE_NAV) {
return context.getString(NAV_TITLES[position]);
} else if (viewType == VIEW_TYPE_SECTION_DIVIDER) {
return context.getString(R.string.podcasts_label);
} else {
return itemAccess.getItem(position);
}
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
if (0 <= position && position < NAV_TITLES.length) {
return VIEW_TYPE_NAV;
} else if (position < NAV_TITLES.length + 1) {
return VIEW_TYPE_SECTION_DIVIDER;
} else {
return VIEW_TYPE_SUBSCRIPTION;
}
}
@Override
public int getViewTypeCount() {
return VIEW_TYPE_COUNT;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
View v = null;
if (viewType == VIEW_TYPE_NAV) {
v = getNavView((String) getItem(position), position, convertView, parent);
} else if (viewType == VIEW_TYPE_SECTION_DIVIDER) {
v = getSectionDividerView((String) getItem(position), position, convertView, parent);
} else {
v = getFeedView(position - SUBSCRIPTION_OFFSET, convertView, parent);
}
if (v != null) {
TextView txtvTitle = (TextView) v.findViewById(R.id.txtvTitle);
if (position == itemAccess.getSelectedItemIndex()) {
txtvTitle.setTypeface(null, Typeface.BOLD);
} else {
txtvTitle.setTypeface(null, Typeface.NORMAL);
}
}
return v;
}
private View getNavView(String title, int position, View convertView, ViewGroup parent) {
NavHolder holder;
if (convertView == null) {
holder = new NavHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.nav_listitem, null);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
convertView.setTag(holder);
} else {
holder = (NavHolder) convertView.getTag();
}
holder.title.setText(title);
return convertView;
}
private View getSectionDividerView(String title, int position, View convertView, ViewGroup parent) {
SectionHolder holder;
if (convertView == null) {
holder = new SectionHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.nav_section_item, null);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
convertView.setTag(holder);
} else {
holder = (SectionHolder) convertView.getTag();
}
holder.title.setText(title);
convertView.setEnabled(false);
convertView.setOnClickListener(null);
return convertView;
}
private View getFeedView(int feedPos, View convertView, ViewGroup parent) {
FeedHolder holder;
Feed feed = itemAccess.getItem(feedPos);
if (convertView == null) {
holder = new FeedHolder();
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.nav_feedlistitem, null);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
holder.image = (ImageView) convertView.findViewById(R.id.imgvCover);
convertView.setTag(holder);
} else {
holder = (FeedHolder) convertView.getTag();
}
holder.title.setText(feed.getTitle());
ImageLoader.getInstance().loadThumbnailBitmap(feed.getImage(), holder.image, (int) context.getResources().getDimension(R.dimen.thumbnail_length_navlist));
return convertView;
}
static class NavHolder {
TextView title;
}
static class SectionHolder {
TextView title;
}
static class FeedHolder {
TextView title;
ImageView image;
}
}
public interface ItemAccess {
int getCount();
Feed getItem(int position);
int getSelectedItemIndex();
}
}

View File

@ -0,0 +1,225 @@
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.BaseAdapter;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.TextView;
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 list of new episodes
*/
public class NewEpisodesListAdapter extends BaseAdapter {
private static final int VIEW_TYPE_FEEDITEM = 0;
private static final int VIEW_TYPE_DIVIDER = 1;
private final Context context;
private final ItemAccess itemAccess;
private final TypedArray drawables;
private final int[] labels;
public NewEpisodesListAdapter(Context context, ItemAccess itemAccess) {
super();
this.context = context;
this.itemAccess = itemAccess;
drawables = context.obtainStyledAttributes(new int[]{
R.attr.navigation_accept, R.attr.navigation_refresh, R.attr.av_download});
labels = new int[]{R.string.status_downloaded_label, R.string.status_downloading_label, R.string.status_not_downloaded_label};
}
@Override
public int getCount() {
int unreadItems = itemAccess.getUnreadItemsCount();
int recentItems = itemAccess.getRecentItemsCount();
return unreadItems + recentItems + 1;
}
@Override
public Object getItem(int position) {
int unreadItems = itemAccess.getUnreadItemsCount();
if (position == unreadItems) {
return null;
}
if (position < unreadItems && unreadItems > 0) {
return itemAccess.getUnreadItem(position);
}
return itemAccess.getRecentItem(position - unreadItems - 1);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public int getItemViewType(int position) {
int unreadItems = itemAccess.getUnreadItemsCount();
if (position == unreadItems) {
return VIEW_TYPE_DIVIDER;
} else {
return VIEW_TYPE_FEEDITEM;
}
}
@Override
public int getViewTypeCount() {
return 2;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
int viewType = getItemViewType(position);
if (viewType == VIEW_TYPE_FEEDITEM) {
return getFeedItemView(position, convertView, parent);
} else {
return getDividerView(position, convertView, parent);
}
}
public View getDividerView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.new_episodes_listdivider,
null);
convertView.setOnClickListener(null);
convertView.setEnabled(false);
return convertView;
}
public View getFeedItemView(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.new_episodes_listitem,
null);
holder.title = (TextView) convertView.findViewById(R.id.txtvTitle);
holder.pubDate = (TextView) convertView
.findViewById(R.id.txtvPublished);
holder.downloadStatus = (ImageView) convertView
.findViewById(R.id.imgvDownloadStatus);
holder.queueStatus = (ImageView) convertView
.findViewById(R.id.imgvInPlaylist);
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.downloadStatus.setVisibility(View.VISIBLE);
holder.downloadStatus.setImageDrawable(drawables
.getDrawable(1));
holder.downloadStatus.setContentDescription(context.getString(labels[1]));
holder.downloadProgress.setProgress(itemAccess.getItemDownloadProgressPercent(item));
} else {
// item is not downloaded and not being downloaded
holder.downloadStatus.setVisibility(View.VISIBLE);
holder.downloadStatus.setImageDrawable(drawables.getDrawable(2));
holder.downloadStatus.setContentDescription(context.getString(labels[2]));
}
} else {
// item is not being downloaded
holder.downloadStatus.setVisibility(View.VISIBLE);
holder.downloadStatus
.setImageDrawable(drawables.getDrawable(0));
holder.downloadStatus.setContentDescription(context.getString(labels[0]));
}
} else {
holder.downloadStatus.setVisibility(View.INVISIBLE);
}
if (itemAccess.isInQueue(item)) {
holder.queueStatus.setVisibility(View.VISIBLE);
} else {
holder.queueStatus.setVisibility(View.INVISIBLE);
}
ImageLoader.getInstance().loadThumbnailBitmap(
item,
holder.imageView,
(int) convertView.getResources().getDimension(
R.dimen.thumbnail_length)
);
return convertView;
}
static class Holder {
TextView title;
TextView pubDate;
ImageView downloadStatus;
ImageView queueStatus;
ImageView imageView;
ImageView statusPlaying;
ProgressBar downloadProgress;
TextView txtvDuration;
}
public interface ItemAccess {
int getUnreadItemsCount();
int getRecentItemsCount();
FeedItem getUnreadItem(int position);
FeedItem getRecentItem(int position);
int getItemDownloadProgressPercent(FeedItem item);
boolean isInQueue(FeedItem item);
}
}

View File

@ -25,7 +25,7 @@ public class DownloadObserver {
*/
public static final int WAITING_INTERVAL_MS = 1000;
private final Activity activity;
private volatile Activity activity;
private final Handler handler;
private final Callback callback;
@ -57,12 +57,16 @@ public class DownloadObserver {
public void onResume() {
if (BuildConfig.DEBUG) Log.d(TAG, "DownloadObserver resumed");
activity.registerReceiver(contentChangedReceiver, new IntentFilter(DownloadService.ACTION_DOWNLOADS_CONTENT_CHANGED));
activity.bindService(new Intent(activity, DownloadService.class), mConnection, 0);
connectToDownloadService();
}
public void onPause() {
if (BuildConfig.DEBUG) Log.d(TAG, "DownloadObserver paused");
activity.unregisterReceiver(contentChangedReceiver);
try {
activity.unregisterReceiver(contentChangedReceiver);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
activity.unbindService(mConnection);
stopRefresher();
}
@ -70,6 +74,10 @@ public class DownloadObserver {
private BroadcastReceiver contentChangedReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// reconnect to DownloadService if connection has been closed
if (downloadService == null) {
connectToDownloadService();
}
callback.onContentChanged();
startRefresher();
}
@ -81,6 +89,10 @@ public class DownloadObserver {
void onDownloadDataAvailable(List<Downloader> downloaderList);
}
private void connectToDownloadService() {
activity.bindService(new Intent(activity, DownloadService.class), mConnection, 0);
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceDisconnected(ComponentName className) {
downloadService = null;
@ -138,13 +150,21 @@ public class DownloadObserver {
@Override
public void run() {
callback.onContentChanged();
List<Downloader> downloaderList = downloadService.getDownloads();
if (downloaderList == null || downloaderList.isEmpty()) {
Thread.currentThread().interrupt();
if (downloadService != null) {
List<Downloader> downloaderList = downloadService.getDownloads();
if (downloaderList == null || downloaderList.isEmpty()) {
Thread.currentThread().interrupt();
}
}
}
});
}
}
public void setActivity(Activity activity) {
if (activity == null) throw new IllegalArgumentException("activity = null");
this.activity = activity;
}
}

View File

@ -0,0 +1,265 @@
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.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.NewEpisodesListAdapter;
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.util.QueueAccess;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
/**
* Shows unread or recently published episodes
*/
public class NewEpisodesFragment extends Fragment {
private static final String TAG = "NewEpisodesFragment";
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
EventDistributor.DOWNLOAD_QUEUED |
EventDistributor.QUEUE_UPDATE |
EventDistributor.UNREAD_ITEMS_UPDATE;
private static final int RECENT_EPISODES_LIMIT = 150;
private DragSortListView listView;
private NewEpisodesListAdapter listAdapter;
private TextView txtvEmpty;
private ProgressBar progLoading;
private List<FeedItem> unreadItems;
private List<FeedItem> recentItems;
private QueueAccess queueAccess;
private List<Downloader> downloaderList;
private boolean itemsLoaded = false;
private boolean viewsCreated = false;
private AtomicReference<MainActivity> activity = new AtomicReference<MainActivity>();
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;
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.new_episodes_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);
viewsCreated = true;
if (itemsLoaded && activity.get() != null) {
onFragmentLoaded();
}
return root;
}
private void onFragmentLoaded() {
if (listAdapter == null) {
listAdapter = new NewEpisodesListAdapter(activity.get(), itemAccess);
listView.setAdapter(listAdapter);
listView.setEmptyView(txtvEmpty);
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) {
NewEpisodesFragment.this.downloaderList = downloaderList;
if (listAdapter != null) {
listAdapter.notifyDataSetChanged();
}
}
};
private NewEpisodesListAdapter.ItemAccess itemAccess = new NewEpisodesListAdapter.ItemAccess() {
@Override
public int getUnreadItemsCount() {
return (itemsLoaded) ? unreadItems.size() : 0;
}
@Override
public int getRecentItemsCount() {
return (itemsLoaded) ? recentItems.size() : 0;
}
@Override
public FeedItem getUnreadItem(int position) {
return (itemsLoaded) ? unreadItems.get(position) : null;
}
@Override
public FeedItem getRecentItem(int position) {
return (itemsLoaded) ? recentItems.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 boolean isInQueue(FeedItem item) {
if (itemsLoaded) {
return queueAccess.contains(item.getId());
} else {
return false;
}
}
};
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, Object[]> {
@Override
protected void onPreExecute() {
super.onPreExecute();
if (viewsCreated && !itemsLoaded) {
listView.setVisibility(View.GONE);
txtvEmpty.setVisibility(View.GONE);
progLoading.setVisibility(View.VISIBLE);
}
}
@Override
protected Object[] doInBackground(Void... params) {
Context context = activity.get();
if (context != null) {
return new Object[]{DBReader.getUnreadItemsList(context),
DBReader.getRecentlyPublishedEpisodes(context, RECENT_EPISODES_LIMIT),
QueueAccess.IDListAccess(DBReader.getQueueIDList(context))};
} else {
return null;
}
}
@Override
protected void onPostExecute(Object[] lists) {
super.onPostExecute(lists);
listView.setVisibility(View.VISIBLE);
progLoading.setVisibility(View.GONE);
if (lists != null) {
unreadItems = (List<FeedItem>) lists[0];
recentItems = (List<FeedItem>) lists[1];
queueAccess = (QueueAccess) lists[2];
itemsLoaded = true;
if (viewsCreated && activity.get() != null) {
onFragmentLoaded();
}
}
}
}
}

View File

@ -504,6 +504,32 @@ public final class DBReader {
return itemIds;
}
/**
* Loads a list of FeedItems sorted by pubDate in descending order.
*
* @param context A context that is used for opening a database connection.
* @param limit The maximum number of episodes that should be loaded.
* */
public static List<FeedItem> getRecentlyPublishedEpisodes(Context context, int limit) {
if (BuildConfig.DEBUG)
Log.d(TAG, "Extracting recently published items list");
PodDBAdapter adapter = new PodDBAdapter(context);
adapter.open();
Cursor itemlistCursor = adapter.getRecentlyPublishedItemsCursor(limit);
List<FeedItem> items = extractItemlistFromCursor(adapter,
itemlistCursor);
itemlistCursor.close();
loadFeedDataOfFeedItemlist(context, items);
adapter.close();
return items;
}
/**
* Loads the playback history from the database. A FeedItem is in the playback history if playback of the correpsonding episode
* has been completed at least once.

View File

@ -996,6 +996,11 @@ public class PodDBAdapter {
}
public final Cursor getRecentlyPublishedItemsCursor(int limit) {
Cursor c = db.query(TABLE_NAME_FEED_ITEMS, FEEDITEM_SEL_FI_SMALL, null, null, null, null, KEY_PUBDATE + " DESC LIMIT " + limit);
return c;
}
public Cursor getDownloadedItemsCursor() {
final String query = "SELECT " + SEL_FI_SMALL_STR + " FROM " + TABLE_NAME_FEED_ITEMS
+ " INNER JOIN " + TABLE_NAME_FEED_MEDIA + " ON "