Merge branch 'master' of github.com:rharriso/AntennaPod
This commit is contained in:
commit
67aca21858
@ -9,6 +9,7 @@ wseemann
|
||||
hzulla
|
||||
andrewgaul
|
||||
peschmae0
|
||||
TomHennen
|
||||
|
||||
Translations:
|
||||
|
||||
|
@ -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
|
||||
|
@ -29,14 +29,12 @@ 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.FeedItem;
|
||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.util.QueueAccess;
|
||||
import de.danoeh.antennapod.menuhandler.MenuItemUtils;
|
||||
import de.danoeh.antennapod.menuhandler.NavDrawerActivity;
|
||||
|
||||
@ -64,9 +62,6 @@ public class QueueFragment extends Fragment {
|
||||
|
||||
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 +117,6 @@ public class QueueFragment extends Fragment {
|
||||
if (downloadObserver != null) {
|
||||
downloadObserver.onPause();
|
||||
}
|
||||
if (feedItemDialog != null) {
|
||||
feedItemDialogSavedInstance = feedItemDialog.save();
|
||||
}
|
||||
feedItemDialog = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -215,8 +206,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 +258,6 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
private DownloadObserver.Callback downloadObserverCallback = new DownloadObserver.Callback() {
|
||||
@ -281,9 +266,6 @@ public class QueueFragment extends Fragment {
|
||||
if (listAdapter != null && !blockDownloadObserverUpdate) {
|
||||
listAdapter.notifyDataSetChanged();
|
||||
}
|
||||
if (feedItemDialog != null && feedItemDialog.isShowing()) {
|
||||
feedItemDialog.updateMenuAppearance();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -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;
|
||||
@ -176,7 +177,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();
|
||||
@ -192,6 +193,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;
|
||||
}
|
||||
@ -373,6 +375,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,173 +1,177 @@
|
||||
<?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"
|
||||
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: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">
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
|
||||
|
||||
</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">
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
</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" />
|
||||
|
||||
<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>
|
||||
|
||||
<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" />
|
||||
|
||||
<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>
|
@ -11,9 +11,7 @@
|
||||
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" />
|
||||
|
||||
</RelativeLayout>
|
@ -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>
|
101
app/src/main/res/layout/feeditem_fragment_header.xml
Normal file
101
app/src/main/res/layout/feeditem_fragment_header.xml
Normal file
@ -0,0 +1,101 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
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">
|
||||
|
||||
|
||||
<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" />
|
||||
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
</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">
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
@ -6,6 +6,12 @@
|
||||
android:layout_height="@dimen/feeditemlist_header_height"
|
||||
tools:context="de.danoeh.antennapod.activity.MainActivity">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvBackground"
|
||||
style="@style/BigBlurryBackground"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imgvCover"
|
||||
android:layout_width="@dimen/thumbnail_length_onlinefeedview"
|
||||
@ -29,7 +35,7 @@
|
||||
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" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvTitle"
|
||||
@ -43,7 +49,10 @@
|
||||
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" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txtvAuthor"
|
||||
@ -56,7 +65,9 @@
|
||||
android:layout_toRightOf="@id/imgvCover"
|
||||
android:ellipsize="end"
|
||||
android:lines="1"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:shadowColor="@color/black"
|
||||
android:shadowRadius="3"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="@dimen/text_size_small" />
|
||||
|
||||
|
||||
|
@ -1,31 +1,38 @@
|
||||
<?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"
|
||||
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" />
|
||||
|
||||
<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"/>
|
||||
<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" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<include layout="@layout/nav_list"/>
|
||||
<include layout="@layout/nav_list" />
|
||||
|
||||
</android.support.v4.widget.DrawerLayout>
|
@ -1,14 +1,67 @@
|
||||
<?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"
|
||||
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" />
|
||||
|
||||
<View
|
||||
android:layout_width="@dimen/drawer_width"
|
||||
android:layout_height="1dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -10,5 +10,5 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="@color/gray" />
|
||||
android:background="?android:attr/listDivider" />
|
||||
</RelativeLayout>
|
@ -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>
|
@ -1,43 +1,61 @@
|
||||
<?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"
|
||||
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">
|
||||
|
||||
<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" />
|
||||
|
||||
<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">
|
||||
|
||||
<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" />
|
||||
|
||||
<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" />
|
||||
|
||||
</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" />
|
||||
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
@ -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>
|
||||
|
@ -40,6 +40,13 @@
|
||||
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"
|
||||
@ -96,6 +103,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();
|
||||
@ -734,8 +748,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 +790,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 +822,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 +993,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 +1006,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 +1018,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 +1050,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 +1061,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 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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
@ -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 |
BIN
core/src/main/res/drawable-hdpi/ic_settings_white_24dp.png
Normal file
BIN
core/src/main/res/drawable-hdpi/ic_settings_white_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 561 B |
BIN
core/src/main/res/drawable-xhdpi/ic_settings_grey600_24dp.png
Normal file
BIN
core/src/main/res/drawable-xhdpi/ic_settings_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 704 B |
BIN
core/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png
Normal file
BIN
core/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 737 B |
BIN
core/src/main/res/drawable-xxhdpi/ic_settings_grey600_24dp.png
Normal file
BIN
core/src/main/res/drawable-xxhdpi/ic_settings_grey600_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 994 B |
BIN
core/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png
Normal file
BIN
core/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 974 B |
@ -35,6 +35,7 @@
|
||||
<attr name="av_pause_big" format="reference"/>
|
||||
<attr name="av_ff_big" format="reference"/>
|
||||
<attr name="av_rew_big" format="reference"/>
|
||||
<attr name="ic_settings" format="reference"/>
|
||||
|
||||
<!-- Used in itemdescription -->
|
||||
<attr name="non_transparent_background" format="reference"/>
|
||||
|
@ -11,11 +11,12 @@
|
||||
<color name="download_failed_red">#CC0000</color>
|
||||
<color name="status_progress">#E033B5E5</color>
|
||||
<color name="status_playing">#E0EE5F52</color>
|
||||
<color name="overlay_dark">#262C31</color>
|
||||
<color name="overlay_light">#DDDDDD</color>
|
||||
<color name="overlay_dark">#2C2C2C</color>
|
||||
<color name="overlay_light">#FFFFFF</color>
|
||||
<color name="swipe_refresh_secondary_color_light">#EDEDED</color>
|
||||
<color name="swipe_refresh_secondary_color_dark">#060708</color>
|
||||
<color name="new_indicator_green">#669900</color>
|
||||
<color name="image_readability_tint">#80000000</color>
|
||||
|
||||
<!-- Use Gingerbread-orange -->
|
||||
<color name="selection_background_color_dark">#FEBB20</color>
|
||||
|
@ -33,4 +33,6 @@
|
||||
<dimen name="listitem_icon_leftpadding">16dp</dimen>
|
||||
<dimen name="listitem_icon_rightpadding">16dp</dimen>
|
||||
|
||||
<dimen name="audioplayer_playercontrols_length">64dp</dimen>
|
||||
|
||||
</resources>
|
@ -205,6 +205,7 @@
|
||||
<string name="services_label">Services</string>
|
||||
<string name="flattr_label">Flattr</string>
|
||||
<string name="pref_pauseOnHeadsetDisconnect_sum">Pause playback when the headphones are disconnected</string>
|
||||
<string name="pref_unpauseOnHeadsetReconnect_sum">Resume playback when the headphones are reconnected</string>
|
||||
<string name="pref_followQueue_sum">Jump to next queue item when playback completes</string>
|
||||
<string name="playback_pref">Playback</string>
|
||||
<string name="network_pref">Network</string>
|
||||
@ -214,6 +215,7 @@
|
||||
<string name="pref_followQueue_title">Continuous playback</string>
|
||||
<string name="pref_downloadMediaOnWifiOnly_title">WiFi media download</string>
|
||||
<string name="pref_pauseOnHeadsetDisconnect_title">Headphones disconnect</string>
|
||||
<string name="pref_unpauseOnHeadsetReconnect_title">Headphones reconnect</string>
|
||||
<string name="pref_mobileUpdate_title">Mobile updates</string>
|
||||
<string name="pref_mobileUpdate_sum">Allow updates over the mobile data connection</string>
|
||||
<string name="refreshing_label">Refreshing</string>
|
||||
@ -233,6 +235,8 @@
|
||||
<string name="pref_automatic_download_sum">Configure the automatic download of episodes.</string>
|
||||
<string name="pref_autodl_wifi_filter_title">Enable Wi-Fi filter</string>
|
||||
<string name="pref_autodl_wifi_filter_sum">Allow automatic download only for selected Wi-Fi networks.</string>
|
||||
<string name="pref_automatic_download_on_battery_title">Automatic download on battery</string>
|
||||
<string name="pref_automatic_download_on_battery_sum">Allow automatic download while on battery</string>
|
||||
<string name="pref_episode_cache_title">Episode cache</string>
|
||||
<string name="pref_theme_title_light">Light</string>
|
||||
<string name="pref_theme_title_dark">Dark</string>
|
||||
|
@ -40,6 +40,7 @@
|
||||
<item name="attr/av_pause_big">@drawable/ic_pause_grey600_36dp</item>
|
||||
<item name="attr/av_ff_big">@drawable/ic_fast_forward_grey600_36dp</item>
|
||||
<item name="attr/av_rew_big">@drawable/ic_fast_rewind_grey600_36dp</item>
|
||||
<item name="attr/ic_settings">@drawable/ic_settings_grey600_24dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AntennaPod.Dark" parent="@style/Theme.AppCompat">
|
||||
@ -80,6 +81,94 @@
|
||||
<item name="attr/av_pause_big">@drawable/ic_pause_white_36dp</item>
|
||||
<item name="attr/av_ff_big">@drawable/ic_fast_forward_white_36dp</item>
|
||||
<item name="attr/av_rew_big">@drawable/ic_fast_rewind_white_36dp</item>
|
||||
<item name="attr/ic_settings">@drawable/ic_settings_white_24dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AntennaPod.Light.NoTitle" parent="@style/Theme.AppCompat.Light.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="colorPrimary">@color/primary_light</item>
|
||||
<item name="colorAccent">@color/color_accent</item>
|
||||
<item name="attr/action_about">@drawable/ic_info_grey600_24dp</item>
|
||||
<item name="attr/action_search">@drawable/ic_search_grey600_24dp</item>
|
||||
<item name="attr/action_stream">@drawable/ic_settings_input_antenna_grey600_24dp</item>
|
||||
<item name="attr/av_download">@drawable/ic_file_download_grey600_24dp</item>
|
||||
<item name="attr/av_fast_forward">@drawable/ic_fast_forward_grey600_24dp</item>
|
||||
<item name="attr/av_pause">@drawable/ic_pause_grey600_24dp</item>
|
||||
<item name="attr/av_play">@drawable/ic_play_arrow_grey600_24dp</item>
|
||||
<item name="attr/av_rewind">@drawable/ic_fast_rewind_grey600_24dp</item>
|
||||
<item name="attr/content_discard">@drawable/ic_delete_grey600_24dp</item>
|
||||
<item name="attr/content_new">@drawable/ic_add_grey600_24dp</item>
|
||||
<item name="attr/device_access_time">@drawable/ic_timer_grey600_24dp</item>
|
||||
<item name="attr/location_web_site">@drawable/ic_web_grey600_24dp</item>
|
||||
<item name="attr/navigation_accept">@drawable/ic_done_grey600_24dp</item>
|
||||
<item name="attr/navigation_cancel">@drawable/ic_cancel_grey600_24dp</item>
|
||||
<item name="attr/navigation_expand">@drawable/ic_expand_more_grey600_36dp</item>
|
||||
<item name="attr/navigation_refresh">@drawable/ic_refresh_grey600_24dp</item>
|
||||
<item name="attr/navigation_up">@drawable/navigation_up</item>
|
||||
<item name="attr/navigation_shownotes">@drawable/ic_description_grey600_36dp</item>
|
||||
<item name="attr/navigation_chapters">@drawable/ic_toc_grey600_36dp</item>
|
||||
<item name="attr/social_share">@drawable/ic_share_grey600_24dp</item>
|
||||
<item name="attr/stat_playlist">@drawable/ic_list_grey600_24dp</item>
|
||||
<item name="attr/type_audio">@drawable/ic_hearing_grey600_18dp</item>
|
||||
<item name="attr/type_video">@drawable/ic_remove_red_eye_grey600_18dp</item>
|
||||
<item name="attr/non_transparent_background">@color/white</item>
|
||||
<item name="attr/overlay_background">@color/overlay_light</item>
|
||||
<item name="attr/overlay_drawable">@drawable/overlay_drawable</item>
|
||||
<item name="attr/dragview_background">@drawable/ic_drag_handle</item>
|
||||
<item name="attr/dragview_float_background">@color/white</item>
|
||||
<item name="attr/nav_drawer_background">@color/white</item>
|
||||
<item name="attr/ic_action_overflow">@drawable/ic_more_vert_grey600_24dp</item>
|
||||
<item name="attr/ic_new">@drawable/ic_new_releases_grey600_24dp</item>
|
||||
<item name="attr/ic_history">@drawable/ic_history_grey600_24dp</item>
|
||||
<item name="attr/av_play_big">@drawable/ic_play_arrow_grey600_36dp</item>
|
||||
<item name="attr/av_pause_big">@drawable/ic_pause_grey600_36dp</item>
|
||||
<item name="attr/av_ff_big">@drawable/ic_fast_forward_grey600_36dp</item>
|
||||
<item name="attr/av_rew_big">@drawable/ic_fast_rewind_grey600_36dp</item>
|
||||
<item name="attr/ic_settings">@drawable/ic_settings_grey600_24dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AntennaPod.Dark.NoTitle" parent="@style/Theme.AppCompat.NoActionBar">
|
||||
<item name="windowActionBar">false</item>
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="colorAccent">@color/color_accent</item>
|
||||
<item name="attr/action_about">@drawable/ic_info_white_24dp</item>
|
||||
<item name="attr/action_search">@drawable/ic_search_white_24dp</item>
|
||||
<item name="attr/action_stream">@drawable/ic_settings_input_antenna_white_24dp</item>
|
||||
<item name="attr/av_download">@drawable/ic_file_download_white_24dp</item>
|
||||
<item name="attr/av_fast_forward">@drawable/ic_fast_forward_white_24dp</item>
|
||||
<item name="attr/av_pause">@drawable/ic_pause_white_24dp</item>
|
||||
<item name="attr/av_play">@drawable/ic_play_arrow_white_24dp</item>
|
||||
<item name="attr/av_rewind">@drawable/ic_fast_rewind_white_24dp</item>
|
||||
<item name="attr/content_discard">@drawable/ic_delete_white_24dp</item>
|
||||
<item name="attr/content_new">@drawable/ic_add_white_24dp</item>
|
||||
<item name="attr/device_access_time">@drawable/ic_timer_white_24dp</item>
|
||||
<item name="attr/location_web_site">@drawable/ic_web_white_24dp</item>
|
||||
<item name="attr/navigation_accept">@drawable/ic_done_white_24dp</item>
|
||||
<item name="attr/navigation_cancel">@drawable/ic_cancel_white_24dp</item>
|
||||
<item name="attr/navigation_expand">@drawable/ic_expand_more_white_36dp</item>
|
||||
<item name="attr/navigation_refresh">@drawable/ic_refresh_white_24dp</item>
|
||||
<item name="attr/navigation_up">@drawable/navigation_up_dark</item>
|
||||
<item name="attr/navigation_shownotes">@drawable/ic_description_white_36dp</item>
|
||||
<item name="attr/navigation_chapters">@drawable/ic_toc_white_36dp</item>
|
||||
<item name="attr/social_share">@drawable/ic_share_white_24dp</item>
|
||||
<item name="attr/stat_playlist">@drawable/ic_list_white_24dp</item>
|
||||
<item name="attr/type_audio">@drawable/ic_hearing_white_18dp</item>
|
||||
<item name="attr/type_video">@drawable/ic_remove_red_eye_white_18dp</item>
|
||||
<item name="attr/non_transparent_background">@color/black</item>
|
||||
<item name="attr/overlay_background">@color/overlay_dark</item>
|
||||
<item name="attr/overlay_drawable">@drawable/overlay_drawable_dark</item>
|
||||
<item name="attr/dragview_background">@drawable/ic_drag_handle_dark</item>
|
||||
<item name="attr/dragview_float_background">@color/black</item>
|
||||
<item name="attr/nav_drawer_background">#3B3B3B</item>
|
||||
<item name="attr/ic_action_overflow">@drawable/ic_more_vert_white_24dp</item>
|
||||
<item name="attr/ic_new">@drawable/ic_new_releases_white_24dp</item>
|
||||
<item name="attr/ic_history">@drawable/ic_history_white_24dp</item>
|
||||
<item name="attr/av_play_big">@drawable/ic_play_arrow_white_36dp</item>
|
||||
<item name="attr/av_pause_big">@drawable/ic_pause_white_36dp</item>
|
||||
<item name="attr/av_ff_big">@drawable/ic_fast_forward_white_36dp</item>
|
||||
<item name="attr/av_rew_big">@drawable/ic_fast_rewind_white_36dp</item>
|
||||
<item name="attr/ic_settings">@drawable/ic_settings_white_24dp</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.AntennaPod.VideoPlayer" parent="@style/Theme.AntennaPod.Dark">
|
||||
@ -157,4 +246,10 @@
|
||||
<item name="android:text">@string/new_label</item>
|
||||
</style>
|
||||
|
||||
<style name="BigBlurryBackground">
|
||||
<item name="android:scaleType">centerCrop</item>
|
||||
<item name="android:tint">@color/image_readability_tint</item>
|
||||
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user