Merge branch 'develop'
This commit is contained in:
commit
c9e8af52c2
@ -1,6 +1,14 @@
|
||||
Change Log
|
||||
==========
|
||||
|
||||
Version 1.0
|
||||
-----------
|
||||
* The queue can now be sorted
|
||||
* Added option to delete episode after playback
|
||||
* Fixed a bug that caused chapters to be displayed multiple times
|
||||
* Several other improvements and bugfixes
|
||||
|
||||
|
||||
Version 0.9.9.6
|
||||
---------------
|
||||
* Fixed problems related to variable playback speed plugins
|
||||
|
@ -1,3 +1,7 @@
|
||||
```
|
||||
Please note that AntennaPod is no longer maintained until further notice.
|
||||
```
|
||||
|
||||
How to report a bug
|
||||
-------------------
|
||||
- Use the search function to see if someone else has already reported the bug. If an issue has already been opened, see if you can add any useful information to it.
|
||||
|
@ -9,6 +9,7 @@ wseemann
|
||||
hzulla
|
||||
andrewgaul
|
||||
peschmae0
|
||||
TomHennen
|
||||
|
||||
Translations:
|
||||
|
||||
|
@ -1,5 +1,10 @@
|
||||
# AntennaPod
|
||||
|
||||
```
|
||||
Please note that AntennaPod will not receive any future updates until further notice.
|
||||
```
|
||||
|
||||
|
||||
This is the official repository of AntennaPod, a podcast manager for Android.
|
||||
|
||||
[![Download from Google Play](http://www.android.com/images/brand/android_app_on_play_large.png "Download from Google Play")](https://play.google.com/store/apps/details?id=de.danoeh.antennapod)
|
||||
|
@ -4,12 +4,10 @@ repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
compile 'com.android.support:support-v4:21.0.2'
|
||||
compile 'com.android.support:appcompat-v7:21.0.2'
|
||||
compile 'com.android.support:support-v4:21.0.3'
|
||||
compile 'com.android.support:appcompat-v7:21.0.3'
|
||||
compile 'org.apache.commons:commons-lang3:3.3.2'
|
||||
compile('org.shredzone.flattr4j:flattr4j-core:2.11') {
|
||||
exclude group: 'org.apache.httpcomponents', module: 'httpcore'
|
||||
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
|
||||
compile('org.shredzone.flattr4j:flattr4j-core:2.12') {
|
||||
exclude group: 'org.json', module: 'json'
|
||||
}
|
||||
compile 'commons-io:commons-io:2.4'
|
||||
@ -17,15 +15,15 @@ dependencies {
|
||||
compile 'com.jayway.android.robotium:robotium-solo:5.2.1'
|
||||
compile 'org.jsoup:jsoup:1.7.3'
|
||||
compile 'com.squareup.picasso:picasso:2.4.0'
|
||||
compile 'com.squareup.okhttp:okhttp:2.1.0'
|
||||
compile 'com.squareup.okhttp:okhttp-urlconnection:2.1.0'
|
||||
compile 'com.squareup.okio:okio:1.0.1'
|
||||
compile 'com.squareup.okhttp:okhttp:2.2.0'
|
||||
compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'
|
||||
compile 'com.squareup.okio:okio:1.2.0'
|
||||
compile project(':core')
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1.1"
|
||||
buildToolsVersion "21.1.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 10
|
||||
|
@ -41,6 +41,7 @@ public class PlaybackTest extends ActivityInstrumentationTestCase2<MainActivity>
|
||||
adapter.open();
|
||||
adapter.close();
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getInstrumentation().getTargetContext());
|
||||
prefs.edit().putBoolean(UserPreferences.PREF_UNPAUSE_ON_HEADSET_RECONNECT, false).commit();
|
||||
prefs.edit().putBoolean(UserPreferences.PREF_PAUSE_ON_HEADSET_DISCONNECT, false).commit();
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="de.danoeh.antennapod"
|
||||
android:versionCode="43"
|
||||
android:versionName="0.9.9.6">
|
||||
android:versionCode="44"
|
||||
android:versionName="1.0">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
@ -304,6 +304,13 @@
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receiver.PowerConnectionReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.ACTION_POWER_CONNECTED"/>
|
||||
<action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/>
|
||||
</intent-filter>
|
||||
</receiver>
|
||||
|
||||
<receiver android:name=".receiver.SPAReceiver">
|
||||
<intent-filter>
|
||||
<action android:name="de.danoeh.antennapdsp.intent.SP_APPS_QUERY_FEEDS_RESPONSE"/>
|
||||
|
@ -41,7 +41,7 @@
|
||||
<div id="header" align="center">
|
||||
<img src="logo.png" alt="Logo" width="100px" height="100px"/>
|
||||
|
||||
<p>AntennaPod, Version 0.9.9.6</p>
|
||||
<p>AntennaPod, Version 1.0</p>
|
||||
|
||||
<p>Copyright © 2014 Daniel Oeh</p>
|
||||
|
||||
|
@ -11,6 +11,7 @@ import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
@ -21,7 +22,6 @@ import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView.ScaleType;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -49,6 +49,7 @@ import de.danoeh.antennapod.fragment.CoverFragment;
|
||||
import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
import de.danoeh.antennapod.preferences.PreferenceController;
|
||||
|
||||
/**
|
||||
* Activity for playing audio files.
|
||||
@ -59,6 +60,7 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
private static final int POS_DESCR = 1;
|
||||
private static final int POS_CHAPTERS = 2;
|
||||
private static final int NUM_CONTENT_FRAGMENTS = 3;
|
||||
private static final int POS_NONE = -1;
|
||||
|
||||
final String TAG = "AudioplayerActivity";
|
||||
private static final String PREFS = "AudioPlayerActivityPreferences";
|
||||
@ -68,6 +70,7 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
private DrawerLayout drawerLayout;
|
||||
private NavListAdapter navAdapter;
|
||||
private ListView navList;
|
||||
private View navDrawer;
|
||||
private ActionBarDrawerToggle drawerToggle;
|
||||
|
||||
private Fragment[] detachedFragments;
|
||||
@ -78,6 +81,7 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
|
||||
private Fragment currentlyShownFragment;
|
||||
private int currentlyShownPosition = -1;
|
||||
private int lastShownPosition = POS_NONE;
|
||||
/**
|
||||
* Used if onResume was called without loadMediaInfo.
|
||||
*/
|
||||
@ -85,8 +89,8 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
|
||||
private TextView txtvTitle;
|
||||
private Button butPlaybackSpeed;
|
||||
private ImageButton butNavLeft;
|
||||
private ImageButton butNavRight;
|
||||
private ImageButton butNavChaptersShownotes;
|
||||
private ImageButton butShowCover;
|
||||
|
||||
private void resetFragmentView() {
|
||||
FragmentTransaction fT = getSupportFragmentManager().beginTransaction();
|
||||
@ -138,10 +142,14 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void chooseTheme() {
|
||||
setTheme(UserPreferences.getNoTitleTheme());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
getSupportActionBar().setDisplayShowTitleEnabled(false);
|
||||
detachedFragments = new Fragment[NUM_CONTENT_FRAGMENTS];
|
||||
}
|
||||
|
||||
@ -320,24 +328,32 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
chapterFragment = new ListFragment() {
|
||||
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v,
|
||||
int position, long id) {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
Chapter chapter = (Chapter) this
|
||||
.getListAdapter().getItem(position);
|
||||
controller.seekToChapter(chapter);
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
// add padding
|
||||
final ListView lv = getListView();
|
||||
lv.setClipToPadding(false);
|
||||
final int vertPadding = getResources().getDimensionPixelSize(R.dimen.list_vertical_padding);
|
||||
lv.setPadding(0, vertPadding, 0, vertPadding);
|
||||
}
|
||||
|
||||
};
|
||||
chapterFragment.setListAdapter(new ChapterListAdapter(
|
||||
AudioplayerActivity.this, 0, media
|
||||
.getChapters(), media
|
||||
.getChapters(), media, new ChapterListAdapter.Callback() {
|
||||
@Override
|
||||
public void onPlayChapterButtonClicked(int position) {
|
||||
Chapter chapter = (Chapter)
|
||||
chapterFragment.getListAdapter().getItem(position);
|
||||
controller.seekToChapter(chapter);
|
||||
}
|
||||
}
|
||||
));
|
||||
}
|
||||
currentlyShownFragment = chapterFragment;
|
||||
break;
|
||||
}
|
||||
if (currentlyShownFragment != null) {
|
||||
lastShownPosition = currentlyShownPosition;
|
||||
currentlyShownPosition = pos;
|
||||
if (detachedFragments[pos] != null) {
|
||||
if (BuildConfig.DEBUG)
|
||||
@ -355,78 +371,70 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Switches to the fragment that was displayed before the current one or the description fragment
|
||||
* if no fragment was previously displayed.
|
||||
*/
|
||||
public void switchToLastFragment() {
|
||||
if (lastShownPosition != POS_NONE) {
|
||||
switchToFragment(lastShownPosition);
|
||||
} else {
|
||||
switchToFragment(POS_DESCR);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateNavButtonDrawable() {
|
||||
|
||||
final int[] buttonTexts = new int[]{R.string.show_shownotes_label,
|
||||
R.string.show_chapters_label, R.string.show_cover_label};
|
||||
R.string.show_chapters_label};
|
||||
|
||||
final TypedArray drawables = obtainStyledAttributes(new int[]{
|
||||
R.attr.navigation_shownotes, R.attr.navigation_chapters});
|
||||
final Playable media = controller.getMedia();
|
||||
if (butNavLeft != null && butNavRight != null && media != null) {
|
||||
|
||||
butNavRight.setTag(R.id.imageloader_key, null);
|
||||
butNavLeft.setTag(R.id.imageloader_key, null);
|
||||
if (butNavChaptersShownotes != null && butShowCover != null && media != null) {
|
||||
|
||||
butNavChaptersShownotes.setTag(R.id.imageloader_key, null);
|
||||
setNavButtonVisibility();
|
||||
switch (currentlyShownPosition) {
|
||||
case POS_COVER:
|
||||
butNavLeft.setScaleType(ScaleType.CENTER);
|
||||
butNavLeft.setImageDrawable(drawables.getDrawable(0));
|
||||
butNavLeft.setContentDescription(getString(buttonTexts[0]));
|
||||
|
||||
butNavRight.setImageDrawable(drawables.getDrawable(1));
|
||||
butNavRight.setContentDescription(getString(buttonTexts[1]));
|
||||
|
||||
butShowCover.setVisibility(View.GONE);
|
||||
if (lastShownPosition == POS_CHAPTERS) {
|
||||
butNavChaptersShownotes.setImageDrawable(drawables.getDrawable(1));
|
||||
butNavChaptersShownotes.setContentDescription(getString(buttonTexts[1]));
|
||||
} else {
|
||||
butNavChaptersShownotes.setImageDrawable(drawables.getDrawable(0));
|
||||
butNavChaptersShownotes.setContentDescription(getString(buttonTexts[0]));
|
||||
}
|
||||
break;
|
||||
case POS_DESCR:
|
||||
butNavLeft.setScaleType(ScaleType.CENTER_CROP);
|
||||
butNavLeft.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Picasso.with(AudioplayerActivity.this)
|
||||
.load(media.getImageUri())
|
||||
.fit()
|
||||
.into(butNavLeft);
|
||||
}
|
||||
});
|
||||
butNavLeft.setContentDescription(getString(buttonTexts[2]));
|
||||
|
||||
butNavRight.setImageDrawable(drawables.getDrawable(1));
|
||||
butNavRight.setContentDescription(getString(buttonTexts[1]));
|
||||
butShowCover.setVisibility(View.VISIBLE);
|
||||
butNavChaptersShownotes.setImageDrawable(drawables.getDrawable(1));
|
||||
butNavChaptersShownotes.setContentDescription(getString(buttonTexts[1]));
|
||||
break;
|
||||
case POS_CHAPTERS:
|
||||
butNavLeft.setScaleType(ScaleType.CENTER_CROP);
|
||||
butNavLeft.post(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Picasso.with(AudioplayerActivity.this)
|
||||
.load(media.getImageUri())
|
||||
.fit()
|
||||
.into(butNavLeft);
|
||||
}
|
||||
|
||||
});
|
||||
butNavLeft.setContentDescription(getString(buttonTexts[2]));
|
||||
|
||||
butNavRight.setImageDrawable(drawables.getDrawable(0));
|
||||
butNavRight.setContentDescription(getString(buttonTexts[0]));
|
||||
butShowCover.setVisibility(View.VISIBLE);
|
||||
butNavChaptersShownotes.setImageDrawable(drawables.getDrawable(0));
|
||||
butNavChaptersShownotes.setContentDescription(getString(buttonTexts[0]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
drawables.recycle();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setupGUI() {
|
||||
super.setupGUI();
|
||||
resetFragmentView();
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
navList = (ListView) findViewById(R.id.nav_list);
|
||||
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
|
||||
butNavLeft = (ImageButton) findViewById(R.id.butNavLeft);
|
||||
butNavRight = (ImageButton) findViewById(R.id.butNavRight);
|
||||
navDrawer = findViewById(R.id.nav_layout);
|
||||
butPlaybackSpeed = (Button) findViewById(R.id.butPlaybackSpeed);
|
||||
butNavChaptersShownotes = (ImageButton) findViewById(R.id.butNavChaptersShownotes);
|
||||
butShowCover = (ImageButton) findViewById(R.id.butCover);
|
||||
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
|
||||
|
||||
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close) {
|
||||
CharSequence currentTitle = getSupportActionBar().getTitle();
|
||||
@ -463,38 +471,39 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
intent.putExtra(MainActivity.EXTRA_NAV_INDEX, relPos);
|
||||
startActivity(intent);
|
||||
}
|
||||
drawerLayout.closeDrawer(navList);
|
||||
drawerLayout.closeDrawer(navDrawer);
|
||||
}
|
||||
});
|
||||
drawerToggle.syncState();
|
||||
|
||||
butNavLeft.setOnClickListener(new OnClickListener() {
|
||||
|
||||
findViewById(R.id.nav_settings).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (currentlyShownFragment == null
|
||||
|| currentlyShownPosition == POS_DESCR) {
|
||||
switchToFragment(POS_COVER);
|
||||
} else if (currentlyShownPosition == POS_COVER) {
|
||||
switchToFragment(POS_DESCR);
|
||||
} else if (currentlyShownPosition == POS_CHAPTERS) {
|
||||
switchToFragment(POS_COVER);
|
||||
}
|
||||
drawerLayout.closeDrawer(navDrawer);
|
||||
startActivity(new Intent(AudioplayerActivity.this, PreferenceController.getPreferenceActivity()));
|
||||
}
|
||||
});
|
||||
|
||||
butNavRight.setOnClickListener(new OnClickListener() {
|
||||
|
||||
butNavChaptersShownotes.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (currentlyShownPosition == POS_CHAPTERS) {
|
||||
switchToFragment(POS_DESCR);
|
||||
} else {
|
||||
} else if (currentlyShownPosition == POS_DESCR) {
|
||||
switchToFragment(POS_CHAPTERS);
|
||||
} else if (currentlyShownPosition == POS_COVER) {
|
||||
switchToLastFragment();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
butShowCover.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
switchToFragment(POS_COVER);
|
||||
}
|
||||
});
|
||||
|
||||
butPlaybackSpeed.setOnClickListener(new OnClickListener() {
|
||||
|
||||
@Override
|
||||
@ -539,6 +548,22 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
});
|
||||
}
|
||||
|
||||
private void setNavButtonVisibility() {
|
||||
if (butNavChaptersShownotes != null) {
|
||||
if (controller != null) {
|
||||
Playable media = controller.getMedia();
|
||||
if (media != null) {
|
||||
if (media.getChapters() != null || currentlyShownPosition == POS_COVER) {
|
||||
butNavChaptersShownotes.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
butNavChaptersShownotes.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPlaybackSpeedChange() {
|
||||
super.onPlaybackSpeedChange();
|
||||
@ -567,12 +592,13 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
return false;
|
||||
}
|
||||
txtvTitle.setText(media.getEpisodeTitle());
|
||||
if (media.getChapters() != null) {
|
||||
butNavRight.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
butNavRight.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
getSupportActionBar().setTitle("");
|
||||
Picasso.with(this)
|
||||
.load(media.getImageUri())
|
||||
.fit()
|
||||
.into(butShowCover);
|
||||
|
||||
setNavButtonVisibility();
|
||||
|
||||
if (currentlyShownPosition == -1) {
|
||||
if (!restoreFromPreferences()) {
|
||||
@ -632,7 +658,7 @@ public class AudioplayerActivity extends MediaplayerActivity implements ItemDesc
|
||||
|
||||
@Override
|
||||
public boolean isDrawerOpen() {
|
||||
return drawerLayout != null && navList != null && drawerLayout.isDrawerOpen(navList);
|
||||
return drawerLayout != null && navDrawer != null && drawerLayout.isDrawerOpen(navDrawer);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -14,9 +14,8 @@ import android.support.v4.widget.DrawerLayout;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.app.ActionBarDrawerToggle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
@ -62,15 +61,22 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
public static final String EXTRA_NAV_TYPE = "nav_type";
|
||||
public static final String EXTRA_FRAGMENT_ARGS = "fragment_args";
|
||||
|
||||
public static final String SAVE_BACKSTACK_COUNT = "backstackCount";
|
||||
public static final String SAVE_SELECTED_NAV_INDEX = "selectedNavIndex";
|
||||
public static final String SAVE_TITLE = "title";
|
||||
|
||||
|
||||
public static final int POS_NEW = 0,
|
||||
POS_QUEUE = 1,
|
||||
POS_DOWNLOADS = 2,
|
||||
POS_HISTORY = 3,
|
||||
POS_ADD = 4;
|
||||
|
||||
private Toolbar toolbar;
|
||||
private ExternalPlayerFragment externalPlayerFragment;
|
||||
private DrawerLayout drawerLayout;
|
||||
|
||||
private View navDrawer;
|
||||
private ListView navList;
|
||||
private NavListAdapter navAdapter;
|
||||
|
||||
@ -82,17 +88,22 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
setTheme(UserPreferences.getTheme());
|
||||
setTheme(UserPreferences.getNoTitleTheme());
|
||||
super.onCreate(savedInstanceState);
|
||||
StorageUtils.checkStorageAvailability(this);
|
||||
setContentView(R.layout.main);
|
||||
setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
|
||||
toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
getSupportActionBar().setElevation(3.0f);
|
||||
|
||||
drawerTitle = currentTitle = getTitle();
|
||||
|
||||
drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
|
||||
navList = (ListView) findViewById(R.id.nav_list);
|
||||
|
||||
navDrawer = findViewById(R.id.nav_layout);
|
||||
Log.i(TAG, "");
|
||||
drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, R.string.drawer_open, R.string.drawer_close) {
|
||||
@Override
|
||||
public void onDrawerOpened(View drawerView) {
|
||||
@ -111,8 +122,21 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
}
|
||||
};
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
int backstackCount = savedInstanceState.getInt(SAVE_BACKSTACK_COUNT, 0);
|
||||
drawerToggle.setDrawerIndicatorEnabled(backstackCount == 0);
|
||||
}
|
||||
|
||||
drawerLayout.setDrawerListener(drawerToggle);
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
|
||||
final FragmentManager fm = getSupportFragmentManager();
|
||||
|
||||
fm.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
|
||||
@Override
|
||||
public void onBackStackChanged() {
|
||||
drawerToggle.setDrawerIndicatorEnabled(fm.getBackStackEntryCount() == 0);
|
||||
}
|
||||
});
|
||||
|
||||
FragmentTransaction transaction = fm.beginTransaction();
|
||||
|
||||
@ -120,7 +144,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
if (mainFragment != null) {
|
||||
transaction.replace(R.id.main_view, mainFragment);
|
||||
} else {
|
||||
loadFragment(NavListAdapter.VIEW_TYPE_NAV, POS_NEW, null);
|
||||
loadFragment(NavListAdapter.VIEW_TYPE_NAV, POS_QUEUE, null);
|
||||
}
|
||||
|
||||
externalPlayerFragment = new ExternalPlayerFragment();
|
||||
@ -134,6 +158,14 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
navList.setAdapter(navAdapter);
|
||||
navList.setOnItemClickListener(navListClickListener);
|
||||
|
||||
findViewById(R.id.nav_settings).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
drawerLayout.closeDrawer(navDrawer);
|
||||
startActivity(new Intent(MainActivity.this, PreferenceController.getPreferenceActivity()));
|
||||
}
|
||||
});
|
||||
|
||||
checkFirstLaunch();
|
||||
}
|
||||
|
||||
@ -143,7 +175,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
drawerLayout.openDrawer(navList);
|
||||
drawerLayout.openDrawer(navDrawer);
|
||||
}
|
||||
}, 1500);
|
||||
|
||||
@ -158,7 +190,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
}
|
||||
|
||||
public boolean isDrawerOpen() {
|
||||
return drawerLayout != null && navList != null && drawerLayout.isDrawerOpen(navList);
|
||||
return drawerLayout != null && navDrawer != null && drawerLayout.isDrawerOpen(navDrawer);
|
||||
}
|
||||
|
||||
public List<Feed> getFeeds() {
|
||||
@ -241,6 +273,14 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
.commit();
|
||||
}
|
||||
|
||||
public void dismissChildFragment() {
|
||||
getSupportFragmentManager().popBackStack();
|
||||
}
|
||||
|
||||
public Toolbar getToolbar() {
|
||||
return toolbar;
|
||||
}
|
||||
|
||||
private AdapterView.OnItemClickListener navListClickListener = new AdapterView.OnItemClickListener() {
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
@ -251,7 +291,7 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
selectedNavListIndex = position;
|
||||
navAdapter.notifyDataSetChanged();
|
||||
}
|
||||
drawerLayout.closeDrawer(navList);
|
||||
drawerLayout.closeDrawer(navDrawer);
|
||||
}
|
||||
};
|
||||
|
||||
@ -260,11 +300,11 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
super.onPostCreate(savedInstanceState);
|
||||
drawerToggle.syncState();
|
||||
if (savedInstanceState != null) {
|
||||
currentTitle = savedInstanceState.getString("title");
|
||||
if (!drawerLayout.isDrawerOpen(navList)) {
|
||||
currentTitle = savedInstanceState.getString(SAVE_TITLE);
|
||||
if (!drawerLayout.isDrawerOpen(navDrawer)) {
|
||||
getSupportActionBar().setTitle(currentTitle);
|
||||
}
|
||||
selectedNavListIndex = savedInstanceState.getInt("selectedNavIndex");
|
||||
selectedNavListIndex = savedInstanceState.getInt(SAVE_SELECTED_NAV_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
@ -277,8 +317,9 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString("title", getSupportActionBar().getTitle().toString());
|
||||
outState.putInt("selectedNavIndex", selectedNavListIndex);
|
||||
outState.putString(SAVE_TITLE, getSupportActionBar().getTitle().toString());
|
||||
outState.putInt(SAVE_SELECTED_NAV_INDEX, selectedNavListIndex);
|
||||
outState.putInt(SAVE_BACKSTACK_COUNT, getSupportFragmentManager().getBackStackEntryCount());
|
||||
|
||||
}
|
||||
|
||||
@ -312,29 +353,16 @@ public class MainActivity extends ActionBarActivity implements NavDrawerActivity
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (drawerToggle.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
switch (item.getItemId()) {
|
||||
case R.id.show_preferences:
|
||||
startActivity(new Intent(this, PreferenceController.getPreferenceActivity()));
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
} else if (item.getItemId() == android.R.id.home) {
|
||||
if (getSupportFragmentManager().getBackStackEntryCount() > 0) {
|
||||
dismissChildFragment();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareOptionsMenu(Menu menu) {
|
||||
super.onPrepareOptionsMenu(menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.main, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
private DBReader.NavDrawerData navDrawerData;
|
||||
private AsyncTask<Void, Void, DBReader.NavDrawerData> loadTask;
|
||||
|
@ -174,7 +174,6 @@ public abstract class MediaplayerActivity extends ActionBarActivity
|
||||
|
||||
orientation = getResources().getConfiguration().orientation;
|
||||
getWindow().setFormat(PixelFormat.TRANSPARENT);
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,15 +72,6 @@ public class PreferenceActivity extends ActionBarActivity {
|
||||
preferenceController.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// The default back button behavior has to be overwritten because changing the theme clears the back stack
|
||||
Intent destIntent = new Intent(this, MainActivity.class);
|
||||
destIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(destIntent);
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
super.onCreateOptionsMenu(menu);
|
||||
@ -91,9 +82,6 @@ public class PreferenceActivity extends ActionBarActivity {
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
Intent destIntent = new Intent(this, MainActivity.class);
|
||||
destIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(destIntent);
|
||||
finish();
|
||||
return true;
|
||||
default:
|
||||
|
@ -84,13 +84,4 @@ public class PreferenceActivityGingerbread extends android.preference.Preference
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// The default back button behavior has to be overwritten because changing the theme clears the back stack
|
||||
Intent destIntent = new Intent(this, MainActivity.class);
|
||||
destIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(destIntent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +111,7 @@ public class VideoplayerActivity extends MediaplayerActivity {
|
||||
@Override
|
||||
protected void setupGUI() {
|
||||
super.setupGUI();
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
videoOverlay = (LinearLayout) findViewById(R.id.overlay);
|
||||
videoview = (AspectRatioVideoView) findViewById(R.id.videoview);
|
||||
progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator);
|
||||
|
@ -14,6 +14,7 @@ import android.view.View;
|
||||
import android.view.View.OnTouchListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.feed.Chapter;
|
||||
@ -31,16 +32,18 @@ public class ChapterListAdapter extends ArrayAdapter<Chapter> {
|
||||
private Playable media;
|
||||
|
||||
private int defaultTextColor;
|
||||
private final Callback callback;
|
||||
|
||||
public ChapterListAdapter(Context context, int textViewResourceId,
|
||||
List<Chapter> objects, Playable media) {
|
||||
List<Chapter> objects, Playable media, Callback callback) {
|
||||
super(context, textViewResourceId, objects);
|
||||
this.chapters = objects;
|
||||
this.media = media;
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
public View getView(final int position, View convertView, ViewGroup parent) {
|
||||
Holder holder;
|
||||
|
||||
Chapter sc = getItem(position);
|
||||
@ -56,6 +59,7 @@ public class ChapterListAdapter extends ArrayAdapter<Chapter> {
|
||||
defaultTextColor = holder.title.getTextColors().getDefaultColor();
|
||||
holder.start = (TextView) convertView.findViewById(R.id.txtvStart);
|
||||
holder.link = (TextView) convertView.findViewById(R.id.txtvLink);
|
||||
holder.butPlayChapter = (ImageButton) convertView.findViewById(R.id.butPlayChapter);
|
||||
convertView.setTag(holder);
|
||||
} else {
|
||||
holder = (Holder) convertView.getTag();
|
||||
@ -122,6 +126,14 @@ public class ChapterListAdapter extends ArrayAdapter<Chapter> {
|
||||
|
||||
}
|
||||
});
|
||||
holder.butPlayChapter.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (callback != null) {
|
||||
callback.onPlayChapterButtonClicked(position);
|
||||
}
|
||||
}
|
||||
});
|
||||
Chapter current = ChapterUtils.getCurrentChapter(media);
|
||||
if (current != null) {
|
||||
if (current == sc) {
|
||||
@ -144,6 +156,7 @@ public class ChapterListAdapter extends ArrayAdapter<Chapter> {
|
||||
TextView title;
|
||||
TextView start;
|
||||
TextView link;
|
||||
ImageButton butPlayChapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -177,4 +190,8 @@ public class ChapterListAdapter extends ArrayAdapter<Chapter> {
|
||||
return super.getItem(position);
|
||||
}
|
||||
|
||||
public static interface Callback {
|
||||
public void onPlayChapterButtonClicked(int position);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package de.danoeh.antennapod.config;
|
||||
|
||||
import de.danoeh.antennapod.BuildConfig;
|
||||
import de.danoeh.antennapod.core.ClientConfig;
|
||||
|
||||
/**
|
||||
@ -8,12 +9,13 @@ import de.danoeh.antennapod.core.ClientConfig;
|
||||
public class ClientConfigurator {
|
||||
|
||||
static {
|
||||
ClientConfig.USER_AGENT = "AntennaPod/0.9.9.6";
|
||||
ClientConfig.USER_AGENT = "AntennaPod/" + BuildConfig.VERSION_NAME;
|
||||
ClientConfig.applicationCallbacks = new ApplicationCallbacksImpl();
|
||||
ClientConfig.downloadServiceCallbacks = new DownloadServiceCallbacksImpl();
|
||||
ClientConfig.gpodnetCallbacks = new GpodnetCallbacksImpl();
|
||||
ClientConfig.playbackServiceCallbacks = new PlaybackServiceCallbacksImpl();
|
||||
ClientConfig.storageCallbacks = new StorageCallbacksImpl();
|
||||
ClientConfig.flattrCallbacks = new FlattrCallbacksImpl();
|
||||
ClientConfig.dbTasksCallbacks = new DBTasksCallbacksImpl();
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package de.danoeh.antennapod.config;
|
||||
|
||||
import de.danoeh.antennapod.core.DBTasksCallbacks;
|
||||
import de.danoeh.antennapod.core.storage.APCleanupAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.APDownloadAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.AutomaticDownloadAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
|
||||
|
||||
public class DBTasksCallbacksImpl implements DBTasksCallbacks {
|
||||
|
||||
@Override
|
||||
public AutomaticDownloadAlgorithm getAutomaticDownloadAlgorithm() {
|
||||
return new APDownloadAlgorithm();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EpisodeCleanupAlgorithm getEpisodeCacheCleanupAlgorithm() {
|
||||
return new APCleanupAlgorithm();
|
||||
}
|
||||
}
|
@ -13,7 +13,7 @@ public class StorageCallbacksImpl implements StorageCallbacks {
|
||||
|
||||
@Override
|
||||
public int getDatabaseVersion() {
|
||||
return 13;
|
||||
return 14;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -105,9 +105,24 @@ public class StorageCallbacksImpl implements StorageCallbacks {
|
||||
}
|
||||
if (oldVersion <= 12) {
|
||||
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
|
||||
+ " ADD COLUMN " + PodDBAdapter.KEY_IS_PAGED + " INTEGER DEFAULT 0");
|
||||
+ " ADD COLUMN " + PodDBAdapter.KEY_IS_PAGED + " INTEGER DEFAULT 0");
|
||||
db.execSQL("ALTER TABLE " + PodDBAdapter.TABLE_NAME_FEEDS
|
||||
+ " ADD COLUMN " + PodDBAdapter.KEY_NEXT_PAGE_LINK + " TEXT");
|
||||
}
|
||||
if (oldVersion <= 13) {
|
||||
// remove duplicate rows in "Chapters" table that were created because of a bug.
|
||||
db.execSQL(String.format("DELETE FROM %s WHERE %s NOT IN " +
|
||||
"(SELECT MIN(%s) as %s FROM %s GROUP BY %s,%s,%s,%s,%s)",
|
||||
PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
|
||||
PodDBAdapter.KEY_ID,
|
||||
PodDBAdapter.KEY_ID,
|
||||
PodDBAdapter.KEY_ID,
|
||||
PodDBAdapter.TABLE_NAME_SIMPLECHAPTERS,
|
||||
PodDBAdapter.KEY_TITLE,
|
||||
PodDBAdapter.KEY_START,
|
||||
PodDBAdapter.KEY_FEEDITEM,
|
||||
PodDBAdapter.KEY_LINK,
|
||||
PodDBAdapter.KEY_CHAPTER_TYPE));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,445 +0,0 @@
|
||||
package de.danoeh.antennapod.dialog;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Dialog;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.util.TypedValue;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.apache.commons.lang3.StringEscapeUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import de.danoeh.antennapod.BuildConfig;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.util.ShownotesProvider;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
|
||||
/**
|
||||
* Shows information about a specific FeedItem and provides actions like playing, downloading, etc.
|
||||
*/
|
||||
public class FeedItemDialog extends Dialog {
|
||||
private static final String TAG = "FeedItemDialog";
|
||||
|
||||
private FeedItem item;
|
||||
private QueueAccess queue;
|
||||
|
||||
private ViewGroup contentContainer;
|
||||
private View header;
|
||||
private TextView txtvTitle;
|
||||
private WebView webvDescription;
|
||||
private ImageButton butAction1;
|
||||
private ImageButton butAction2;
|
||||
private ImageButton butMore;
|
||||
private PopupMenu popupMenu;
|
||||
|
||||
public static FeedItemDialog newInstance(Context context, FeedItemDialogSavedInstance savedInstance) {
|
||||
Validate.notNull(savedInstance);
|
||||
FeedItemDialog dialog = newInstance(context, savedInstance.item, savedInstance.queueAccess);
|
||||
if (savedInstance.isShowing) {
|
||||
dialog.show();
|
||||
}
|
||||
return dialog;
|
||||
}
|
||||
|
||||
public static FeedItemDialog newInstance(Context context, FeedItem item, QueueAccess queue) {
|
||||
if (useDarkThemeWorkAround()) {
|
||||
return new FeedItemDialog(context, R.style.Theme_AntennaPod_Dark, item, queue);
|
||||
} else {
|
||||
return new FeedItemDialog(context, item, queue);
|
||||
}
|
||||
}
|
||||
|
||||
public FeedItemDialog(Context context, int theme, FeedItem item, QueueAccess queue) {
|
||||
super(context, theme);
|
||||
Validate.notNull(item);
|
||||
Validate.notNull(queue);
|
||||
this.item = item;
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
private FeedItemDialog(Context context, FeedItem item, QueueAccess queue) {
|
||||
this(context, 0, item, queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the dialog should use a dark theme. This has to be done on Gingerbread devices
|
||||
* because dialogs are only available in a dark theme.
|
||||
*/
|
||||
private static boolean useDarkThemeWorkAround() {
|
||||
return Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1
|
||||
&& UserPreferences.getTheme() != R.style.Theme_AntennaPod_Dark;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.feeditem_dialog);
|
||||
|
||||
contentContainer = (ViewGroup) findViewById(R.id.contentContainer);
|
||||
txtvTitle = (TextView) findViewById(R.id.txtvTitle);
|
||||
header = findViewById(R.id.header);
|
||||
webvDescription = (WebView) findViewById(R.id.webview);
|
||||
butAction1 = (ImageButton) findViewById(R.id.butAction1);
|
||||
butAction2 = (ImageButton) findViewById(R.id.butAction2);
|
||||
butMore = (ImageButton) findViewById(R.id.butMoreActions);
|
||||
popupMenu = new PopupMenu(getContext(), butMore);
|
||||
|
||||
webvDescription.setWebViewClient(new WebViewClient());
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 14) { // ellipsize is causing problems on old versions, see #448
|
||||
txtvTitle.setEllipsize(TextUtils.TruncateAt.END);
|
||||
}
|
||||
|
||||
txtvTitle.setText(item.getTitle());
|
||||
|
||||
if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
|
||||
if (Build.VERSION.SDK_INT >= 11
|
||||
&& Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
}
|
||||
webvDescription.setBackgroundColor(getContext().getResources().getColor(
|
||||
R.color.black));
|
||||
}
|
||||
webvDescription.getSettings().setUseWideViewPort(false);
|
||||
webvDescription.getSettings().setLayoutAlgorithm(
|
||||
WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||
webvDescription.getSettings().setLoadWithOverviewMode(true);
|
||||
webvDescription.setWebViewClient(new WebViewClient() {
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
try {
|
||||
getContext().startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
loadDescriptionWebview(item);
|
||||
|
||||
butAction1.setOnClickListener(new View.OnClickListener() {
|
||||
DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getContext());
|
||||
|
||||
@Override
|
||||
|
||||
public void onClick(View v) {
|
||||
actionButtonCallback.onActionButtonPressed(item);
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media != null && media.isDownloaded()) {
|
||||
// playback was started, dialog should close itself
|
||||
dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
butAction2.setOnClickListener(new View.OnClickListener()
|
||||
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (item.hasMedia()) {
|
||||
FeedMedia media = item.getMedia();
|
||||
if (!media.isDownloaded()) {
|
||||
DBTasks.playMedia(getContext(), media, true, true, true);
|
||||
dismiss();
|
||||
} else {
|
||||
DBWriter.deleteFeedMediaOfItem(getContext(), media.getId());
|
||||
}
|
||||
} else if (item.getLink() != null) {
|
||||
Uri uri = Uri.parse(item.getLink());
|
||||
getContext().startActivity(new Intent(Intent.ACTION_VIEW, uri));
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
butMore.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
popupMenu.getMenu().clear();
|
||||
popupMenu.inflate(R.menu.feeditem_dialog);
|
||||
if (item.hasMedia()) {
|
||||
FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue);
|
||||
} else {
|
||||
// these are already available via button1 and button2
|
||||
FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue,
|
||||
R.id.mark_read_item, R.id.visit_website_item);
|
||||
}
|
||||
popupMenu.show();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||
|
||||
try {
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getContext(), menuItem.getItemId(), item);
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
updateMenuAppearance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismiss() {
|
||||
super.dismiss();
|
||||
if (contentContainer != null && webvDescription != null) {
|
||||
contentContainer.removeAllViews();
|
||||
webvDescription.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
private final FeedItemMenuHandler.MenuInterface popupMenuInterface = new FeedItemMenuHandler.MenuInterface() {
|
||||
@Override
|
||||
public void setItemVisibility(int id, boolean visible) {
|
||||
MenuItem item = popupMenu.getMenu().findItem(id);
|
||||
if (item != null) {
|
||||
item.setVisible(visible);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public void updateMenuAppearance() {
|
||||
if (item == null || queue == null) {
|
||||
Log.w(TAG, "UpdateMenuAppearance called while item or queue was null");
|
||||
return;
|
||||
}
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media == null) {
|
||||
TypedArray drawables = getContext().obtainStyledAttributes(new int[]{R.attr.navigation_accept,
|
||||
R.attr.location_web_site});
|
||||
|
||||
if (!item.isRead()) {
|
||||
butAction1.setImageDrawable(drawables.getDrawable(0));
|
||||
butAction1.setContentDescription(getContext().getString(R.string.mark_read_label));
|
||||
butAction1.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
butAction1.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (item.getLink() != null) {
|
||||
butAction2.setImageDrawable(drawables.getDrawable(1));
|
||||
butAction2.setContentDescription(getContext().getString(R.string.visit_website_label));
|
||||
} else {
|
||||
butAction2.setEnabled(false);
|
||||
}
|
||||
|
||||
drawables.recycle();
|
||||
} else {
|
||||
boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media);
|
||||
TypedArray drawables = getContext().obtainStyledAttributes(new int[]{R.attr.av_play,
|
||||
R.attr.av_download, R.attr.action_stream, R.attr.content_discard, R.attr.navigation_cancel});
|
||||
|
||||
if (!media.isDownloaded()) {
|
||||
butAction2.setImageDrawable(drawables.getDrawable(2));
|
||||
butAction2.setContentDescription(getContext().getString(R.string.stream_label));
|
||||
} else {
|
||||
butAction2.setImageDrawable(drawables.getDrawable(3));
|
||||
butAction2.setContentDescription(getContext().getString(R.string.remove_episode_lable));
|
||||
}
|
||||
|
||||
if (isDownloading) {
|
||||
butAction1.setImageDrawable(drawables.getDrawable(4));
|
||||
butAction1.setContentDescription(getContext().getString(R.string.cancel_download_label));
|
||||
} else if (media.isDownloaded()) {
|
||||
butAction1.setImageDrawable(drawables.getDrawable(0));
|
||||
butAction1.setContentDescription(getContext().getString(R.string.play_label));
|
||||
} else {
|
||||
butAction1.setImageDrawable(drawables.getDrawable(1));
|
||||
butAction1.setContentDescription(getContext().getString(R.string.download_label));
|
||||
}
|
||||
|
||||
drawables.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void loadDescriptionWebview(final ShownotesProvider shownotesProvider) {
|
||||
AsyncTask<Void, Void, Void> loadTask = new AsyncTask<Void, Void, Void>() {
|
||||
String data;
|
||||
|
||||
|
||||
private String applyWebviewStyle(String textColor, String data) {
|
||||
final String WEBVIEW_STYLE = "<html><head><style type=\"text/css\"> @font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }</style></head><body>%s</body></html>";
|
||||
final int pageMargin = (int) TypedValue.applyDimension(
|
||||
TypedValue.COMPLEX_UNIT_DIP, 8, getContext().getResources()
|
||||
.getDisplayMetrics()
|
||||
);
|
||||
return String.format(WEBVIEW_STYLE, textColor, "100%", pageMargin,
|
||||
pageMargin, pageMargin, pageMargin, data);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
super.onPostExecute(result);
|
||||
// /webvDescription.loadData(url, "text/html", "utf-8");
|
||||
if (FeedItemDialog.this.isShowing() && webvDescription != null) {
|
||||
webvDescription.loadDataWithBaseURL(null, data, "text/html",
|
||||
"utf-8", "about:blank");
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Webview loaded");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Loading Webview");
|
||||
try {
|
||||
Callable<String> shownotesLoadTask = shownotesProvider.loadShownotes();
|
||||
final String shownotes = shownotesLoadTask.call();
|
||||
|
||||
data = StringEscapeUtils.unescapeHtml4(shownotes);
|
||||
TypedArray res = getContext()
|
||||
.getTheme()
|
||||
.obtainStyledAttributes(
|
||||
new int[]{android.R.attr.textColorPrimary});
|
||||
int colorResource;
|
||||
if (useDarkThemeWorkAround()) {
|
||||
colorResource = getContext().getResources().getColor(R.color.black);
|
||||
} else {
|
||||
colorResource = res.getColor(0, 0);
|
||||
}
|
||||
String colorString = String.format("#%06X",
|
||||
0xFFFFFF & colorResource);
|
||||
Log.i(TAG, "text color: " + colorString);
|
||||
res.recycle();
|
||||
data = applyWebviewStyle(colorString, data);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
};
|
||||
loadTask.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method that calls setQueue() and setItemFromCollection() with
|
||||
* the given arguments.
|
||||
*
|
||||
* @return true if one of the calls to setItemFromCollection returned true,
|
||||
* false otherwise.
|
||||
*/
|
||||
public boolean updateContent(QueueAccess queue, List<FeedItem>... collections) {
|
||||
setQueue(queue);
|
||||
|
||||
boolean setItemFromCollectionResult = false;
|
||||
if (collections != null) {
|
||||
for (List<FeedItem> list : collections) {
|
||||
setItemFromCollectionResult |= setItemFromCollection(list);
|
||||
}
|
||||
}
|
||||
if (isShowing()) {
|
||||
updateMenuAppearance();
|
||||
}
|
||||
|
||||
return setItemFromCollectionResult;
|
||||
}
|
||||
|
||||
|
||||
public void setItem(FeedItem item) {
|
||||
Validate.notNull(item);
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the FeedItem of this dialog in a collection and updates its state from that
|
||||
* collection.
|
||||
*
|
||||
* @return true if the FeedItem was found, false otherwise.
|
||||
*/
|
||||
public boolean setItemFromCollection(Collection<FeedItem> items) {
|
||||
for (FeedItem item : items) {
|
||||
if (item.getId() == this.item.getId()) {
|
||||
setItem(item);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setQueue(QueueAccess queue) {
|
||||
Validate.notNull(queue);
|
||||
this.queue = queue;
|
||||
}
|
||||
|
||||
public FeedItem getItem() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public QueueAccess getQueue() {
|
||||
return queue;
|
||||
}
|
||||
|
||||
public FeedItemDialogSavedInstance save() {
|
||||
return new FeedItemDialogSavedInstance(item, queue, isShowing());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to save the FeedItemDialog's state across configuration changes
|
||||
*/
|
||||
public static class FeedItemDialogSavedInstance {
|
||||
final FeedItem item;
|
||||
final QueueAccess queueAccess;
|
||||
final boolean isShowing;
|
||||
|
||||
private FeedItemDialogSavedInstance(FeedItem item, QueueAccess queueAccess, boolean isShowing) {
|
||||
this.item = item;
|
||||
this.queueAccess = queueAccess;
|
||||
this.isShowing = isShowing;
|
||||
}
|
||||
}
|
||||
}
|
@ -8,17 +8,17 @@ import android.support.v4.app.ListFragment;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.DownloadedEpisodesListAdapter;
|
||||
import de.danoeh.antennapod.dialog.FeedItemDialog;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Displays all running downloads and provides a button to delete them
|
||||
*/
|
||||
@ -36,8 +36,6 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
private boolean viewCreated = false;
|
||||
private boolean itemsLoaded = false;
|
||||
|
||||
private FeedItemDialog feedItemDialog;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -69,7 +67,6 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
super.onDestroyView();
|
||||
listAdapter = null;
|
||||
viewCreated = false;
|
||||
feedItemDialog = null;
|
||||
stopItemLoader();
|
||||
}
|
||||
|
||||
@ -102,8 +99,7 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
FeedItem item = listAdapter.getItem(position - l.getHeaderViewsCount());
|
||||
if (item != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(getActivity(), item, queue);
|
||||
feedItemDialog.show();
|
||||
((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
@ -115,12 +111,6 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
}
|
||||
setListShown(true);
|
||||
listAdapter.notifyDataSetChanged();
|
||||
if (feedItemDialog != null) {
|
||||
boolean res = feedItemDialog.updateContent(queue, items);
|
||||
if (!res && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.dismiss();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private DownloadedEpisodesListAdapter.ItemAccess itemAccess = new DownloadedEpisodesListAdapter.ItemAccess() {
|
||||
@ -143,11 +133,7 @@ public class CompletedDownloadsFragment extends ListFragment {
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & EventDistributor.DOWNLOAD_QUEUED) != 0) {
|
||||
if (feedItemDialog != null && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.updateMenuAppearance();
|
||||
}
|
||||
} else if ((arg & EVENTS) != 0) {
|
||||
if ((arg & EVENTS) != 0) {
|
||||
startItemLoader();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
@ -13,6 +14,7 @@ import com.squareup.picasso.Picasso;
|
||||
|
||||
import de.danoeh.antennapod.BuildConfig;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.AudioplayerActivity;
|
||||
import de.danoeh.antennapod.activity.AudioplayerActivity.AudioplayerContentFragment;
|
||||
import de.danoeh.antennapod.core.util.playback.Playable;
|
||||
|
||||
@ -57,6 +59,15 @@ public class CoverFragment extends Fragment implements
|
||||
Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.cover_fragment, container, false);
|
||||
imgvCover = (ImageView) root.findViewById(R.id.imgvCover);
|
||||
imgvCover.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Activity activity = getActivity();
|
||||
if (activity != null && activity instanceof AudioplayerActivity) {
|
||||
((AudioplayerActivity)activity).switchToLastFragment();
|
||||
}
|
||||
}
|
||||
});
|
||||
viewCreated = true;
|
||||
return root;
|
||||
}
|
||||
|
@ -1,19 +1,16 @@
|
||||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
|
||||
/**
|
||||
* Shows the CompletedDownloadsFragment and the RunningDownloadsFragment
|
||||
@ -27,7 +24,6 @@ public class DownloadsFragment extends Fragment {
|
||||
public static final int POS_LOG = 2;
|
||||
|
||||
private ViewPager pager;
|
||||
private MainActivity activity;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
@ -36,42 +32,6 @@ public class DownloadsFragment extends Fragment {
|
||||
pager = (ViewPager) root.findViewById(R.id.pager);
|
||||
DownloadsPagerAdapter pagerAdapter = new DownloadsPagerAdapter(getChildFragmentManager(), getResources());
|
||||
pager.setAdapter(pagerAdapter);
|
||||
final ActionBar actionBar = activity.getMainActivtyActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
|
||||
@Override
|
||||
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
|
||||
pager.setCurrentItem(tab.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
|
||||
|
||||
}
|
||||
};
|
||||
actionBar.removeAllTabs();
|
||||
actionBar.addTab(actionBar.newTab()
|
||||
.setText(R.string.downloads_running_label)
|
||||
.setTabListener(tabListener));
|
||||
actionBar.addTab(actionBar.newTab()
|
||||
.setText(R.string.downloads_completed_label)
|
||||
.setTabListener(tabListener));
|
||||
actionBar.addTab(actionBar.newTab()
|
||||
.setText(R.string.downloads_log_label)
|
||||
.setTabListener(tabListener));
|
||||
|
||||
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
super.onPageSelected(position);
|
||||
actionBar.setSelectedNavigationItem(position);
|
||||
}
|
||||
});
|
||||
return root;
|
||||
}
|
||||
|
||||
@ -84,24 +44,8 @@ public class DownloadsFragment extends Fragment {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
this.activity = (MainActivity) activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetach() {
|
||||
super.onDetach();
|
||||
activity.getMainActivtyActionBar().removeAllTabs();
|
||||
activity.getMainActivtyActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
}
|
||||
|
||||
public class DownloadsPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
|
||||
|
||||
|
||||
Resources resources;
|
||||
|
||||
public DownloadsPagerAdapter(FragmentManager fm, Resources resources) {
|
||||
|
@ -12,7 +12,6 @@ import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
|
@ -0,0 +1,442 @@
|
||||
package de.danoeh.antennapod.fragment;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v4.util.Pair;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
|
||||
import de.danoeh.antennapod.core.asynctask.DBTaskLoader;
|
||||
import de.danoeh.antennapod.core.asynctask.DownloadObserver;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.util.playback.Timeline;
|
||||
import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler;
|
||||
|
||||
/**
|
||||
* Displays information about a FeedItem and actions.
|
||||
*/
|
||||
public class ItemFragment extends Fragment implements LoaderManager.LoaderCallbacks<Pair<FeedItem, QueueAccess>> {
|
||||
|
||||
private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED |
|
||||
EventDistributor.DOWNLOAD_QUEUED |
|
||||
EventDistributor.QUEUE_UPDATE |
|
||||
EventDistributor.UNREAD_ITEMS_UPDATE;
|
||||
|
||||
private static final String ARG_FEEDITEM = "feeditem";
|
||||
|
||||
/**
|
||||
* Creates a new instance of an ItemFragment
|
||||
*
|
||||
* @param feeditem The ID of the FeedItem that should be displayed.
|
||||
* @return The ItemFragment instance
|
||||
*/
|
||||
public static ItemFragment newInstance(long feeditem) {
|
||||
ItemFragment fragment = new ItemFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putLong(ARG_FEEDITEM, feeditem);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
private boolean itemsLoaded = false;
|
||||
private long itemID;
|
||||
private FeedItem item;
|
||||
private QueueAccess queue;
|
||||
private String webviewData;
|
||||
private DownloadObserver downloadObserver;
|
||||
private List<Downloader> downloaderList;
|
||||
|
||||
private ViewGroup root;
|
||||
private View header;
|
||||
private WebView webvDescription;
|
||||
private TextView txtvTitle;
|
||||
private ImageView imgvCover;
|
||||
private ProgressBar progbarDownload;
|
||||
private ProgressBar progbarLoading;
|
||||
private Button butAction1;
|
||||
private Button butAction2;
|
||||
private ImageButton butMore;
|
||||
private PopupMenu popupMenu;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setRetainInstance(true);
|
||||
setHasOptionsMenu(false);
|
||||
|
||||
itemID = getArguments().getLong(ARG_FEEDITEM, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
Toolbar toolbar = ((MainActivity) getActivity()).getToolbar();
|
||||
toolbar.addView(header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
EventDistributor.getInstance().register(contentUpdate);
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.setActivity(getActivity());
|
||||
downloadObserver.onResume();
|
||||
}
|
||||
if (itemsLoaded) {
|
||||
onFragmentLoaded();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
EventDistributor.getInstance().unregister(contentUpdate);
|
||||
}
|
||||
|
||||
private void resetViewState() {
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.onPause();
|
||||
}
|
||||
Toolbar toolbar = ((MainActivity) getActivity()).getToolbar();
|
||||
toolbar.removeView(header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
resetViewState();
|
||||
if (webvDescription != null && root != null) {
|
||||
root.removeView(webvDescription);
|
||||
webvDescription.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
((MainActivity) getActivity()).getSupportActionBar().setTitle("");
|
||||
Toolbar toolbar = ((MainActivity) getActivity()).getToolbar();
|
||||
View layout = inflater.inflate(R.layout.feeditem_fragment, container, false);
|
||||
|
||||
header = inflater.inflate(R.layout.feeditem_fragment_header, toolbar, false);
|
||||
root = (ViewGroup) layout.findViewById(R.id.content_root);
|
||||
txtvTitle = (TextView) header.findViewById(R.id.txtvTitle);
|
||||
if (Build.VERSION.SDK_INT >= 14) { // ellipsize is causing problems on old versions, see #448
|
||||
txtvTitle.setEllipsize(TextUtils.TruncateAt.END);
|
||||
}
|
||||
webvDescription = (WebView) layout.findViewById(R.id.webvDescription);
|
||||
if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) {
|
||||
if (Build.VERSION.SDK_INT >= 11
|
||||
&& Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
|
||||
webvDescription.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
|
||||
}
|
||||
webvDescription.setBackgroundColor(getResources().getColor(
|
||||
R.color.black));
|
||||
}
|
||||
webvDescription.getSettings().setUseWideViewPort(false);
|
||||
webvDescription.getSettings().setLayoutAlgorithm(
|
||||
WebSettings.LayoutAlgorithm.NARROW_COLUMNS);
|
||||
webvDescription.getSettings().setLoadWithOverviewMode(true);
|
||||
webvDescription.setWebViewClient(new WebViewClient() {
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
try {
|
||||
startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
|
||||
progbarDownload = (ProgressBar) header.findViewById(R.id.progbarDownload);
|
||||
progbarLoading = (ProgressBar) layout.findViewById(R.id.progbarLoading);
|
||||
butAction1 = (Button) header.findViewById(R.id.butAction1);
|
||||
butAction2 = (Button) header.findViewById(R.id.butAction2);
|
||||
butMore = (ImageButton) header.findViewById(R.id.butMoreActions);
|
||||
popupMenu = new PopupMenu(getActivity(), butMore);
|
||||
|
||||
butAction1.setOnClickListener(new View.OnClickListener() {
|
||||
DefaultActionButtonCallback actionButtonCallback = new DefaultActionButtonCallback(getActivity());
|
||||
|
||||
@Override
|
||||
|
||||
public void onClick(View v) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
actionButtonCallback.onActionButtonPressed(item);
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media != null && media.isDownloaded()) {
|
||||
// playback was started, dialog should close itself
|
||||
((MainActivity) getActivity()).dismissChildFragment();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
butAction2.setOnClickListener(new View.OnClickListener()
|
||||
|
||||
{
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.hasMedia()) {
|
||||
FeedMedia media = item.getMedia();
|
||||
if (!media.isDownloaded()) {
|
||||
DBTasks.playMedia(getActivity(), media, true, true, true);
|
||||
((MainActivity) getActivity()).dismissChildFragment();
|
||||
} else {
|
||||
DBWriter.deleteFeedMediaOfItem(getActivity(), media.getId());
|
||||
}
|
||||
} else if (item.getLink() != null) {
|
||||
Uri uri = Uri.parse(item.getLink());
|
||||
getActivity().startActivity(new Intent(Intent.ACTION_VIEW, uri));
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
butMore.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (item == null) {
|
||||
return;
|
||||
}
|
||||
popupMenu.getMenu().clear();
|
||||
popupMenu.inflate(R.menu.feeditem_dialog);
|
||||
if (item.hasMedia()) {
|
||||
FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue);
|
||||
} else {
|
||||
// these are already available via button1 and button2
|
||||
FeedItemMenuHandler.onPrepareMenu(popupMenuInterface, item, true, queue,
|
||||
R.id.mark_read_item, R.id.visit_website_item);
|
||||
}
|
||||
popupMenu.show();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem menuItem) {
|
||||
|
||||
try {
|
||||
return FeedItemMenuHandler.onMenuItemClicked(getActivity(), menuItem.getItemId(), item);
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
private final FeedItemMenuHandler.MenuInterface popupMenuInterface = new FeedItemMenuHandler.MenuInterface() {
|
||||
@Override
|
||||
public void setItemVisibility(int id, boolean visible) {
|
||||
MenuItem item = popupMenu.getMenu().findItem(id);
|
||||
if (item != null) {
|
||||
item.setVisible(visible);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private void onFragmentLoaded() {
|
||||
progbarLoading.setVisibility(View.GONE);
|
||||
if (webviewData != null) {
|
||||
webvDescription.loadDataWithBaseURL(null, webviewData, "text/html",
|
||||
"utf-8", "about:blank");
|
||||
}
|
||||
updateAppearance();
|
||||
downloadObserver = new DownloadObserver(getActivity(), new Handler(), downloadObserverCallback);
|
||||
downloadObserver.onResume();
|
||||
}
|
||||
|
||||
private void updateAppearance() {
|
||||
txtvTitle.setText(item.getTitle());
|
||||
Picasso.with(getActivity()).load(item.getImageUri())
|
||||
.fit()
|
||||
.into(imgvCover);
|
||||
progbarDownload.setVisibility(View.GONE);
|
||||
if (item.hasMedia() && downloaderList != null) {
|
||||
for (Downloader downloader : downloaderList) {
|
||||
if (downloader.getDownloadRequest().getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA
|
||||
&& downloader.getDownloadRequest().getFeedfileId() == item.getMedia().getId()) {
|
||||
progbarDownload.setVisibility(View.VISIBLE);
|
||||
progbarDownload.setProgress(downloader.getDownloadRequest().getProgressPercent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FeedMedia media = item.getMedia();
|
||||
if (media == null) {
|
||||
TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.navigation_accept,
|
||||
R.attr.location_web_site});
|
||||
|
||||
if (!item.isRead()) {
|
||||
butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(0), null, null, null);
|
||||
butAction1.setText(getActivity().getString(R.string.mark_read_label));
|
||||
butAction1.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
butAction1.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
if (item.getLink() != null) {
|
||||
butAction2.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(1), null, null, null);
|
||||
butAction2.setText(getActivity().getString(R.string.visit_website_label));
|
||||
} else {
|
||||
butAction2.setEnabled(false);
|
||||
}
|
||||
|
||||
drawables.recycle();
|
||||
} else {
|
||||
boolean isDownloading = DownloadRequester.getInstance().isDownloadingFile(media);
|
||||
TypedArray drawables = getActivity().obtainStyledAttributes(new int[]{R.attr.av_play,
|
||||
R.attr.av_download, R.attr.action_stream, R.attr.content_discard, R.attr.navigation_cancel});
|
||||
|
||||
if (!media.isDownloaded()) {
|
||||
butAction2.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(2), null, null, null);
|
||||
butAction2.setText(getActivity().getString(R.string.stream_label));
|
||||
} else {
|
||||
butAction2.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(3), null, null, null);
|
||||
butAction2.setText(getActivity().getString(R.string.remove_episode_lable));
|
||||
}
|
||||
|
||||
if (isDownloading) {
|
||||
butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(4), null, null, null);
|
||||
butAction1.setText(getActivity().getString(R.string.cancel_download_label));
|
||||
} else if (media.isDownloaded()) {
|
||||
butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(0), null, null, null);
|
||||
butAction1.setText(getActivity().getString(R.string.play_label));
|
||||
} else {
|
||||
butAction1.setCompoundDrawablesWithIntrinsicBounds(drawables.getDrawable(1), null, null, null);
|
||||
butAction1.setText(getActivity().getString(R.string.download_label));
|
||||
}
|
||||
|
||||
drawables.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Loader<Pair<FeedItem, QueueAccess>> onCreateLoader(int id, Bundle args) {
|
||||
return new DBTaskLoader<Pair<FeedItem, QueueAccess>>(getActivity()) {
|
||||
@Override
|
||||
public Pair<FeedItem, QueueAccess> loadInBackground() {
|
||||
FeedItem data1 = DBReader.getFeedItem(getContext(), itemID);
|
||||
if (data1 != null) {
|
||||
Timeline t = new Timeline(getActivity(), data1);
|
||||
webviewData = t.processShownotes(false);
|
||||
}
|
||||
QueueAccess data2 = QueueAccess.IDListAccess(DBReader.getQueueIDList(getContext()));
|
||||
return Pair.create(data1, data2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<Pair<FeedItem, QueueAccess>> loader, Pair<FeedItem, QueueAccess> data) {
|
||||
|
||||
if (data != null) {
|
||||
item = data.first;
|
||||
queue = data.second;
|
||||
if (!itemsLoaded) {
|
||||
itemsLoaded = true;
|
||||
onFragmentLoaded();
|
||||
} else {
|
||||
updateAppearance();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<Pair<FeedItem, QueueAccess>> loader) {
|
||||
|
||||
}
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & EVENTS) != 0) {
|
||||
getLoaderManager().restartLoader(0, null, ItemFragment.this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
|
||||
|
||||
@Override
|
||||
public void onContentChanged() {
|
||||
if (itemsLoaded && getActivity() != null) {
|
||||
updateAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadDataAvailable(List<Downloader> downloaderList) {
|
||||
ItemFragment.this.downloaderList = downloaderList;
|
||||
if (itemsLoaded && getActivity() != null) {
|
||||
updateAppearance();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
@ -5,6 +5,7 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.ListFragment;
|
||||
@ -18,6 +19,7 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListAdapter;
|
||||
import android.widget.ListView;
|
||||
import android.widget.TextView;
|
||||
|
||||
@ -35,6 +37,7 @@ import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
|
||||
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
|
||||
import de.danoeh.antennapod.core.asynctask.DownloadObserver;
|
||||
import de.danoeh.antennapod.core.asynctask.FeedRemover;
|
||||
import de.danoeh.antennapod.core.asynctask.PicassoProvider;
|
||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
||||
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
@ -49,7 +52,6 @@ import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil;
|
||||
import de.danoeh.antennapod.dialog.FeedItemDialog;
|
||||
import de.danoeh.antennapod.menuhandler.FeedMenuHandler;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
@ -81,9 +83,6 @@ public class ItemlistFragment extends ListFragment {
|
||||
private DownloadObserver downloadObserver;
|
||||
private List<Downloader> downloaderList;
|
||||
|
||||
private FeedItemDialog feedItemDialog;
|
||||
private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
|
||||
|
||||
private MoreContentListFooterUtil listFooter;
|
||||
|
||||
private boolean isUpdatingFeed;
|
||||
@ -156,13 +155,10 @@ public class ItemlistFragment extends ListFragment {
|
||||
private void resetViewState() {
|
||||
adapter = null;
|
||||
viewsCreated = false;
|
||||
listFooter = null;
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.onPause();
|
||||
}
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialogSavedInstance = feedItemDialog.save();
|
||||
}
|
||||
feedItemDialog = null;
|
||||
}
|
||||
|
||||
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = new MenuItemUtils.UpdateRefreshMenuItemChecker() {
|
||||
@ -258,6 +254,15 @@ public class ItemlistFragment extends ListFragment {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListAdapter(ListAdapter adapter) {
|
||||
// This workaround prevents the ListFragment from setting a list adapter when its state is restored.
|
||||
// This is only necessary on API 10 because addFooterView throws an internal exception in this case.
|
||||
if (Build.VERSION.SDK_INT > 10 || insideOnFragmentLoaded) {
|
||||
super.setListAdapter(adapter);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
@ -272,8 +277,9 @@ public class ItemlistFragment extends ListFragment {
|
||||
@Override
|
||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
FeedItem selection = adapter.getItem(position - l.getHeaderViewsCount());
|
||||
feedItemDialog = FeedItemDialog.newInstance(getActivity(), selection, queue);
|
||||
feedItemDialog.show();
|
||||
if (selection != null) {
|
||||
((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(selection.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
@ -303,9 +309,12 @@ public class ItemlistFragment extends ListFragment {
|
||||
|
||||
}
|
||||
|
||||
private boolean insideOnFragmentLoaded = false;
|
||||
|
||||
private void onFragmentLoaded() {
|
||||
insideOnFragmentLoaded = true;
|
||||
if (adapter == null) {
|
||||
getListView().setAdapter(null);
|
||||
setListAdapter(null);
|
||||
setupHeaderView();
|
||||
setupFooterView();
|
||||
adapter = new FeedItemlistAdapter(getActivity(), itemAccess, new DefaultActionButtonCallback(getActivity()), false);
|
||||
@ -316,17 +325,14 @@ public class ItemlistFragment extends ListFragment {
|
||||
setListShown(true);
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialog.updateContent(queue, feed.getItems());
|
||||
} else if (feedItemDialogSavedInstance != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(getActivity(), feedItemDialogSavedInstance);
|
||||
}
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
|
||||
if (feed != null && feed.getNextPageLink() == null && listFooter != null) {
|
||||
getListView().removeFooterView(listFooter.getRoot());
|
||||
}
|
||||
|
||||
insideOnFragmentLoaded = false;
|
||||
|
||||
}
|
||||
|
||||
private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
|
||||
@ -335,9 +341,6 @@ public class ItemlistFragment extends ListFragment {
|
||||
if (adapter != null) {
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
if (feedItemDialog != null && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.updateMenuAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -362,12 +365,21 @@ public class ItemlistFragment extends ListFragment {
|
||||
|
||||
TextView txtvTitle = (TextView) header.findViewById(R.id.txtvTitle);
|
||||
TextView txtvAuthor = (TextView) header.findViewById(R.id.txtvAuthor);
|
||||
ImageView imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground);
|
||||
ImageView imgvCover = (ImageView) header.findViewById(R.id.imgvCover);
|
||||
ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo);
|
||||
|
||||
txtvTitle.setText(feed.getTitle());
|
||||
txtvAuthor.setText(feed.getAuthor());
|
||||
|
||||
Picasso.with(getActivity())
|
||||
.load(feed.getImageUri())
|
||||
.placeholder(R.color.image_readability_tint)
|
||||
.error(R.color.image_readability_tint)
|
||||
.transform(PicassoProvider.blurTransformation)
|
||||
.resize(PicassoProvider.BLUR_IMAGE_SIZE, PicassoProvider.BLUR_IMAGE_SIZE)
|
||||
.into(imgvBackground);
|
||||
|
||||
Picasso.with(getActivity())
|
||||
.load(feed.getImageUri())
|
||||
.fit()
|
||||
|
@ -7,21 +7,28 @@ import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.support.v7.app.ActionBarActivity;
|
||||
import android.support.v7.widget.SearchView;
|
||||
import android.view.*;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.mobeta.android.dslv.DragSortListView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
|
||||
import de.danoeh.antennapod.adapter.NewEpisodesListAdapter;
|
||||
import de.danoeh.antennapod.core.asynctask.DownloadObserver;
|
||||
import de.danoeh.antennapod.dialog.FeedItemDialog;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
@ -37,9 +44,6 @@ import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
/**
|
||||
* Shows unread or recently published episodes
|
||||
*/
|
||||
@ -73,9 +77,6 @@ public class NewEpisodesFragment extends Fragment {
|
||||
|
||||
private DownloadObserver downloadObserver = null;
|
||||
|
||||
private FeedItemDialog feedItemDialog;
|
||||
private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
|
||||
|
||||
private boolean isUpdatingFeeds;
|
||||
|
||||
@Override
|
||||
@ -133,10 +134,6 @@ public class NewEpisodesFragment extends Fragment {
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.onPause();
|
||||
}
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialogSavedInstance = feedItemDialog.save();
|
||||
}
|
||||
feedItemDialog = null;
|
||||
}
|
||||
|
||||
|
||||
@ -226,8 +223,7 @@ public class NewEpisodesFragment extends Fragment {
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
FeedItem item = (FeedItem) listAdapter.getItem(position - listView.getHeaderViewsCount());
|
||||
if (item != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(activity.get(), item, queueAccess);
|
||||
feedItemDialog.show();
|
||||
((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
@ -257,11 +253,6 @@ public class NewEpisodesFragment extends Fragment {
|
||||
downloadObserver = new DownloadObserver(activity.get(), new Handler(), downloadObserverCallback);
|
||||
downloadObserver.onResume();
|
||||
}
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialog.updateContent(queueAccess, unreadItems, recentItems);
|
||||
} else if (feedItemDialogSavedInstance != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(activity.get(), feedItemDialogSavedInstance);
|
||||
}
|
||||
listAdapter.notifyDataSetChanged();
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
updateShowOnlyEpisodesListViewState();
|
||||
@ -273,9 +264,6 @@ public class NewEpisodesFragment extends Fragment {
|
||||
if (listAdapter != null) {
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
if (feedItemDialog != null && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.updateMenuAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -13,11 +13,15 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
|
||||
import de.danoeh.antennapod.adapter.FeedItemlistAdapter;
|
||||
import de.danoeh.antennapod.core.asynctask.DownloadObserver;
|
||||
import de.danoeh.antennapod.dialog.FeedItemDialog;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
@ -28,9 +32,6 @@ import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class PlaybackHistoryFragment extends ListFragment {
|
||||
private static final String TAG = "PlaybackHistoryFragment";
|
||||
|
||||
@ -46,9 +47,6 @@ public class PlaybackHistoryFragment extends ListFragment {
|
||||
private DownloadObserver downloadObserver;
|
||||
private List<Downloader> downloaderList;
|
||||
|
||||
private FeedItemDialog feedItemDialog;
|
||||
private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@ -103,10 +101,6 @@ public class PlaybackHistoryFragment extends ListFragment {
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.onPause();
|
||||
}
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialogSavedInstance = feedItemDialog.save();
|
||||
}
|
||||
feedItemDialog = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -130,8 +124,7 @@ public class PlaybackHistoryFragment extends ListFragment {
|
||||
super.onListItemClick(l, v, position, id);
|
||||
FeedItem item = adapter.getItem(position - l.getHeaderViewsCount());
|
||||
if (item != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(activity.get(), item, queue);
|
||||
feedItemDialog.show();
|
||||
((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,7 +151,7 @@ public class PlaybackHistoryFragment extends ListFragment {
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (!super.onOptionsItemSelected(item)) {
|
||||
switch(item.getItemId()) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.clear_history_item:
|
||||
DBWriter.clearPlaybackHistory(getActivity());
|
||||
return true;
|
||||
@ -190,11 +183,6 @@ public class PlaybackHistoryFragment extends ListFragment {
|
||||
}
|
||||
setListShown(true);
|
||||
adapter.notifyDataSetChanged();
|
||||
if (feedItemDialog != null && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.updateContent(queue, playbackHistory);
|
||||
} else if (feedItemDialogSavedInstance != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(activity.get(), feedItemDialogSavedInstance);
|
||||
}
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
}
|
||||
|
||||
@ -204,9 +192,6 @@ public class PlaybackHistoryFragment extends ListFragment {
|
||||
if (adapter != null) {
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
if (feedItemDialog != null && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.updateMenuAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -3,6 +3,7 @@ package de.danoeh.antennapod.fragment;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.support.v4.app.Fragment;
|
||||
@ -29,14 +30,17 @@ import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.DefaultActionButtonCallback;
|
||||
import de.danoeh.antennapod.adapter.QueueListAdapter;
|
||||
import de.danoeh.antennapod.core.asynctask.DownloadObserver;
|
||||
import de.danoeh.antennapod.dialog.FeedItemDialog;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadService;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
import de.danoeh.antennapod.core.util.QueueSorter;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
|
||||
@ -59,14 +63,12 @@ public class QueueFragment extends Fragment {
|
||||
|
||||
private boolean itemsLoaded = false;
|
||||
private boolean viewsCreated = false;
|
||||
private boolean isUpdatingFeeds = false;
|
||||
|
||||
private AtomicReference<Activity> activity = new AtomicReference<Activity>();
|
||||
|
||||
private DownloadObserver downloadObserver = null;
|
||||
|
||||
private FeedItemDialog feedItemDialog;
|
||||
private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
|
||||
|
||||
/**
|
||||
* Download observer updates won't result in an upate of the list adapter if this is true.
|
||||
*/
|
||||
@ -122,10 +124,6 @@ public class QueueFragment extends Fragment {
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.onPause();
|
||||
}
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialogSavedInstance = feedItemDialog.save();
|
||||
}
|
||||
feedItemDialog = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -134,10 +132,19 @@ public class QueueFragment extends Fragment {
|
||||
resetViewState();
|
||||
}
|
||||
|
||||
private final MenuItemUtils.UpdateRefreshMenuItemChecker updateRefreshMenuItemChecker = new MenuItemUtils.UpdateRefreshMenuItemChecker() {
|
||||
@Override
|
||||
public boolean isRefreshing() {
|
||||
return DownloadService.isRunning && DownloadRequester.getInstance().isDownloadingFeeds();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
if (itemsLoaded && !MenuItemUtils.isActivityDrawerOpen((NavDrawerActivity) getActivity())) {
|
||||
inflater.inflate(R.menu.queue, menu);
|
||||
|
||||
final SearchView sv = new SearchView(getActivity());
|
||||
MenuItemUtils.addSearchItem(menu, sv);
|
||||
sv.setQueryHint(getString(R.string.search_hint));
|
||||
@ -154,9 +161,47 @@ public class QueueFragment extends Fragment {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
isUpdatingFeeds = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (!super.onOptionsItemSelected(item)) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.refresh_item:
|
||||
List<Feed> feeds = ((MainActivity) getActivity()).getFeeds();
|
||||
if (feeds != null) {
|
||||
DBTasks.refreshAllFeeds(getActivity(), feeds);
|
||||
}
|
||||
return true;
|
||||
case R.id.queue_sort_alpha_asc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.ALPHA_ASC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_alpha_desc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.ALPHA_DESC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_date_asc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DATE_ASC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_date_desc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DATE_DESC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_duration_asc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DURATION_ASC, true);
|
||||
return true;
|
||||
case R.id.queue_sort_duration_desc:
|
||||
QueueSorter.sort(getActivity(), QueueSorter.Rule.DURATION_DESC, true);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
@ -215,8 +260,7 @@ public class QueueFragment extends Fragment {
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
FeedItem item = (FeedItem) listAdapter.getItem(position - listView.getHeaderViewsCount());
|
||||
if (item != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(activity.get(), item, QueueAccess.ItemListAccess(queue));
|
||||
feedItemDialog.show();
|
||||
((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -268,11 +312,10 @@ public class QueueFragment extends Fragment {
|
||||
downloadObserver.onResume();
|
||||
}
|
||||
listAdapter.notifyDataSetChanged();
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialog.updateContent(QueueAccess.ItemListAccess(queue), queue);
|
||||
} else if (feedItemDialogSavedInstance != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(activity.get(), feedItemDialogSavedInstance);
|
||||
}
|
||||
|
||||
// we need to refresh the options menu because it sometimes
|
||||
// needs data that may have just been loaded.
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
}
|
||||
|
||||
private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
|
||||
@ -281,9 +324,6 @@ public class QueueFragment extends Fragment {
|
||||
if (listAdapter != null && !blockDownloadObserverUpdate) {
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
if (feedItemDialog != null && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.updateMenuAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -325,6 +365,9 @@ public class QueueFragment extends Fragment {
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & EVENTS) != 0) {
|
||||
startItemLoader();
|
||||
if (isUpdatingFeeds != updateRefreshMenuItemChecker.isRefreshing()) {
|
||||
getActivity().supportInvalidateOptionsMenu();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -12,19 +12,23 @@ import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.adapter.SearchlistAdapter;
|
||||
import de.danoeh.antennapod.dialog.FeedItemDialog;
|
||||
import de.danoeh.antennapod.core.feed.*;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedComponent;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.SearchResult;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.FeedSearcher;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Performs a search operation on all feeds or one specific feed and displays the search result.
|
||||
*/
|
||||
@ -42,9 +46,6 @@ public class SearchFragment extends ListFragment {
|
||||
|
||||
private QueueAccess queue;
|
||||
|
||||
private FeedItemDialog feedItemDialog;
|
||||
private FeedItemDialog.FeedItemDialogSavedInstance feedItemDialogSavedInstance;
|
||||
|
||||
/**
|
||||
* Create a new SearchFragment that searches all feeds.
|
||||
*/
|
||||
@ -99,10 +100,6 @@ public class SearchFragment extends ListFragment {
|
||||
super.onDestroyView();
|
||||
searchAdapter = null;
|
||||
viewCreated = false;
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialogSavedInstance = feedItemDialog.save();
|
||||
}
|
||||
feedItemDialog = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -128,11 +125,11 @@ public class SearchFragment extends ListFragment {
|
||||
SearchResult result = (SearchResult) l.getAdapter().getItem(position);
|
||||
FeedComponent comp = result.getComponent();
|
||||
if (comp.getClass() == Feed.class) {
|
||||
((MainActivity)getActivity()).loadFeedFragment(comp.getId());
|
||||
((MainActivity) getActivity()).loadFeedFragment(comp.getId());
|
||||
} else {
|
||||
if (comp.getClass() == FeedItem.class) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(getActivity(), (FeedItem) comp, queue);
|
||||
feedItemDialog.show();
|
||||
FeedItem item = (FeedItem) comp;
|
||||
((MainActivity) getActivity()).loadChildFragment(ItemFragment.newInstance(item.getId()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -167,9 +164,6 @@ public class SearchFragment extends ListFragment {
|
||||
private final EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() {
|
||||
@Override
|
||||
public void update(EventDistributor eventDistributor, Integer arg) {
|
||||
if ((arg & (EventDistributor.DOWNLOAD_QUEUED)) != 0 && feedItemDialog != null) {
|
||||
feedItemDialog.updateMenuAppearance();
|
||||
}
|
||||
if ((arg & (EventDistributor.UNREAD_ITEMS_UPDATE
|
||||
| EventDistributor.DOWNLOAD_HANDLED
|
||||
| EventDistributor.QUEUE_UPDATE)) != 0) {
|
||||
@ -185,18 +179,6 @@ public class SearchFragment extends ListFragment {
|
||||
}
|
||||
searchAdapter.notifyDataSetChanged();
|
||||
setListShown(true);
|
||||
if (feedItemDialog != null && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.setQueue(queue);
|
||||
for (SearchResult result : searchResults) {
|
||||
FeedComponent comp = result.getComponent();
|
||||
if (comp.getClass() == FeedItem.class && ((FeedItem) comp).getId() == feedItemDialog.getItem().getId()) {
|
||||
feedItemDialog.setItem((FeedItem) comp);
|
||||
}
|
||||
}
|
||||
feedItemDialog.updateMenuAppearance();
|
||||
} else if (feedItemDialogSavedInstance != null) {
|
||||
feedItemDialog = FeedItemDialog.newInstance(getActivity(), feedItemDialogSavedInstance);
|
||||
}
|
||||
}
|
||||
|
||||
private final SearchlistAdapter.ItemAccess itemAccess = new SearchlistAdapter.ItemAccess() {
|
||||
|
@ -1,85 +1,32 @@
|
||||
package de.danoeh.antennapod.fragment.gpodnet;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
|
||||
/**
|
||||
* Main navigation hub for gpodder.net podcast directory
|
||||
*/
|
||||
public class GpodnetMainFragment extends Fragment {
|
||||
|
||||
private ViewPager pager;
|
||||
private MainActivity activity;
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
View root = inflater.inflate(R.layout.pager_fragment, container, false);
|
||||
pager = (ViewPager) root.findViewById(R.id.pager);
|
||||
ViewPager pager = (ViewPager) root.findViewById(R.id.pager);
|
||||
GpodnetPagerAdapter pagerAdapter = new GpodnetPagerAdapter(getChildFragmentManager(), getResources());
|
||||
pager.setAdapter(pagerAdapter);
|
||||
final ActionBar actionBar = activity.getMainActivtyActionBar();
|
||||
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
|
||||
@Override
|
||||
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
|
||||
pager.setCurrentItem(tab.getPosition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
|
||||
|
||||
}
|
||||
};
|
||||
actionBar.removeAllTabs();
|
||||
actionBar.addTab(actionBar.newTab()
|
||||
.setText(R.string.gpodnet_taglist_header)
|
||||
.setTabListener(tabListener));
|
||||
actionBar.addTab(actionBar.newTab()
|
||||
.setText(R.string.gpodnet_toplist_header)
|
||||
.setTabListener(tabListener));
|
||||
actionBar.setTitle(R.string.gpodnet_main_label);
|
||||
|
||||
pager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
super.onPageSelected(position);
|
||||
actionBar.setSelectedNavigationItem(position);
|
||||
}
|
||||
});
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
super.onDestroyView();
|
||||
activity.getMainActivtyActionBar().removeAllTabs();
|
||||
activity.getMainActivtyActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
this.activity = (MainActivity) activity;
|
||||
}
|
||||
|
||||
public class GpodnetPagerAdapter extends FragmentPagerAdapter {
|
||||
|
||||
|
||||
|
@ -10,7 +10,7 @@ import de.danoeh.antennapod.core.R;
|
||||
/**
|
||||
* Utilities for menu items
|
||||
*/
|
||||
public class MenuItemUtils {
|
||||
public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuItemUtils {
|
||||
|
||||
public static MenuItem addSearchItem(Menu menu, SearchView searchView) {
|
||||
MenuItem item = menu.add(Menu.NONE, R.id.search_item, Menu.NONE, R.string.search_label);
|
||||
@ -28,29 +28,4 @@ public class MenuItemUtils {
|
||||
public static boolean isActivityDrawerOpen(NavDrawerActivity activity) {
|
||||
return activity != null && activity.isDrawerOpen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the appearance of a MenuItem depending on whether the given UpdateRefreshMenuItemChecker
|
||||
* is refreshing or not. If it returns true, the menu item will be replaced by an indeterminate progress
|
||||
* bar, otherwise nothing will happen.
|
||||
*
|
||||
* @param menu The menu that the MenuItem belongs to
|
||||
* @param resId The id of the MenuItem
|
||||
* @param checker Is used for checking whether to show the progress indicator or not.
|
||||
* @return The returned value of the UpdateRefreshMenuItemChecker's isRefreshing() method.
|
||||
*/
|
||||
public static boolean updateRefreshMenuItem(Menu menu, int resId, UpdateRefreshMenuItemChecker checker) {
|
||||
// expand actionview if feeds are being downloaded, collapse otherwise
|
||||
if (checker.isRefreshing()) {
|
||||
MenuItem refreshItem = menu.findItem(resId);
|
||||
MenuItemCompat.setActionView(refreshItem, de.danoeh.antennapod.R.layout.refresh_action_view);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface UpdateRefreshMenuItemChecker {
|
||||
public boolean isRefreshing();
|
||||
}
|
||||
}
|
||||
|
@ -24,6 +24,7 @@ import de.danoeh.antennapod.BuildConfig;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.AboutActivity;
|
||||
import de.danoeh.antennapod.activity.DirectoryChooserActivity;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||
import de.danoeh.antennapod.activity.PreferenceActivityGingerbread;
|
||||
import de.danoeh.antennapod.asynctask.OpmlExportWorker;
|
||||
@ -178,7 +179,7 @@ public class PreferenceController {
|
||||
@Override
|
||||
public boolean onPreferenceChange(
|
||||
Preference preference, Object newValue) {
|
||||
Intent i = activity.getIntent();
|
||||
Intent i = new Intent(activity, MainActivity.class);
|
||||
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
| Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
activity.finish();
|
||||
@ -194,6 +195,7 @@ public class PreferenceController {
|
||||
if (newValue instanceof Boolean) {
|
||||
ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_WIFI_FILTER).setEnabled((Boolean) newValue);
|
||||
setSelectedNetworksEnabled((Boolean) newValue && UserPreferences.isEnableAutodownloadWifiFilter());
|
||||
ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY).setEnabled((Boolean) newValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -375,6 +377,8 @@ public class PreferenceController {
|
||||
setSelectedNetworksEnabled(UserPreferences.isEnableAutodownload()
|
||||
&& UserPreferences.isEnableAutodownloadWifiFilter());
|
||||
|
||||
ui.findPreference(UserPreferences.PREF_ENABLE_AUTODL_ON_BATTERY)
|
||||
.setEnabled(UserPreferences.isEnableAutodownload());
|
||||
}
|
||||
|
||||
private void setEpisodeCacheSizeText(int cacheSize) {
|
||||
|
@ -0,0 +1,45 @@
|
||||
package de.danoeh.antennapod.receiver;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.BatteryManager;
|
||||
import android.util.Log;
|
||||
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBTasks;
|
||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||
|
||||
// modified from http://developer.android.com/training/monitoring-device-state/battery-monitoring.html
|
||||
// and ConnectivityActionReceiver.java
|
||||
public class PowerConnectionReceiver extends BroadcastReceiver {
|
||||
private static final String TAG = "PowerConnectionReceiver";
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
|
||||
boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
|
||||
status == BatteryManager.BATTERY_STATUS_FULL;
|
||||
|
||||
if (isCharging) {
|
||||
Log.d(TAG, "charging, starting auto-download");
|
||||
// we're plugged in, this is a great time to auto-download if everything else is
|
||||
// right. So, even if the user allows auto-dl on battery, let's still start
|
||||
// downloading now. They shouldn't mind.
|
||||
// autodownloadUndownloadedItems will make sure we're on the right wifi networks,
|
||||
// etc... so we don't have to worry about it.
|
||||
DBTasks.autodownloadUndownloadedItems(context);
|
||||
} else {
|
||||
// if we're not supposed to be auto-downloading when we're not charging, stop it
|
||||
if (!UserPreferences.isEnableAutodownloadOnBattery()) {
|
||||
Log.d(TAG, "not charging anymore, canceling auto-download");
|
||||
DownloadRequester.getInstance().cancelAllDownloads(context);
|
||||
} else {
|
||||
Log.d(TAG, "not charging anymore, but the user allows auto-download " +
|
||||
"when on battery so we'll keep going");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,188 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/contentView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.5">
|
||||
</FrameLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_weight="0.5"
|
||||
android:background="?attr/non_transparent_background"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/navBar"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_alignParentTop="true">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butNavLeft"
|
||||
android:contentDescription="@string/show_shownotes_label"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="4dp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butNavRight"
|
||||
android:contentDescription="@string/show_chapters_label"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_toLeftOf="@id/butNavRight"
|
||||
android:layout_toRightOf="@id/butNavLeft"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvFeed"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/txtvTitle"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_toLeftOf="@id/butNavRight"
|
||||
android:layout_toRightOf="@id/butNavLeft"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:maxLines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_small"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/navBarDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_below="@id/navBar"
|
||||
android:background="@color/bright_blue"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/player_control"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="?attr/overlay_background">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butPlay"
|
||||
android:contentDescription="@string/pause_label"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/av_pause"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butRev"
|
||||
android:contentDescription="@string/rewind_label"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/butPlay"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/av_rew_big"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butFF"
|
||||
android:contentDescription="@string/fast_forward_label"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/butPlay"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/av_ff_big"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/butPlaybackSpeed"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/butFF"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/av_fast_forward"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:visibility="gone"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/playtime_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/player_control"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:background="?attr/overlay_drawable">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPosition"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/position_default_label"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_micro"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvLength"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/position_default_label"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_micro"/>
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/sbPosition"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toLeftOf="@id/txtvLength"
|
||||
android:layout_toRightOf="@id/txtvPosition"
|
||||
android:max="500"/>
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/nav_list"/>
|
||||
|
||||
</android.support.v4.widget.DrawerLayout>
|
@ -1,7 +1,9 @@
|
||||
<?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" >
|
||||
android:layout_height="match_parent"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/footer"
|
||||
@ -62,7 +64,9 @@
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/navigation_up" />
|
||||
android:src="?attr/navigation_up"
|
||||
tools:src="@drawable/navigation_up"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvSelectedFolderLabel"
|
||||
@ -74,7 +78,8 @@
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_toRightOf="@id/butNavUp"
|
||||
android:text="@string/selected_folder_label"
|
||||
android:textStyle="bold" >
|
||||
android:textStyle="bold"
|
||||
tools:background="@android:color/holo_green_dark">
|
||||
</TextView>
|
||||
|
||||
<TextView
|
||||
@ -87,7 +92,9 @@
|
||||
android:layout_toRightOf="@id/butNavUp"
|
||||
android:ellipsize="start"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"
|
||||
tools:text="/path/to/selected/folder"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
|
@ -1,173 +1,198 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.DrawerLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
tools:background="@android:color/holo_red_dark">
|
||||
|
||||
<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:background="?attr/non_transparent_background"
|
||||
android:orientation="vertical">
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/navBar"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="60dp"
|
||||
android:layout_alignParentTop="true">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butNavLeft"
|
||||
android:contentDescription="@string/show_shownotes_label"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="4dp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butNavRight"
|
||||
android:contentDescription="@string/show_chapters_label"
|
||||
android:layout_width="60dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentRight="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:padding="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_toLeftOf="@id/butNavRight"
|
||||
android:layout_toRightOf="@id/butNavLeft"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
android:fontFamily="sans-serif-light"
|
||||
/>
|
||||
</RelativeLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/navBarDivider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_below="@id/navBar"
|
||||
android:background="@color/bright_blue"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/player_control"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="80dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="?attr/overlay_background">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butPlay"
|
||||
android:contentDescription="@string/pause_label"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/av_pause"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butRev"
|
||||
android:contentDescription="@string/rewind_label"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/butPlay"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/av_rew_big"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butFF"
|
||||
android:contentDescription="@string/fast_forward_label"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/butPlay"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/av_ff_big"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/butPlaybackSpeed"
|
||||
android:contentDescription="@string/set_playback_speed_label"
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/butFF"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/av_fast_forward"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:visibility="gone"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/playtime_layout"
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/player_control"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:background="?attr/overlay_drawable">
|
||||
android:background="?attr/colorPrimary"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPosition"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
android:paddingLeft="8dp"
|
||||
android:paddingRight="8dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_weight="1"
|
||||
android:ellipsize="end"
|
||||
android:gravity="left"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
tools:text="Audio title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butCover"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/show_cover_label"
|
||||
android:gravity="right"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</android.support.v7.widget.Toolbar>
|
||||
|
||||
<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:background="?attr/non_transparent_background"
|
||||
android:foreground="?android:windowContentOverlay"
|
||||
android:orientation="vertical">
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/player_control"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/audioplayer_playercontrols_length"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="?attr/overlay_background"
|
||||
tools:background="@android:color/holo_purple">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butPlay"
|
||||
android:layout_width="@dimen/audioplayer_playercontrols_length"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/pause_label"
|
||||
android:src="?attr/av_pause"
|
||||
tools:src="@drawable/ic_pause_white_36dp"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butRev"
|
||||
android:layout_width="@dimen/audioplayer_playercontrols_length"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/butPlay"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/rewind_label"
|
||||
android:src="?attr/av_rew_big"
|
||||
tools:src="@drawable/ic_fast_rewind_white_36dp"
|
||||
tools:background="@android:color/holo_blue_dark" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butFF"
|
||||
android:layout_width="@dimen/audioplayer_playercontrols_length"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/butPlay"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/fast_forward_label"
|
||||
android:src="?attr/av_ff_big"
|
||||
tools:src="@drawable/ic_fast_forward_white_36dp"
|
||||
tools:background="@android:color/holo_blue_dark" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/butPlaybackSpeed"
|
||||
android:layout_width="@dimen/audioplayer_playercontrols_length"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toRightOf="@id/butFF"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/set_playback_speed_label"
|
||||
android:src="?attr/av_fast_forward"
|
||||
android:textColor="@color/gray"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
android:visibility="gone"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butNavChaptersShownotes"
|
||||
android:layout_width="@dimen/audioplayer_playercontrols_length"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_toLeftOf="@id/butRev"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/ic_toc_white_36dp"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/playtime_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@id/player_control"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/position_default_label"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:textSize="@dimen/text_size_micro"/>
|
||||
android:background="?attr/overlay_drawable">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvLength"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
<TextView
|
||||
android:id="@+id/txtvPosition"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/position_default_label"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_micro"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvLength"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/position_default_label"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_micro"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/sbPosition"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toLeftOf="@id/txtvLength"
|
||||
android:layout_toRightOf="@id/txtvPosition"
|
||||
android:max="500"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</RelativeLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/contentView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_above="@id/playtime_layout"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/position_default_label"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:fontFamily="sans-serif-light"
|
||||
android:textSize="@dimen/text_size_micro"/>
|
||||
android:foreground="?android:windowContentOverlay"
|
||||
tools:background="@android:color/holo_orange_light" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/sbPosition"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toLeftOf="@id/txtvLength"
|
||||
android:layout_toRightOf="@id/txtvPosition"
|
||||
android:max="500"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/contentView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_above="@id/playtime_layout"
|
||||
android:layout_below="@id/navBarDivider">
|
||||
</FrameLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/nav_list"/>
|
||||
<include layout="@layout/nav_list" />
|
||||
|
||||
</android.support.v4.widget.DrawerLayout>
|
@ -1,5 +1,6 @@
|
||||
<?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:id="@+id/cover_fragment_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
@ -11,9 +12,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="centerInside" />
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@android:drawable/sym_def_app_icon" />
|
||||
|
||||
</RelativeLayout>
|
@ -1,5 +1,6 @@
|
||||
<?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" >
|
||||
|
||||
@ -40,7 +41,9 @@
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:src="?attr/navigation_up" />
|
||||
android:src="?attr/navigation_up"
|
||||
tools:src="@drawable/navigation_up"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvSelectedFolderLabel"
|
||||
@ -52,7 +55,8 @@
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_toRightOf="@id/butNavUp"
|
||||
android:text="@string/selected_folder_label"
|
||||
android:textStyle="bold" >
|
||||
android:textStyle="bold"
|
||||
tools:background="@android:color/holo_blue_bright">
|
||||
</TextView>
|
||||
|
||||
<TextView
|
||||
@ -65,7 +69,9 @@
|
||||
android:layout_toRightOf="@id/butNavUp"
|
||||
android:ellipsize="start"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true" />
|
||||
android:singleLine="true"
|
||||
tools:text="/path/to/selected/folder"
|
||||
tools:background="@android:color/holo_blue_bright"/>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
|
@ -1,9 +1,11 @@
|
||||
<?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:layout_height="@dimen/listitem_threeline_height"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvImage"
|
||||
@ -14,7 +16,9 @@
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:contentDescription="@string/cover_label"
|
||||
android:scaleType="centerCrop" />
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
@ -22,7 +26,8 @@
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding"
|
||||
android:layout_marginRight="@dimen/listitem_threeline_textrightpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
tools:background="@android:color/holo_red_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -33,7 +38,9 @@
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginBottom="4dp" />
|
||||
android:layout_marginBottom="4dp"
|
||||
tools:text="Downloaded episode title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvSize"
|
||||
@ -41,7 +48,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@id/txtvTitle" />
|
||||
android:layout_below="@id/txtvTitle"
|
||||
tools:text="23 MB"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPublished"
|
||||
@ -49,7 +58,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/txtvTitle" />
|
||||
android:layout_below="@id/txtvTitle"
|
||||
tools:text="Jan 23"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -64,6 +75,8 @@
|
||||
android:contentDescription="@string/remove_episode_lable"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:src="?attr/content_discard" />
|
||||
android:src="?attr/content_discard"
|
||||
tools:src="@drawable/ic_delete_white_24dp"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
</LinearLayout>
|
@ -1,8 +1,10 @@
|
||||
<?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:layout_height="@dimen/listitem_threeline_height"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
@ -19,7 +21,9 @@
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp" />
|
||||
android:textSize="16sp"
|
||||
tools:text="Download item title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progProgress"
|
||||
@ -29,7 +33,8 @@
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_marginRight="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_marginTop="4dp" />
|
||||
android:layout_marginTop="4dp"
|
||||
tools:background="@android:color/holo_blue_light" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -46,7 +51,9 @@
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small" />
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="21 MB / 42 MB"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPercent"
|
||||
@ -56,7 +63,9 @@
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small" />
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="50%"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@ -72,5 +81,7 @@
|
||||
android:contentDescription="@string/cancel_download_label"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:src="?attr/navigation_cancel" />
|
||||
</LinearLayout>
|
||||
android:src="?attr/navigation_cancel"
|
||||
tools:src="@drawable/ic_cancel_white_24dp"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</LinearLayout>
|
||||
|
@ -1,8 +1,10 @@
|
||||
<?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:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -17,7 +19,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding" />
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding"
|
||||
tools:text="Media file"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -26,7 +30,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toLeftOf="@id/txtvType" />
|
||||
android:layout_toLeftOf="@id/txtvType"
|
||||
tools:text="Download item title"
|
||||
tools:background="@android:color/holo_blue_light" />
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
@ -42,14 +48,18 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_marginRight="8dp" />
|
||||
android:layout_marginRight="8dp"
|
||||
tools:text="January 23"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvStatus"
|
||||
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true" />
|
||||
android:layout_alignParentRight="true"
|
||||
tools:text="successful"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
@ -61,6 +71,8 @@
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_marginRight="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:textColor="?android:attr/textColorTertiary"
|
||||
android:textSize="@dimen/text_size_micro" />
|
||||
android:textSize="@dimen/text_size_micro"
|
||||
tools:text="@string/design_time_downloaded_log_failure_reason"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
</LinearLayout>
|
@ -1,9 +1,11 @@
|
||||
<?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:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
android:layout_height="match_parent"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -14,6 +16,8 @@
|
||||
android:lines="1"
|
||||
android:singleLine="true"
|
||||
android:layout_margin="16dp"
|
||||
android:ellipsize="start"/>
|
||||
android:ellipsize="start"
|
||||
tools:text="List item title"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
</LinearLayout>
|
@ -1,11 +1,14 @@
|
||||
<?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:id="@+id/fragmentLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone"
|
||||
android:background="?attr/colorPrimary">
|
||||
android:background="?attr/colorPrimary"
|
||||
tools:visibility="visible"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
@ -32,7 +35,9 @@
|
||||
android:padding="4dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:cropToPadding="true"
|
||||
android:scaleType="fitXY"/>
|
||||
android:scaleType="fitXY"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -46,7 +51,9 @@
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textSize="18sp"
|
||||
android:fontFamily="sans-serif-light"/>
|
||||
android:fontFamily="sans-serif-light"
|
||||
tools:text="Playback item title"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<ImageButton
|
||||
@ -54,7 +61,9 @@
|
||||
android:contentDescription="@string/pause_label"
|
||||
android:layout_width="@dimen/external_player_height"
|
||||
android:layout_height="@dimen/external_player_height"
|
||||
android:background="?attr/selectableItemBackground"/>
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:src="@drawable/ic_play_arrow_white_36dp"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -1,5 +1,6 @@
|
||||
<?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:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
@ -19,7 +20,9 @@
|
||||
android:layout_height="70dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_margin="4dp"/>
|
||||
android:layout_margin="4dp"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -28,7 +31,9 @@
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
style="@style/AntennaPod.TextView.Heading"/>
|
||||
style="@style/AntennaPod.TextView.Heading"
|
||||
tools:text="Feed title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
@ -67,7 +72,8 @@
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/author_label"
|
||||
android:textColor="?android:attr/textColorPrimary"/>
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
tools:background="@android:color/holo_red_light" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvAuthor"
|
||||
@ -75,7 +81,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_toRightOf="@id/center_divider"/>
|
||||
android:layout_toRightOf="@id/center_divider"
|
||||
tools:text="Daniel Oeh"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lblLanguage"
|
||||
@ -85,7 +93,8 @@
|
||||
android:layout_below="@id/txtvAuthor"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/language_label"
|
||||
android:textColor="?android:attr/textColorPrimary"/>
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
tools:background="@android:color/holo_red_light" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvLanguage"
|
||||
@ -94,7 +103,9 @@
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_below="@id/txtvAuthor"
|
||||
android:layout_margin="8dp"
|
||||
android:layout_toRightOf="@id/center_divider"/>
|
||||
android:layout_toRightOf="@id/center_divider"
|
||||
tools:text="English"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
@ -115,7 +126,8 @@
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/auto_download_label"
|
||||
android:enabled="false"
|
||||
android:textColor="?android:attr/textColorPrimary"/>
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
tools:background="@android:color/holo_red_light" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvAuthentication"
|
||||
@ -196,7 +208,9 @@
|
||||
android:id="@+id/txtvDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"/>
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/design_time_lorem_ipsum"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
@ -1,73 +0,0 @@
|
||||
<?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:id="@+id/contentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
style="@style/AntennaPod.Dialog.Title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_margin="16dp"
|
||||
android:ellipsize="none"
|
||||
android:maxLines="5" />
|
||||
|
||||
<View
|
||||
android:id="@+id/title_divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_below="@id/txtvTitle"
|
||||
android:background="@color/bright_blue" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/title_divider"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butAction1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butAction2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butMoreActions"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/butAction_label"
|
||||
android:src="?attr/ic_action_overflow" />
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:layout_below="@id/header"
|
||||
android:background="@color/bright_blue" />
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_below="@id/divider" />
|
||||
|
||||
</RelativeLayout>
|
25
app/src/main/res/layout/feeditem_fragment.xml
Normal file
25
app/src/main/res/layout/feeditem_fragment.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/content_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<WebView
|
||||
android:id="@+id/webvDescription"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:foreground="?android:windowContentOverlay" />
|
||||
|
||||
<FrameLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progbarLoading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true" />
|
||||
</FrameLayout>
|
||||
</FrameLayout>
|
114
app/src/main/res/layout/feeditem_fragment_header.xml
Normal file
114
app/src/main/res/layout/feeditem_fragment_header.xml
Normal file
@ -0,0 +1,114 @@
|
||||
<?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:id="@+id/header"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:orientation="horizontal"
|
||||
android:paddingBottom="8dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvCover"
|
||||
android:layout_width="50dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:contentDescription="@string/cover_label"
|
||||
android:gravity="center_vertical"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butMoreActions"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/butAction_label"
|
||||
android:paddingTop="4dp"
|
||||
android:src="?attr/ic_action_overflow"
|
||||
tools:src="@drawable/ic_info_white_24dp"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
style="@style/TextAppearance.AppCompat.Widget.ActionBar.Title"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toLeftOf="@id/butMoreActions"
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
android:maxLines="5"
|
||||
tools:text="Podcast title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</RelativeLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progbarDownload"
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:layout_marginRight="8dp"
|
||||
android:orientation="horizontal"
|
||||
tools:background="@android:color/holo_blue_bright">
|
||||
|
||||
<Button
|
||||
android:id="@+id/butAction1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:ellipsize="end"
|
||||
android:paddingTop="4dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="Button 1"
|
||||
tools:background="@android:color/holo_red_light" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/butAction2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_weight="1"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:ellipsize="end"
|
||||
android:paddingTop="4dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="Button 2"
|
||||
tools:background="@android:color/holo_orange_dark" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
@ -4,7 +4,14 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/feeditemlist_header_height"
|
||||
tools:context="de.danoeh.antennapod.activity.MainActivity">
|
||||
tools:context="de.danoeh.antennapod.activity.MainActivity"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvBackground"
|
||||
style="@style/BigBlurryBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvCover"
|
||||
@ -16,7 +23,9 @@
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:contentDescription="@string/cover_label" />
|
||||
android:contentDescription="@string/cover_label"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/butShowInfo"
|
||||
@ -29,7 +38,8 @@
|
||||
android:layout_marginTop="8dp"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/show_info_label"
|
||||
android:src="?attr/action_about" />
|
||||
android:src="@drawable/ic_info_white_24dp"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -43,7 +53,12 @@
|
||||
android:layout_toLeftOf="@id/butShowInfo"
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2" />
|
||||
android:maxLines="2"
|
||||
android:shadowColor="@color/black"
|
||||
android:shadowRadius="3"
|
||||
android:textColor="@color/white"
|
||||
tools:text="Podcast title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvAuthor"
|
||||
@ -56,8 +71,12 @@
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_small" />
|
||||
android:shadowColor="@color/black"
|
||||
android:shadowRadius="3"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="Podcast author"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
|
||||
</RelativeLayout>
|
@ -4,14 +4,16 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/listitem_threeline_height"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<RelativeLayout
|
||||
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
tools:background="@android:color/holo_orange_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/statusUnread"
|
||||
@ -20,7 +22,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_margin="16dp" />
|
||||
android:layout_margin="16dp"
|
||||
tools:text="Status unread"
|
||||
tools:background="@android:color/white" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvItemname"
|
||||
@ -31,7 +35,9 @@
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_toLeftOf="@id/statusUnread" />
|
||||
android:layout_toLeftOf="@id/statusUnread"
|
||||
tools:text="Feed item name"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
|
||||
<ImageView
|
||||
@ -43,7 +49,9 @@
|
||||
android:layout_marginRight="4dp"
|
||||
android:contentDescription="@string/in_queue_label"
|
||||
android:src="?attr/stat_playlist"
|
||||
android:visibility="visible" />
|
||||
android:visibility="visible"
|
||||
tools:src="@drawable/ic_list_white_24dp"
|
||||
tools:background="@android:color/holo_red_light" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvType"
|
||||
@ -52,7 +60,9 @@
|
||||
android:layout_below="@id/txtvItemname"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_toLeftOf="@+id/imgvInPlaylist"
|
||||
tools:ignore="ContentDescription" />
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/ic_hearing_white_18dp"
|
||||
tools:background="@android:color/holo_red_light" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvLenSize"
|
||||
@ -60,7 +70,9 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@id/txtvItemname" />
|
||||
android:layout_below="@id/txtvItemname"
|
||||
tools:text="00:42:23"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbar_episode_progress"
|
||||
@ -71,7 +83,8 @@
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_toLeftOf="@id/imgvType"
|
||||
android:layout_toRightOf="@id/txtvLenSize" />
|
||||
android:layout_toRightOf="@id/txtvLenSize"
|
||||
tools:background="@android:color/holo_blue_light" />
|
||||
|
||||
|
||||
<TextView
|
||||
@ -81,7 +94,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/txtvItemname"
|
||||
android:layout_marginRight="4dp"
|
||||
android:layout_toLeftOf="@id/imgvType" />
|
||||
android:layout_toLeftOf="@id/imgvType"
|
||||
tools:text="Jan 23"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</RelativeLayout>
|
||||
|
||||
<include layout="@layout/vertical_list_divider"/>
|
||||
|
@ -35,7 +35,10 @@
|
||||
android:layout_margin="16dp"
|
||||
android:textAlignment="center"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
android:visibility="gone" />
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:text="Error message"
|
||||
tools:background="@android:color/holo_red_light" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/butRetry"
|
||||
@ -45,5 +48,7 @@
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_margin="16dp"
|
||||
android:text="@string/retry_label"
|
||||
android:visibility="gone" />
|
||||
</RelativeLayout>
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:background="@android:color/holo_red_light" />
|
||||
</RelativeLayout>
|
||||
|
@ -1,8 +1,10 @@
|
||||
<?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="@dimen/listitem_threeline_height">
|
||||
android:layout_height="@dimen/listitem_threeline_height"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvCover"
|
||||
@ -17,7 +19,9 @@
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/cover_label"
|
||||
android:cropToPadding="true"
|
||||
android:scaleType="fitXY" />
|
||||
android:scaleType="fitXY"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -28,5 +32,7 @@
|
||||
android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_marginRight="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
android:maxLines="1" />
|
||||
</RelativeLayout>
|
||||
android:maxLines="1"
|
||||
tools:text="Podcast title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</RelativeLayout>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?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">
|
||||
|
||||
@ -61,7 +62,9 @@
|
||||
android:maxLines="2"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center"
|
||||
android:layout_margin="16dp"/>
|
||||
android:layout_margin="16dp"
|
||||
tools:text="Error message"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progBarLogin"
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?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">
|
||||
|
||||
@ -70,7 +71,8 @@
|
||||
android:textColor="@color/download_failed_red"
|
||||
android:layout_margin="16dp"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
/>
|
||||
tools:text="Error message"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progbarCreateDevice"
|
||||
|
@ -1,16 +1,20 @@
|
||||
<?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:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
tools:background="@android:color/holo_orange_light">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
style="@style/AntennaPod.TextView.ListItemPrimaryTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp" />
|
||||
android:layout_margin="16dp"
|
||||
tools:text="Feed item title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvDescription"
|
||||
@ -20,5 +24,7 @@
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:lines="3" />
|
||||
</LinearLayout>
|
||||
android:lines="3"
|
||||
tools:text="Feed item description"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
</LinearLayout>
|
||||
|
@ -1,31 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.widget.DrawerLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<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:id="@+id/content"
|
||||
android:layout_width="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"/>
|
||||
android:layout_alignParentBottom="true"
|
||||
tools:layout_height="64dp"
|
||||
tools:background="@android:color/holo_green_light" />
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:minHeight="?attr/actionBarSize"
|
||||
tools:background="@android:color/holo_blue_dark" />
|
||||
<FrameLayout
|
||||
android:id="@+id/main_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0px"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_above="@id/playerFragment"/>
|
||||
android:layout_above="@id/playerFragment"
|
||||
android:layout_below="@id/toolbar"
|
||||
android:foreground="?android:windowContentOverlay"
|
||||
tools:background="@android:color/holo_red_dark" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<include layout="@layout/nav_list"/>
|
||||
<include layout="@layout/nav_list" />
|
||||
|
||||
</android.support.v4.widget.DrawerLayout>
|
@ -1,9 +1,11 @@
|
||||
<?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:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/listitem_iconwithtext_height">
|
||||
android:layout_height="@dimen/listitem_iconwithtext_height"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
|
||||
<ImageView
|
||||
@ -18,7 +20,9 @@
|
||||
android:scaleType="fitXY"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="@dimen/listitem_icon_leftpadding"/>
|
||||
android:layout_marginLeft="@dimen/listitem_icon_leftpadding"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
|
||||
<TextView
|
||||
@ -36,5 +40,7 @@
|
||||
android:layout_marginBottom="@dimen/listitem_iconwithtext_textverticalpadding"
|
||||
android:layout_marginRight="@dimen/listitem_icon_rightpadding"
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
tools:text="Navigation feed item title"
|
||||
tools:background="@android:color/holo_green_dark"
|
||||
/>
|
||||
</RelativeLayout>
|
@ -1,14 +1,74 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/nav_list"
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/nav_layout"
|
||||
android:layout_width="@dimen/drawer_width"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="start"
|
||||
android:background="?attr/nav_drawer_background"
|
||||
android:choiceMode="singleChoice"
|
||||
android:clipToPadding="false"
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="0dp"
|
||||
android:paddingBottom="@dimen/list_vertical_padding"
|
||||
android:paddingTop="@dimen/list_vertical_padding"
|
||||
android:scrollbarStyle="outsideOverlay" />
|
||||
android:orientation="vertical">
|
||||
|
||||
<ListView
|
||||
android:id="@+id/nav_list"
|
||||
android:layout_width="@dimen/drawer_width"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:choiceMode="singleChoice"
|
||||
android:clipToPadding="false"
|
||||
android:divider="@android:color/transparent"
|
||||
android:dividerHeight="0dp"
|
||||
android:paddingBottom="@dimen/list_vertical_padding"
|
||||
android:paddingTop="@dimen/list_vertical_padding"
|
||||
android:scrollbarStyle="outsideOverlay"
|
||||
tools:listitem="@layout/nav_listitem"
|
||||
tools:background="@android:color/holo_purple" />
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/drawer_width"
|
||||
android:layout_height="1dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?android:attr/listDivider"
|
||||
tools:background="@android:color/holo_red_dark" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/nav_settings"
|
||||
android:layout_width="@dimen/drawer_width"
|
||||
android:layout_height="@dimen/listitem_iconwithtext_height"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:contentDescription="@string/settings_label"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvCover"
|
||||
android:layout_width="@dimen/thumbnail_length_navlist"
|
||||
android:layout_height="@dimen/thumbnail_length_navlist"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:layout_marginLeft="@dimen/listitem_icon_leftpadding"
|
||||
android:layout_marginTop="8dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/cover_label"
|
||||
android:cropToPadding="true"
|
||||
android:padding="8dp"
|
||||
android:scaleType="centerCrop"
|
||||
android:src="?attr/ic_settings"
|
||||
tools:src="@android:drawable/sym_def_app_icon"
|
||||
tools:background="@android:color/holo_orange_dark" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/settings_label"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_navdrawer"
|
||||
tools:background="@android:color/holo_green_light"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -1,9 +1,11 @@
|
||||
<?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:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/listitem_iconwithtext_height">
|
||||
android:layout_height="@dimen/listitem_iconwithtext_height"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvCover"
|
||||
@ -18,7 +20,9 @@
|
||||
android:padding="8dp"
|
||||
android:layout_marginLeft="@dimen/listitem_icon_leftpadding"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
android:layout_marginBottom="8dp"
|
||||
tools:src="@drawable/ic_new_releases_white_24dp"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
|
||||
<TextView
|
||||
@ -36,6 +40,8 @@
|
||||
android:layout_marginBottom="@dimen/listitem_iconwithtext_textverticalpadding"
|
||||
android:layout_marginRight="48dp"
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
tools:text="Navigation item title"
|
||||
tools:background="@android:color/holo_green_dark"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
@ -50,5 +56,7 @@
|
||||
android:layout_marginBottom="14dp"
|
||||
android:layout_marginRight="@dimen/listitem_icon_rightpadding"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"/>
|
||||
</RelativeLayout>
|
||||
android:layout_centerVertical="true"
|
||||
tools:text="23"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
</RelativeLayout>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?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="24dp"
|
||||
android:background="@android:color/transparent"
|
||||
@ -10,5 +11,6 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@color/gray" />
|
||||
</RelativeLayout>
|
||||
android:background="?android:attr/listDivider"
|
||||
tools:background="@android:color/holo_red_dark"/>
|
||||
</RelativeLayout>
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:dslv="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@ -25,7 +26,8 @@
|
||||
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"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
@ -41,6 +43,10 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminateOnly="true"
|
||||
android:visibility="gone"/>
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:layout_width="match_parent"
|
||||
tools:layout_height="64dp"
|
||||
tools:background="@android:color/holo_red_light"/>
|
||||
|
||||
</FrameLayout>
|
@ -1,9 +1,11 @@
|
||||
<?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:layout_height="@dimen/listitem_threeline_height"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvImage"
|
||||
@ -14,7 +16,9 @@
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:contentDescription="@string/cover_label"
|
||||
android:scaleType="centerCrop" />
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
@ -23,7 +27,8 @@
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding"
|
||||
android:layout_marginRight="@dimen/listitem_threeline_textrightpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
tools:background="@android:color/white" >
|
||||
|
||||
|
||||
<TextView
|
||||
@ -41,7 +46,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toLeftOf="@id/statusUnread" />
|
||||
android:layout_toLeftOf="@id/statusUnread"
|
||||
tools:text="Episode title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/bottom_bar"
|
||||
@ -50,7 +57,8 @@
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginTop="16dp">
|
||||
android:layout_marginTop="16dp"
|
||||
tools:background="@android:color/holo_red_light" >
|
||||
|
||||
<ImageView
|
||||
android:id="@id/imgvInPlaylist"
|
||||
@ -60,7 +68,9 @@
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:contentDescription="@string/in_queue_label"
|
||||
android:src="?attr/stat_playlist" />
|
||||
android:src="?attr/stat_playlist"
|
||||
tools:src="@drawable/ic_list_grey600_24dp"
|
||||
tools:background="@android:color/black" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbar_download_progress"
|
||||
@ -78,7 +88,9 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_toLeftOf="@id/imgvInPlaylist" />
|
||||
android:layout_toLeftOf="@id/imgvInPlaylist"
|
||||
tools:text="00:42:23"
|
||||
tools:background="@android:color/holo_blue_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPublished"
|
||||
@ -87,7 +99,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_toLeftOf="@id/imgvInPlaylist"
|
||||
android:ellipsize="end" />
|
||||
android:ellipsize="end"
|
||||
tools:text="Jan 23"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?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">
|
||||
|
||||
@ -13,7 +14,9 @@
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:contentDescription="@string/cover_label" />
|
||||
android:contentDescription="@string/cover_label"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -27,7 +30,9 @@
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
android:ellipsize="end"
|
||||
android:gravity="center_vertical"
|
||||
android:maxLines="2" />
|
||||
android:maxLines="2"
|
||||
tools:text="Online feed title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvAuthor"
|
||||
@ -40,7 +45,9 @@
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_small" />
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="Online feed author"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -75,7 +82,9 @@
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_small" />
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:text="@string/design_time_lorem_ipsum"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
@ -1,20 +1,25 @@
|
||||
<?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:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
android:orientation="vertical"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:text="@string/opml_import_explanation" />
|
||||
android:text="@string/opml_import_explanation"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvPath"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp" />
|
||||
android:layout_margin="8dp"
|
||||
tools:text="Path"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/butStartImport"
|
||||
|
@ -1,12 +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">
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v4.view.PagerTabStrip
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top" />
|
||||
</android.support.v4.view.ViewPager>
|
||||
</LinearLayout>
|
@ -4,7 +4,8 @@
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/listitem_threeline_height"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
tools:background="@android:color/darker_gray" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/drag_handle"
|
||||
@ -13,7 +14,9 @@
|
||||
android:layout_margin="8dp"
|
||||
android:contentDescription="@string/drag_handle_content_description"
|
||||
android:scaleType="center"
|
||||
android:src="?attr/dragview_background" />
|
||||
android:src="?attr/dragview_background"
|
||||
tools:src="@drawable/ic_drag_handle"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvImage"
|
||||
@ -23,7 +26,9 @@
|
||||
android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:contentDescription="@string/cover_label"
|
||||
android:scaleType="centerCrop" />
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
@ -32,7 +37,8 @@
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_textleftpadding"
|
||||
android:layout_marginRight="@dimen/listitem_threeline_textrightpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_weight="1">
|
||||
android:layout_weight="1"
|
||||
tools:background="@android:color/holo_red_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -41,7 +47,9 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true" />
|
||||
android:layout_alignParentTop="true"
|
||||
android:text="Queue item title"
|
||||
tools:background="@android:color/holo_blue_light" />
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/bottom_bar"
|
||||
@ -57,7 +65,9 @@
|
||||
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true" />
|
||||
android:layout_alignParentLeft="true"
|
||||
android:text="00:42:23"
|
||||
tools:background="@android:color/holo_blue_light" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/pbar_download_progress"
|
||||
@ -67,7 +77,8 @@
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_toRightOf="@id/txtvPosition"
|
||||
android:max="100" />
|
||||
android:max="100"
|
||||
tools:background="@android:color/holo_blue_light" />
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/listitem_threeline_height">
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/listitem_threeline_height"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvFeedimage"
|
||||
@ -13,7 +15,9 @@
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:contentDescription="@string/cover_label"
|
||||
android:scaleType="centerCrop" />
|
||||
android:scaleType="centerCrop"
|
||||
tools:src="@drawable/ic_stat_antenna_default"
|
||||
tools:background="@android:color/holo_green_dark"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
@ -22,21 +26,26 @@
|
||||
android:layout_marginRight="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_toRightOf="@id/imgvFeedimage"
|
||||
android:orientation="vertical">
|
||||
android:orientation="vertical"
|
||||
tools:background="@android:color/holo_red_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
style="@style/AntennaPod.TextView.ListItemPrimaryTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp" />
|
||||
android:layout_marginBottom="8dp"
|
||||
tools:text="Search item title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvSubtitle"
|
||||
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:lines="1" />
|
||||
android:lines="1"
|
||||
tools:text="Search item subtitle"
|
||||
tools:background="@android:color/holo_blue_light"/>
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
@ -8,4 +8,6 @@
|
||||
android:clickable="false"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
tools:ignore="ContentDescription" />
|
||||
tools:ignore="ContentDescription"
|
||||
tools:src="@drawable/ic_play_arrow_grey600_36dp"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
@ -1,43 +1,73 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="12dp"
|
||||
android:paddingTop="12dp">
|
||||
android:layout_height="@dimen/listitem_threeline_height"
|
||||
android:orientation="horizontal"
|
||||
tools:background="@android:color/darker_gray">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvStart"
|
||||
style="@style/AntennaPod.TextView.ListItemSecondaryTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="8dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:textSize="@dimen/text_size_small"/>
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:gravity="center_vertical"
|
||||
tools:text="Start"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:padding="8dp"
|
||||
android:layout_toLeftOf="@id/txtvStart"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="@dimen/text_size_small"/>
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_marginLeft="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_marginRight="@dimen/listitem_threeline_horizontalpadding"
|
||||
android:layout_marginTop="@dimen/listitem_threeline_verticalpadding"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
tools:background="@android:color/holo_red_dark">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvLink"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_below="@id/txtvTitle"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_toLeftOf="@id/txtvStart"
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="16sp"
|
||||
tools:text="Chapter title"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvLink"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:maxLines="1"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible"
|
||||
tools:text="Link"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<include layout="@layout/vertical_list_divider" />
|
||||
|
||||
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/butPlayChapter"
|
||||
android:layout_width="@dimen/listview_secondary_button_width"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="false"
|
||||
android:contentDescription="@string/chapters_label"
|
||||
android:focusable="false"
|
||||
android:focusableInTouchMode="false"
|
||||
android:visibility="gone"
|
||||
android:maxLines="2" />
|
||||
android:src="?attr/av_play"
|
||||
tools:src="@drawable/ic_play_arrow_white_36dp"
|
||||
tools:background="@android:color/holo_green_dark" />
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
@ -1,5 +1,6 @@
|
||||
<?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:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
@ -42,13 +43,15 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="8dp"
|
||||
android:layout_weight="1" />
|
||||
android:layout_weight="1"
|
||||
tools:text="Confirm" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/butCancel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
android:layout_weight="1"
|
||||
tools:text="Cancel" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -1,7 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<View xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="?android:attr/listDivider"/>
|
||||
android:background="?android:attr/listDivider"
|
||||
tools:background="@android:color/holo_red_dark" />
|
||||
|
@ -5,19 +5,19 @@
|
||||
<item
|
||||
android:id="@+id/download_item"
|
||||
android:icon="?attr/av_download"
|
||||
custom:showAsAction="ifRoom|collapseActionView"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:title="@string/download_label">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/stream_item"
|
||||
android:icon="?attr/action_stream"
|
||||
custom:showAsAction="ifRoom|collapseActionView"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:title="@string/stream_label">
|
||||
</item>
|
||||
<item
|
||||
android:id="@+id/play_item"
|
||||
android:icon="?attr/av_play"
|
||||
custom:showAsAction="ifRoom|collapseActionView"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:title="@string/play_label">
|
||||
</item>
|
||||
<item
|
||||
@ -65,7 +65,7 @@
|
||||
<item
|
||||
android:id="@+id/visit_website_item"
|
||||
android:icon="?attr/location_web_site"
|
||||
custom:showAsAction="ifRoom|collapseActionView"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:title="@string/visit_website_label">
|
||||
</item>
|
||||
<item
|
||||
|
@ -1,12 +0,0 @@
|
||||
<?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/show_preferences"
|
||||
android:title="@string/settings_label"
|
||||
android:menuCategory="system"
|
||||
custom:showAsAction="collapseActionView"/>
|
||||
|
||||
|
||||
</menu>
|
@ -21,7 +21,7 @@
|
||||
<item
|
||||
android:id="@+id/visit_website_item"
|
||||
android:icon="?attr/location_web_site"
|
||||
custom:showAsAction="ifRoom|collapseActionView"
|
||||
custom:showAsAction="collapseActionView"
|
||||
android:title="@string/visit_website_label"
|
||||
android:visible="false">
|
||||
</item>
|
||||
|
63
app/src/main/res/menu/queue.xml
Normal file
63
app/src/main/res/menu/queue.xml
Normal file
@ -0,0 +1,63 @@
|
||||
<?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/refresh_item"
|
||||
android:title="@string/refresh_label"
|
||||
android:menuCategory="container"
|
||||
custom:showAsAction="ifRoom"
|
||||
android:icon="?attr/navigation_refresh"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/queue_sort"
|
||||
android:title="@string/sort">
|
||||
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/queue_sort_alpha"
|
||||
android:title="@string/alpha">
|
||||
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/queue_sort_alpha_asc"
|
||||
android:title="@string/ascending"/>
|
||||
<item
|
||||
android:id="@+id/queue_sort_alpha_desc"
|
||||
android:title="@string/descending"/>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/queue_sort_date"
|
||||
android:title="@string/date">
|
||||
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/queue_sort_date_asc"
|
||||
android:title="@string/ascending"/>
|
||||
<item
|
||||
android:id="@+id/queue_sort_date_desc"
|
||||
android:title="@string/descending"/>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/queue_sort_duration"
|
||||
android:title="@string/duration">
|
||||
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/queue_sort_duration_asc"
|
||||
android:title="@string/ascending"/>
|
||||
<item
|
||||
android:id="@+id/queue_sort_duration_desc"
|
||||
android:title="@string/descending"/>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
</menu>
|
24
app/src/main/res/values/design_time_attributes.xml
Normal file
24
app/src/main/res/values/design_time_attributes.xml
Normal file
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:ignore="MissingTranslation">
|
||||
|
||||
<!--
|
||||
DESIGN TIME ATTRIBUTES
|
||||
Put too long strings to embed in layout files here.
|
||||
-->
|
||||
|
||||
<string name="design_time_lorem_ipsum">
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus ullamcorper
|
||||
tempor metus, at varius tellus dignissim et. Fusce quis justo sollicitudin,
|
||||
feugiat mi in, accumsan erat. Fusce tempor, sapien ut luctus scelerisque,
|
||||
lectus nisi hendrerit odio, eget mattis lorem massa id eros. Integer consequat
|
||||
tellus eu rhoncus pellentesque. Quisque et leo faucibus, aliquam nisi ut,
|
||||
feugiat lectus.
|
||||
</string>
|
||||
<string name="design_time_downloaded_log_failure_reason">
|
||||
IO Error: failed to connect to feeds.example.com/100.100.100.100
|
||||
(port 80) after 3000ms: isConnected failed: ECONNREFUSED (Connection refused)
|
||||
</string>
|
||||
|
||||
</resources>
|
@ -29,17 +29,30 @@
|
||||
android:key="prefPauseOnHeadsetDisconnect"
|
||||
android:summary="@string/pref_pauseOnHeadsetDisconnect_sum"
|
||||
android:title="@string/pref_pauseOnHeadsetDisconnect_title"/>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="true"
|
||||
android:enabled="true"
|
||||
android:dependency="prefPauseOnHeadsetDisconnect"
|
||||
android:key="prefUnpauseOnHeadsetReconnect"
|
||||
android:summary="@string/pref_unpauseOnHeadsetReconnect_sum"
|
||||
android:title="@string/pref_unpauseOnHeadsetReconnect_title"/>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:enabled="true"
|
||||
android:key="prefFollowQueue"
|
||||
android:summary="@string/pref_followQueue_sum"
|
||||
android:title="@string/pref_followQueue_title"/>
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:enabled="true"
|
||||
android:key="prefAutoDelete"
|
||||
android:summary="@string/pref_auto_delete_sum"
|
||||
android:title="@string/pref_auto_delete_title"/>
|
||||
<Preference
|
||||
android:key="prefPlaybackSpeedLauncher"
|
||||
android:summary="@string/pref_playback_speed_sum"
|
||||
android:title="@string/pref_playback_speed_title" />
|
||||
|
||||
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:enabled="true"
|
||||
@ -85,6 +98,11 @@
|
||||
android:key="prefEnableAutoDl"
|
||||
android:title="@string/pref_automatic_download_title"
|
||||
android:defaultValue="false"/>
|
||||
<CheckBoxPreference
|
||||
android:key="prefEnableAutoDownloadOnBattery"
|
||||
android:title="@string/pref_automatic_download_on_battery_title"
|
||||
android:summary="@string/pref_automatic_download_on_battery_sum"
|
||||
android:defaultValue="true"/>
|
||||
<CheckBoxPreference
|
||||
android:key="prefEnableAutoDownloadWifiFilter"
|
||||
android:title="@string/pref_autodl_wifi_filter_title"
|
||||
|
@ -5,7 +5,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:1.0.0-rc4'
|
||||
classpath 'com.android.tools.build:gradle:1.0.0'
|
||||
|
||||
// NOTE: Do not place your application dependencies here; they belong
|
||||
// in the individual module build.gradle files
|
||||
|
@ -2,7 +2,7 @@ apply plugin: 'com.android.library'
|
||||
|
||||
android {
|
||||
compileSdkVersion 21
|
||||
buildToolsVersion "21.1.1"
|
||||
buildToolsVersion "21.1.2"
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 10
|
||||
@ -31,19 +31,17 @@ android {
|
||||
|
||||
dependencies {
|
||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
||||
compile 'com.android.support:appcompat-v7:21.0.2'
|
||||
compile 'com.android.support:support-v4:21.0.2'
|
||||
compile 'com.android.support:appcompat-v7:21.0.3'
|
||||
compile 'com.android.support:support-v4:21.0.3'
|
||||
compile 'org.apache.commons:commons-lang3:3.3.2'
|
||||
compile ('org.shredzone.flattr4j:flattr4j-core:2.11') {
|
||||
exclude group: 'org.apache.httpcomponents', module: 'httpcore'
|
||||
exclude group: 'org.apache.httpcomponents', module: 'httpclient'
|
||||
compile ('org.shredzone.flattr4j:flattr4j-core:2.12') {
|
||||
exclude group: 'org.json', module: 'json'
|
||||
}
|
||||
compile 'commons-io:commons-io:2.4'
|
||||
compile 'com.jayway.android.robotium:robotium-solo:5.2.1'
|
||||
compile 'org.jsoup:jsoup:1.7.3'
|
||||
compile 'com.squareup.picasso:picasso:2.4.0'
|
||||
compile 'com.squareup.okhttp:okhttp:2.1.0'
|
||||
compile 'com.squareup.okhttp:okhttp-urlconnection:2.1.0'
|
||||
compile 'com.squareup.okio:okio:1.0.1'
|
||||
compile 'com.squareup.okhttp:okhttp:2.2.0'
|
||||
compile 'com.squareup.okhttp:okhttp-urlconnection:2.2.0'
|
||||
compile 'com.squareup.okio:okio:1.2.0'
|
||||
}
|
@ -22,4 +22,6 @@ public class ClientConfig {
|
||||
public static FlattrCallbacks flattrCallbacks;
|
||||
|
||||
public static StorageCallbacks storageCallbacks;
|
||||
|
||||
public static DBTasksCallbacks dbTasksCallbacks;
|
||||
}
|
||||
|
@ -0,0 +1,20 @@
|
||||
package de.danoeh.antennapod.core;
|
||||
|
||||
import de.danoeh.antennapod.core.storage.AutomaticDownloadAlgorithm;
|
||||
import de.danoeh.antennapod.core.storage.EpisodeCleanupAlgorithm;
|
||||
|
||||
/**
|
||||
* Callbacks for the DBTasks class of the storage module.
|
||||
*/
|
||||
public interface DBTasksCallbacks {
|
||||
|
||||
/**
|
||||
* Returns the client's implementation of the AutomaticDownloadAlgorithm interface.
|
||||
*/
|
||||
public AutomaticDownloadAlgorithm getAutomaticDownloadAlgorithm();
|
||||
|
||||
/**
|
||||
* Returns the client's implementation of the EpisodeCacheCleanupAlgorithm interface.
|
||||
*/
|
||||
public EpisodeCleanupAlgorithm getEpisodeCacheCleanupAlgorithm();
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package de.danoeh.antennapod.core.asynctask;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
|
||||
/**
|
||||
* Subclass of AsyncTaskLoader that is made for loading data with one of the DB*-classes.
|
||||
* This class will provide a useful default implementation that would otherwise always be necessary when interacting
|
||||
* with the DB*-classes with an AsyncTaskLoader.
|
||||
*/
|
||||
public abstract class DBTaskLoader<D> extends AsyncTaskLoader<D> {
|
||||
|
||||
public DBTaskLoader(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStopLoading() {
|
||||
super.onStopLoading();
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
super.onStartLoading();
|
||||
// according to https://code.google.com/p/android/issues/detail?id=14944, this has to be called manually
|
||||
forceLoad();
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ import com.squareup.picasso.OkHttpDownloader;
|
||||
import com.squareup.picasso.Picasso;
|
||||
import com.squareup.picasso.Request;
|
||||
import com.squareup.picasso.RequestHandler;
|
||||
import com.squareup.picasso.Transformation;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -209,4 +210,254 @@ public class PicassoProvider {
|
||||
options.inJustDecodeBounds = false;
|
||||
}
|
||||
}
|
||||
|
||||
public static final int BLUR_RADIUS = 1;
|
||||
public static final int BLUR_IMAGE_SIZE = 100;
|
||||
public static final String BLUR_KEY = "blur";
|
||||
|
||||
public static final Transformation blurTransformation = new Transformation() {
|
||||
@Override
|
||||
public Bitmap transform(Bitmap source) {
|
||||
Bitmap result = fastblur(source, BLUR_RADIUS);
|
||||
source.recycle();
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String key() {
|
||||
return BLUR_KEY;
|
||||
}
|
||||
};
|
||||
|
||||
public static Bitmap fastblur(Bitmap sentBitmap, int radius) {
|
||||
|
||||
// Stack Blur v1.0 from
|
||||
// http://www.quasimondo.com/StackBlurForCanvas/StackBlurDemo.html
|
||||
//
|
||||
// Java Author: Mario Klingemann <mario at quasimondo.com>
|
||||
// http://incubator.quasimondo.com
|
||||
// created Feburary 29, 2004
|
||||
// Android port : Yahel Bouaziz <yahel at kayenko.com>
|
||||
// http://www.kayenko.com
|
||||
// ported april 5th, 2012
|
||||
|
||||
// This is a compromise between Gaussian Blur and Box blur
|
||||
// It creates much better looking blurs than Box Blur, but is
|
||||
// 7x faster than my Gaussian Blur implementation.
|
||||
//
|
||||
// I called it Stack Blur because this describes best how this
|
||||
// filter works internally: it creates a kind of moving stack
|
||||
// of colors whilst scanning through the image. Thereby it
|
||||
// just has to add one new block of color to the right side
|
||||
// of the stack and remove the leftmost color. The remaining
|
||||
// colors on the topmost layer of the stack are either added on
|
||||
// or reduced by one, depending on if they are on the right or
|
||||
// on the left side of the stack.
|
||||
//
|
||||
// If you are using this algorithm in your code please add
|
||||
// the following line:
|
||||
//
|
||||
// Stack Blur Algorithm by Mario Klingemann <mario@quasimondo.com>
|
||||
|
||||
Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
|
||||
|
||||
if (radius < 1) {
|
||||
return (null);
|
||||
}
|
||||
|
||||
int w = bitmap.getWidth();
|
||||
int h = bitmap.getHeight();
|
||||
|
||||
int[] pix = new int[w * h];
|
||||
Log.e("pix", w + " " + h + " " + pix.length);
|
||||
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
|
||||
|
||||
int wm = w - 1;
|
||||
int hm = h - 1;
|
||||
int wh = w * h;
|
||||
int div = radius + radius + 1;
|
||||
|
||||
int r[] = new int[wh];
|
||||
int g[] = new int[wh];
|
||||
int b[] = new int[wh];
|
||||
int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
|
||||
int vmin[] = new int[Math.max(w, h)];
|
||||
|
||||
int divsum = (div + 1) >> 1;
|
||||
divsum *= divsum;
|
||||
int dv[] = new int[256 * divsum];
|
||||
for (i = 0; i < 256 * divsum; i++) {
|
||||
dv[i] = (i / divsum);
|
||||
}
|
||||
|
||||
yw = yi = 0;
|
||||
|
||||
int[][] stack = new int[div][3];
|
||||
int stackpointer;
|
||||
int stackstart;
|
||||
int[] sir;
|
||||
int rbs;
|
||||
int r1 = radius + 1;
|
||||
int routsum, goutsum, boutsum;
|
||||
int rinsum, ginsum, binsum;
|
||||
|
||||
for (y = 0; y < h; y++) {
|
||||
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
|
||||
for (i = -radius; i <= radius; i++) {
|
||||
p = pix[yi + Math.min(wm, Math.max(i, 0))];
|
||||
sir = stack[i + radius];
|
||||
sir[0] = (p & 0xff0000) >> 16;
|
||||
sir[1] = (p & 0x00ff00) >> 8;
|
||||
sir[2] = (p & 0x0000ff);
|
||||
rbs = r1 - Math.abs(i);
|
||||
rsum += sir[0] * rbs;
|
||||
gsum += sir[1] * rbs;
|
||||
bsum += sir[2] * rbs;
|
||||
if (i > 0) {
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
} else {
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
}
|
||||
}
|
||||
stackpointer = radius;
|
||||
|
||||
for (x = 0; x < w; x++) {
|
||||
|
||||
r[yi] = dv[rsum];
|
||||
g[yi] = dv[gsum];
|
||||
b[yi] = dv[bsum];
|
||||
|
||||
rsum -= routsum;
|
||||
gsum -= goutsum;
|
||||
bsum -= boutsum;
|
||||
|
||||
stackstart = stackpointer - radius + div;
|
||||
sir = stack[stackstart % div];
|
||||
|
||||
routsum -= sir[0];
|
||||
goutsum -= sir[1];
|
||||
boutsum -= sir[2];
|
||||
|
||||
if (y == 0) {
|
||||
vmin[x] = Math.min(x + radius + 1, wm);
|
||||
}
|
||||
p = pix[yw + vmin[x]];
|
||||
|
||||
sir[0] = (p & 0xff0000) >> 16;
|
||||
sir[1] = (p & 0x00ff00) >> 8;
|
||||
sir[2] = (p & 0x0000ff);
|
||||
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
|
||||
rsum += rinsum;
|
||||
gsum += ginsum;
|
||||
bsum += binsum;
|
||||
|
||||
stackpointer = (stackpointer + 1) % div;
|
||||
sir = stack[(stackpointer) % div];
|
||||
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
|
||||
rinsum -= sir[0];
|
||||
ginsum -= sir[1];
|
||||
binsum -= sir[2];
|
||||
|
||||
yi++;
|
||||
}
|
||||
yw += w;
|
||||
}
|
||||
for (x = 0; x < w; x++) {
|
||||
rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
|
||||
yp = -radius * w;
|
||||
for (i = -radius; i <= radius; i++) {
|
||||
yi = Math.max(0, yp) + x;
|
||||
|
||||
sir = stack[i + radius];
|
||||
|
||||
sir[0] = r[yi];
|
||||
sir[1] = g[yi];
|
||||
sir[2] = b[yi];
|
||||
|
||||
rbs = r1 - Math.abs(i);
|
||||
|
||||
rsum += r[yi] * rbs;
|
||||
gsum += g[yi] * rbs;
|
||||
bsum += b[yi] * rbs;
|
||||
|
||||
if (i > 0) {
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
} else {
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
}
|
||||
|
||||
if (i < hm) {
|
||||
yp += w;
|
||||
}
|
||||
}
|
||||
yi = x;
|
||||
stackpointer = radius;
|
||||
for (y = 0; y < h; y++) {
|
||||
// Preserve alpha channel: ( 0xff000000 & pix[yi] )
|
||||
pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
|
||||
|
||||
rsum -= routsum;
|
||||
gsum -= goutsum;
|
||||
bsum -= boutsum;
|
||||
|
||||
stackstart = stackpointer - radius + div;
|
||||
sir = stack[stackstart % div];
|
||||
|
||||
routsum -= sir[0];
|
||||
goutsum -= sir[1];
|
||||
boutsum -= sir[2];
|
||||
|
||||
if (x == 0) {
|
||||
vmin[y] = Math.min(y + r1, hm) * w;
|
||||
}
|
||||
p = x + vmin[y];
|
||||
|
||||
sir[0] = r[p];
|
||||
sir[1] = g[p];
|
||||
sir[2] = b[p];
|
||||
|
||||
rinsum += sir[0];
|
||||
ginsum += sir[1];
|
||||
binsum += sir[2];
|
||||
|
||||
rsum += rinsum;
|
||||
gsum += ginsum;
|
||||
bsum += binsum;
|
||||
|
||||
stackpointer = (stackpointer + 1) % div;
|
||||
sir = stack[stackpointer];
|
||||
|
||||
routsum += sir[0];
|
||||
goutsum += sir[1];
|
||||
boutsum += sir[2];
|
||||
|
||||
rinsum -= sir[0];
|
||||
ginsum -= sir[1];
|
||||
binsum -= sir[2];
|
||||
|
||||
yi += w;
|
||||
}
|
||||
}
|
||||
|
||||
Log.e("pix", w + " " + h + " " + pix.length);
|
||||
bitmap.setPixels(pix, 0, w, 0, 0, w, h);
|
||||
|
||||
return (bitmap);
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ public class FeedItem extends FeedComponent implements ShownotesProvider, Flattr
|
||||
paymentLink = other.paymentLink;
|
||||
}
|
||||
if (other.chapters != null) {
|
||||
if (chapters == null) {
|
||||
if (!hasChapters) {
|
||||
chapters = other.chapters;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,38 @@
|
||||
package de.danoeh.antennapod.core.menuhandler;
|
||||
|
||||
import android.support.v4.view.MenuItemCompat;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import de.danoeh.antennapod.core.R;
|
||||
|
||||
/**
|
||||
* Utilities for menu items
|
||||
*/
|
||||
public class MenuItemUtils {
|
||||
|
||||
/**
|
||||
* Changes the appearance of a MenuItem depending on whether the given UpdateRefreshMenuItemChecker
|
||||
* is refreshing or not. If it returns true, the menu item will be replaced by an indeterminate progress
|
||||
* bar, otherwise nothing will happen.
|
||||
*
|
||||
* @param menu The menu that the MenuItem belongs to
|
||||
* @param resId The id of the MenuItem
|
||||
* @param checker Is used for checking whether to show the progress indicator or not.
|
||||
* @return The returned value of the UpdateRefreshMenuItemChecker's isRefreshing() method.
|
||||
*/
|
||||
public static boolean updateRefreshMenuItem(Menu menu, int resId, UpdateRefreshMenuItemChecker checker) {
|
||||
// expand actionview if feeds are being downloaded, collapse otherwise
|
||||
if (checker.isRefreshing()) {
|
||||
MenuItem refreshItem = menu.findItem(resId);
|
||||
MenuItemCompat.setActionView(refreshItem, R.layout.refresh_action_view);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static interface UpdateRefreshMenuItemChecker {
|
||||
public boolean isRefreshing();
|
||||
}
|
||||
}
|
@ -38,6 +38,7 @@ public class UserPreferences implements
|
||||
private static final String TAG = "UserPreferences";
|
||||
|
||||
public static final String PREF_PAUSE_ON_HEADSET_DISCONNECT = "prefPauseOnHeadsetDisconnect";
|
||||
public static final String PREF_UNPAUSE_ON_HEADSET_RECONNECT = "prefUnpauseOnHeadsetReconnect";
|
||||
public static final String PREF_FOLLOW_QUEUE = "prefFollowQueue";
|
||||
public static final String PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY = "prefDownloadMediaOnWifiOnly";
|
||||
public static final String PREF_UPDATE_INTERVAL = "prefAutoUpdateIntervall";
|
||||
@ -50,6 +51,7 @@ public class UserPreferences implements
|
||||
public static final String PREF_DATA_FOLDER = "prefDataFolder";
|
||||
public static final String PREF_ENABLE_AUTODL = "prefEnableAutoDl";
|
||||
public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
|
||||
public static final String PREF_ENABLE_AUTODL_ON_BATTERY = "prefEnableAutoDownloadOnBattery";
|
||||
private static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
|
||||
public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize";
|
||||
private static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed";
|
||||
@ -69,6 +71,7 @@ public class UserPreferences implements
|
||||
|
||||
// Preferences
|
||||
private boolean pauseOnHeadsetDisconnect;
|
||||
private boolean unpauseOnHeadsetReconnect;
|
||||
private boolean followQueue;
|
||||
private boolean downloadMediaOnWifiOnly;
|
||||
private long updateInterval;
|
||||
@ -80,6 +83,7 @@ public class UserPreferences implements
|
||||
private int theme;
|
||||
private boolean enableAutodownload;
|
||||
private boolean enableAutodownloadWifiFilter;
|
||||
private boolean enableAutodownloadOnBattery;
|
||||
private String[] autodownloadSelectedNetworks;
|
||||
private int episodeCacheSize;
|
||||
private String playbackSpeed;
|
||||
@ -121,6 +125,8 @@ public class UserPreferences implements
|
||||
R.integer.episode_cache_size_unlimited);
|
||||
pauseOnHeadsetDisconnect = sp.getBoolean(
|
||||
PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
|
||||
unpauseOnHeadsetReconnect = sp.getBoolean(
|
||||
PREF_UNPAUSE_ON_HEADSET_RECONNECT, true);
|
||||
followQueue = sp.getBoolean(PREF_FOLLOW_QUEUE, false);
|
||||
downloadMediaOnWifiOnly = sp.getBoolean(
|
||||
PREF_DOWNLOAD_MEDIA_ON_WIFI_ONLY, true);
|
||||
@ -140,6 +146,7 @@ public class UserPreferences implements
|
||||
episodeCacheSize = readEpisodeCacheSizeInternal(sp.getString(
|
||||
PREF_EPISODE_CACHE_SIZE, "20"));
|
||||
enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
|
||||
enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true);
|
||||
playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
|
||||
playbackSpeedArray = readPlaybackSpeedArray(sp.getString(
|
||||
PREF_PLAYBACK_SPEED_ARRAY, null));
|
||||
@ -221,6 +228,11 @@ public class UserPreferences implements
|
||||
return instance.pauseOnHeadsetDisconnect;
|
||||
}
|
||||
|
||||
public static boolean isUnpauseOnHeadsetReconnect() {
|
||||
instanceAvailable();
|
||||
return instance.unpauseOnHeadsetReconnect;
|
||||
}
|
||||
|
||||
public static boolean isFollowQueue() {
|
||||
instanceAvailable();
|
||||
return instance.followQueue;
|
||||
@ -282,6 +294,15 @@ public class UserPreferences implements
|
||||
return instance.theme;
|
||||
}
|
||||
|
||||
public static int getNoTitleTheme() {
|
||||
int theme = getTheme();
|
||||
if (theme == R.style.Theme_AntennaPod_Dark) {
|
||||
return R.style.Theme_AntennaPod_Dark_NoTitle;
|
||||
} else {
|
||||
return R.style.Theme_AntennaPod_Light_NoTitle;
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEnableAutodownloadWifiFilter() {
|
||||
instanceAvailable();
|
||||
return instance.enableAutodownloadWifiFilter;
|
||||
@ -326,6 +347,11 @@ public class UserPreferences implements
|
||||
return instance.enableAutodownload;
|
||||
}
|
||||
|
||||
public static boolean isEnableAutodownloadOnBattery() {
|
||||
instanceAvailable();
|
||||
return instance.enableAutodownloadOnBattery;
|
||||
}
|
||||
|
||||
public static boolean shouldPauseForFocusLoss() {
|
||||
instanceAvailable();
|
||||
return instance.pauseForFocusLoss;
|
||||
@ -377,6 +403,8 @@ public class UserPreferences implements
|
||||
PREF_EPISODE_CACHE_SIZE, "20"));
|
||||
} else if (key.equals(PREF_ENABLE_AUTODL)) {
|
||||
enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
|
||||
} else if (key.equals(PREF_ENABLE_AUTODL_ON_BATTERY)) {
|
||||
enableAutodownloadOnBattery = sp.getBoolean(PREF_ENABLE_AUTODL_ON_BATTERY, true);
|
||||
} else if (key.equals(PREF_PLAYBACK_SPEED)) {
|
||||
playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
|
||||
} else if (key.equals(PREF_PLAYBACK_SPEED_ARRAY)) {
|
||||
@ -388,6 +416,8 @@ public class UserPreferences implements
|
||||
seekDeltaSecs = Integer.valueOf(sp.getString(PREF_SEEK_DELTA_SECS, "30"));
|
||||
} else if (key.equals(PREF_PAUSE_ON_HEADSET_DISCONNECT)) {
|
||||
pauseOnHeadsetDisconnect = sp.getBoolean(PREF_PAUSE_ON_HEADSET_DISCONNECT, true);
|
||||
} else if (key.equals(PREF_UNPAUSE_ON_HEADSET_RECONNECT)) {
|
||||
unpauseOnHeadsetReconnect = sp.getBoolean(PREF_UNPAUSE_ON_HEADSET_RECONNECT, true);
|
||||
} else if (key.equals(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD)) {
|
||||
autoFlattrPlayedDurationThreshold = sp.getFloat(PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD,
|
||||
PREF_AUTO_FLATTR_PLAYED_DURATION_THRESHOLD_DEFAULT);
|
||||
|
@ -144,6 +144,10 @@ public class PlaybackService extends Service {
|
||||
* Is true if service has received a valid start command.
|
||||
*/
|
||||
public static boolean started = false;
|
||||
/**
|
||||
* Is true if the service was running, but paused due to headphone disconnect
|
||||
*/
|
||||
public static boolean transientPause = false;
|
||||
|
||||
private static final int NOTIFICATION_ID = 1;
|
||||
|
||||
@ -206,6 +210,8 @@ public class PlaybackService extends Service {
|
||||
Intent.ACTION_HEADSET_PLUG));
|
||||
registerReceiver(shutdownReceiver, new IntentFilter(
|
||||
ACTION_SHUTDOWN_PLAYBACK_SERVICE));
|
||||
registerReceiver(bluetoothStateUpdated, new IntentFilter(
|
||||
AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
|
||||
registerReceiver(audioBecomingNoisy, new IntentFilter(
|
||||
AudioManager.ACTION_AUDIO_BECOMING_NOISY));
|
||||
registerReceiver(skipCurrentEpisodeReceiver, new IntentFilter(
|
||||
@ -228,6 +234,7 @@ public class PlaybackService extends Service {
|
||||
|
||||
unregisterReceiver(headsetDisconnected);
|
||||
unregisterReceiver(shutdownReceiver);
|
||||
unregisterReceiver(bluetoothStateUpdated);
|
||||
unregisterReceiver(audioBecomingNoisy);
|
||||
unregisterReceiver(skipCurrentEpisodeReceiver);
|
||||
mediaPlayer.shutdown();
|
||||
@ -284,7 +291,6 @@ public class PlaybackService extends Service {
|
||||
private void handleKeycode(int keycode) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Handling keycode: " + keycode);
|
||||
|
||||
final PlaybackServiceMediaPlayer.PSMPInfo info = mediaPlayer.getPSMPInfo();
|
||||
final PlayerStatus status = info.playerStatus;
|
||||
switch (keycode) {
|
||||
@ -315,12 +321,14 @@ public class PlaybackService extends Service {
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_PAUSE:
|
||||
if (status == PlayerStatus.PLAYING) {
|
||||
if (UserPreferences.isPersistNotify()) {
|
||||
mediaPlayer.pause(false, true);
|
||||
} else {
|
||||
mediaPlayer.pause(true, true);
|
||||
}
|
||||
mediaPlayer.pause(false, true);
|
||||
}
|
||||
if (UserPreferences.isPersistNotify()) {
|
||||
mediaPlayer.pause(false, true);
|
||||
} else {
|
||||
mediaPlayer.pause(true, true);
|
||||
}
|
||||
|
||||
break;
|
||||
case KeyEvent.KEYCODE_MEDIA_NEXT:
|
||||
case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
|
||||
@ -333,7 +341,9 @@ public class PlaybackService extends Service {
|
||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||
if (status == PlayerStatus.PLAYING) {
|
||||
mediaPlayer.pause(true, true);
|
||||
started = false;
|
||||
}
|
||||
|
||||
stopForeground(true); // gets rid of persistent notification
|
||||
break;
|
||||
default:
|
||||
@ -411,10 +421,13 @@ public class PlaybackService extends Service {
|
||||
taskManager.cancelWidgetUpdater();
|
||||
if (UserPreferences.isPersistNotify() && android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
// do not remove notification on pause based on user pref and whether android version supports expanded notifications
|
||||
} else {
|
||||
// Change [Play] button to [Pause]
|
||||
setupNotification(newInfo);
|
||||
} else if (!UserPreferences.isPersistNotify()) {
|
||||
// remove notifcation on pause
|
||||
stopForeground(true);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case STOPPED:
|
||||
@ -431,6 +444,7 @@ public class PlaybackService extends Service {
|
||||
taskManager.startPositionSaver();
|
||||
taskManager.startWidgetUpdater();
|
||||
setupNotification(newInfo);
|
||||
started = true;
|
||||
break;
|
||||
case ERROR:
|
||||
writePlaybackPreferencesNoMediaPlaying();
|
||||
@ -539,6 +553,15 @@ public class PlaybackService extends Service {
|
||||
if (isAutoFlattrable(media) && UserPreferences.getAutoFlattrPlayedDurationThreshold() == 1.0f) {
|
||||
DBTasks.flattrItemIfLoggedIn(PlaybackService.this, item);
|
||||
}
|
||||
|
||||
//Delete episode if enabled
|
||||
if(UserPreferences.isAutoDelete()) {
|
||||
DBWriter.deleteFeedMediaOfItem(PlaybackService.this, item.getMedia().getId());
|
||||
|
||||
if(BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Episode Deleted");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Load next episode if previous episode was in the queue and if there
|
||||
@ -734,8 +757,9 @@ public class PlaybackService extends Service {
|
||||
PlaybackServiceMediaPlayer.PSMPInfo newInfo = mediaPlayer.getPSMPInfo();
|
||||
final int smallIcon = ClientConfig.playbackServiceCallbacks.getNotificationIconResource(getApplicationContext());
|
||||
|
||||
if (!isCancelled() && info.playerStatus == PlayerStatus.PLAYING
|
||||
&& info.playable != null) {
|
||||
if (!isCancelled() &&
|
||||
started &&
|
||||
info.playable != null) {
|
||||
String contentText = info.playable.getFeedTitle();
|
||||
String contentTitle = info.playable.getEpisodeTitle();
|
||||
Notification notification = null;
|
||||
@ -775,16 +799,30 @@ public class PlaybackService extends Service {
|
||||
.setContentIntent(pIntent)
|
||||
.setLargeIcon(icon)
|
||||
.setSmallIcon(smallIcon)
|
||||
.setPriority(UserPreferences.getNotifyPriority()) // set notification priority
|
||||
.addAction(android.R.drawable.ic_media_play, //play action
|
||||
getString(R.string.play_label),
|
||||
playButtonPendingIntent)
|
||||
.addAction(android.R.drawable.ic_media_pause, //pause action
|
||||
getString(R.string.pause_label),
|
||||
pauseButtonPendingIntent)
|
||||
.addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action
|
||||
getString(R.string.stop_label),
|
||||
stopButtonPendingIntent);
|
||||
.setPriority(UserPreferences.getNotifyPriority()); // set notification priority
|
||||
if (newInfo.playerStatus == PlayerStatus.PLAYING) {
|
||||
notificationBuilder.addAction(android.R.drawable.ic_media_pause, //pause action
|
||||
getString(R.string.pause_label),
|
||||
pauseButtonPendingIntent);
|
||||
} else {
|
||||
notificationBuilder.addAction(android.R.drawable.ic_media_play, //play action
|
||||
getString(R.string.play_label),
|
||||
playButtonPendingIntent);
|
||||
}
|
||||
if (UserPreferences.isPersistNotify()) {
|
||||
notificationBuilder.addAction(android.R.drawable.ic_menu_close_clear_cancel, // stop action
|
||||
getString(R.string.stop_label),
|
||||
stopButtonPendingIntent);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
notificationBuilder.setStyle(new Notification.MediaStyle()
|
||||
.setMediaSession((android.media.session.MediaSession.Token) mediaPlayer.getSessionToken().getToken())
|
||||
.setShowActionsInCompactView(0))
|
||||
.setVisibility(Notification.VISIBILITY_PUBLIC)
|
||||
.setColor(Notification.COLOR_DEFAULT);
|
||||
}
|
||||
|
||||
notification = notificationBuilder.build();
|
||||
} else {
|
||||
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(
|
||||
@ -793,11 +831,9 @@ public class PlaybackService extends Service {
|
||||
.setContentText(contentText).setOngoing(true)
|
||||
.setContentIntent(pIntent).setLargeIcon(icon)
|
||||
.setSmallIcon(smallIcon);
|
||||
notification = notificationBuilder.getNotification();
|
||||
}
|
||||
if (newInfo.playerStatus == PlayerStatus.PLAYING) {
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
notification = notificationBuilder.build();
|
||||
}
|
||||
startForeground(NOTIFICATION_ID, notification);
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Notification set up");
|
||||
}
|
||||
@ -966,6 +1002,7 @@ public class PlaybackService extends Service {
|
||||
private BroadcastReceiver headsetDisconnected = new BroadcastReceiver() {
|
||||
private static final String TAG = "headsetDisconnected";
|
||||
private static final int UNPLUGGED = 0;
|
||||
private static final int PLUGGED = 1;
|
||||
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@ -978,6 +1015,10 @@ public class PlaybackService extends Service {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Headset was unplugged during playback.");
|
||||
pauseIfPauseOnDisconnect();
|
||||
} else if (state == PLUGGED) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Headset was plugged in during playback.");
|
||||
unpauseIfPauseOnDisconnect();
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "Received invalid ACTION_HEADSET_PLUG intent");
|
||||
@ -986,6 +1027,21 @@ public class PlaybackService extends Service {
|
||||
}
|
||||
};
|
||||
|
||||
private BroadcastReceiver bluetoothStateUpdated = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (StringUtils.equals(intent.getAction(), AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) {
|
||||
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
|
||||
int prevState = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_PREVIOUS_STATE, -1);
|
||||
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Received bluetooth connection intent");
|
||||
unpauseIfPauseOnDisconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private BroadcastReceiver audioBecomingNoisy = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
@ -1003,6 +1059,9 @@ public class PlaybackService extends Service {
|
||||
*/
|
||||
private void pauseIfPauseOnDisconnect() {
|
||||
if (UserPreferences.isPauseOnHeadsetDisconnect()) {
|
||||
if (mediaPlayer.getPlayerStatus() == PlayerStatus.PLAYING) {
|
||||
transientPause = true;
|
||||
}
|
||||
if (UserPreferences.isPersistNotify()) {
|
||||
mediaPlayer.pause(false, true);
|
||||
} else {
|
||||
@ -1011,6 +1070,15 @@ public class PlaybackService extends Service {
|
||||
}
|
||||
}
|
||||
|
||||
private void unpauseIfPauseOnDisconnect() {
|
||||
if (transientPause) {
|
||||
transientPause = false;
|
||||
if (UserPreferences.isPauseOnHeadsetDisconnect() && UserPreferences.isUnpauseOnHeadsetReconnect()) {
|
||||
mediaPlayer.resume();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BroadcastReceiver shutdownReceiver = new BroadcastReceiver() {
|
||||
|
||||
@Override
|
||||
|
@ -6,6 +6,9 @@ import android.media.AudioManager;
|
||||
import android.media.RemoteControlClient;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.PowerManager;
|
||||
import android.support.v4.media.MediaMetadataCompat;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
@ -48,6 +51,10 @@ public class PlaybackServiceMediaPlayer {
|
||||
private volatile PlayerStatus statusBeforeSeeking;
|
||||
private volatile IPlayer mediaPlayer;
|
||||
private volatile Playable media;
|
||||
/**
|
||||
* Only used for Lollipop notifications.
|
||||
*/
|
||||
private final MediaSessionCompat mediaSession;
|
||||
|
||||
private volatile boolean stream;
|
||||
private volatile MediaType mediaType;
|
||||
@ -89,6 +96,10 @@ public class PlaybackServiceMediaPlayer {
|
||||
}
|
||||
);
|
||||
|
||||
mediaSession = new MediaSessionCompat(context, TAG);
|
||||
mediaSession.setCallback(sessionCallback);
|
||||
mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
||||
|
||||
mediaPlayer = null;
|
||||
statusBeforeSeeking = null;
|
||||
pausedBecauseOfTransientAudiofocusLoss = false;
|
||||
@ -181,6 +192,7 @@ public class PlaybackServiceMediaPlayer {
|
||||
setPlayerStatus(PlayerStatus.INITIALIZING, media);
|
||||
try {
|
||||
media.loadMetadata();
|
||||
mediaSession.setMetadata(getMediaSessionMetadata(media));
|
||||
if (stream) {
|
||||
mediaPlayer.setDataSource(media.getStreamUrl());
|
||||
} else {
|
||||
@ -211,6 +223,13 @@ public class PlaybackServiceMediaPlayer {
|
||||
}
|
||||
}
|
||||
|
||||
private MediaMetadataCompat getMediaSessionMetadata(Playable p) {
|
||||
MediaMetadataCompat.Builder builder = new MediaMetadataCompat.Builder();
|
||||
builder.putString(MediaMetadataCompat.METADATA_KEY_TITLE, p.getEpisodeTitle());
|
||||
builder.putString(MediaMetadataCompat.METADATA_KEY_ALBUM, p.getFeedTitle());
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Resumes playback if the PSMP object is in PREPARED or PAUSED state. If the PSMP object is in an invalid state.
|
||||
@ -586,6 +605,10 @@ public class PlaybackServiceMediaPlayer {
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
public PlayerStatus getPlayerStatus() {
|
||||
return playerStatus;
|
||||
}
|
||||
|
||||
public boolean isStreaming() {
|
||||
return stream;
|
||||
}
|
||||
@ -599,6 +622,9 @@ public class PlaybackServiceMediaPlayer {
|
||||
if (mediaPlayer != null) {
|
||||
mediaPlayer.release();
|
||||
}
|
||||
if (mediaSession != null) {
|
||||
mediaSession.release();
|
||||
}
|
||||
releaseWifiLockIfNecessary();
|
||||
}
|
||||
|
||||
@ -662,6 +688,16 @@ public class PlaybackServiceMediaPlayer {
|
||||
return new PSMPInfo(playerStatus, media);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a token to this object's MediaSession. The MediaSession should only be used for notifications
|
||||
* at the moment.
|
||||
*
|
||||
* @return The MediaSessionCompat.Token object.
|
||||
*/
|
||||
public MediaSessionCompat.Token getSessionToken() {
|
||||
return mediaSession.getSessionToken();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player status of the PSMP object. PlayerStatus and media attributes have to be set at the same time
|
||||
* so that getPSMPInfo can't return an invalid state (e.g. status is PLAYING, but media is null).
|
||||
@ -679,6 +715,45 @@ public class PlaybackServiceMediaPlayer {
|
||||
|
||||
this.playerStatus = newStatus;
|
||||
this.media = newMedia;
|
||||
|
||||
PlaybackStateCompat.Builder sessionState = new PlaybackStateCompat.Builder();
|
||||
|
||||
int state;
|
||||
if (playerStatus != null) {
|
||||
switch (playerStatus) {
|
||||
case PLAYING:
|
||||
state = PlaybackStateCompat.STATE_PLAYING;
|
||||
break;
|
||||
case PREPARED:
|
||||
case PAUSED:
|
||||
state = PlaybackStateCompat.STATE_PAUSED;
|
||||
break;
|
||||
case STOPPED:
|
||||
state = PlaybackStateCompat.STATE_STOPPED;
|
||||
break;
|
||||
case SEEKING:
|
||||
state = PlaybackStateCompat.STATE_FAST_FORWARDING;
|
||||
break;
|
||||
case PREPARING:
|
||||
case INITIALIZING:
|
||||
state = PlaybackStateCompat.STATE_CONNECTING;
|
||||
break;
|
||||
case INITIALIZED:
|
||||
case INDETERMINATE:
|
||||
state = PlaybackStateCompat.STATE_NONE;
|
||||
break;
|
||||
case ERROR:
|
||||
state = PlaybackStateCompat.STATE_ERROR;
|
||||
break;
|
||||
default:
|
||||
state = PlaybackStateCompat.STATE_NONE;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
state = PlaybackStateCompat.STATE_NONE;
|
||||
}
|
||||
sessionState.setState(state, PlaybackStateCompat.PLAYBACK_POSITION_UNKNOWN, getPlaybackSpeed());
|
||||
|
||||
callback.statusChanged(new PSMPInfo(playerStatus, media));
|
||||
}
|
||||
|
||||
@ -976,4 +1051,54 @@ public class PlaybackServiceMediaPlayer {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final MediaSessionCompat.Callback sessionCallback = new MediaSessionCompat.Callback() {
|
||||
|
||||
@Override
|
||||
public void onPlay() {
|
||||
if (playerStatus == PlayerStatus.PAUSED || playerStatus == PlayerStatus.PREPARED) {
|
||||
resume();
|
||||
} else if (playerStatus == PlayerStatus.INITIALIZED) {
|
||||
setStartWhenPrepared(true);
|
||||
prepare();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
if (playerStatus == PlayerStatus.PLAYING) {
|
||||
pause(false, true);
|
||||
}
|
||||
if (UserPreferences.isPersistNotify()) {
|
||||
pause(false, true);
|
||||
} else {
|
||||
pause(true, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSkipToNext() {
|
||||
super.onSkipToNext();
|
||||
endPlayback();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFastForward() {
|
||||
super.onFastForward();
|
||||
seekDelta(UserPreferences.getSeekDeltaMs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewind() {
|
||||
super.onRewind();
|
||||
seekDelta(-UserPreferences.getSeekDeltaMs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSeekTo(long pos) {
|
||||
super.onSeekTo(pos);
|
||||
seekTo((int) pos);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -0,0 +1,103 @@
|
||||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
|
||||
/**
|
||||
* Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPod.
|
||||
*/
|
||||
public class APCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
|
||||
private static final String TAG = "APCleanupAlgorithm";
|
||||
|
||||
@Override
|
||||
public int performCleanup(Context context, Integer episodeNumber) {
|
||||
List<FeedItem> candidates = new ArrayList<FeedItem>();
|
||||
List<FeedItem> downloadedItems = DBReader.getDownloadedItems(context);
|
||||
QueueAccess queue = QueueAccess.IDListAccess(DBReader.getQueueIDList(context));
|
||||
List<FeedItem> delete;
|
||||
for (FeedItem item : downloadedItems) {
|
||||
if (item.hasMedia() && item.getMedia().isDownloaded()
|
||||
&& !queue.contains(item.getId()) && item.isRead()) {
|
||||
candidates.add(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Collections.sort(candidates, new Comparator<FeedItem>() {
|
||||
@Override
|
||||
public int compare(FeedItem lhs, FeedItem rhs) {
|
||||
Date l = lhs.getMedia().getPlaybackCompletionDate();
|
||||
Date r = rhs.getMedia().getPlaybackCompletionDate();
|
||||
|
||||
if (l == null) {
|
||||
l = new Date(0);
|
||||
}
|
||||
if (r == null) {
|
||||
r = new Date(0);
|
||||
}
|
||||
return l.compareTo(r);
|
||||
}
|
||||
});
|
||||
|
||||
if (candidates.size() > episodeNumber) {
|
||||
delete = candidates.subList(0, episodeNumber);
|
||||
} else {
|
||||
delete = candidates;
|
||||
}
|
||||
|
||||
for (FeedItem item : delete) {
|
||||
try {
|
||||
DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int counter = delete.size();
|
||||
|
||||
|
||||
Log.i(TAG, String.format(
|
||||
"Auto-delete deleted %d episodes (%d requested)", counter,
|
||||
episodeNumber));
|
||||
|
||||
return counter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefaultCleanupParameter(Context context) {
|
||||
return getPerformAutoCleanupArgs(context, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPerformCleanupParameter(Context context, List<FeedItem> items) {
|
||||
return getPerformAutoCleanupArgs(context, items.size());
|
||||
}
|
||||
|
||||
static int getPerformAutoCleanupArgs(Context context,
|
||||
final int episodeNumber) {
|
||||
if (episodeNumber >= 0
|
||||
&& UserPreferences.getEpisodeCacheSize() != UserPreferences
|
||||
.getEpisodeCacheSizeUnlimited()) {
|
||||
int downloadedEpisodes = DBReader
|
||||
.getNumberOfDownloadedEpisodes(context);
|
||||
if (downloadedEpisodes + episodeNumber >= UserPreferences
|
||||
.getEpisodeCacheSize()) {
|
||||
|
||||
return downloadedEpisodes + episodeNumber
|
||||
- UserPreferences.getEpisodeCacheSize();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.util.NetworkUtils;
|
||||
import de.danoeh.antennapod.core.util.PowerUtils;
|
||||
|
||||
/**
|
||||
* Implements the automatic download algorithm used by AntennaPod. This class assumes that
|
||||
* the client uses the APEpisodeCleanupAlgorithm.
|
||||
*/
|
||||
public class APDownloadAlgorithm implements AutomaticDownloadAlgorithm {
|
||||
private static final String TAG = "APDownloadAlgorithm";
|
||||
|
||||
private final APCleanupAlgorithm cleanupAlgorithm = new APCleanupAlgorithm();
|
||||
|
||||
/**
|
||||
* Looks for undownloaded episodes in the queue or list of unread items and request a download if
|
||||
* 1. Network is available
|
||||
* 2. The device is charging or the user allows auto download on battery
|
||||
* 3. There is free space in the episode cache
|
||||
* This method is executed on an internal single thread executor.
|
||||
*
|
||||
* @param context Used for accessing the DB.
|
||||
* @param mediaIds If this list is not empty, the method will only download a candidate for automatic downloading if
|
||||
* its media ID is in the mediaIds list.
|
||||
* @return A Runnable that will be submitted to an ExecutorService.
|
||||
*/
|
||||
@Override
|
||||
public Runnable autoDownloadUndownloadedItems(final Context context, final long... mediaIds) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
// true if we should auto download based on network status
|
||||
boolean networkShouldAutoDl = NetworkUtils.autodownloadNetworkAvailable(context)
|
||||
&& UserPreferences.isEnableAutodownload();
|
||||
|
||||
// true if we should auto download based on power status
|
||||
boolean powerShouldAutoDl = PowerUtils.deviceCharging(context)
|
||||
|| UserPreferences.isEnableAutodownloadOnBattery();
|
||||
|
||||
// we should only auto download if both network AND power are happy
|
||||
if (networkShouldAutoDl && powerShouldAutoDl) {
|
||||
|
||||
Log.d(TAG, "Performing auto-dl of undownloaded episodes");
|
||||
|
||||
final List<FeedItem> queue = DBReader.getQueue(context);
|
||||
final List<FeedItem> unreadItems = DBReader
|
||||
.getUnreadItemsList(context);
|
||||
|
||||
int undownloadedEpisodes = DBTasks.getNumberOfUndownloadedEpisodes(queue,
|
||||
unreadItems);
|
||||
int downloadedEpisodes = DBReader
|
||||
.getNumberOfDownloadedEpisodes(context);
|
||||
int deletedEpisodes = cleanupAlgorithm.performCleanup(context,
|
||||
APCleanupAlgorithm.getPerformAutoCleanupArgs(context, undownloadedEpisodes));
|
||||
int episodeSpaceLeft = undownloadedEpisodes;
|
||||
boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences
|
||||
.getEpisodeCacheSizeUnlimited();
|
||||
|
||||
if (!cacheIsUnlimited
|
||||
&& UserPreferences.getEpisodeCacheSize() < downloadedEpisodes
|
||||
+ undownloadedEpisodes) {
|
||||
episodeSpaceLeft = UserPreferences.getEpisodeCacheSize()
|
||||
- (downloadedEpisodes - deletedEpisodes);
|
||||
}
|
||||
|
||||
Arrays.sort(mediaIds); // sort for binary search
|
||||
final boolean ignoreMediaIds = mediaIds.length == 0;
|
||||
List<FeedItem> itemsToDownload = new ArrayList<FeedItem>();
|
||||
|
||||
if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
|
||||
for (int i = 0; i < queue.size(); i++) { // ignore playing item
|
||||
FeedItem item = queue.get(i);
|
||||
long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
|
||||
if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
|
||||
&& item.hasMedia()
|
||||
&& !item.getMedia().isDownloaded()
|
||||
&& !item.getMedia().isPlaying()
|
||||
&& item.getFeed().getPreferences().getAutoDownload()) {
|
||||
itemsToDownload.add(item);
|
||||
episodeSpaceLeft--;
|
||||
undownloadedEpisodes--;
|
||||
if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
|
||||
for (FeedItem item : unreadItems) {
|
||||
long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
|
||||
if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
|
||||
&& item.hasMedia()
|
||||
&& !item.getMedia().isDownloaded()
|
||||
&& item.getFeed().getPreferences().getAutoDownload()) {
|
||||
itemsToDownload.add(item);
|
||||
episodeSpaceLeft--;
|
||||
undownloadedEpisodes--;
|
||||
if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Enqueueing " + itemsToDownload.size()
|
||||
+ " items for download");
|
||||
|
||||
try {
|
||||
DBTasks.downloadFeedItems(false, context,
|
||||
itemsToDownload.toArray(new FeedItem[itemsToDownload
|
||||
.size()])
|
||||
);
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
|
||||
/**
|
||||
* Implementation of the EpisodeCleanupAlgorithm interface used by AntennaPodSP apps.
|
||||
*/
|
||||
public class APSPCleanupAlgorithm implements EpisodeCleanupAlgorithm<Integer> {
|
||||
private static final String TAG = "APSPCleanupAlgorithm";
|
||||
|
||||
final int numberOfNewAutomaticallyDownloadedEpisodes;
|
||||
|
||||
public APSPCleanupAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) {
|
||||
this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs an automatic cleanup. Episodes that have been downloaded first will also be deleted first.
|
||||
* The episode that is currently playing as well as the n most recent episodes (the exact value is determined
|
||||
* by AppPreferences.numberOfNewAutomaticallyDownloadedEpisodes) will never be deleted.
|
||||
*
|
||||
* @param context
|
||||
* @param episodeSize The maximum amount of space that should be freed by this method
|
||||
* @return The number of episodes that have been deleted
|
||||
*/
|
||||
@Override
|
||||
public int performCleanup(Context context, Integer episodeSize) {
|
||||
Log.i(TAG, String.format("performAutoCleanup(%d)", episodeSize));
|
||||
if (episodeSize <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
List<FeedItem> candidates = getAutoCleanupCandidates(context);
|
||||
List<FeedItem> deleteList = new ArrayList<FeedItem>();
|
||||
long deletedEpisodesSize = 0;
|
||||
Collections.sort(candidates, new Comparator<FeedItem>() {
|
||||
@Override
|
||||
public int compare(FeedItem lhs, FeedItem rhs) {
|
||||
File lFile = new File(lhs.getMedia().getFile_url());
|
||||
File rFile = new File(rhs.getMedia().getFile_url());
|
||||
if (!lFile.exists() || !rFile.exists()) {
|
||||
return 0;
|
||||
}
|
||||
if (FileUtils.isFileOlder(lFile, rFile)) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
// listened episodes will be deleted first
|
||||
Iterator<FeedItem> it = candidates.iterator();
|
||||
if (it.hasNext()) {
|
||||
for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) {
|
||||
if (!i.getMedia().isPlaying() && i.getMedia().getPlaybackCompletionDate() != null) {
|
||||
it.remove();
|
||||
deleteList.add(i);
|
||||
deletedEpisodesSize += i.getMedia().getSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// delete unlistened old episodes if necessary
|
||||
it = candidates.iterator();
|
||||
if (it.hasNext()) {
|
||||
for (FeedItem i = it.next(); it.hasNext() && deletedEpisodesSize <= episodeSize; i = it.next()) {
|
||||
if (!i.getMedia().isPlaying()) {
|
||||
it.remove();
|
||||
deleteList.add(i);
|
||||
deletedEpisodesSize += i.getMedia().getSize();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (FeedItem item : deleteList) {
|
||||
try {
|
||||
DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
Log.i(TAG, String.format("performAutoCleanup(%d) deleted %d episodes and freed %d bytes of memory",
|
||||
episodeSize, deleteList.size(), deletedEpisodesSize));
|
||||
return deleteList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getDefaultCleanupParameter(Context context) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPerformCleanupParameter(Context context, List<FeedItem> items) {
|
||||
int episodeSize = 0;
|
||||
for (FeedItem item : items) {
|
||||
if (item.hasMedia() && !item.getMedia().isDownloaded()) {
|
||||
episodeSize += item.getMedia().getSize();
|
||||
}
|
||||
}
|
||||
return episodeSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of FeedItems that have been downloaded, but are not one of the
|
||||
* [numberOfNewAutomaticallyDownloadedEpisodes] most recent items.
|
||||
*/
|
||||
private List<FeedItem> getAutoCleanupCandidates(Context context) {
|
||||
List<FeedItem> downloaded = new ArrayList<FeedItem>(DBReader.getDownloadedItems(context));
|
||||
List<FeedItem> recent = new ArrayList<FeedItem>(DBReader.getRecentlyPublishedEpisodes(context,
|
||||
numberOfNewAutomaticallyDownloadedEpisodes));
|
||||
for (FeedItem r : recent) {
|
||||
if (r.hasMedia() && r.getMedia().isDownloaded()) {
|
||||
for (int i = 0; i < downloaded.size(); i++) {
|
||||
if (downloaded.get(i).getId() == r.getId()) {
|
||||
downloaded.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return downloaded;
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.util.NetworkUtils;
|
||||
|
||||
/**
|
||||
* Implements the automatic download algorithm used by AntennaPodSP apps.
|
||||
*/
|
||||
public class APSPDownloadAlgorithm implements AutomaticDownloadAlgorithm {
|
||||
private static final String TAG = "APSPDownloadAlgorithm";
|
||||
|
||||
private final int numberOfNewAutomaticallyDownloadedEpisodes;
|
||||
|
||||
public APSPDownloadAlgorithm(int numberOfNewAutomaticallyDownloadedEpisodes) {
|
||||
this.numberOfNewAutomaticallyDownloadedEpisodes = numberOfNewAutomaticallyDownloadedEpisodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads the most recent episodes automatically. The exact number of
|
||||
* episodes that will be downloaded can be set in the AppPreferences.
|
||||
*
|
||||
* @param context Used for accessing the DB.
|
||||
* @return A Runnable that will be submitted to an ExecutorService.
|
||||
*/
|
||||
@Override
|
||||
public Runnable autoDownloadUndownloadedItems(final Context context, final long... mediaIds) {
|
||||
return new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Performing auto-dl of undownloaded episodes");
|
||||
if (NetworkUtils.autodownloadNetworkAvailable(context)
|
||||
&& UserPreferences.isEnableAutodownload()) {
|
||||
|
||||
Arrays.sort(mediaIds);
|
||||
List<FeedItem> itemsToDownload = DBReader.getRecentlyPublishedEpisodes(context,
|
||||
numberOfNewAutomaticallyDownloadedEpisodes);
|
||||
Iterator<FeedItem> it = itemsToDownload.iterator();
|
||||
|
||||
for (FeedItem item = it.next(); it.hasNext(); item = it.next()) {
|
||||
if (!item.hasMedia()
|
||||
|| item.getMedia().isDownloaded()
|
||||
|| Arrays.binarySearch(mediaIds, item.getMedia().getId()) < 0) {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Enqueueing " + itemsToDownload.size()
|
||||
+ " items for automatic download");
|
||||
if (!itemsToDownload.isEmpty()) {
|
||||
try {
|
||||
DBTasks.downloadFeedItems(false, context,
|
||||
itemsToDownload.toArray(new FeedItem[itemsToDownload
|
||||
.size()]));
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
public interface AutomaticDownloadAlgorithm {
|
||||
|
||||
/**
|
||||
* Looks for undownloaded episodes and request a download if
|
||||
* 1. Network is available
|
||||
* 2. The device is charging or the user allows auto download on battery
|
||||
* 3. There is free space in the episode cache
|
||||
* This method is executed on an internal single thread executor.
|
||||
*
|
||||
* @param context Used for accessing the DB.
|
||||
* @param mediaIds If this list is not empty, the method will only download a candidate for automatic downloading if
|
||||
* its media ID is in the mediaIds list.
|
||||
* @return A Runnable that will be submitted to an ExecutorService.
|
||||
*/
|
||||
public Runnable autoDownloadUndownloadedItems(Context context, long... mediaIds);
|
||||
}
|
@ -8,7 +8,6 @@ import android.util.Log;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -35,7 +34,6 @@ import de.danoeh.antennapod.core.service.GpodnetSyncService;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadStatus;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.util.DownloadError;
|
||||
import de.danoeh.antennapod.core.util.NetworkUtils;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.util.comparator.FeedItemPubdateComparator;
|
||||
import de.danoeh.antennapod.core.util.exception.MediaFileNotFoundException;
|
||||
@ -386,8 +384,8 @@ public final class DBTasks {
|
||||
downloadFeedItems(true, context, items);
|
||||
}
|
||||
|
||||
private static void downloadFeedItems(boolean performAutoCleanup,
|
||||
final Context context, final FeedItem... items)
|
||||
static void downloadFeedItems(boolean performAutoCleanup,
|
||||
final Context context, final FeedItem... items)
|
||||
throws DownloadRequestException {
|
||||
final DownloadRequester requester = DownloadRequester.getInstance();
|
||||
|
||||
@ -396,8 +394,10 @@ public final class DBTasks {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
performAutoCleanup(context,
|
||||
getPerformAutoCleanupArgs(context, items.length));
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm()
|
||||
.performCleanup(context,
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm()
|
||||
.getPerformCleanupParameter(context, Arrays.asList(items)));
|
||||
}
|
||||
|
||||
}.start();
|
||||
@ -427,7 +427,7 @@ public final class DBTasks {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getNumberOfUndownloadedEpisodes(
|
||||
static int getNumberOfUndownloadedEpisodes(
|
||||
final List<FeedItem> queue, final List<FeedItem> unreadItems) {
|
||||
int counter = 0;
|
||||
for (FeedItem item : queue) {
|
||||
@ -449,7 +449,8 @@ public final class DBTasks {
|
||||
/**
|
||||
* Looks for undownloaded episodes in the queue or list of unread items and request a download if
|
||||
* 1. Network is available
|
||||
* 2. There is free space in the episode cache
|
||||
* 2. The device is charging or the user allows auto download on battery
|
||||
* 3. There is free space in the episode cache
|
||||
* This method is executed on an internal single thread executor.
|
||||
*
|
||||
* @param context Used for accessing the DB.
|
||||
@ -458,107 +459,9 @@ public final class DBTasks {
|
||||
* @return A Future that can be used for waiting for the methods completion.
|
||||
*/
|
||||
public static Future<?> autodownloadUndownloadedItems(final Context context, final long... mediaIds) {
|
||||
return autodownloadExec.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Performing auto-dl of undownloaded episodes");
|
||||
if (NetworkUtils.autodownloadNetworkAvailable(context)
|
||||
&& UserPreferences.isEnableAutodownload()) {
|
||||
final List<FeedItem> queue = DBReader.getQueue(context);
|
||||
final List<FeedItem> unreadItems = DBReader
|
||||
.getUnreadItemsList(context);
|
||||
return autodownloadExec.submit(ClientConfig.dbTasksCallbacks.getAutomaticDownloadAlgorithm()
|
||||
.autoDownloadUndownloadedItems(context, mediaIds));
|
||||
|
||||
int undownloadedEpisodes = getNumberOfUndownloadedEpisodes(queue,
|
||||
unreadItems);
|
||||
int downloadedEpisodes = DBReader
|
||||
.getNumberOfDownloadedEpisodes(context);
|
||||
int deletedEpisodes = performAutoCleanup(context,
|
||||
getPerformAutoCleanupArgs(context, undownloadedEpisodes));
|
||||
int episodeSpaceLeft = undownloadedEpisodes;
|
||||
boolean cacheIsUnlimited = UserPreferences.getEpisodeCacheSize() == UserPreferences
|
||||
.getEpisodeCacheSizeUnlimited();
|
||||
|
||||
if (!cacheIsUnlimited
|
||||
&& UserPreferences.getEpisodeCacheSize() < downloadedEpisodes
|
||||
+ undownloadedEpisodes) {
|
||||
episodeSpaceLeft = UserPreferences.getEpisodeCacheSize()
|
||||
- (downloadedEpisodes - deletedEpisodes);
|
||||
}
|
||||
|
||||
Arrays.sort(mediaIds); // sort for binary search
|
||||
final boolean ignoreMediaIds = mediaIds.length == 0;
|
||||
List<FeedItem> itemsToDownload = new ArrayList<FeedItem>();
|
||||
|
||||
if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
|
||||
for (int i = 0; i < queue.size(); i++) { // ignore playing item
|
||||
FeedItem item = queue.get(i);
|
||||
long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
|
||||
if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
|
||||
&& item.hasMedia()
|
||||
&& !item.getMedia().isDownloaded()
|
||||
&& !item.getMedia().isPlaying()
|
||||
&& item.getFeed().getPreferences().getAutoDownload()) {
|
||||
itemsToDownload.add(item);
|
||||
episodeSpaceLeft--;
|
||||
undownloadedEpisodes--;
|
||||
if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (episodeSpaceLeft > 0 && undownloadedEpisodes > 0) {
|
||||
for (FeedItem item : unreadItems) {
|
||||
long mediaId = (item.hasMedia()) ? item.getMedia().getId() : -1;
|
||||
if ((ignoreMediaIds || Arrays.binarySearch(mediaIds, mediaId) >= 0)
|
||||
&& item.hasMedia()
|
||||
&& !item.getMedia().isDownloaded()
|
||||
&& item.getFeed().getPreferences().getAutoDownload()) {
|
||||
itemsToDownload.add(item);
|
||||
episodeSpaceLeft--;
|
||||
undownloadedEpisodes--;
|
||||
if (episodeSpaceLeft == 0 || undownloadedEpisodes == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Enqueueing " + itemsToDownload.size()
|
||||
+ " items for download");
|
||||
|
||||
try {
|
||||
downloadFeedItems(false, context,
|
||||
itemsToDownload.toArray(new FeedItem[itemsToDownload
|
||||
.size()])
|
||||
);
|
||||
} catch (DownloadRequestException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static int getPerformAutoCleanupArgs(Context context,
|
||||
final int episodeNumber) {
|
||||
if (episodeNumber >= 0
|
||||
&& UserPreferences.getEpisodeCacheSize() != UserPreferences
|
||||
.getEpisodeCacheSizeUnlimited()) {
|
||||
int downloadedEpisodes = DBReader
|
||||
.getNumberOfDownloadedEpisodes(context);
|
||||
if (downloadedEpisodes + episodeNumber >= UserPreferences
|
||||
.getEpisodeCacheSize()) {
|
||||
|
||||
return downloadedEpisodes + episodeNumber
|
||||
- UserPreferences.getEpisodeCacheSize();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -570,63 +473,8 @@ public final class DBTasks {
|
||||
* @param context Used for accessing the DB.
|
||||
*/
|
||||
public static void performAutoCleanup(final Context context) {
|
||||
performAutoCleanup(context, getPerformAutoCleanupArgs(context, 0));
|
||||
}
|
||||
|
||||
private static int performAutoCleanup(final Context context,
|
||||
final int episodeNumber) {
|
||||
List<FeedItem> candidates = new ArrayList<FeedItem>();
|
||||
List<FeedItem> downloadedItems = DBReader.getDownloadedItems(context);
|
||||
QueueAccess queue = QueueAccess.IDListAccess(DBReader.getQueueIDList(context));
|
||||
List<FeedItem> delete;
|
||||
for (FeedItem item : downloadedItems) {
|
||||
if (item.hasMedia() && item.getMedia().isDownloaded()
|
||||
&& !queue.contains(item.getId()) && item.isRead()) {
|
||||
candidates.add(item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Collections.sort(candidates, new Comparator<FeedItem>() {
|
||||
@Override
|
||||
public int compare(FeedItem lhs, FeedItem rhs) {
|
||||
Date l = lhs.getMedia().getPlaybackCompletionDate();
|
||||
Date r = rhs.getMedia().getPlaybackCompletionDate();
|
||||
|
||||
if (l == null) {
|
||||
l = new Date(0);
|
||||
}
|
||||
if (r == null) {
|
||||
r = new Date(0);
|
||||
}
|
||||
return l.compareTo(r);
|
||||
}
|
||||
});
|
||||
|
||||
if (candidates.size() > episodeNumber) {
|
||||
delete = candidates.subList(0, episodeNumber);
|
||||
} else {
|
||||
delete = candidates;
|
||||
}
|
||||
|
||||
for (FeedItem item : delete) {
|
||||
try {
|
||||
DBWriter.deleteFeedMediaOfItem(context, item.getMedia().getId()).get();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
int counter = delete.size();
|
||||
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, String.format(
|
||||
"Auto-delete deleted %d episodes (%d requested)", counter,
|
||||
episodeNumber));
|
||||
|
||||
return counter;
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().performCleanup(context,
|
||||
ClientConfig.dbTasksCallbacks.getEpisodeCacheCleanupAlgorithm().getDefaultCleanupParameter(context));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7,23 +7,14 @@ import android.content.SharedPreferences;
|
||||
import android.database.Cursor;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.ClientConfig;
|
||||
import de.danoeh.antennapod.core.asynctask.FlattrClickWorker;
|
||||
import de.danoeh.antennapod.core.feed.*;
|
||||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadStatus;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
|
||||
import de.danoeh.antennapod.core.util.flattr.FlattrThing;
|
||||
import de.danoeh.antennapod.core.util.flattr.SimpleFlattrThing;
|
||||
|
||||
import org.shredzone.flattr4j.model.Flattr;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -33,6 +24,24 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
|
||||
import de.danoeh.antennapod.core.BuildConfig;
|
||||
import de.danoeh.antennapod.core.ClientConfig;
|
||||
import de.danoeh.antennapod.core.asynctask.FlattrClickWorker;
|
||||
import de.danoeh.antennapod.core.feed.EventDistributor;
|
||||
import de.danoeh.antennapod.core.feed.Feed;
|
||||
import de.danoeh.antennapod.core.feed.FeedImage;
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.feed.FeedPreferences;
|
||||
import de.danoeh.antennapod.core.preferences.GpodnetPreferences;
|
||||
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
||||
import de.danoeh.antennapod.core.service.download.DownloadStatus;
|
||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.core.util.flattr.FlattrStatus;
|
||||
import de.danoeh.antennapod.core.util.flattr.FlattrThing;
|
||||
import de.danoeh.antennapod.core.util.flattr.SimpleFlattrThing;
|
||||
|
||||
/**
|
||||
* Provides methods for writing data to AntennaPod's database.
|
||||
* In general, DBWriter-methods will be executed on an internal ExecutorService.
|
||||
@ -819,7 +828,8 @@ public class DBWriter {
|
||||
PodDBAdapter adapter = new PodDBAdapter(context);
|
||||
adapter.open();
|
||||
for (String key : urls.keySet()) {
|
||||
if (BuildConfig.DEBUG) Log.d(TAG, "Replacing URL " + key + " with url " + urls.get(key));
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Replacing URL " + key + " with url " + urls.get(key));
|
||||
|
||||
adapter.setFeedDownloadUrl(key, urls.get(key));
|
||||
}
|
||||
@ -976,4 +986,35 @@ public class DBWriter {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the FeedItems in the queue with the given Comparator.
|
||||
*
|
||||
* @param context A context that is used for opening a database connection.
|
||||
* @param comparator FeedItem comparator
|
||||
* @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
|
||||
* false if the caller wants to avoid unexpected updates of the GUI.
|
||||
*/
|
||||
public static Future<?> sortQueue(final Context context, final Comparator<FeedItem> comparator, final boolean broadcastUpdate) {
|
||||
return dbExec.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final PodDBAdapter adapter = new PodDBAdapter(context);
|
||||
adapter.open();
|
||||
final List<FeedItem> queue = DBReader.getQueue(context, adapter);
|
||||
|
||||
if (queue != null) {
|
||||
Collections.sort(queue, comparator);
|
||||
adapter.setQueue(queue);
|
||||
if (broadcastUpdate) {
|
||||
EventDistributor.getInstance()
|
||||
.sendQueueUpdateBroadcast();
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "sortQueue: Could not load queue");
|
||||
}
|
||||
adapter.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -92,8 +92,9 @@ public class DownloadRequester {
|
||||
|
||||
private void download(Context context, FeedFile item, FeedFile container, File dest,
|
||||
boolean overwriteIfExists, String username, String password, boolean deleteOnFailure, Bundle arguments) {
|
||||
final boolean partiallyDownloadedFileExists = item.getFile_url() != null;
|
||||
if (!isDownloadingFile(item)) {
|
||||
if (!isFilenameAvailable(dest.toString()) || (deleteOnFailure && dest.exists())) {
|
||||
if (!isFilenameAvailable(dest.toString()) || (!partiallyDownloadedFileExists && dest.exists())) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Filename already used.");
|
||||
if (isFilenameAvailable(dest.toString()) && overwriteIfExists) {
|
||||
@ -254,8 +255,7 @@ public class DownloadRequester {
|
||||
* Cancels all running downloads
|
||||
*/
|
||||
public synchronized void cancelAllDownloads(Context context) {
|
||||
if (BuildConfig.DEBUG)
|
||||
Log.d(TAG, "Cancelling all running downloads");
|
||||
Log.d(TAG, "Cancelling all running downloads");
|
||||
context.sendBroadcast(new Intent(
|
||||
DownloadService.ACTION_CANCEL_ALL_DOWNLOADS));
|
||||
}
|
||||
@ -377,10 +377,13 @@ public class DownloadRequester {
|
||||
|
||||
String URLBaseFilename = URLUtil.guessFileName(media.getDownload_url(),
|
||||
null, media.getMime_type());
|
||||
;
|
||||
|
||||
if (titleBaseFilename != "") {
|
||||
if (!titleBaseFilename.equals("")) {
|
||||
// Append extension
|
||||
final int FILENAME_MAX_LENGTH = 220;
|
||||
if (titleBaseFilename.length() > FILENAME_MAX_LENGTH) {
|
||||
titleBaseFilename = titleBaseFilename.substring(0, FILENAME_MAX_LENGTH);
|
||||
}
|
||||
filename = titleBaseFilename + FilenameUtils.EXTENSION_SEPARATOR +
|
||||
FilenameUtils.getExtension(URLBaseFilename);
|
||||
} else {
|
||||
|
@ -0,0 +1,36 @@
|
||||
package de.danoeh.antennapod.core.storage;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
|
||||
public interface EpisodeCleanupAlgorithm<T> {
|
||||
|
||||
/**
|
||||
* Deletes downloaded episodes that are no longer needed. What episodes are deleted and how many
|
||||
* of them depends on the implementation.
|
||||
*
|
||||
* @param context Can be used for accessing the database
|
||||
* @param parameter An additional parameter. This parameter is either returned by getDefaultCleanupParameter
|
||||
* or getPerformCleanupParameter.
|
||||
* @return The number of episodes that were deleted.
|
||||
*/
|
||||
public int performCleanup(Context context, T parameter);
|
||||
|
||||
/**
|
||||
* Returns a parameter for performCleanup. The implementation of this interface should decide how much
|
||||
* space to free to satisfy the episode cache conditions. If the conditions are already satisfied, this
|
||||
* method should not have any effects.
|
||||
*/
|
||||
public T getDefaultCleanupParameter(Context context);
|
||||
|
||||
/**
|
||||
* Returns a parameter for performCleanup.
|
||||
*
|
||||
* @param items A list of FeedItems that are about to be downloaded. The implementation of this interface
|
||||
* should decide how much space to free to satisfy the episode cache conditions.
|
||||
*/
|
||||
public T getPerformCleanupParameter(Context context, List<FeedItem> items);
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
package de.danoeh.antennapod.core.util;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.os.BatteryManager;
|
||||
|
||||
/**
|
||||
* Created by Tom on 1/5/15.
|
||||
*/
|
||||
public class PowerUtils {
|
||||
|
||||
private static final String TAG = "PowerUtils";
|
||||
|
||||
private PowerUtils() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the device is charging
|
||||
*/
|
||||
public static boolean deviceCharging(Context context) {
|
||||
// from http://developer.android.com/training/monitoring-device-state/battery-monitoring.html
|
||||
IntentFilter iFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
|
||||
Intent batteryStatus = context.registerReceiver(null, iFilter);
|
||||
|
||||
int status = batteryStatus.getIntExtra(BatteryManager.EXTRA_STATUS, -1);
|
||||
return (status == BatteryManager.BATTERY_STATUS_CHARGING ||
|
||||
status == BatteryManager.BATTERY_STATUS_FULL);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package de.danoeh.antennapod.core.util;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
/**
|
||||
* Provides method for sorting the queue according to rules.
|
||||
*/
|
||||
public class QueueSorter {
|
||||
public enum Rule {
|
||||
ALPHA_ASC,
|
||||
ALPHA_DESC,
|
||||
DATE_ASC,
|
||||
DATE_DESC,
|
||||
DURATION_ASC,
|
||||
DURATION_DESC
|
||||
}
|
||||
|
||||
public static void sort(final Context context, final Rule rule, final boolean broadcastUpdate) {
|
||||
Comparator<FeedItem> comparator = null;
|
||||
|
||||
switch (rule) {
|
||||
case ALPHA_ASC:
|
||||
comparator = new Comparator<FeedItem>() {
|
||||
public int compare(FeedItem f1, FeedItem f2) {
|
||||
return f1.getTitle().compareTo(f2.getTitle());
|
||||
}
|
||||
};
|
||||
break;
|
||||
case ALPHA_DESC:
|
||||
comparator = new Comparator<FeedItem>() {
|
||||
public int compare(FeedItem f1, FeedItem f2) {
|
||||
return f2.getTitle().compareTo(f1.getTitle());
|
||||
}
|
||||
};
|
||||
break;
|
||||
case DATE_ASC:
|
||||
comparator = new Comparator<FeedItem>() {
|
||||
public int compare(FeedItem f1, FeedItem f2) {
|
||||
return f1.getPubDate().compareTo(f2.getPubDate());
|
||||
}
|
||||
};
|
||||
break;
|
||||
case DATE_DESC:
|
||||
comparator = new Comparator<FeedItem>() {
|
||||
public int compare(FeedItem f1, FeedItem f2) {
|
||||
return f2.getPubDate().compareTo(f1.getPubDate());
|
||||
}
|
||||
};
|
||||
break;
|
||||
case DURATION_ASC:
|
||||
comparator = new Comparator<FeedItem>() {
|
||||
public int compare(FeedItem f1, FeedItem f2) {
|
||||
FeedMedia f1Media = f1.getMedia();
|
||||
FeedMedia f2Media = f2.getMedia();
|
||||
int duration1 = f1Media != null ? f1Media.getDuration() : -1;
|
||||
int duration2 = f2Media != null ? f2Media.getDuration() : -1;
|
||||
|
||||
if (duration1 == -1 || duration2 == -1)
|
||||
return duration2 - duration1;
|
||||
else
|
||||
return duration1 - duration2;
|
||||
}
|
||||
};
|
||||
break;
|
||||
case DURATION_DESC:
|
||||
comparator = new Comparator<FeedItem>() {
|
||||
public int compare(FeedItem f1, FeedItem f2) {
|
||||
FeedMedia f1Media = f1.getMedia();
|
||||
FeedMedia f2Media = f2.getMedia();
|
||||
int duration1 = f1Media != null ? f1Media.getDuration() : -1;
|
||||
int duration2 = f2Media != null ? f2Media.getDuration() : -1;
|
||||
|
||||
return -1 * (duration1 - duration2);
|
||||
}
|
||||
};
|
||||
default:
|
||||
}
|
||||
|
||||
if (comparator != null) {
|
||||
DBWriter.sortQueue(context, comparator, broadcastUpdate);
|
||||
}
|
||||
}
|
||||
}
|
@ -28,7 +28,7 @@ import de.danoeh.antennapod.core.util.ShownotesProvider;
|
||||
public class Timeline {
|
||||
private static final String TAG = "Timeline";
|
||||
|
||||
private static final String WEBVIEW_STYLE = "@font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 11pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } a.timecode { color: #669900; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }";
|
||||
private static final String WEBVIEW_STYLE = "@font-face { font-family: 'Roboto-Light'; src: url('file:///android_asset/Roboto-Light.ttf'); } * { color: %s; font-family: roboto-Light; font-size: 13pt; } a { font-style: normal; text-decoration: none; font-weight: normal; color: #00A8DF; } a.timecode { color: #669900; } img { display: block; margin: 10 auto; max-width: %s; height: auto; } body { margin: %dpx %dpx %dpx %dpx; }";
|
||||
|
||||
|
||||
private ShownotesProvider shownotesProvider;
|
||||
|
BIN
core/src/main/res/drawable-hdpi/ic_settings_grey600_24dp.png
Normal file
BIN
core/src/main/res/drawable-hdpi/ic_settings_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 572 B |
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user