diff options
67 files changed, 1162 insertions, 522 deletions
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b457aa4e9..c84b0110b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,8 +2,8 @@ <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.danoeh.antennapod" android:installLocation="auto" - android:versionCode="1060501" - android:versionName="1.6.5-RC1"> + android:versionCode="1060595" + android:versionName="1.6.5"> <!-- Version code schema: "1.2.3-SNAPSHOT" -> 1020300 @@ -105,7 +105,15 @@ android:value="de.danoeh.antennapod.activity.MainActivity"/> </activity> - <activity android:name=".activity.FeedInfoActivity"> + <activity + android:name=".activity.FeedInfoActivity" + android:label="@string/feed_info_label"> + </activity> + + <activity + android:name=".activity.FeedSettingsActivity" + android:windowSoftInputMode="stateHidden" + android:label="@string/feed_settings_label"> </activity> <service @@ -222,7 +230,8 @@ <activity android:name=".activity.VideoplayerActivity" - android:configChanges="keyboardHidden|orientation" + android:configChanges="keyboardHidden|orientation|screenSize|screenLayout|smallestScreenSize" + android:supportsPictureInPicture="true" android:screenOrientation="sensorLandscape"> <meta-data android:name="android.support.PARENT_ACTIVITY" diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java index 8dea41b7c..6b1272b01 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java @@ -2,51 +2,37 @@ package de.danoeh.antennapod.activity; import android.content.ClipData; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; +import android.graphics.LightingColorFilter; import android.net.Uri; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; -import android.text.Editable; import android.text.TextUtils; -import android.text.TextWatcher; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.CheckBox; -import android.widget.EditText; import android.widget.ImageView; -import android.widget.RadioButton; -import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; - import com.bumptech.glide.Glide; import com.joanzapata.iconify.Iconify; - -import org.apache.commons.lang3.StringUtils; -import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; - import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.dialog.ConfirmationDialog; import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedFilter; -import de.danoeh.antennapod.core.feed.FeedPreferences; import de.danoeh.antennapod.core.glide.ApGlideSettings; +import de.danoeh.antennapod.core.glide.FastBlurTransformation; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.LangUtils; import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; +import org.apache.commons.lang3.StringUtils; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; @@ -59,7 +45,6 @@ public class FeedInfoActivity extends AppCompatActivity { public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; private static final String TAG = "FeedInfoActivity"; - private boolean autoDeleteChanged = false; private Feed feed; private ImageView imgvCover; @@ -70,15 +55,6 @@ public class FeedInfoActivity extends AppCompatActivity { private TextView lblAuthor; private TextView txtvAuthor; private TextView txtvUrl; - private EditText etxtUsername; - private EditText etxtPassword; - private EditText etxtFilterText; - private RadioButton rdoFilterInclude; - private RadioButton rdoFilterExclude; - private CheckBox cbxAutoDownload; - private CheckBox cbxKeepUpdated; - private Spinner spnAutoDelete; - private boolean filterInclude = true; private Subscription subscription; @@ -98,40 +74,6 @@ public class FeedInfoActivity extends AppCompatActivity { } }; - private boolean authInfoChanged = false; - - private final TextWatcher authTextWatcher = new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - authInfoChanged = true; - } - }; - - private boolean filterTextChanged = false; - - private final TextWatcher filterTextWatcher = new TextWatcher() { - @Override - public void beforeTextChanged(CharSequence s, int start, int count, int after) { - } - - @Override - public void onTextChanged(CharSequence s, int start, int before, int count) { - } - - @Override - public void afterTextChanged(Editable s) { - filterTextChanged = true; - } - }; - @Override protected void onCreate(Bundle savedInstanceState) { setTheme(UserPreferences.getTheme()); @@ -142,28 +84,20 @@ public class FeedInfoActivity extends AppCompatActivity { imgvCover = (ImageView) findViewById(R.id.imgvCover); txtvTitle = (TextView) findViewById(R.id.txtvTitle); + TextView txtvAuthorHeader = (TextView) findViewById(R.id.txtvAuthor); + ImageView imgvBackground = (ImageView) findViewById(R.id.imgvBackground); + findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE); + findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE); + // https://github.com/bumptech/glide/issues/529 + imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000)); + + txtvDescription = (TextView) findViewById(R.id.txtvDescription); lblLanguage = (TextView) findViewById(R.id.lblLanguage); txtvLanguage = (TextView) findViewById(R.id.txtvLanguage); lblAuthor = (TextView) findViewById(R.id.lblAuthor); - txtvAuthor = (TextView) findViewById(R.id.txtvAuthor); + txtvAuthor = (TextView) findViewById(R.id.txtvDetailsAuthor); txtvUrl = (TextView) findViewById(R.id.txtvUrl); - cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload); - cbxKeepUpdated = (CheckBox) findViewById(R.id.cbxKeepUpdated); - spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete); - etxtUsername = (EditText) findViewById(R.id.etxtUsername); - etxtPassword = (EditText) findViewById(R.id.etxtPassword); - etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText); - rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include); - rdoFilterInclude.setOnClickListener(v -> { - filterInclude = true; - filterTextChanged = true; - }); - rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude); - rdoFilterExclude.setOnClickListener(v -> { - filterInclude = false; - filterTextChanged = true; - }); txtvUrl.setOnClickListener(copyUrlToClipboard); @@ -179,7 +113,6 @@ public class FeedInfoActivity extends AppCompatActivity { Log.d(TAG, "Language is " + feed.getLanguage()); Log.d(TAG, "Author is " + feed.getAuthor()); Log.d(TAG, "URL is " + feed.getDownload_url()); - FeedPreferences prefs = feed.getPreferences(); Glide.with(FeedInfoActivity.this) .load(feed.getImageLocation()) .placeholder(R.color.light_gray) @@ -188,6 +121,14 @@ public class FeedInfoActivity extends AppCompatActivity { .fitCenter() .dontAnimate() .into(imgvCover); + Glide.with(FeedInfoActivity.this) + .load(feed.getImageLocation()) + .placeholder(R.color.image_readability_tint) + .error(R.color.image_readability_tint) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .transform(new FastBlurTransformation(FeedInfoActivity.this)) + .dontAnimate() + .into(imgvBackground); txtvTitle.setText(feed.getTitle()); @@ -205,6 +146,7 @@ public class FeedInfoActivity extends AppCompatActivity { if (!TextUtils.isEmpty(feed.getAuthor())) { txtvAuthor.setText(feed.getAuthor()); + txtvAuthorHeader.setText(feed.getAuthor()); } else { lblAuthor.setVisibility(View.GONE); txtvAuthor.setVisibility(View.GONE); @@ -218,76 +160,7 @@ public class FeedInfoActivity extends AppCompatActivity { txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}"); Iconify.addIcons(txtvUrl); - cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload()); - cbxAutoDownload.setChecked(prefs.getAutoDownload()); - cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> { - feed.getPreferences().setAutoDownload(checked); - feed.savePreferences(); - updateAutoDownloadSettings(); - ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedInfoActivity.this, - feed, checked); - dialog.createNewDialog().show(); - }); - cbxKeepUpdated.setChecked(prefs.getKeepUpdated()); - cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> { - feed.getPreferences().setKeepUpdated(checked); - feed.savePreferences(); - }); - spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { - FeedPreferences.AutoDeleteAction auto_delete_action; - switch (parent.getSelectedItemPosition()) { - case 0: - auto_delete_action = FeedPreferences.AutoDeleteAction.GLOBAL; - break; - case 1: - auto_delete_action = FeedPreferences.AutoDeleteAction.YES; - break; - case 2: - auto_delete_action = FeedPreferences.AutoDeleteAction.NO; - break; - default: // TODO - add exceptions here - return; - } - feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p - autoDeleteChanged = true; - } - - @Override - public void onNothingSelected(AdapterView<?> parent) { - // Another interface callback - } - }); - spnAutoDelete.setSelection(prefs.getAutoDeleteAction().ordinal()); - - etxtUsername.setText(prefs.getUsername()); - etxtPassword.setText(prefs.getPassword()); - - etxtUsername.addTextChangedListener(authTextWatcher); - etxtPassword.addTextChangedListener(authTextWatcher); - - FeedFilter filter = prefs.getFilter(); - if (filter.includeOnly()) { - etxtFilterText.setText(filter.getIncludeFilter()); - rdoFilterInclude.setChecked(true); - rdoFilterExclude.setChecked(false); - filterInclude = true; - } else if (filter.excludeOnly()) { - etxtFilterText.setText(filter.getExcludeFilter()); - rdoFilterInclude.setChecked(false); - rdoFilterExclude.setChecked(true); - filterInclude = false; - } else { - Log.d(TAG, "No filter set"); - rdoFilterInclude.setChecked(false); - rdoFilterExclude.setChecked(false); - etxtFilterText.setText(""); - } - etxtFilterText.addTextChangedListener(filterTextWatcher); - supportInvalidateOptionsMenu(); - updateAutoDownloadSettings(); }, error -> { Log.d(TAG, Log.getStackTraceString(error)); finish(); @@ -295,37 +168,6 @@ public class FeedInfoActivity extends AppCompatActivity { } @Override - protected void onPause() { - super.onPause(); - if (feed != null) { - FeedPreferences prefs = feed.getPreferences(); - if (authInfoChanged) { - Log.d(TAG, "Auth info changed, saving credentials"); - prefs.setUsername(etxtUsername.getText().toString()); - prefs.setPassword(etxtPassword.getText().toString()); - } - if (filterTextChanged) { - Log.d(TAG, "Filter info changed, saving..."); - String filterText = etxtFilterText.getText().toString(); - String includeString = ""; - String excludeString = ""; - if (filterInclude) { - includeString = filterText; - } else { - excludeString = filterText; - } - prefs.setFilter(new FeedFilter(includeString, excludeString)); - } - if (authInfoChanged || autoDeleteChanged || filterTextChanged) { - DBWriter.setFeedPreferences(prefs); - } - authInfoChanged = false; - autoDeleteChanged = false; - filterTextChanged = false; - } - } - - @Override public void onDestroy() { super.onDestroy(); if(subscription != null) { @@ -369,34 +211,4 @@ public class FeedInfoActivity extends AppCompatActivity { return super.onOptionsItemSelected(item); } } - - private void updateAutoDownloadSettings() { - if (feed != null && feed.getPreferences() != null) { - boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload(); - rdoFilterInclude.setEnabled(enabled); - rdoFilterExclude.setEnabled(enabled); - etxtFilterText.setEnabled(enabled); - } - } - - private static class ApplyToEpisodesDialog extends ConfirmationDialog { - - private final Feed feed; - private final boolean autoDownload; - - ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) { - super(context, R.string.auto_download_apply_to_items_title, - R.string.auto_download_apply_to_items_message); - this.feed = feed; - this.autoDownload = autoDownload; - setPositiveText(R.string.yes); - setNegativeText(R.string.no); - } - - @Override - public void onConfirmButtonPressed(DialogInterface dialog) { - DBWriter.setFeedsItemsAutoDownload(feed, autoDownload); - } - } - } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java new file mode 100644 index 000000000..5e15585a5 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedSettingsActivity.java @@ -0,0 +1,370 @@ +package de.danoeh.antennapod.activity; + +import android.content.ClipData; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.LightingColorFilter; +import android.net.Uri; +import android.os.Bundle; +import android.support.v7.app.AppCompatActivity; +import android.text.Editable; +import android.text.TextUtils; +import android.text.TextWatcher; +import android.util.Log; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; +import android.widget.AdapterView.OnItemSelectedListener; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.RadioButton; +import android.widget.Spinner; +import android.widget.TextView; +import android.widget.Toast; +import com.bumptech.glide.Glide; +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.dialog.ConfirmationDialog; +import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedFilter; +import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.glide.ApGlideSettings; +import de.danoeh.antennapod.core.glide.FastBlurTransformation; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DBWriter; +import de.danoeh.antennapod.core.storage.DownloadRequestException; +import de.danoeh.antennapod.core.util.IntentUtils; +import de.danoeh.antennapod.menuhandler.FeedMenuHandler; +import rx.Observable; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +/** + * Displays information about a feed. + */ +public class FeedSettingsActivity extends AppCompatActivity { + + public static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; + private static final String TAG = "FeedSettingsActivity"; + private boolean autoDeleteChanged = false; + private Feed feed; + + private ImageView imgvCover; + private TextView txtvTitle; + private EditText etxtUsername; + private EditText etxtPassword; + private EditText etxtFilterText; + private RadioButton rdoFilterInclude; + private RadioButton rdoFilterExclude; + private CheckBox cbxAutoDownload; + private CheckBox cbxKeepUpdated; + private Spinner spnAutoDelete; + private boolean filterInclude = true; + + private Subscription subscription; + + + private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() { + @Override + public void onClick(View v) { + if(feed != null && feed.getDownload_url() != null) { + String url = feed.getDownload_url(); + ClipData clipData = ClipData.newPlainText(url, url); + android.content.ClipboardManager cm = (android.content.ClipboardManager) FeedSettingsActivity.this + .getSystemService(Context.CLIPBOARD_SERVICE); + cm.setPrimaryClip(clipData); + Toast t = Toast.makeText(FeedSettingsActivity.this, R.string.copied_url_msg, Toast.LENGTH_SHORT); + t.show(); + } + } + }; + + private boolean authInfoChanged = false; + + private final TextWatcher authTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + authInfoChanged = true; + } + }; + + private boolean filterTextChanged = false; + + private final TextWatcher filterTextWatcher = new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + filterTextChanged = true; + } + }; + + @Override + protected void onCreate(Bundle savedInstanceState) { + setTheme(UserPreferences.getTheme()); + super.onCreate(savedInstanceState); + setContentView(R.layout.feedsettings); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); + long feedId = getIntent().getLongExtra(EXTRA_FEED_ID, -1); + + imgvCover = (ImageView) findViewById(R.id.imgvCover); + txtvTitle = (TextView) findViewById(R.id.txtvTitle); + TextView txtvAuthorHeader = (TextView) findViewById(R.id.txtvAuthor); + ImageView imgvBackground = (ImageView) findViewById(R.id.imgvBackground); + findViewById(R.id.butShowInfo).setVisibility(View.INVISIBLE); + findViewById(R.id.butShowSettings).setVisibility(View.INVISIBLE); + // https://github.com/bumptech/glide/issues/529 + imgvBackground.setColorFilter(new LightingColorFilter(0xff828282, 0x000000)); + + cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload); + cbxKeepUpdated = (CheckBox) findViewById(R.id.cbxKeepUpdated); + spnAutoDelete = (Spinner) findViewById(R.id.spnAutoDelete); + etxtUsername = (EditText) findViewById(R.id.etxtUsername); + etxtPassword = (EditText) findViewById(R.id.etxtPassword); + etxtFilterText = (EditText) findViewById(R.id.etxtEpisodeFilterText); + rdoFilterInclude = (RadioButton) findViewById(R.id.radio_filter_include); + rdoFilterInclude.setOnClickListener(v -> { + filterInclude = true; + filterTextChanged = true; + }); + rdoFilterExclude = (RadioButton) findViewById(R.id.radio_filter_exclude); + rdoFilterExclude.setOnClickListener(v -> { + filterInclude = false; + filterTextChanged = true; + }); + + subscription = Observable.fromCallable(()-> DBReader.getFeed(feedId)) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + if (result == null) { + Log.e(TAG, "Activity was started with invalid arguments"); + finish(); + } + feed = result; + FeedPreferences prefs = feed.getPreferences(); + Glide.with(FeedSettingsActivity.this) + .load(feed.getImageLocation()) + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate() + .into(imgvCover); + Glide.with(FeedSettingsActivity.this) + .load(feed.getImageLocation()) + .placeholder(R.color.image_readability_tint) + .error(R.color.image_readability_tint) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .transform(new FastBlurTransformation(FeedSettingsActivity.this)) + .dontAnimate() + .into(imgvBackground); + + txtvTitle.setText(feed.getTitle()); + + if (!TextUtils.isEmpty(feed.getAuthor())) { + txtvAuthorHeader.setText(feed.getAuthor()); + } + + cbxAutoDownload.setEnabled(UserPreferences.isEnableAutodownload()); + cbxAutoDownload.setChecked(prefs.getAutoDownload()); + cbxAutoDownload.setOnCheckedChangeListener((compoundButton, checked) -> { + feed.getPreferences().setAutoDownload(checked); + feed.savePreferences(); + updateAutoDownloadSettings(); + ApplyToEpisodesDialog dialog = new ApplyToEpisodesDialog(FeedSettingsActivity.this, + feed, checked); + dialog.createNewDialog().show(); + }); + cbxKeepUpdated.setChecked(prefs.getKeepUpdated()); + cbxKeepUpdated.setOnCheckedChangeListener((compoundButton, checked) -> { + feed.getPreferences().setKeepUpdated(checked); + feed.savePreferences(); + }); + spnAutoDelete.setOnItemSelectedListener(new OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) { + FeedPreferences.AutoDeleteAction auto_delete_action; + switch (parent.getSelectedItemPosition()) { + case 0: + auto_delete_action = FeedPreferences.AutoDeleteAction.GLOBAL; + break; + case 1: + auto_delete_action = FeedPreferences.AutoDeleteAction.YES; + break; + case 2: + auto_delete_action = FeedPreferences.AutoDeleteAction.NO; + break; + default: // TODO - add exceptions here + return; + } + feed.getPreferences().setAutoDeleteAction(auto_delete_action);// p + autoDeleteChanged = true; + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + // Another interface callback + } + }); + spnAutoDelete.setSelection(prefs.getAutoDeleteAction().ordinal()); + + etxtUsername.setText(prefs.getUsername()); + etxtPassword.setText(prefs.getPassword()); + + etxtUsername.addTextChangedListener(authTextWatcher); + etxtPassword.addTextChangedListener(authTextWatcher); + + FeedFilter filter = prefs.getFilter(); + if (filter.includeOnly()) { + etxtFilterText.setText(filter.getIncludeFilter()); + rdoFilterInclude.setChecked(true); + rdoFilterExclude.setChecked(false); + filterInclude = true; + } else if (filter.excludeOnly()) { + etxtFilterText.setText(filter.getExcludeFilter()); + rdoFilterInclude.setChecked(false); + rdoFilterExclude.setChecked(true); + filterInclude = false; + } else { + Log.d(TAG, "No filter set"); + rdoFilterInclude.setChecked(false); + rdoFilterExclude.setChecked(false); + etxtFilterText.setText(""); + } + etxtFilterText.addTextChangedListener(filterTextWatcher); + + supportInvalidateOptionsMenu(); + updateAutoDownloadSettings(); + }, error -> { + Log.d(TAG, Log.getStackTraceString(error)); + finish(); + }); + } + + @Override + protected void onPause() { + super.onPause(); + if (feed != null) { + FeedPreferences prefs = feed.getPreferences(); + if (authInfoChanged) { + Log.d(TAG, "Auth info changed, saving credentials"); + prefs.setUsername(etxtUsername.getText().toString()); + prefs.setPassword(etxtPassword.getText().toString()); + } + if (filterTextChanged) { + Log.d(TAG, "Filter info changed, saving..."); + String filterText = etxtFilterText.getText().toString(); + String includeString = ""; + String excludeString = ""; + if (filterInclude) { + includeString = filterText; + } else { + excludeString = filterText; + } + prefs.setFilter(new FeedFilter(includeString, excludeString)); + } + if (authInfoChanged || autoDeleteChanged || filterTextChanged) { + DBWriter.setFeedPreferences(prefs); + } + authInfoChanged = false; + autoDeleteChanged = false; + filterTextChanged = false; + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if(subscription != null) { + subscription.unsubscribe(); + } + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + super.onCreateOptionsMenu(menu); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.feedinfo, menu); + return true; + } + + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + menu.findItem(R.id.support_item).setVisible( + feed != null && feed.getPaymentLink() != null); + menu.findItem(R.id.share_link_item).setVisible(feed != null && feed.getLink() != null); + menu.findItem(R.id.visit_website_item).setVisible(feed != null && feed.getLink() != null && + IntentUtils.isCallable(this, new Intent(Intent.ACTION_VIEW, Uri.parse(feed.getLink())))); + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + finish(); + return true; + default: + try { + return FeedMenuHandler.onOptionsItemClicked(this, item, feed); + } catch (DownloadRequestException e) { + e.printStackTrace(); + DownloadRequestErrorDialogCreator.newRequestErrorDialog(this, + e.getMessage()); + } + return super.onOptionsItemSelected(item); + } + } + + private void updateAutoDownloadSettings() { + if (feed != null && feed.getPreferences() != null) { + boolean enabled = feed.getPreferences().getAutoDownload() && UserPreferences.isEnableAutodownload(); + rdoFilterInclude.setEnabled(enabled); + rdoFilterExclude.setEnabled(enabled); + etxtFilterText.setEnabled(enabled); + } + } + + private static class ApplyToEpisodesDialog extends ConfirmationDialog { + + private final Feed feed; + private final boolean autoDownload; + + ApplyToEpisodesDialog(Context context, Feed feed, boolean autoDownload) { + super(context, R.string.auto_download_apply_to_items_title, + R.string.auto_download_apply_to_items_message); + this.feed = feed; + this.autoDownload = autoDownload; + setPositiveText(R.string.yes); + setNegativeText(R.string.no); + } + + @Override + public void onConfirmButtonPressed(DialogInterface dialog) { + DBWriter.setFeedsItemsAutoDownload(feed, autoDownload); + } + } + +} diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java index 232ff4311..21e375435 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -46,6 +46,7 @@ import de.danoeh.antennapod.core.util.Flavors; import de.danoeh.antennapod.core.util.ShareUtils; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.Supplier; +import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; import de.danoeh.antennapod.core.util.playback.MediaPlayerError; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; @@ -225,9 +226,11 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements @Override protected void onPause() { - if(controller != null) { - controller.reinitServiceIfPaused(); - controller.pause(); + if (!PictureInPictureUtil.isInPictureInPictureMode(this)) { + if (controller != null) { + controller.reinitServiceIfPaused(); + controller.pause(); + } } super.onPause(); } @@ -379,6 +382,7 @@ public abstract class MediaplayerActivity extends CastEnabledActivity implements } else { startActivity(intent); } + finish(); return true; } else { if (media != null) { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java index 54758acf4..733f39b63 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/VideoplayerActivity.java @@ -10,27 +10,31 @@ import android.support.v4.view.WindowCompat; import android.support.v7.app.ActionBar; import android.util.Log; import android.util.Pair; +import android.view.Menu; +import android.view.MenuItem; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.View; import android.view.WindowManager; import android.view.animation.Animation; import android.view.animation.AnimationUtils; +import android.widget.FrameLayout; import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.SeekBar; - -import java.lang.ref.WeakReference; -import java.util.concurrent.atomic.AtomicBoolean; - import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.feed.MediaType; +import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.service.playback.PlayerStatus; +import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; import de.danoeh.antennapod.core.util.playback.ExternalMedia; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.view.AspectRatioVideoView; +import java.lang.ref.WeakReference; +import java.util.concurrent.atomic.AtomicBoolean; + /** * Activity for playing video files. */ @@ -52,6 +56,7 @@ public class VideoplayerActivity extends MediaplayerActivity { private LinearLayout videoOverlay; private AspectRatioVideoView videoview; private ProgressBar progressIndicator; + private FrameLayout videoframe; @Override protected void chooseTheme() { @@ -96,10 +101,27 @@ public class VideoplayerActivity extends MediaplayerActivity { } @Override + protected void onStop() { + super.onStop(); + if (!PictureInPictureUtil.isInPictureInPictureMode(this)) { + videoControlsHider.stop(); + } + } + + @Override + public void onUserLeaveHint () { + if (!PictureInPictureUtil.isInPictureInPictureMode(this) && UserPreferences.getVideoBackgroundBehavior() + == UserPreferences.VideoBackgroundBehavior.PICTURE_IN_PICTURE) { + compatEnterPictureInPicture(); + } + } + + @Override protected void onPause() { - videoControlsHider.stop(); - if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) { - controller.pause(); + if (!PictureInPictureUtil.isInPictureInPictureMode(this)) { + if (controller != null && controller.getStatus() == PlayerStatus.PLAYING) { + controller.pause(); + } } super.onPause(); } @@ -127,7 +149,7 @@ public class VideoplayerActivity extends MediaplayerActivity { @Override protected void setupGUI() { - if(isSetup.getAndSet(true)) { + if (isSetup.getAndSet(true)) { return; } super.setupGUI(); @@ -135,20 +157,23 @@ public class VideoplayerActivity extends MediaplayerActivity { controls = (LinearLayout) findViewById(R.id.controls); videoOverlay = (LinearLayout) findViewById(R.id.overlay); videoview = (AspectRatioVideoView) findViewById(R.id.videoview); + videoframe = (FrameLayout) findViewById(R.id.videoframe); progressIndicator = (ProgressBar) findViewById(R.id.progressIndicator); videoview.getHolder().addCallback(surfaceHolderCallback); - videoview.setOnTouchListener(onVideoviewTouched); + videoframe.setOnTouchListener(onVideoviewTouched); + videoOverlay.setOnTouchListener((view, motionEvent) -> true); // To suppress touches directly below the slider if (Build.VERSION.SDK_INT >= 16) { videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); } - if (Build.VERSION.SDK_INT >= 14) { - videoOverlay.setFitsSystemWindows(true); - } + videoOverlay.setFitsSystemWindows(true); setupVideoControlsToggler(); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + + videoframe.getViewTreeObserver().addOnGlobalLayoutListener(() -> + videoview.setAvailableSize(videoframe.getWidth(), videoframe.getHeight())); } @Override @@ -176,6 +201,9 @@ public class VideoplayerActivity extends MediaplayerActivity { private final View.OnTouchListener onVideoviewTouched = (v, event) -> { if (event.getAction() == MotionEvent.ACTION_DOWN) { + if (PictureInPictureUtil.isInPictureInPictureMode(this)) { + return true; + } videoControlsHider.stop(); toggleVideoControlsVisibility(); if (videoControlsShowing) { @@ -260,7 +288,9 @@ public class VideoplayerActivity extends MediaplayerActivity { public void surfaceDestroyed(SurfaceHolder holder) { Log.d(TAG, "Videosurface was destroyed"); videoSurfaceCreated = false; - if (controller != null && !destroyingDueToReload) { + if (controller != null && !destroyingDueToReload + && UserPreferences.getVideoBackgroundBehavior() + != UserPreferences.VideoBackgroundBehavior.CONTINUE_PLAYING) { controller.notifyVideoSurfaceAbandoned(); } } @@ -269,6 +299,13 @@ public class VideoplayerActivity extends MediaplayerActivity { @Override protected void onReloadNotification(int notificationCode) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && PictureInPictureUtil.isInPictureInPictureMode(this)) { + if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO + || notificationCode == PlaybackService.EXTRA_CODE_CAST) { + finish(); + } + return; + } if (notificationCode == PlaybackService.EXTRA_CODE_AUDIO) { Log.d(TAG, "ReloadNotification received, switching to Audioplayer now"); destroyingDueToReload = true; @@ -313,28 +350,31 @@ public class VideoplayerActivity extends MediaplayerActivity { videoOverlay.startAnimation(animation); controls.startAnimation(animation); } - if (Build.VERSION.SDK_INT >= 14) { - videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); - } + videoview.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); } @SuppressLint("NewApi") - private void hideVideoControls() { - final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out); - if (animation != null) { - videoOverlay.startAnimation(animation); - controls.startAnimation(animation); - } - if (Build.VERSION.SDK_INT >= 14) { - int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0; - getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | videoviewFlag); - videoOverlay.setFitsSystemWindows(true); + private void hideVideoControls(boolean showAnimation) { + if (showAnimation) { + final Animation animation = AnimationUtils.loadAnimation(this, R.anim.fade_out); + if (animation != null) { + videoOverlay.startAnimation(animation); + controls.startAnimation(animation); + } } + int videoviewFlag = (Build.VERSION.SDK_INT >= 16) ? View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION : 0; + getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_FULLSCREEN + | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | videoviewFlag); + videoOverlay.setFitsSystemWindows(true); + videoOverlay.setVisibility(View.GONE); controls.setVisibility(View.GONE); } + private void hideVideoControls() { + hideVideoControls(true); + } + @Override protected int getContentViewResourceId() { return R.layout.videoplayer_activity; @@ -350,6 +390,32 @@ public class VideoplayerActivity extends MediaplayerActivity { } } + @Override + public boolean onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + if (PictureInPictureUtil.supportsPictureInPicture(this)) { + menu.findItem(R.id.player_go_to_picture_in_picture).setVisible(true); + } + return true; + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == R.id.player_go_to_picture_in_picture) { + compatEnterPictureInPicture(); + return true; + } + return super.onOptionsItemSelected(item); + } + + private void compatEnterPictureInPicture() { + if (PictureInPictureUtil.supportsPictureInPicture(this) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + getSupportActionBar().hide(); + hideVideoControls(false); + enterPictureInPictureMode(); + } + } + private static class VideoControlsHider extends Handler { private static final int DELAY = 2500; @@ -362,7 +428,7 @@ public class VideoplayerActivity extends MediaplayerActivity { private final Runnable hideVideoControls = () -> { VideoplayerActivity vpa = activity != null ? activity.get() : null; - if(vpa == null) { + if (vpa == null) { return; } if (vpa.videoControlsShowing) { diff --git a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java index 1ab60ef61..83dd3fe9c 100644 --- a/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java +++ b/app/src/main/java/de/danoeh/antennapod/config/PlaybackServiceCallbacksImpl.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.config; import android.content.Context; import android.content.Intent; +import android.os.Build; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.AudioplayerActivity; import de.danoeh.antennapod.activity.CastplayerActivity; @@ -18,7 +19,11 @@ public class PlaybackServiceCallbacksImpl implements PlaybackServiceCallbacks { return new Intent(context, CastplayerActivity.class); } if (mediaType == MediaType.VIDEO) { - return new Intent(context, VideoplayerActivity.class); + Intent i = new Intent(context, VideoplayerActivity.class); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + i.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT); + } + return i; } else { return new Intent(context, AudioplayerActivity.class); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java index f37ecd5e7..f59bc88bf 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -140,18 +140,7 @@ public class CompletedDownloadsFragment extends ListFragment { super.onCreateOptionsMenu(menu, inflater); if(items != null) { inflater.inflate(R.menu.downloads_completed, menu); - MenuItem episodeActions = menu.findItem(R.id.episode_actions); - if(items.size() > 0) { - int[] attrs = {R.attr.action_bar_icon_color}; - TypedArray ta = getActivity().obtainStyledAttributes(UserPreferences.getTheme(), attrs); - int textColor = ta.getColor(0, Color.GRAY); - ta.recycle(); - episodeActions.setIcon(new IconDrawable(getActivity(), - FontAwesomeIcons.fa_gears).color(textColor).actionBarSize()); - episodeActions.setVisible(true); - } else { - episodeActions.setVisible(false); - } + menu.findItem(R.id.episode_actions).setVisible(items.size() > 0); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java index 8928d2bf3..417ecff89 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java @@ -106,7 +106,7 @@ public class EpisodesFragment extends Fragment { case POS_ALL_EPISODES: return resources.getString(R.string.all_episodes_short_label); case POS_NEW_EPISODES: - return resources.getString(R.string.new_label); + return resources.getString(R.string.new_episodes_label); case POS_FAV_EPISODES: return resources.getString(R.string.favorite_episodes_label); default: diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java index a9bf39632..4ef26ad6c 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ExternalPlayerFragment.java @@ -209,6 +209,10 @@ public class ExternalPlayerFragment extends Fragment { } private void onPositionObserverUpdate() { + if (controller.getPosition() == PlaybackService.INVALID_TIME + || controller.getDuration() == PlaybackService.INVALID_TIME) { + return; + } mProgressBar.setProgress((int) ((double) controller.getPosition() / controller.getDuration() * 100)); } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java index 890f31f57..83d6f9615 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -31,6 +31,7 @@ import com.joanzapata.iconify.Iconify; import com.joanzapata.iconify.fonts.FontAwesomeIcons; import com.joanzapata.iconify.widget.IconTextView; +import de.danoeh.antennapod.activity.FeedSettingsActivity; import org.apache.commons.lang3.Validate; import java.util.List; @@ -221,13 +222,6 @@ public class ItemlistFragment extends ListFragment { menu.findItem(R.id.share_link_item).setVisible(false); menu.findItem(R.id.visit_website_item).setVisible(false); } - int[] attrs = { R.attr.action_bar_icon_color }; - TypedArray ta = getActivity().obtainStyledAttributes(UserPreferences.getTheme(), attrs); - int textColor = ta.getColor(0, Color.GRAY); - ta.recycle(); - - menu.findItem(R.id.episode_actions).setIcon(new IconDrawable(getActivity(), - FontAwesomeIcons.fa_gears).color(textColor).actionBarSize()); isUpdatingFeed = MenuItemUtils.updateRefreshMenuItem(menu, R.id.refresh_item, updateRefreshMenuItemChecker); } @@ -497,6 +491,7 @@ public class ItemlistFragment extends ListFragment { imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground); imgvCover = (ImageView) header.findViewById(R.id.imgvCover); ImageButton butShowInfo = (ImageButton) header.findViewById(R.id.butShowInfo); + ImageButton butShowSettings = (ImageButton) header.findViewById(R.id.butShowSettings); txtvInformation = (TextView) header.findViewById(R.id.txtvInformation); txtvFailure = (IconTextView) header.findViewById(R.id.txtvFailure); @@ -509,10 +504,12 @@ public class ItemlistFragment extends ListFragment { loadFeedImage(); - butShowInfo.setOnClickListener(v -> { + butShowInfo.setOnClickListener(v -> showFeedInfo()); + imgvCover.setOnClickListener(v -> showFeedInfo()); + butShowSettings.setOnClickListener(v -> { if (viewsCreated && itemsLoaded) { - Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); - startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, + Intent startIntent = new Intent(getActivity(), FeedSettingsActivity.class); + startIntent.putExtra(FeedSettingsActivity.EXTRA_FEED_ID, feed.getId()); startActivity(startIntent); } @@ -520,6 +517,15 @@ public class ItemlistFragment extends ListFragment { headerCreated = true; } + private void showFeedInfo() { + if (viewsCreated && itemsLoaded) { + Intent startIntent = new Intent(getActivity(), FeedInfoActivity.class); + startIntent.putExtra(FeedInfoActivity.EXTRA_FEED_ID, + feed.getId()); + startActivity(startIntent); + } + } + private void loadFeedImage() { Glide.with(getActivity()) .load(feed.getImageLocation()) diff --git a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java index 06d88156c..407ab0bdb 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -42,6 +42,7 @@ import android.widget.Toast; import com.afollestad.materialdialogs.MaterialDialog; import de.danoeh.antennapod.activity.AboutActivity; +import com.afollestad.materialdialogs.prefs.MaterialListPreference; import de.danoeh.antennapod.activity.ImportExportActivity; import de.danoeh.antennapod.activity.MediaplayerActivity; import de.danoeh.antennapod.activity.OpmlImportFromPathActivity; @@ -55,6 +56,7 @@ import de.danoeh.antennapod.dialog.AutoFlattrPreferenceDialog; import de.danoeh.antennapod.dialog.GpodnetSetHostnameDialog; import de.danoeh.antennapod.dialog.ProxyDialog; import de.danoeh.antennapod.dialog.VariableSpeedDialog; +import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil; import org.apache.commons.lang3.ArrayUtils; import java.io.File; @@ -389,6 +391,11 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc MediaplayerActivity.showSkipPreference(activity, MediaplayerActivity.SkipDirection.SKIP_FORWARD); return true; }); + if (!PictureInPictureUtil.supportsPictureInPicture(activity)) { + MaterialListPreference behaviour = (MaterialListPreference) ui.findPreference(UserPreferences.PREF_VIDEO_BEHAVIOR); + behaviour.setEntries(R.array.video_background_behavior_options_without_pip); + behaviour.setEntryValues(R.array.video_background_behavior_values_without_pip); + } } private void setupDownloadsScreen() { diff --git a/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java b/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java index f930c912a..e79389fb3 100644 --- a/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java +++ b/app/src/main/java/de/danoeh/antennapod/view/AspectRatioVideoView.java @@ -25,6 +25,8 @@ public class AspectRatioVideoView extends VideoView { private int mVideoWidth; private int mVideoHeight; + private float mAvailableWidth = -1; + private float mAvailableHeight = -1; public AspectRatioVideoView(Context context) { this(context, null); @@ -48,8 +50,13 @@ public class AspectRatioVideoView extends VideoView { return; } - float heightRatio = (float) mVideoHeight / (float) getHeight(); - float widthRatio = (float) mVideoWidth / (float) getWidth(); + if (mAvailableWidth < 0 || mAvailableHeight < 0) { + mAvailableWidth = getWidth(); + mAvailableHeight = getHeight(); + } + + float heightRatio = (float) mVideoHeight / mAvailableHeight; + float widthRatio = (float) mVideoWidth / mAvailableWidth; int scaledHeight; int scaledWidth; @@ -94,4 +101,15 @@ public class AspectRatioVideoView extends VideoView { invalidate(); } + /** + * Sets the maximum size that the view might expand to + * @param width + * @param height + */ + public void setAvailableSize(float width, float height) { + mAvailableWidth = width; + mAvailableHeight = height; + requestLayout(); + } + } diff --git a/app/src/main/play/ca/listing/video b/app/src/main/play/ca/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/ca/listing/video +++ /dev/null diff --git a/app/src/main/play/contactPhone b/app/src/main/play/contactPhone deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/contactPhone +++ /dev/null diff --git a/app/src/main/play/cs-CZ/listing/video b/app/src/main/play/cs-CZ/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/cs-CZ/listing/video +++ /dev/null diff --git a/app/src/main/play/da-DK/listing/video b/app/src/main/play/da-DK/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/da-DK/listing/video +++ /dev/null diff --git a/app/src/main/play/de-DE/listing/video b/app/src/main/play/de-DE/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/de-DE/listing/video +++ /dev/null diff --git a/app/src/main/play/en-US/listing/featureGraphic/feature-graphic.png b/app/src/main/play/en-US/listing/featureGraphic/feature-graphic.png Binary files differnew file mode 100644 index 000000000..3b5261b28 --- /dev/null +++ b/app/src/main/play/en-US/listing/featureGraphic/feature-graphic.png diff --git a/app/src/main/play/en-US/listing/video b/app/src/main/play/en-US/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/en-US/listing/video +++ /dev/null diff --git a/app/src/main/play/es-ES/listing/video b/app/src/main/play/es-ES/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/es-ES/listing/video +++ /dev/null diff --git a/app/src/main/play/fr-FR/listing/video b/app/src/main/play/fr-FR/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/fr-FR/listing/video +++ /dev/null diff --git a/app/src/main/play/hi-IN/listing/video b/app/src/main/play/hi-IN/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/hi-IN/listing/video +++ /dev/null diff --git a/app/src/main/play/it-IT/listing/video b/app/src/main/play/it-IT/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/it-IT/listing/video +++ /dev/null diff --git a/app/src/main/play/iw-IL/listing/video b/app/src/main/play/iw-IL/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/iw-IL/listing/video +++ /dev/null diff --git a/app/src/main/play/ja-JP/listing/video b/app/src/main/play/ja-JP/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/ja-JP/listing/video +++ /dev/null diff --git a/app/src/main/play/ko-KR/listing/video b/app/src/main/play/ko-KR/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/ko-KR/listing/video +++ /dev/null diff --git a/app/src/main/play/nl-NL/listing/video b/app/src/main/play/nl-NL/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/nl-NL/listing/video +++ /dev/null diff --git a/app/src/main/play/pl-PL/listing/video b/app/src/main/play/pl-PL/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/pl-PL/listing/video +++ /dev/null diff --git a/app/src/main/play/pt-BR/listing/video b/app/src/main/play/pt-BR/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/pt-BR/listing/video +++ /dev/null diff --git a/app/src/main/play/pt-PT/listing/video b/app/src/main/play/pt-PT/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/pt-PT/listing/video +++ /dev/null diff --git a/app/src/main/play/ro/listing/video b/app/src/main/play/ro/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/ro/listing/video +++ /dev/null diff --git a/app/src/main/play/ru-RU/listing/video b/app/src/main/play/ru-RU/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/ru-RU/listing/video +++ /dev/null diff --git a/app/src/main/play/sv-SE/listing/video b/app/src/main/play/sv-SE/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/sv-SE/listing/video +++ /dev/null diff --git a/app/src/main/play/tr-TR/listing/video b/app/src/main/play/tr-TR/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/tr-TR/listing/video +++ /dev/null diff --git a/app/src/main/play/uk/listing/video b/app/src/main/play/uk/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/uk/listing/video +++ /dev/null diff --git a/app/src/main/play/zh-CN/listing/video b/app/src/main/play/zh-CN/listing/video deleted file mode 100644 index e69de29bb..000000000 --- a/app/src/main/play/zh-CN/listing/video +++ /dev/null diff --git a/app/src/main/res/layout/feedinfo.xml b/app/src/main/res/layout/feedinfo.xml index 549c8ce22..bb544d289 100644 --- a/app/src/main/res/layout/feedinfo.xml +++ b/app/src/main/res/layout/feedinfo.xml @@ -6,48 +6,7 @@ android:layout_height="match_parent" android:orientation="vertical"> - <RelativeLayout - android:id="@+id/header" - android:focusable="true" - android:focusableInTouchMode="true" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:gravity="center_vertical" - android:layout_marginLeft="16dp" - android:layout_marginRight="16dp" - android:layout_marginTop="8dp"> - - <ImageView - android:id="@+id/imgvCover" - android:contentDescription="@string/cover_label" - android:layout_width="80dp" - android:layout_height="80dp" - android:layout_alignParentLeft="true" - android:layout_alignParentTop="true" - tools:src="@drawable/ic_stat_antenna_default" - tools:background="@android:color/holo_green_dark"/> - - <TextView - android:id="@+id/txtvTitle" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_centerVertical="true" - android:layout_marginLeft="8dp" - android:layout_alignTop="@id/imgvCover" - android:layout_toRightOf="@id/imgvCover" - android:layout_alignBottom="@id/imgvCover" - style="@style/AntennaPod.TextView.Heading" - tools:text="Feed title" - tools:background="@android:color/holo_green_dark"/> - - <View - android:id="@+id/divider" - android:layout_width="match_parent" - android:layout_height="1dp" - android:layout_below="@id/imgvCover" - android:layout_marginTop="8dp" - android:background="@color/holo_blue_light"/> - </RelativeLayout> + <include layout="@layout/feeditemlist_header" /> <ScrollView android:id="@+id/scrollView" @@ -57,7 +16,8 @@ android:scrollbarStyle="outsideOverlay" android:paddingLeft="16dp" android:paddingRight="16dp" - android:paddingBottom="8dp"> + android:paddingBottom="8dp" + android:clipToPadding="false"> <LinearLayout android:layout_width="match_parent" @@ -86,9 +46,10 @@ tools:background="@android:color/holo_red_light"/> <TextView - android:id="@+id/txtvAuthor" + android:id="@+id/txtvDetailsAuthor" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:textIsSelectable="true" app:layout_row="0" app:layout_column="1" tools:text="Daniel Oeh" @@ -111,6 +72,7 @@ android:id="@+id/txtvLanguage" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:textIsSelectable="true" app:layout_row="1" app:layout_column="1" tools:text="English" @@ -133,6 +95,7 @@ android:layout_width="0dp" android:layout_height="wrap_content" android:paddingBottom="4dp" + android:background="?attr/selectableItemBackground" app:layout_row="2" app:layout_column="1" app:layout_gravity="fill" @@ -143,198 +106,6 @@ </android.support.v7.widget.GridLayout> <TextView - android:id="@+id/txtvSettings" - style="@style/AntennaPod.TextView.Heading" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:text="@string/podcast_settings_label" - android:layout_marginTop="8dp"/> - - <android.support.v7.widget.GridLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - app:columnCount="2" - app:rowCount="1"> - - <TextView - android:id="@+id/txtvFeedAutoDelete" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/auto_delete_label" - app:layout_row="0" - app:layout_column="0" - app:layout_gravity="center_vertical" - android:layout_marginRight="10dp" /> - - <Spinner - android:layout_width="wrap_content" - android:layout_height="match_parent" - android:id="@+id/spnAutoDelete" - android:entries="@array/spnAutoDeleteItems" - android:layout_marginTop="8dp" - app:layout_row="0" - app:layout_column="1" - android:spinnerMode="dropdown" - app:layout_gravity="center" - android:dropDownWidth="wrap_content" - android:clickable="true" /> - </android.support.v7.widget.GridLayout> - - <CheckBox - android:id="@+id/cbxKeepUpdated" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:text="@string/keep_updated" - android:enabled="true" - android:textColor="?android:attr/textColorPrimary" - tools:background="@android:color/holo_red_light" - android:checked="true" /> - - <TextView - android:id="@+id/txtvAuthentication" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:text="@string/authentication_label" - android:textSize="@dimen/text_size_medium" - android:textColor="?android:attr/textColorPrimary"/> - - <TextView - android:id="@+id/txtvAuthenticationDescr" - android:text="@string/authentication_descr" - android:textSize="@dimen/text_size_small" - android:textColor="?android:attr/textColorPrimary" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp"/> - - <android.support.v7.widget.GridLayout - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - app:columnCount="2" - app:rowCount="3" - android:layout_gravity="center_horizontal"> - - <TextView - android:id="@+id/txtvUsername" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginRight="8dp" - android:layout_marginBottom="8dp" - app:layout_row="0" - app:layout_column="0" - android:text="@string/username_label" - android:textColor="?android:attr/textColorPrimary"/> - - <EditText - android:id="@+id/etxtUsername" - android:layout_width="140sp" - android:layout_height="wrap_content" - app:layout_row="0" - app:layout_column="1" - android:hint="@string/username_label" - android:focusable="true" - android:focusableInTouchMode="true" - android:cursorVisible="true"/> - - <TextView - android:id="@+id/txtvPassword" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginRight="8dp" - android:layout_marginBottom="8dp" - app:layout_row="1" - app:layout_column="0" - android:text="@string/password_label" - android:textColor="?android:attr/textColorPrimary" /> - - <EditText - android:id="@+id/etxtPassword" - android:layout_width="140sp" - android:layout_height="wrap_content" - app:layout_row="1" - app:layout_column="1" - android:hint="@string/password_label" - android:inputType="textPassword" - android:focusable="true" - android:focusableInTouchMode="true" - android:cursorVisible="true"/> - - </android.support.v7.widget.GridLayout> - - <TextView - android:id="@+id/txtvAutoDownloadSettings" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:text="@string/auto_download_settings_label" - android:textSize="@dimen/text_size_medium" - android:textColor="?android:attr/textColorPrimary"/> - - <CheckBox - android:id="@+id/cbxAutoDownload" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:text="@string/auto_download_label" - android:enabled="false" - android:textColor="?android:attr/textColorPrimary" - tools:background="@android:color/holo_red_light" - android:checked="false" /> - - <TextView - android:id="@+id/txtvEpisodeFilters" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:text="@string/episode_filters_label" - android:textSize="@dimen/text_size_medium" - android:textColor="?android:attr/textColorPrimary"/> - - <TextView - android:id="@+id/txtvEpisodeFiltersDescription" - android:text="@string/episode_filters_description" - android:textSize="@dimen/text_size_small" - android:textColor="?android:attr/textColorPrimary" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="8dp"/> - - <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/radio_filter_group" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:gravity="center" - android:orientation="horizontal"> - <RadioButton android:id="@+id/radio_filter_include" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/episode_filters_include" /> - <RadioButton android:id="@+id/radio_filter_exclude" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="@string/episode_filters_exclude" /> - </RadioGroup> - - <EditText - android:id="@+id/etxtEpisodeFilterText" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:lines="8" - android:minLines="1" - android:maxLines="20" - android:scrollbars="vertical" - android:hint="@string/episode_filters_hint" - android:focusable="true" - android:focusableInTouchMode="true" - android:cursorVisible="true"/> - - <TextView style="@style/AntennaPod.TextView.Heading" android:layout_width="match_parent" android:layout_height="wrap_content" @@ -346,6 +117,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="8dp" + android:textIsSelectable="true" android:text="@string/design_time_lorem_ipsum" tools:background="@android:color/holo_green_dark"/> diff --git a/app/src/main/res/layout/feeditemlist_header.xml b/app/src/main/res/layout/feeditemlist_header.xml index c6ba80e2a..1478e35d7 100644 --- a/app/src/main/res/layout/feeditemlist_header.xml +++ b/app/src/main/res/layout/feeditemlist_header.xml @@ -30,11 +30,10 @@ <ImageButton android:id="@+id/butShowInfo" - android:layout_width="48dp" - android:layout_height="48dp" + android:layout_width="40dp" + android:layout_height="40dp" android:layout_alignParentRight="true" android:layout_alignParentTop="true" - android:layout_marginBottom="16dp" android:layout_marginLeft="16dp" android:layout_marginTop="8dp" android:background="?attr/selectableItemBackground" @@ -42,6 +41,19 @@ android:src="@drawable/ic_info_white_24dp" tools:background="@android:color/holo_green_dark"/> + <ImageButton + android:id="@+id/butShowSettings" + android:layout_width="40dp" + android:layout_height="40dp" + android:background="?attr/selectableItemBackground" + android:contentDescription="@string/show_feed_settings_label" + android:src="@drawable/ic_settings_white_24dp" + tools:background="@android:color/holo_green_dark" + android:layout_below="@+id/butShowInfo" + android:layout_marginBottom="16dp" + android:layout_alignParentRight="true" + android:layout_alignParentEnd="true"/> + <TextView android:id="@+id/txtvTitle" style="@style/AntennaPod.TextView.Heading" @@ -63,12 +75,12 @@ <TextView android:id="@+id/txtvAuthor" - android:layout_width="wrap_content" + android:layout_width="0dip" android:layout_height="wrap_content" android:layout_below="@id/txtvTitle" android:layout_marginBottom="16dp" android:layout_marginLeft="16dp" - android:layout_marginRight="16dp" + android:layout_toLeftOf="@id/butShowSettings" android:layout_toRightOf="@id/imgvCover" android:ellipsize="end" android:lines="1" @@ -77,7 +89,7 @@ android:textColor="@color/white" android:textSize="@dimen/text_size_small" tools:text="Podcast author" - tools:background="@android:color/holo_green_dark" /> + tools:background="@android:color/holo_green_dark"/> <com.joanzapata.iconify.widget.IconTextView android:id="@+id/txtvFailure" diff --git a/app/src/main/res/layout/feedsettings.xml b/app/src/main/res/layout/feedsettings.xml new file mode 100644 index 000000000..23d116d4c --- /dev/null +++ b/app/src/main/res/layout/feedsettings.xml @@ -0,0 +1,215 @@ +<?xml version="1.0" encoding="utf-8"?> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <include layout="@layout/feeditemlist_header" /> + + <ScrollView + android:id="@+id/scrollView" + android:layout_width="match_parent" + android:layout_height="0dp" + android:layout_weight="1" + android:scrollbarStyle="outsideOverlay" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:paddingBottom="8dp" + android:clipToPadding="false"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <android.support.v7.widget.GridLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + app:columnCount="2" + app:rowCount="1"> + + <TextView + android:id="@+id/txtvFeedAutoDelete" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/auto_delete_label" + app:layout_row="0" + app:layout_column="0" + app:layout_gravity="center_vertical" + android:layout_marginRight="10dp" /> + + <Spinner + android:layout_width="wrap_content" + android:layout_height="match_parent" + android:id="@+id/spnAutoDelete" + android:entries="@array/spnAutoDeleteItems" + android:layout_marginTop="8dp" + app:layout_row="0" + app:layout_column="1" + android:spinnerMode="dropdown" + app:layout_gravity="center" + android:dropDownWidth="wrap_content" + android:clickable="true" /> + </android.support.v7.widget.GridLayout> + + <CheckBox + android:id="@+id/cbxKeepUpdated" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/keep_updated" + android:enabled="true" + android:textColor="?android:attr/textColorPrimary" + tools:background="@android:color/holo_red_light" + android:checked="true" /> + + <TextView + android:id="@+id/txtvAuthentication" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/authentication_label" + android:textSize="@dimen/text_size_medium" + android:textColor="?android:attr/textColorPrimary"/> + + <TextView + android:id="@+id/txtvAuthenticationDescr" + android:text="@string/authentication_descr" + android:textSize="@dimen/text_size_small" + android:textColor="?android:attr/textColorPrimary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp"/> + + <android.support.v7.widget.GridLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + app:columnCount="2" + app:rowCount="3" + android:layout_gravity="center_horizontal"> + + <TextView + android:id="@+id/txtvUsername" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="8dp" + android:layout_marginBottom="8dp" + app:layout_row="0" + app:layout_column="0" + android:text="@string/username_label" + android:textColor="?android:attr/textColorPrimary"/> + + <EditText + android:id="@+id/etxtUsername" + android:layout_width="140sp" + android:layout_height="wrap_content" + app:layout_row="0" + app:layout_column="1" + android:hint="@string/username_label" + android:focusable="true" + android:focusableInTouchMode="true" + android:cursorVisible="true"/> + + <TextView + android:id="@+id/txtvPassword" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginRight="8dp" + android:layout_marginBottom="8dp" + app:layout_row="1" + app:layout_column="0" + android:text="@string/password_label" + android:textColor="?android:attr/textColorPrimary" /> + + <EditText + android:id="@+id/etxtPassword" + android:layout_width="140sp" + android:layout_height="wrap_content" + app:layout_row="1" + app:layout_column="1" + android:hint="@string/password_label" + android:inputType="textPassword" + android:focusable="true" + android:focusableInTouchMode="true" + android:cursorVisible="true"/> + + </android.support.v7.widget.GridLayout> + + <TextView + android:id="@+id/txtvAutoDownloadSettings" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/auto_download_settings_label" + android:textSize="@dimen/text_size_medium" + android:textColor="?android:attr/textColorPrimary"/> + + <CheckBox + android:id="@+id/cbxAutoDownload" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/auto_download_label" + android:enabled="false" + android:textColor="?android:attr/textColorPrimary" + tools:background="@android:color/holo_red_light" + android:checked="false" /> + + <TextView + android:id="@+id/txtvEpisodeFilters" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:text="@string/episode_filters_label" + android:textSize="@dimen/text_size_medium" + android:textColor="?android:attr/textColorPrimary"/> + + <TextView + android:id="@+id/txtvEpisodeFiltersDescription" + android:text="@string/episode_filters_description" + android:textSize="@dimen/text_size_small" + android:textColor="?android:attr/textColorPrimary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp"/> + + <RadioGroup xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/radio_filter_group" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:gravity="center" + android:orientation="horizontal"> + <RadioButton android:id="@+id/radio_filter_include" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/episode_filters_include" /> + <RadioButton android:id="@+id/radio_filter_exclude" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/episode_filters_exclude" /> + </RadioGroup> + + <EditText + android:id="@+id/etxtEpisodeFilterText" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:lines="8" + android:minLines="1" + android:maxLines="20" + android:scrollbars="vertical" + android:hint="@string/episode_filters_hint" + android:focusable="true" + android:focusableInTouchMode="true" + android:cursorVisible="true"/> + + </LinearLayout> + + </ScrollView> + +</LinearLayout>
\ No newline at end of file diff --git a/app/src/main/res/layout/videoplayer_activity.xml b/app/src/main/res/layout/videoplayer_activity.xml index 4db663e19..10fbf8f49 100644 --- a/app/src/main/res/layout/videoplayer_activity.xml +++ b/app/src/main/res/layout/videoplayer_activity.xml @@ -3,7 +3,8 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/black" - android:orientation="vertical"> + android:orientation="vertical" + android:id="@+id/videoframe"> <de.danoeh.antennapod.view.AspectRatioVideoView android:id="@+id/videoview" @@ -103,6 +104,7 @@ android:layout_height="wrap_content" android:layout_toLeftOf="@+id/txtvLength" android:layout_toRightOf="@+id/txtvPosition" + android:layout_centerInParent="true" android:max="500" /> </RelativeLayout> diff --git a/app/src/main/res/menu/downloads_completed.xml b/app/src/main/res/menu/downloads_completed.xml index dc2996893..a88d93913 100644 --- a/app/src/main/res/menu/downloads_completed.xml +++ b/app/src/main/res/menu/downloads_completed.xml @@ -6,7 +6,8 @@ <item android:id="@+id/episode_actions" android:menuCategory="container" - android:title="@string/episode_actions" + android:title="@string/batch_edit" + android:icon="?attr/checkbox_multiple" custom:showAsAction="always"> </item> diff --git a/app/src/main/res/menu/feedlist.xml b/app/src/main/res/menu/feedlist.xml index 0646dc70f..3882cdff1 100644 --- a/app/src/main/res/menu/feedlist.xml +++ b/app/src/main/res/menu/feedlist.xml @@ -12,7 +12,8 @@ <item android:id="@+id/episode_actions" android:menuCategory="container" - android:title="@string/episode_actions" + android:icon="?attr/checkbox_multiple" + android:title="@string/batch_edit" custom:showAsAction="always"> </item> <item diff --git a/app/src/main/res/menu/mediaplayer.xml b/app/src/main/res/menu/mediaplayer.xml index 530eb3400..98c7478a6 100644 --- a/app/src/main/res/menu/mediaplayer.xml +++ b/app/src/main/res/menu/mediaplayer.xml @@ -41,6 +41,14 @@ android:title="@string/visit_website_label" android:visible="false"> </item> + + <item + android:id="@+id/player_go_to_picture_in_picture" + custom:showAsAction="collapseActionView" + android:title="@string/player_go_to_picture_in_picture" + android:visible="false"> + </item> + <item android:id="@+id/share_item" android:icon="?attr/social_share" diff --git a/app/src/main/res/xml/preferences_playback.xml b/app/src/main/res/xml/preferences_playback.xml index 96bb7379a..49a53726c 100644 --- a/app/src/main/res/xml/preferences_playback.xml +++ b/app/src/main/res/xml/preferences_playback.xml @@ -36,6 +36,14 @@ android:key="prefResumeAfterCall" android:summary="@string/pref_resumeAfterCall_sum" android:title="@string/pref_resumeAfterCall_title"/> + <com.afollestad.materialdialogs.prefs.MaterialListPreference + android:defaultValue="stop" + android:entries="@array/video_background_behavior_options" + android:entryValues="@array/video_background_behavior_values" + android:key="prefVideoBehavior" + android:summary="@string/pref_videoBehavior_sum" + android:title="@string/pref_videoBehavior_title" + app:useStockLayout="true"/> </PreferenceCategory> <PreferenceCategory android:title="@string/buttons"> diff --git a/artwork/feature-graphic.svg b/artwork/feature-graphic.svg new file mode 100644 index 000000000..69e7902ec --- /dev/null +++ b/artwork/feature-graphic.svg @@ -0,0 +1,164 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="1024" + height="500" + viewBox="0 0 270.93333 132.29167" + version="1.1" + id="svg8" + inkscape:version="0.92.2 2405546, 2018-03-11" + sodipodi:docname="feature-graphic.svg" + inkscape:export-filename="../app/src/main/play/en-US/listing/featureGraphic/feature-graphic.png" + inkscape:export-xdpi="96" + inkscape:export-ydpi="96"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#000000" + borderopacity="1" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="0.62493324" + inkscape:cx="475.1951" + inkscape:cy="288.63643" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + units="px" + inkscape:window-width="1600" + inkscape:window-height="835" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + borderlayer="true" + inkscape:showpageshadow="false" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title /> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-164.70832)"> + <path + style="fill:#42a5f5;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 241.57724,93.688693 153.83631,322.70237 129.26786,237.27975 Z" + id="path4549" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + style="fill:#90caf9;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 129.26786,237.27975 v 0 l 77.66392,-84.70466 -101.47643,-10.54534 z" + id="path4547" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" /> + <path + style="fill:#64b5f6;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 111.88095,149.96725 v 0 L 179.16071,374.10712 67.657738,209.68749 Z" + id="path4545" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" /> + <path + style="fill:#0277bd;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M -5.2916667,329.12796 -5.6696427,217.24701 127.37797,308.71725 Z" + id="path4537" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + style="fill:#90caf9;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 71.059523,210.44344 -3.401785,-0.75595 -79.741849,5.15409 173.172371,131.21195 z" + id="path4539" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccccc" /> + <path + style="fill:#2196f3;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m -5.6696427,217.24701 v 0 L 71.059523,210.44344 110.36905,157.90475 -14.363095,139.00594 Z" + id="path4541" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccccc" /> + <path + style="fill:#2196f3;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 293.68749,172.26785 -76.35118,94.87201 58.5863,58.9643 z" + id="path4553" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + style="fill:#64b5f6;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="M 184.64136,236.90177 378.4505,95.09124 217.33631,267.13986 Z" + id="path4555" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + style="fill:#1976d2;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" + d="m 216.58035,147.69939 77.48513,10.58333 -109.42412,78.61905 z" + id="path4557" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + id="path4603" + d="m 131.14882,195.24411 c -6.94441,0 -12.5,5.55559 -12.5,12.5 v 9.72225 a 4.1666667,4.1666667 0 0 0 4.16667,4.16667 h 4.16666 V 210.5219 h -5.55553 v -2.77779 a 9.722222,9.722222 0 0 1 9.7222,-9.72221 9.722222,9.722222 0 0 1 9.72226,9.72221 v 2.77779 h -5.55559 v 11.11113 h 4.16666 a 4.1666667,4.1666667 0 0 0 4.16667,-4.16667 v -9.72225 c 0,-6.94441 -5.59722,-12.5 -12.5,-12.5 z" + inkscape:connector-curvature="0" + style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.38888884" /> + <path + id="path4614" + d="m 131.1488,253.95301 a 3.9473708,3.9473708 0 0 1 3.94736,3.94737 v 7.89475 a 3.9473708,3.9473708 0 0 1 -3.94736,3.94736 3.9473708,3.9473708 0 0 1 -3.94737,-3.94736 v -7.89475 a 3.9473708,3.9473708 0 0 1 3.94737,-3.94737 m 9.21056,11.84212 c 0,4.64474 -3.43425,8.47365 -7.89474,9.11841 v 4.03947 h -2.6316 v -4.03947 c -4.46054,-0.64476 -7.89474,-4.47367 -7.89474,-9.11841 h 2.6316 a 6.5789516,6.5789516 0 0 0 6.57892,6.57891 6.5789516,6.5789516 0 0 0 6.57896,-6.57891 z" + inkscape:connector-curvature="0" + style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.31579018" /> + <path + id="path4625" + d="m 211.96825,213.93341 a 3.5025768,3.5025768 0 0 1 3.50256,3.50257 c 0,1.8959 -1.57454,3.50263 -3.50256,3.50263 -1.89591,0 -3.50257,-1.60673 -3.50257,-3.50263 a 3.5025768,3.5025768 0 0 1 3.50257,-3.50257 m -3.50257,-17.99487 a 25.000044,25.000044 0 0 1 25,25.00007 h -4.54692 a 20.45312,20.45312 0 0 0 -20.45308,-20.45315 v -4.54692 m 0,9.09384 a 15.906197,15.906197 0 0 1 15.90617,15.90623 h -4.54692 A 11.359274,11.359274 0 0 0 208.46568,209.5793 Z" + inkscape:connector-curvature="0" + style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.60668647" /> + <path + id="path4655" + d="m 163.79069,220.93857 h 20.58824 v -2.94119 h -20.58824 m 20.58824,-13.23528 h -5.88239 v -8.82353 h -8.82352 v 8.82353 h -5.88233 l 10.29409,10.29408 z" + inkscape:connector-curvature="0" + style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.47058702" /> + <path + style="fill:#1565c0;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0.60962572" + d="m 184.64136,236.90177 87.50149,77.8631 -118.30654,7.9375 z" + id="path4551" + inkscape:connector-curvature="0" + sodipodi:nodetypes="cccc" /> + <path + id="path4636" + d="m 227.91014,264.36965 v -4.8611 a 1.3888889,1.3888889 0 0 0 -1.38887,-1.38887 H 209.8546 a 1.3888889,1.3888889 0 0 0 -1.38892,1.38887 v 13.88893 a 1.3888889,1.3888889 0 0 0 1.38892,1.38887 h 16.66667 a 1.3888889,1.3888889 0 0 0 1.38887,-1.38887 v -4.86116 l 5.55554,5.55559 v -15.27779 z" + inkscape:connector-curvature="0" + style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.38888884" /> + <path + id="path4666" + d="m 174.08479,263.04394 a 3.4090929,3.4090929 0 0 0 -3.40909,3.40909 3.4090929,3.4090929 0 0 0 3.40909,3.40909 3.4090929,3.4090929 0 0 0 3.40909,-3.40909 3.4090929,3.4090929 0 0 0 -3.40909,-3.40909 m 0,9.09093 a 5.6818216,5.6818216 0 0 1 -5.68179,-5.68184 5.6818216,5.6818216 0 0 1 5.68179,-5.68184 5.6818216,5.6818216 0 0 1 5.68183,5.68184 5.6818216,5.6818216 0 0 1 -5.68183,5.68184 m 0,-14.20459 c -5.68179,0 -10.53407,3.53411 -12.49998,8.52275 1.96591,4.98863 6.81819,8.52271 12.49998,8.52271 5.68183,0 10.53411,-3.53408 12.50002,-8.52271 -1.96591,-4.98864 -6.81819,-8.52275 -12.50002,-8.52275 z" + inkscape:connector-curvature="0" + style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.13636422;stroke-opacity:1" /> + <g + transform="matrix(10.48853,0,0,10.48853,9.606285,-2891.1165)" + id="layer1-3" + inkscape:label="Ebene 1"> + <path + sodipodi:nodetypes="ccsccscccsccscccsccsccccccccccccccccccccccccccccc" + inkscape:connector-curvature="0" + id="path845" + d="m 4.3909501,292.40513 v 0.28377 c 1.0037008,0.0216 1.6560447,0.3661 2.2523926,0.96964 0.5963478,0.60354 0.9467125,1.47696 0.9641258,2.5345 h 0.2782303 c 0.00673,-1.19521 -0.4584817,-2.15822 -1.0382469,-2.73639 -0.5797652,-0.57816 -1.3486655,-1.05093 -2.4565018,-1.05152 z m 0,0.82805 v 0.29924 c 0.7443971,0.0312 1.1668558,0.18401 1.6809974,0.70029 0.5141415,0.51628 0.7305748,1.18454 0.7450816,1.96033 h 0.2948245 c -0.00762,-1.06881 -0.4691861,-1.81182 -0.8291591,-2.17052 -0.3599732,-0.35872 -0.8621337,-0.78563 -1.8917444,-0.78934 z m -5.665e-4,0.87009 5.665e-4,0.27491 c 0.3438797,0.006 0.7199551,0.1209 1.0476503,0.48898 0.3276951,0.36807 0.4289716,0.88778 0.4419601,1.32588 h 0.282102 c -0.00135,-0.57972 -0.2415301,-1.20375 -0.5332283,-1.51395 -0.2916983,-0.31021 -0.6385502,-0.57378 -1.2390371,-0.57582 z m 0.024339,1.16492 c -0.3517826,1.2e-4 -0.6368407,0.28543 -0.636666,0.63722 1.22e-4,0.23202 0.1264212,0.44563 0.3296724,0.55757 l -2.6086157,5.39256 0.4463853,0.29041 0.5260374,-1.08194 4.6640899,1.33914 0.071908,0.13941 0.496721,-0.21739 -3.0267779,-5.84062 c 0.2273717,-0.10308 0.3735565,-0.3295 0.3739235,-0.57914 1.749e-4,-0.35179 -0.2848831,-0.6371 -0.6366657,-0.63722 z m -0.022127,1.80822 0.4574483,0.88834 -1.1306216,0.50944 z m 0.5481634,1.06479 0.7876737,1.52889 -2.1401047,-0.9138 z m -1.4486778,0.80427 2.2402234,0.95196 -3.1020179,0.83801 z m 2.438262,1.11679 1.0758604,2.08978 -4.2741251,-1.22466 z" + style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.28320846;stroke-opacity:1" /> + </g> + </g> +</svg> diff --git a/artwork/ic_launcher.svg b/artwork/ic_launcher.svg new file mode 100644 index 000000000..cd65ace03 --- /dev/null +++ b/artwork/ic_launcher.svg @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="48" + height="48" + viewBox="0 0 12.7 12.7" + version="1.1" + id="svg8" + inkscape:version="0.92.2 2405546, 2018-03-11" + sodipodi:docname="ic_launcher_foreground.svg"> + <defs + id="defs2" /> + <sodipodi:namedview + id="base" + pagecolor="#ffffff" + bordercolor="#666666" + borderopacity="1.0" + inkscape:pageopacity="0.0" + inkscape:pageshadow="2" + inkscape:zoom="11.313709" + inkscape:cx="23.22737" + inkscape:cy="21.198035" + inkscape:document-units="mm" + inkscape:current-layer="layer1" + showgrid="false" + units="px" + inkscape:window-width="1600" + inkscape:window-height="835" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="1" + borderlayer="true" + inkscape:showpageshadow="false" + inkscape:measure-start="22.5502,25.5372" + inkscape:measure-end="22.0529,26.5828" /> + <metadata + id="metadata5"> + <rdf:RDF> + <cc:Work + rdf:about=""> + <dc:format>image/svg+xml</dc:format> + <dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> + <dc:title></dc:title> + </cc:Work> + </rdf:RDF> + </metadata> + <g + inkscape:label="Ebene 1" + inkscape:groupmode="layer" + id="layer1" + transform="translate(0,-284.29998)"> + <circle + style="opacity:1;fill:#008ab8;fill-opacity:1;stroke:none;stroke-width:0.00865707;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" + id="path905" + cx="6.2915349" + cy="290.91675" + r="5.4972386" /> + <path + style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999994;stroke-opacity:1" + d="m 21.751953,8.4707031 v 1.0019531 c 3.544035,0.076347 5.84744,1.2927418 7.953125,3.4238278 2.105685,2.131087 3.342811,5.215084 3.404297,8.949219 h 0.982422 C 34.11557,17.625445 32.472913,14.225068 30.425781,12.183594 28.378649,10.14212 25.663687,8.4727819 21.751953,8.4707031 Z m 0,2.9238279 v 1.056641 c 2.628442,0.110362 4.12013,0.649714 5.935547,2.472656 1.815417,1.822942 2.579636,4.182587 2.630859,6.921875 h 1.041016 c -0.02691,-3.773934 -1.656681,-6.397467 -2.927734,-7.664062 -1.271054,-1.266596 -3.044166,-2.773995 -6.679688,-2.78711 z m -0.002,3.072266 0.002,0.970703 c 1.214228,0.02268 2.542138,0.426896 3.699219,1.726562 1.157081,1.299667 1.514685,3.134718 1.560547,4.681641 h 0.996093 C 28.003013,19.798749 27.154977,17.595307 26.125,16.5 25.095023,15.404693 23.8703,14.474016 21.75,14.466797 Z m 0.08594,4.113281 c -1.242133,4.62e-4 -2.248664,1.007867 -2.248047,2.25 4.31e-4,0.819298 0.446389,1.573535 1.164062,1.96875 l -9.210937,19.041016 1.576172,1.02539 1.857421,-3.820312 16.46875,4.728516 0.253907,0.492187 1.753906,-0.767578 L 22.763672,22.875 c 0.802842,-0.363971 1.319016,-1.16343 1.320312,-2.044922 6.17e-4,-1.242133 -1.005913,-2.249537 -2.248046,-2.25 z m -0.07813,6.384766 1.615235,3.136718 -3.992188,1.798829 z m 1.935547,3.759765 2.78125,5.398438 -7.55664,-3.226563 z m -5.115234,2.839844 7.910156,3.361328 -10.953125,2.958985 z M 27.1875,35.507812 30.986328,42.886719 15.894531,38.5625 Z" + id="path845" + transform="matrix(0.26458333,0,0,0.26458333,0,284.29998)" + inkscape:connector-curvature="0" + sodipodi:nodetypes="ccsccscccsccscccsccsccccccccccccccccccccccccccccc" /> + </g> +</svg> diff --git a/build.gradle b/build.gradle index 4d5fded46..9edb7f350 100644 --- a/build.gradle +++ b/build.gradle @@ -45,6 +45,7 @@ project.ext { supportVersion = "25.3.1" commonsioVersion = "2.5" commonslangVersion = "3.6" + commonstextVersion = "1.3" eventbusVersion = "2.4.0" flattr4jVersion = "2.14" glideVersion = "3.8.0" diff --git a/core/build.gradle b/core/build.gradle index 9967e99ff..af1ac7ad0 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -50,6 +50,7 @@ dependencies { implementation "com.android.support:support-v4:$supportVersion" implementation "com.android.support:appcompat-v7:$supportVersion" implementation "org.apache.commons:commons-lang3:$commonslangVersion" + implementation "org.apache.commons:commons-text:$commonstextVersion" implementation ("org.shredzone.flattr4j:flattr4j-core:$flattr4jVersion") { exclude group: "org.json", module: "json" } diff --git a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java index 743ee135d..bad48e4cc 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java +++ b/core/src/main/java/de/danoeh/antennapod/core/preferences/UserPreferences.java @@ -74,6 +74,7 @@ public class UserPreferences { private static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray"; private static final String PREF_PAUSE_PLAYBACK_FOR_FOCUS_LOSS = "prefPauseForFocusLoss"; private static final String PREF_RESUME_AFTER_CALL = "prefResumeAfterCall"; + public static final String PREF_VIDEO_BEHAVIOR = "prefVideoBehavior"; // Network private static final String PREF_ENQUEUE_DOWNLOADED = "prefEnqueueDownloaded"; @@ -661,6 +662,14 @@ public class UserPreferences { .apply(); } + public static VideoBackgroundBehavior getVideoBackgroundBehavior() { + switch (prefs.getString(PREF_VIDEO_BEHAVIOR, "stop")) { + case "stop": return VideoBackgroundBehavior.STOP; + case "pip": return VideoBackgroundBehavior.PICTURE_IN_PICTURE; + case "continue": return VideoBackgroundBehavior.CONTINUE_PLAYING; + default: return VideoBackgroundBehavior.STOP; + } + } public static EpisodeCleanupAlgorithm getEpisodeCleanupAlgorithm() { int cleanupValue = Integer.parseInt(prefs.getString(PREF_EPISODE_CLEANUP, "-1")); @@ -839,4 +848,8 @@ public class UserPreferences { public static boolean isCastEnabled() { return prefs.getBoolean(PREF_CAST_ENABLED, false); } + + public enum VideoBackgroundBehavior { + STOP, PICTURE_IN_PICTURE, CONTINUE_PLAYING + } } diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java index ab25f0a5f..67a2cdad2 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java +++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java @@ -1436,6 +1436,12 @@ public class PlaybackService extends MediaBrowserServiceCompat { @Override public void onReceive(Context context, Intent intent) { + if (isInitialStickyBroadcast ()) { + // Don't pause playback after we just started, just because the receiver + // delivers the current headset state (instead of a change) + return; + } + if (TextUtils.equals(intent.getAction(), Intent.ACTION_HEADSET_PLUG)) { int state = intent.getIntExtra("state", -1); if (state != -1) { diff --git a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java index ea1b724d4..b512dce3f 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java +++ b/core/src/main/java/de/danoeh/antennapod/core/syndication/namespace/atom/AtomText.java @@ -1,6 +1,6 @@ package de.danoeh.antennapod.core.syndication.namespace.atom; -import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.text.StringEscapeUtils; import de.danoeh.antennapod.core.syndication.namespace.Namespace; import de.danoeh.antennapod.core.syndication.namespace.SyndElement; diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java b/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java index a93dd8ee3..e99461806 100644 --- a/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java +++ b/core/src/main/java/de/danoeh/antennapod/core/util/FileNameGenerator.java @@ -3,7 +3,8 @@ package de.danoeh.antennapod.core.util; import android.text.TextUtils; import org.apache.commons.lang3.ArrayUtils; -import org.apache.commons.lang3.RandomStringUtils; +import org.apache.commons.text.RandomStringGenerator; + /** Generates valid filenames for a given string. */ public class FileNameGenerator { @@ -34,7 +35,11 @@ public class FileNameGenerator { } String filename = buf.toString().trim(); if(TextUtils.isEmpty(filename)) { - return RandomStringUtils.randomAlphanumeric(8); + return new RandomStringGenerator.Builder() + .withinRange('0', 'z') + .filteredBy(Character::isLetterOrDigit) + .build() + .generate(8); } return filename; } diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/gui/PictureInPictureUtil.java b/core/src/main/java/de/danoeh/antennapod/core/util/gui/PictureInPictureUtil.java new file mode 100644 index 000000000..f763653a1 --- /dev/null +++ b/core/src/main/java/de/danoeh/antennapod/core/util/gui/PictureInPictureUtil.java @@ -0,0 +1,27 @@ +package de.danoeh.antennapod.core.util.gui; + +import android.app.Activity; +import android.content.pm.PackageManager; +import android.os.Build; + +public class PictureInPictureUtil { + private PictureInPictureUtil() { + } + + public static boolean supportsPictureInPicture(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + PackageManager packageManager = activity.getPackageManager(); + return packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE); + } else { + return false; + } + } + + public static boolean isInPictureInPictureMode(Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N && supportsPictureInPicture(activity)) { + return activity.isInPictureInPictureMode(); + } else { + return false; + } + } +} diff --git a/core/src/main/res/drawable-hdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png b/core/src/main/res/drawable-hdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png Binary files differnew file mode 100644 index 000000000..212948b70 --- /dev/null +++ b/core/src/main/res/drawable-hdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png diff --git a/core/src/main/res/drawable-hdpi/ic_checkbox_multiple_marked_outline_white_24dp.png b/core/src/main/res/drawable-hdpi/ic_checkbox_multiple_marked_outline_white_24dp.png Binary files differnew file mode 100644 index 000000000..cce69655d --- /dev/null +++ b/core/src/main/res/drawable-hdpi/ic_checkbox_multiple_marked_outline_white_24dp.png diff --git a/core/src/main/res/drawable-mdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png b/core/src/main/res/drawable-mdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png Binary files differnew file mode 100644 index 000000000..498ddf8eb --- /dev/null +++ b/core/src/main/res/drawable-mdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png diff --git a/core/src/main/res/drawable-mdpi/ic_checkbox_multiple_marked_outline_white_24dp.png b/core/src/main/res/drawable-mdpi/ic_checkbox_multiple_marked_outline_white_24dp.png Binary files differnew file mode 100644 index 000000000..66a6d7681 --- /dev/null +++ b/core/src/main/res/drawable-mdpi/ic_checkbox_multiple_marked_outline_white_24dp.png diff --git a/core/src/main/res/drawable-xhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png b/core/src/main/res/drawable-xhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png Binary files differnew file mode 100644 index 000000000..df64c26fe --- /dev/null +++ b/core/src/main/res/drawable-xhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png diff --git a/core/src/main/res/drawable-xhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png b/core/src/main/res/drawable-xhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png Binary files differnew file mode 100644 index 000000000..9e49cbe0a --- /dev/null +++ b/core/src/main/res/drawable-xhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png diff --git a/core/src/main/res/drawable-xxhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png Binary files differnew file mode 100644 index 000000000..951244d68 --- /dev/null +++ b/core/src/main/res/drawable-xxhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png diff --git a/core/src/main/res/drawable-xxhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png b/core/src/main/res/drawable-xxhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png Binary files differnew file mode 100644 index 000000000..3eaedd318 --- /dev/null +++ b/core/src/main/res/drawable-xxhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png diff --git a/core/src/main/res/drawable-xxxhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png Binary files differnew file mode 100644 index 000000000..6c4c2b94c --- /dev/null +++ b/core/src/main/res/drawable-xxxhdpi/ic_checkbox_multiple_marked_outline_grey600_24dp.png diff --git a/core/src/main/res/drawable-xxxhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png b/core/src/main/res/drawable-xxxhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png Binary files differnew file mode 100644 index 000000000..fd5114044 --- /dev/null +++ b/core/src/main/res/drawable-xxxhdpi/ic_checkbox_multiple_marked_outline_white_24dp.png diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml index 45650495c..9d9a2453d 100644 --- a/core/src/main/res/values/arrays.xml +++ b/core/src/main/res/values/arrays.xml @@ -224,4 +224,26 @@ <item>@string/fast_forward_label</item> <item>@string/skip_episode_label</item> </string-array> + + <string-array name="video_background_behavior_options"> + <item>@string/stop_playback</item> + <item>@string/player_go_to_picture_in_picture</item> + <item>@string/continue_playback</item> + </string-array> + + <string-array name="video_background_behavior_values"> + <item>stop</item> + <item>pip</item> + <item>continue</item> + </string-array> + + <string-array name="video_background_behavior_options_without_pip"> + <item>@string/stop_playback</item> + <item>@string/continue_playback</item> + </string-array> + + <string-array name="video_background_behavior_values_without_pip"> + <item>stop</item> + <item>continue</item> + </string-array> </resources> diff --git a/core/src/main/res/values/attrs.xml b/core/src/main/res/values/attrs.xml index 16cbfb751..dd3039fca 100644 --- a/core/src/main/res/values/attrs.xml +++ b/core/src/main/res/values/attrs.xml @@ -46,6 +46,7 @@ <attr name="ic_unfav" format="reference"/> <attr name="ic_sleep" format="reference"/> <attr name="ic_sleep_off" format="reference"/> + <attr name="checkbox_multiple" format="reference"/> <attr name="ic_check_box" format="reference"/> <attr name="ic_check_box_outline" format="reference"/> <attr name="ic_indeterminate_check_box" format="reference"/> diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index 9a8e3f654..2997b51b2 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -11,6 +11,7 @@ <string name="add_feed_label">Add Podcast</string> <string name="episodes_label">Episodes</string> <string name="all_episodes_short_label">All</string> + <string name="new_episodes_label">New</string> <string name="favorite_episodes_label">Favorites</string> <string name="new_label">New</string> <string name="settings_label">Settings</string> @@ -123,6 +124,9 @@ <string name="mark_all_seen_msg">Marked all Episodes as seen</string> <string name="mark_all_seen_confirmation_msg">Please confirm that you want to mark all episodes as seen.</string> <string name="show_info_label">Show information</string> + <string name="show_feed_settings_label">Show feed settings</string> + <string name="feed_info_label">Feed info</string> + <string name="feed_settings_label">Feed settings</string> <string name="rename_feed_label">Rename Podcast</string> <string name="remove_feed_label">Remove Podcast</string> <string name="share_label">Share…</string> @@ -136,7 +140,7 @@ <string name="feed_remover_msg">Removing Feed</string> <string name="load_complete_feed">Refresh complete Feed</string> <string name="hide_episodes_title">Hide Episodes</string> - <string name="episode_actions">Apply actions</string> + <string name="batch_edit">Batch edit</string> <string name="hide_unplayed_episodes_label">Unplayed</string> <string name="hide_paused_episodes_label">Paused</string> <string name="hide_played_episodes_label">Played</string> @@ -237,6 +241,7 @@ <string name="no_media_playing_label">No media playing</string> <string name="position_default_label" translate="false">00:00:00</string> <string name="player_buffering_msg">Buffering</string> + <string name="player_go_to_picture_in_picture">Picture-in-picture mode</string> <string name="playbackservice_notification_title">Playing podcast</string> <string name="unknown_media_key">AntennaPod - Unknown media key: %1$d</string> @@ -449,6 +454,10 @@ <string name="pref_cast_message_free_flavor">Chromecast requires third party proprietary libraries that are disabled in this version of AntennaPod</string> <string name="pref_enqueue_downloaded_title">Enqueue Downloaded</string> <string name="pref_enqueue_downloaded_summary">Add downloaded episodes to the queue</string> + <string name="pref_videoBehavior_title">Video behavior</string> + <string name="pref_videoBehavior_sum">Behavior when leaving video playback</string> + <string name="stop_playback">Stop playback</string> + <string name="continue_playback">Continue playback</string> <!-- Auto-Flattr dialog --> <string name="auto_flattr_enable">Enable automatic flattring</string> diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml index 22f0f304d..fa500354b 100644 --- a/core/src/main/res/values/styles.xml +++ b/core/src/main/res/values/styles.xml @@ -15,6 +15,7 @@ <item type="attr" name="storage">@drawable/ic_sd_grey600_24dp</item> <item type="attr" name="statistics">@drawable/ic_poll_box_grey600_24dp</item> <item type="attr" name="action_about">@drawable/ic_info_grey600_24dp</item> + <item type="attr" name="checkbox_multiple">@drawable/ic_checkbox_multiple_marked_outline_grey600_24dp</item> <item type="attr" name="action_search">@drawable/ic_search_grey600_24dp</item> <item type="attr" name="action_stream">@drawable/ic_settings_input_antenna_grey600_24dp</item> <item type="attr" name="av_download">@drawable/ic_file_download_grey600_24dp</item> @@ -79,7 +80,7 @@ <item type="attr" name="action_bar_icon_color">@color/white</item> <item type="attr" name="storage">@drawable/ic_sd_white_24dp</item> <item type="attr" name="statistics">@drawable/ic_poll_box_white_24dp</item> - <item type="attr" name="action_about">@drawable/ic_info_white_24dp</item>g + <item type="attr" name="checkbox_multiple">@drawable/ic_checkbox_multiple_marked_outline_white_24dp</item> <item type="attr" name="action_search">@drawable/ic_search_white_24dp</item> <item type="attr" name="action_stream">@drawable/ic_settings_input_antenna_white_24dp</item> <item type="attr" name="av_download">@drawable/ic_file_download_white_24dp</item> @@ -143,7 +144,10 @@ <item name="colorAccent">@color/holo_blue_light</item> <item name="buttonStyle">@style/Widget.AntennaPod.Button</item> <item name="alertDialogTheme">@style/AntennaPod.Dialog.Light</item> + <item type="attr" name="storage">@drawable/ic_sd_grey600_24dp</item> + <item type="attr" name="statistics">@drawable/ic_poll_box_grey600_24dp</item> <item type="attr" name="action_about">@drawable/ic_info_grey600_24dp</item> + <item type="attr" name="checkbox_multiple">@drawable/ic_checkbox_multiple_marked_outline_grey600_24dp</item> <item type="attr" name="action_search">@drawable/ic_search_grey600_24dp</item> <item type="attr" name="action_stream">@drawable/ic_settings_input_antenna_grey600_24dp</item> <item type="attr" name="av_download">@drawable/ic_file_download_grey600_24dp</item> @@ -207,7 +211,10 @@ <item name="colorControlNormal">@color/white</item> <item name="buttonStyle">@style/Widget.AntennaPod.Button</item> <item name="alertDialogTheme">@style/AntennaPod.Dialog.Dark</item> + <item type="attr" name="storage">@drawable/ic_sd_white_24dp</item> + <item type="attr" name="statistics">@drawable/ic_poll_box_white_24dp</item> <item type="attr" name="action_about">@drawable/ic_info_white_24dp</item> + <item type="attr" name="checkbox_multiple">@drawable/ic_checkbox_multiple_marked_outline_white_24dp</item> <item type="attr" name="action_search">@drawable/ic_search_white_24dp</item> <item type="attr" name="action_stream">@drawable/ic_settings_input_antenna_white_24dp</item> <item type="attr" name="av_download">@drawable/ic_file_download_white_24dp</item> |