diff options
author | Martin Fietz <Martin.Fietz@gmail.com> | 2017-04-09 20:34:43 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-04-09 20:34:43 +0200 |
commit | 5cbf092f3bde5c185c1826a941909db5f2a32c7d (patch) | |
tree | f20546ce2e40c7037cb3aaadadbb113afdd8bbae /app/src/main/java | |
parent | dc38ecdd688423232a7c1ac51d6efbecba1f5eab (diff) | |
parent | 4d256b7323d5a00b081508b13eb9141ab3aa9035 (diff) | |
download | AntennaPod-5cbf092f3bde5c185c1826a941909db5f2a32c7d.zip |
Merge branch 'develop' into develop
Diffstat (limited to 'app/src/main/java')
33 files changed, 772 insertions, 388 deletions
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 cfd633fae..19aabfc88 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/FeedInfoActivity.java @@ -8,6 +8,7 @@ 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; @@ -27,6 +28,10 @@ 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; @@ -40,6 +45,7 @@ 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 rx.Observable; import rx.Subscription; @@ -50,17 +56,18 @@ import rx.schedulers.Schedulers; * Displays information about a feed. */ public class FeedInfoActivity extends AppCompatActivity { - private static final String TAG = "FeedInfoActivity"; - private boolean autoDeleteChanged = false; 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; private TextView txtvTitle; private TextView txtvDescription; + private TextView lblLanguage; private TextView txtvLanguage; + private TextView lblAuthor; private TextView txtvAuthor; private TextView txtvUrl; private EditText etxtUsername; @@ -75,6 +82,7 @@ public class FeedInfoActivity extends AppCompatActivity { private Subscription subscription; + private final View.OnClickListener copyUrlToClipboard = new View.OnClickListener() { @Override public void onClick(View v) { @@ -96,6 +104,40 @@ public class FeedInfoActivity extends AppCompatActivity { } }; + private boolean authInfoChanged = false; + + private 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 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()); @@ -107,7 +149,9 @@ public class FeedInfoActivity extends AppCompatActivity { imgvCover = (ImageView) findViewById(R.id.imgvCover); txtvTitle = (TextView) findViewById(R.id.txtvTitle); 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); txtvUrl = (TextView) findViewById(R.id.txtvUrl); cbxAutoDownload = (CheckBox) findViewById(R.id.cbxAutoDownload); @@ -152,14 +196,30 @@ public class FeedInfoActivity extends AppCompatActivity { .into(imgvCover); txtvTitle.setText(feed.getTitle()); + String description = feed.getDescription(); - txtvDescription.setText((description != null) ? description.trim() : ""); - if (feed.getAuthor() != null) { + if(description != null) { + if(Feed.TYPE_ATOM1.equals(feed.getType())) { + HtmlToPlainText formatter = new HtmlToPlainText(); + Document feedDescription = Jsoup.parse(feed.getDescription()); + description = StringUtils.trim(formatter.getPlainText(feedDescription)); + } + } else { + description = ""; + } + txtvDescription.setText(description); + + if (!TextUtils.isEmpty(feed.getAuthor())) { txtvAuthor.setText(feed.getAuthor()); + } else { + lblAuthor.setVisibility(View.GONE); + txtvAuthor.setVisibility(View.GONE); } - if (feed.getLanguage() != null) { - txtvLanguage.setText(LangUtils - .getLanguageString(feed.getLanguage())); + if (!TextUtils.isEmpty(feed.getLanguage())) { + txtvLanguage.setText(LangUtils.getLanguageString(feed.getLanguage())); + } else { + lblLanguage.setVisibility(View.GONE); + txtvLanguage.setVisibility(View.GONE); } txtvUrl.setText(feed.getDownload_url() + " {fa-paperclip}"); Iconify.addIcons(txtvUrl); @@ -241,53 +301,6 @@ public class FeedInfoActivity extends AppCompatActivity { } @Override - public void onDestroy() { - super.onDestroy(); - if(subscription != null) { - subscription.unsubscribe(); - } - } - - - private boolean authInfoChanged = false; - - private 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 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 onPause() { super.onPause(); if (feed != null) { @@ -319,6 +332,14 @@ public class FeedInfoActivity extends AppCompatActivity { } @Override + public void onDestroy() { + super.onDestroy(); + if(subscription != null) { + subscription.unsubscribe(); + } + } + + @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = getMenuInflater(); @@ -369,7 +390,7 @@ public class FeedInfoActivity extends AppCompatActivity { private final Feed feed; private final boolean autoDownload; - public ApplyToEpisodesDialog(Context context, Feed feed, 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; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java index 97732786e..41ed963c2 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MainActivity.java @@ -10,6 +10,7 @@ import android.database.DataSetObserver; import android.os.Build; import android.os.Bundle; import android.os.Handler; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; @@ -38,6 +39,7 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.adapter.NavListAdapter; import de.danoeh.antennapod.core.asynctask.FeedRemover; import de.danoeh.antennapod.core.dialog.ConfirmationDialog; +import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.event.ProgressEvent; import de.danoeh.antennapod.core.event.QueueEvent; import de.danoeh.antennapod.core.feed.EventDistributor; @@ -46,11 +48,13 @@ import de.danoeh.antennapod.core.preferences.PlaybackPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.Flavors; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.dialog.RatingDialog; +import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.fragment.AddFeedFragment; import de.danoeh.antennapod.fragment.DownloadsFragment; import de.danoeh.antennapod.fragment.EpisodesFragment; @@ -463,6 +467,7 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi protected void onResume() { super.onResume(); StorageUtils.checkStorageAvailability(this); + DBTasks.checkShouldRefreshFeeds(getApplicationContext()); Intent intent = getIntent(); if (intent.hasExtra(EXTRA_FEED_ID) || @@ -573,6 +578,9 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi case R.id.mark_all_read_item: DBWriter.markFeedRead(feed.getId()); return true; + case R.id.rename_item: + new RenameFeedDialog(this, feed).show(); + return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover(this, feed) { @Override @@ -731,6 +739,18 @@ public class MainActivity extends CastEnabledActivity implements NavDrawerActivi } } + public void onEventMainThread(MessageEvent event) { + Log.d(TAG, "onEvent(" + event + ")"); + View parentLayout = findViewById(R.id.drawer_layout); + Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT); + if(event.action != null) { + snackbar.setAction(getString(R.string.undo), v -> { + event.action.run(); + }); + } + snackbar.show(); + } + private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { @Override diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java index 2880b26e8..9d2f35e3d 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerInfoActivity.java @@ -8,6 +8,7 @@ import android.content.res.Configuration; import android.os.Build; import android.support.annotation.Nullable; import android.support.design.widget.AppBarLayout; +import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; @@ -36,6 +37,7 @@ import de.danoeh.antennapod.adapter.ChaptersListAdapter; import de.danoeh.antennapod.adapter.NavListAdapter; import de.danoeh.antennapod.core.asynctask.FeedRemover; import de.danoeh.antennapod.core.dialog.ConfirmationDialog; +import de.danoeh.antennapod.core.event.MessageEvent; import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.feed.FeedMedia; @@ -43,9 +45,11 @@ 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.storage.DBReader; +import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; +import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.fragment.AddFeedFragment; import de.danoeh.antennapod.fragment.ChaptersFragment; import de.danoeh.antennapod.fragment.CoverFragment; @@ -57,6 +61,7 @@ import de.danoeh.antennapod.fragment.QueueFragment; import de.danoeh.antennapod.fragment.SubscriptionFragment; import de.danoeh.antennapod.menuhandler.NavDrawerActivity; import de.danoeh.antennapod.preferences.PreferenceController; +import de.greenrobot.event.EventBus; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; @@ -102,6 +107,12 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem private Subscription subscription; @Override + protected void onPause() { + super.onPause(); + EventBus.getDefault().unregister(this); + } + + @Override protected void onStop() { super.onStop(); Log.d(TAG, "onStop()"); @@ -168,8 +179,10 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem pagerAdapter.onMediaChanged(media); pagerAdapter.setController(controller); } + DBTasks.checkShouldRefreshFeeds(getApplicationContext()); EventDistributor.getInstance().register(contentUpdate); + EventBus.getDefault().register(this); loadData(); } @@ -370,6 +383,9 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem case R.id.mark_all_read_item: DBWriter.markFeedRead(feed.getId()); return true; + case R.id.rename_item: + new RenameFeedDialog(this, feed).show(); + return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover(this, feed) { @Override @@ -462,7 +478,17 @@ public abstract class MediaplayerInfoActivity extends MediaplayerActivity implem }, error -> Log.e(TAG, Log.getStackTraceString(error))); } - + public void onEventMainThread(MessageEvent event) { + Log.d(TAG, "onEvent(" + event + ")"); + View parentLayout = findViewById(R.id.drawer_layout); + Snackbar snackbar = Snackbar.make(parentLayout, event.message, Snackbar.LENGTH_SHORT); + if (event.action != null) { + snackbar.setAction(getString(R.string.undo), v -> { + event.action.run(); + }); + } + snackbar.show(); + } private EventDistributor.EventListener contentUpdate = new EventDistributor.EventListener() { diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java index a40877832..a4e661f62 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -29,7 +29,6 @@ import com.bumptech.glide.Glide; import org.apache.commons.lang3.StringUtils; import org.jsoup.Jsoup; -import org.jsoup.examples.HtmlToPlainText; import org.jsoup.nodes.Document; import java.io.File; @@ -63,6 +62,7 @@ import de.danoeh.antennapod.core.util.FileNameGenerator; import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.URLChecker; import de.danoeh.antennapod.core.util.syndication.FeedDiscoverer; +import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; import de.danoeh.antennapod.dialog.AuthenticationDialog; import de.greenrobot.event.EventBus; import rx.Observable; @@ -81,17 +81,12 @@ import rx.schedulers.Schedulers; */ public class OnlineFeedViewActivity extends AppCompatActivity { - private static final String TAG = "OnlineFeedViewActivity"; - public static final String ARG_FEEDURL = "arg.feedurl"; - // Optional argument: specify a title for the actionbar. public static final String ARG_TITLE = "title"; - - private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE; - public static final int RESULT_ERROR = 2; - + private static final String TAG = "OnlineFeedViewActivity"; + private static final int EVENTS = EventDistributor.FEED_LIST_UPDATE; private volatile List<Feed> feeds; private Feed feed; private String selectedDownloadUrl; @@ -106,17 +101,11 @@ public class OnlineFeedViewActivity extends AppCompatActivity { private Subscription download; private Subscription parser; private Subscription updater; - - public void onEventMainThread(DownloadEvent event) { - Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); - setSubscribeButtonState(feed); - } - private EventDistributor.EventListener listener = new EventDistributor.EventListener() { @Override public void update(EventDistributor eventDistributor, Integer arg) { if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) { - updater = Observable.fromCallable(() -> DBReader.getFeedList()) + updater = Observable.fromCallable(DBReader::getFeedList) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( @@ -133,6 +122,11 @@ public class OnlineFeedViewActivity extends AppCompatActivity { } }; + public void onEventMainThread(DownloadEvent event) { + Log.d(TAG, "onEventMainThread() called with: " + "event = [" + event + "]"); + setSubscribeButtonState(feed); + } + @Override protected void onCreate(Bundle savedInstanceState) { setTheme(UserPreferences.getTheme()); @@ -284,7 +278,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { }) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) - .subscribe(status -> checkDownloadResult(status), + .subscribe(this::checkDownloadResult, error -> Log.e(TAG, Log.getStackTraceString(error))); } @@ -360,14 +354,19 @@ public class OnlineFeedViewActivity extends AppCompatActivity { * This method is executed on a background thread */ private void beforeShowFeedInformation(Feed feed) { - // remove HTML tags from descriptions + final HtmlToPlainText formatter = new HtmlToPlainText(); + if(Feed.TYPE_ATOM1.equals(feed.getType()) && feed.getDescription() != null) { + // remove HTML tags from descriptions + Log.d(TAG, "Removing HTML from feed description"); + Document feedDescription = Jsoup.parse(feed.getDescription()); + feed.setDescription(StringUtils.trim(formatter.getPlainText(feedDescription))); + } Log.d(TAG, "Removing HTML from shownotes"); if (feed.getItems() != null) { - HtmlToPlainText formatter = new HtmlToPlainText(); for (FeedItem item : feed.getItems()) { if (item.getDescription() != null) { - Document description = Jsoup.parse(item.getDescription()); - item.setDescription(StringUtils.trim(formatter.getPlainText(description))); + Document itemDescription = Jsoup.parse(item.getDescription()); + item.setDescription(StringUtils.trim(formatter.getPlainText(itemDescription))); } } } @@ -589,7 +588,7 @@ public class OnlineFeedViewActivity extends AppCompatActivity { private String feedUrl; - public FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) { + FeedViewAuthenticationDialog(Context context, int titleRes, String feedUrl) { super(context, titleRes, true, false, null, null); this.feedUrl = feedUrl; } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java index bc1a40b11..355e0f372 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlFeedChooserActivity.java @@ -15,7 +15,7 @@ import java.util.ArrayList; import java.util.List; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.opml.OpmlElement; +import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.preferences.UserPreferences; /** @@ -23,10 +23,8 @@ import de.danoeh.antennapod.core.preferences.UserPreferences; * which feeds he wants to import. */ public class OpmlFeedChooserActivity extends AppCompatActivity { - private static final String TAG = "OpmlFeedChooserActivity"; - public static final String EXTRA_SELECTED_ITEMS = "de.danoeh.antennapod.selectedItems"; - + private static final String TAG = "OpmlFeedChooserActivity"; private Button butConfirm; private Button butCancel; private ListView feedlist; diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java index 8726af281..07b0b3cdb 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportBaseActivity.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.activity; import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; +import android.os.Build; import android.os.Environment; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; @@ -20,7 +21,7 @@ import java.util.ArrayList; import de.danoeh.antennapod.R; import de.danoeh.antennapod.asynctask.OpmlFeedQueuer; import de.danoeh.antennapod.asynctask.OpmlImportWorker; -import de.danoeh.antennapod.core.opml.OpmlElement; +import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.util.LangUtils; /** @@ -29,9 +30,8 @@ import de.danoeh.antennapod.core.util.LangUtils; public class OpmlImportBaseActivity extends AppCompatActivity { private static final String TAG = "OpmlImportBaseActivity"; - private OpmlImportWorker importWorker; - private static final int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = 5; + private OpmlImportWorker importWorker; @Nullable private Uri uri; /** @@ -77,7 +77,8 @@ public class OpmlImportBaseActivity extends AppCompatActivity { return; } this.uri = uri; - if(uri.toString().contains(Environment.getExternalStorageDirectory().toString())) { + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + uri.toString().contains(Environment.getExternalStorageDirectory().toString())) { int permission = ActivityCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE); if (permission != PackageManager.PERMISSION_GRANTED) { requestPermission(); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java index 7afa270cc..b01cf43e4 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OpmlImportHolder.java @@ -1,9 +1,9 @@ package de.danoeh.antennapod.activity; -import de.danoeh.antennapod.core.opml.OpmlElement; - import java.util.ArrayList; +import de.danoeh.antennapod.core.export.opml.OpmlElement; + /** * Hold infos gathered by Ompl-Import * <p/> diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java index 61765d6b7..dd932814f 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivity.java @@ -26,11 +26,9 @@ import de.danoeh.antennapod.preferences.PreferenceController; */ public class PreferenceActivity extends AppCompatActivity { + private static WeakReference<PreferenceActivity> instance; private PreferenceController preferenceController; private MainFragment prefFragment; - private static WeakReference<PreferenceActivity> instance; - - private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() { @TargetApi(Build.VERSION_CODES.HONEYCOMB) @Override @@ -128,5 +126,14 @@ public class PreferenceActivity extends AppCompatActivity { } super.onPause(); } + + @Override + public void onStop() { + PreferenceActivity activity = instance.get(); + if(activity != null && activity.preferenceController != null) { + activity.preferenceController.onStop(); + } + super.onStop(); + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java index 4af988ea0..390bec15c 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/PreferenceActivityGingerbread.java @@ -18,9 +18,6 @@ import de.danoeh.antennapod.preferences.PreferenceController; */ public class PreferenceActivityGingerbread extends android.preference.PreferenceActivity { private static final String TAG = "PreferenceActivity"; - - private PreferenceController preferenceController; - private final PreferenceController.PreferenceUI preferenceUI = new PreferenceController.PreferenceUI() { @SuppressWarnings("deprecation") @@ -34,6 +31,7 @@ public class PreferenceActivityGingerbread extends android.preference.Preference return PreferenceActivityGingerbread.this; } }; + private PreferenceController preferenceController; @SuppressLint("NewApi") @SuppressWarnings("deprecation") @@ -61,6 +59,12 @@ public class PreferenceActivityGingerbread extends android.preference.Preference } @Override + protected void onStop() { + preferenceController.onStop(); + super.onStop(); + } + + @Override protected void onApplyThemeResource(Theme theme, int resid, boolean first) { theme.applyStyle(UserPreferences.getTheme(), true); } diff --git a/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java new file mode 100644 index 000000000..b92ac8577 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/activity/SplashActivity.java @@ -0,0 +1,23 @@ +package de.danoeh.antennapod.activity; + +import android.content.Intent; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.app.AppCompatActivity; + +/** + * Creator: vbarad + * Date: 2016-12-03 + * Project: AntennaPod + */ + +public class SplashActivity extends AppCompatActivity { + @Override + protected void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Intent intent = new Intent(this, MainActivity.class); + startActivity(intent); + finish(); + } +} diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java index 1a8f0a67a..f0210f983 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/ActionButtonUtils.java @@ -47,6 +47,7 @@ public class ActionButtonUtils { * Sets the displayed bitmap and content description of the given * action button so that it matches the state of the FeedItem. */ + @SuppressWarnings("ResourceType") public void configureActionButton(ImageButton butSecondary, FeedItem item, boolean isInQueue) { Validate.isTrue(butSecondary != null && item != null, "butSecondary or item was null"); @@ -57,8 +58,7 @@ public class ActionButtonUtils { if (isDownloadingMedia) { // item is being downloaded butSecondary.setVisibility(View.VISIBLE); - butSecondary.setImageDrawable(drawables - .getDrawable(1)); + butSecondary.setImageDrawable(drawables.getDrawable(1)); butSecondary.setContentDescription(context.getString(labels[1])); } else { // item is not downloaded and not being downloaded diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java index 8aaf0055a..5c58d00f2 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java @@ -15,7 +15,7 @@ import de.danoeh.antennapod.core.util.NetworkUtils; /** * Utility methods for adapters */ -public class AdapterUtils { +class AdapterUtils { private static final String TAG = AdapterUtils.class.getSimpleName(); @@ -26,7 +26,7 @@ public class AdapterUtils { /** * Updates the contents of the TextView that shows the current playback position and the ProgressBar. */ - public static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) { + static void updateEpisodePlaybackProgress(FeedItem item, TextView txtvPos, ProgressBar episodeProgress) { FeedMedia media = item.getMedia(); episodeProgress.setVisibility(View.GONE); if (media == null) { @@ -47,7 +47,6 @@ public class AdapterUtils { - media.getPosition())); } } else if (!media.isDownloaded()) { - Log.d(TAG, "size: " + media.getSize()); if (media.getSize() > 0) { txtvPos.setText(Converter.byteToString(media.getSize())); } else if(NetworkUtils.isDownloadAllowed() && !media.checkedOnSizeButUnknown()) { diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java index 07847d0d1..35c42725c 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/FeedItemlistAdapter.java @@ -87,6 +87,7 @@ public class FeedItemlistAdapter extends BaseAdapter { } @Override + @SuppressWarnings("ResourceType") public View getView(final int position, View convertView, ViewGroup parent) { Holder holder; final FeedItem item = getItem(position); diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java index e9756b467..e381b4651 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/itunes/ItunesAdapter.java @@ -1,6 +1,7 @@ package de.danoeh.antennapod.adapter.itunes; import android.content.Context; +import android.support.annotation.NonNull; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; @@ -18,6 +19,7 @@ import java.util.List; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; +import de.mfietz.fyydlin.SearchHit; public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { /** @@ -42,8 +44,9 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { this.context = context; } + @NonNull @Override - public View getView(int position, View convertView, ViewGroup parent) { + public View getView(int position, View convertView, @NonNull ViewGroup parent) { //Current podcast Podcast podcast = data.get(position); @@ -87,35 +90,6 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { } /** - * View holder object for the GridView - */ - class PodcastViewHolder { - - /** - * ImageView holding the Podcast image - */ - public final ImageView coverView; - - /** - * TextView holding the Podcast title - */ - public final TextView titleView; - - public final TextView urlView; - - - /** - * Constructor - * @param view GridView cell - */ - PodcastViewHolder(View view){ - coverView = (ImageView) view.findViewById(R.id.imgvCover); - titleView = (TextView) view.findViewById(R.id.txtvTitle); - urlView = (TextView) view.findViewById(R.id.txtvUrl); - } - } - - /** * Represents an individual podcast on the iTunes Store. */ public static class Podcast { //TODO: Move this out eventually. Possibly to core.itunes.model @@ -154,6 +128,10 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { return new Podcast(title, imageUrl, feedUrl); } + public static Podcast fromSearch(SearchHit searchHit) { + return new Podcast(searchHit.getTitle(), searchHit.getImageUrl(), searchHit.getXmlUrl()); + } + /** * Constructs a Podcast instance from iTunes toplist entry * @@ -177,4 +155,33 @@ public class ItunesAdapter extends ArrayAdapter<ItunesAdapter.Podcast> { } } + + /** + * View holder object for the GridView + */ + class PodcastViewHolder { + + /** + * ImageView holding the Podcast image + */ + final ImageView coverView; + + /** + * TextView holding the Podcast title + */ + final TextView titleView; + + final TextView urlView; + + + /** + * Constructor + * @param view GridView cell + */ + PodcastViewHolder(View view){ + coverView = (ImageView) view.findViewById(R.id.imgvCover); + titleView = (TextView) view.findViewById(R.id.txtvTitle); + urlView = (TextView) view.findViewById(R.id.txtvUrl); + } + } } diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java new file mode 100644 index 000000000..192df8ca5 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/ExportWorker.java @@ -0,0 +1,65 @@ +package de.danoeh.antennapod.asynctask; + +import android.support.annotation.NonNull; +import android.util.Log; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.preferences.UserPreferences; +import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.util.LangUtils; +import rx.Observable; + +/** + * Writes an OPML file into the export directory in the background. + */ +public class ExportWorker { + + private static final String EXPORT_DIR = "export/"; + private static final String TAG = "ExportWorker"; + private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds"; + + private ExportWriter exportWriter; + private File output; + + public ExportWorker(ExportWriter exportWriter) { + this(exportWriter, new File(UserPreferences.getDataFolder(EXPORT_DIR), + DEFAULT_OUTPUT_NAME + "." + exportWriter.fileExtension())); + } + + public ExportWorker(ExportWriter exportWriter, @NonNull File output) { + this.exportWriter = exportWriter; + this.output = output; + } + + public Observable<File> exportObservable() { + if (output.exists()) { + Log.w(TAG, "Overwriting previously exported file."); + output.delete(); + } + return Observable.create(subscriber -> { + OutputStreamWriter writer = null; + try { + writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8); + exportWriter.writeDocument(DBReader.getFeedList(), writer); + subscriber.onNext(output); + } catch (IOException e) { + subscriber.onError(e); + } finally { + if (writer != null) { + try { + writer.close(); + } catch (IOException e) { + subscriber.onError(e); + } + } + subscriber.onCompleted(); + } + }); + } + +} diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java deleted file mode 100644 index 13abb26ea..000000000 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlExportWorker.java +++ /dev/null @@ -1,122 +0,0 @@ -package de.danoeh.antennapod.asynctask; - -import android.annotation.SuppressLint; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.AsyncTask; -import android.support.v7.app.AlertDialog; -import android.util.Log; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; - -import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.opml.OpmlWriter; -import de.danoeh.antennapod.core.preferences.UserPreferences; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.util.LangUtils; - -/** - * Writes an OPML file into the export directory in the background. - */ -public class OpmlExportWorker extends AsyncTask<Void, Void, Void> { - private static final String TAG = "OpmlExportWorker"; - private static final String DEFAULT_OUTPUT_NAME = "antennapod-feeds.opml"; - public static final String EXPORT_DIR = "export/"; - - private Context context; - private File output; - - private ProgressDialog progDialog; - private Exception exception; - - public OpmlExportWorker(Context context, File output) { - this.context = context; - this.output = output; - } - - public OpmlExportWorker(Context context) { - this.context = context; - } - - @Override - protected Void doInBackground(Void... params) { - OpmlWriter opmlWriter = new OpmlWriter(); - if (output == null) { - output = new File( - UserPreferences.getDataFolder(EXPORT_DIR), - DEFAULT_OUTPUT_NAME); - if (output.exists()) { - Log.w(TAG, "Overwriting previously exported file."); - output.delete(); - } - } - OutputStreamWriter writer = null; - try { - writer = new OutputStreamWriter(new FileOutputStream(output), LangUtils.UTF_8); - opmlWriter.writeDocument(DBReader.getFeedList(), writer); - } catch (IOException e) { - e.printStackTrace(); - exception = e; - } finally { - if (writer != null) { - try { - writer.close(); - } catch (IOException ioe) { - exception = ioe; - } - } - } - return null; - } - - @Override - protected void onPostExecute(Void result) { - progDialog.dismiss(); - AlertDialog.Builder alert = new AlertDialog.Builder(context) - .setNeutralButton(android.R.string.ok, - (dialog, which) -> dialog.dismiss()); - if (exception != null) { - alert.setTitle(R.string.export_error_label); - alert.setMessage(exception.getMessage()); - } else { - alert.setTitle(R.string.opml_export_success_title); - alert.setMessage(context - .getString(R.string.opml_export_success_sum) - + output.toString()) - .setPositiveButton(R.string.send_label, (dialog, which) -> { - Uri outputUri = Uri.fromFile(output); - Intent sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.putExtra(Intent.EXTRA_SUBJECT, - context.getResources().getText(R.string.opml_export_label)); - sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri); - sendIntent.setType("text/plain"); - context.startActivity(Intent.createChooser(sendIntent, - context.getResources().getText(R.string.send_label))); - }); - } - alert.create().show(); - } - - @Override - protected void onPreExecute() { - progDialog = new ProgressDialog(context); - progDialog.setMessage(context.getString(R.string.exporting_label)); - progDialog.setIndeterminate(true); - progDialog.show(); - } - - @SuppressLint("NewApi") - public void executeAsync() { - if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.GINGERBREAD_MR1) { - executeOnExecutor(THREAD_POOL_EXECUTOR); - } else { - execute(); - } - } - -} diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java index 1cb653f01..4449d82c2 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlFeedQueuer.java @@ -9,8 +9,8 @@ import java.util.Arrays; import de.danoeh.antennapod.activity.OpmlImportHolder; import de.danoeh.antennapod.core.R; +import de.danoeh.antennapod.core.export.opml.OpmlElement; import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.opml.OpmlElement; import de.danoeh.antennapod.core.storage.DownloadRequestException; import de.danoeh.antennapod.core.storage.DownloadRequester; diff --git a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java index f3b3aeca9..62ea85811 100644 --- a/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java +++ b/app/src/main/java/de/danoeh/antennapod/asynctask/OpmlImportWorker.java @@ -14,8 +14,8 @@ import java.io.Reader; import java.util.ArrayList; import de.danoeh.antennapod.core.R; -import de.danoeh.antennapod.core.opml.OpmlElement; -import de.danoeh.antennapod.core.opml.OpmlReader; +import de.danoeh.antennapod.core.export.opml.OpmlElement; +import de.danoeh.antennapod.core.export.opml.OpmlReader; public class OpmlImportWorker extends AsyncTask<Void, Void, ArrayList<OpmlElement>> { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java index 577a3ecbe..ac073141d 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/EpisodesApplyActionFragment.java @@ -225,6 +225,10 @@ public class EpisodesApplyActionFragment extends Fragment { checkQueued(false); resId = R.string.selected_not_queued_label; break; + case R.id.check_has_media: + checkWithMedia(); + resId = R.string.selected_has_media_label; + break; case R.id.sort_title_a_z: sortByTitle(false); return true; @@ -357,6 +361,17 @@ public class EpisodesApplyActionFragment extends Fragment { refreshCheckboxes(); } + private void checkWithMedia() { + for (FeedItem episode : episodes) { + if(episode.hasMedia()) { + checkedIds.add(episode.getId()); + } else { + checkedIds.remove(episode.getId()); + } + } + refreshCheckboxes(); + } + private void refreshTitles() { titles.clear(); for(FeedItem episode : episodes) { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java index 98a4b5356..0bd75b5b0 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/ProxyDialog.java @@ -18,10 +18,6 @@ import android.widget.TextView; import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.internal.MDButton; -import com.squareup.okhttp.Credentials; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; import java.io.IOException; import java.net.InetSocketAddress; @@ -33,6 +29,10 @@ import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.core.service.download.ProxyConfig; +import okhttp3.Credentials; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import rx.Observable; import rx.Subscriber; import rx.Subscription; @@ -258,10 +258,11 @@ public class ProxyDialog { SocketAddress address = InetSocketAddress.createUnresolved(host, portValue); Proxy.Type proxyType = Proxy.Type.valueOf(type.toUpperCase()); Proxy proxy = new Proxy(proxyType, address); - OkHttpClient client = AntennapodHttpClient.newHttpClient(); - client.setConnectTimeout(10, TimeUnit.SECONDS); - client.setProxy(proxy); - client.interceptors().clear(); + OkHttpClient.Builder builder = AntennapodHttpClient.newBuilder() + .connectTimeout(10, TimeUnit.SECONDS) + .proxy(proxy); + builder.interceptors().clear(); + OkHttpClient client = builder.build(); if(!TextUtils.isEmpty(username)) { String credentials = Credentials.basic(username, password); client.interceptors().add(chain -> { diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java new file mode 100644 index 000000000..31a544582 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/dialog/RenameFeedDialog.java @@ -0,0 +1,44 @@ +package de.danoeh.antennapod.dialog; + +import android.app.Activity; +import android.text.InputType; + +import com.afollestad.materialdialogs.MaterialDialog; + +import java.lang.ref.WeakReference; + +import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.storage.DBWriter; + +public class RenameFeedDialog { + + private final WeakReference<Activity> activityRef; + private final Feed feed; + + public RenameFeedDialog(Activity activity, Feed feed) { + this.activityRef = new WeakReference<>(activity); + this.feed = feed; + } + + public void show() { + Activity activity = activityRef.get(); + if(activity == null) { + return; + } + new MaterialDialog.Builder(activity) + .title(de.danoeh.antennapod.core.R.string.rename_feed_label) + .inputType(InputType.TYPE_CLASS_TEXT) + .input(feed.getTitle(), feed.getTitle(), true, (dialog, input) -> { + feed.setCustomTitle(input.toString()); + DBWriter.setFeedCustomTitle(feed); + dialog.dismiss(); + }) + .neutralText(de.danoeh.antennapod.core.R.string.reset) + .onNeutral((dialog, which) -> dialog.getInputEditText().setText(feed.getFeedTitle())) + .negativeText(de.danoeh.antennapod.core.R.string.cancel_label) + .onNegative((dialog, which) -> dialog.dismiss()) + .autoDismiss(false) + .show(); + } + +} diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java index 8a13a75d9..7d6a66a54 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java @@ -1,7 +1,7 @@ package de.danoeh.antennapod.dialog; import android.content.Context; -import android.content.SharedPreferences; +import android.support.design.widget.Snackbar; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; @@ -9,6 +9,7 @@ import android.view.View; import android.view.inputmethod.InputMethodManager; import android.widget.ArrayAdapter; import android.widget.CheckBox; +import android.widget.CompoundButton; import android.widget.EditText; import android.widget.Spinner; import android.widget.Toast; @@ -16,36 +17,27 @@ import android.widget.Toast; import com.afollestad.materialdialogs.DialogAction; import com.afollestad.materialdialogs.MaterialDialog; -import java.util.concurrent.TimeUnit; - import de.danoeh.antennapod.R; +import de.danoeh.antennapod.core.event.MessageEvent; +import de.danoeh.antennapod.core.preferences.SleepTimerPreferences; +import de.greenrobot.event.EventBus; public abstract class SleepTimerDialog { private static final String TAG = SleepTimerDialog.class.getSimpleName(); - private static final int DEFAULT_SPINNER_POSITION = 1; - private Context context; - private String PREF_NAME = "SleepTimerDialog"; - private String PREF_VALUE = "LastValue"; - private String PREF_TIME_UNIT = "LastTimeUnit"; - private String PREF_VIBRATE = "Vibrate"; - private String PREF_SHAKE_TO_RESET = "ShakeToReset"; - private SharedPreferences prefs; private MaterialDialog dialog; private EditText etxtTime; private Spinner spTimeUnit; private CheckBox cbShakeToReset; private CheckBox cbVibrate; + private CheckBox chAutoEnable; - private TimeUnit[] units = { TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS }; - - public SleepTimerDialog(Context context) { + protected SleepTimerDialog(Context context) { this.context = context; - prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); } public MaterialDialog createNewDialog() { @@ -58,7 +50,7 @@ public abstract class SleepTimerDialog { builder.onPositive((dialog, which) -> { try { savePreferences(); - long input = readTimeMillis(); + long input = SleepTimerPreferences.timerMillis(); onTimerSet(input, cbShakeToReset.isChecked(), cbVibrate.isChecked()); dialog.dismiss(); } catch (NumberFormatException e) { @@ -75,8 +67,9 @@ public abstract class SleepTimerDialog { spTimeUnit = (Spinner) view.findViewById(R.id.spTimeUnit); cbShakeToReset = (CheckBox) view.findViewById(R.id.cbShakeToReset); cbVibrate = (CheckBox) view.findViewById(R.id.cbVibrate); + chAutoEnable = (CheckBox) view.findViewById(R.id.chAutoEnable); - etxtTime.setText(prefs.getString(PREF_VALUE, "15")); + etxtTime.setText(SleepTimerPreferences.lastTimerValue()); etxtTime.addTextChangedListener(new TextWatcher() { @Override public void afterTextChanged(Editable s) { @@ -104,12 +97,17 @@ public abstract class SleepTimerDialog { android.R.layout.simple_spinner_item, spinnerContent); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spTimeUnit.setAdapter(spinnerAdapter); - int selection = prefs.getInt(PREF_TIME_UNIT, DEFAULT_SPINNER_POSITION); - spTimeUnit.setSelection(selection); + spTimeUnit.setSelection(SleepTimerPreferences.lastTimerTimeUnit()); - cbShakeToReset.setChecked(prefs.getBoolean(PREF_SHAKE_TO_RESET, true)); - cbVibrate.setChecked(prefs.getBoolean(PREF_VIBRATE, true)); + cbShakeToReset.setChecked(SleepTimerPreferences.shakeToReset()); + cbVibrate.setChecked(SleepTimerPreferences.vibrate()); + chAutoEnable.setChecked(SleepTimerPreferences.autoEnable()); + chAutoEnable.setOnCheckedChangeListener((compoundButton, isChecked) -> { + SleepTimerPreferences.setAutoEnable(isChecked); + int messageString = isChecked ? R.string.sleep_timer_enabled_label : R.string.sleep_timer_disabled_label; + EventBus.getDefault().post(new MessageEvent(context.getString(messageString))); + }); return dialog; } @@ -125,19 +123,12 @@ public abstract class SleepTimerDialog { public abstract void onTimerSet(long millis, boolean shakeToReset, boolean vibrate); - private long readTimeMillis() { - TimeUnit selectedUnit = units[spTimeUnit.getSelectedItemPosition()]; - long value = Long.parseLong(etxtTime.getText().toString()); - return selectedUnit.toMillis(value); - } - private void savePreferences() { - prefs.edit() - .putString(PREF_VALUE, etxtTime.getText().toString()) - .putInt(PREF_TIME_UNIT, spTimeUnit.getSelectedItemPosition()) - .putBoolean(PREF_SHAKE_TO_RESET, cbShakeToReset.isChecked()) - .putBoolean(PREF_VIBRATE, cbVibrate.isChecked()) - .apply(); + SleepTimerPreferences.setLastTimer(etxtTime.getText().toString(), + spTimeUnit.getSelectedItemPosition()); + SleepTimerPreferences.setShakeToReset(cbShakeToReset.isChecked()); + SleepTimerPreferences.setVibrate(cbVibrate.isChecked()); + SleepTimerPreferences.setAutoEnable(chAutoEnable.isChecked()); } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java index 45364ca07..f14ebbdaf 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java @@ -39,10 +39,11 @@ public class AddFeedFragment extends Fragment { etxtFeedurl.setText(args.getString(ARG_FEED_URL)); } + Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes); Button butBrowserGpoddernet = (Button) root.findViewById(R.id.butBrowseGpoddernet); + Button butSearchFyyd = (Button) root.findViewById(R.id.butSearchFyyd); Button butOpmlImport = (Button) root.findViewById(R.id.butOpmlImport); Button butConfirm = (Button) root.findViewById(R.id.butConfirm); - Button butSearchITunes = (Button) root.findViewById(R.id.butSearchItunes); final MainActivity activity = (MainActivity) getActivity(); activity.getSupportActionBar().setTitle(R.string.add_feed_label); @@ -51,6 +52,8 @@ public class AddFeedFragment extends Fragment { butBrowserGpoddernet.setOnClickListener(v -> activity.loadChildFragment(new GpodnetMainFragment())); + butSearchFyyd.setOnClickListener(v -> activity.loadChildFragment(new FyydSearchFragment())); + butOpmlImport.setOnClickListener(v -> startActivity(new Intent(getActivity(), OpmlImportFromPathActivity.class))); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java index 29df6617d..ab8808093 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AllEpisodesFragment.java @@ -227,22 +227,32 @@ public class AllEpisodesFragment extends Fragment { } return true; case R.id.mark_all_read_item: - ConfirmationDialog conDialog = new ConfirmationDialog(getActivity(), + ConfirmationDialog markAllReadConfirmationDialog = new ConfirmationDialog(getActivity(), R.string.mark_all_read_label, R.string.mark_all_read_confirmation_msg) { @Override - public void onConfirmButtonPressed( - DialogInterface dialog) { + public void onConfirmButtonPressed(DialogInterface dialog) { dialog.dismiss(); DBWriter.markAllItemsRead(); Toast.makeText(getActivity(), R.string.mark_all_read_msg, Toast.LENGTH_SHORT).show(); } }; - conDialog.createNewDialog().show(); + markAllReadConfirmationDialog.createNewDialog().show(); return true; case R.id.mark_all_seen_item: - DBWriter.markNewItemsSeen(); + ConfirmationDialog markAllSeenConfirmationDialog = new ConfirmationDialog(getActivity(), + R.string.mark_all_seen_label, + R.string.mark_all_seen_confirmation_msg) { + + @Override + public void onConfirmButtonPressed(DialogInterface dialog) { + dialog.dismiss(); + DBWriter.markNewItemsSeen(); + Toast.makeText(getActivity(), R.string.mark_all_seen_msg, Toast.LENGTH_SHORT).show(); + } + }; + markAllSeenConfirmationDialog.createNewDialog().show(); return true; default: return false; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java index 77e66f3b0..4d34d076d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ChaptersFragment.java @@ -69,16 +69,18 @@ public class ChaptersFragment extends ListFragment implements MediaplayerInfoCon @Override public void onMediaChanged(Playable media) { - if(this.media == media || adapter == null) { + if(this.media == media) { return; } this.media = media; - adapter.setMedia(media); - adapter.notifyDataSetChanged(); - if(media == null || media.getChapters() == null || media.getChapters().size() == 0) { - setEmptyText(getString(R.string.no_items_label)); - } else { - setEmptyText(null); + if (adapter != null) { + adapter.setMedia(media); + adapter.notifyDataSetChanged(); + if(media == null || media.getChapters() == null || media.getChapters().size() == 0) { + setEmptyText(getString(R.string.no_items_label)); + } else { + setEmptyText(null); + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java index 856888ee0..1d3fcefba 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CoverFragment.java @@ -33,22 +33,15 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra public static CoverFragment newInstance(Playable item) { CoverFragment f = new CoverFragment(); - if (item != null) { - Bundle args = new Bundle(); - args.putParcelable(ARG_PLAYABLE, item); - f.setArguments(args); - } + f.media = item; return f; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - Bundle args = getArguments(); - if (args != null) { - media = args.getParcelable(ARG_PLAYABLE); - } else { - Log.e(TAG, TAG + " was called with invalid arguments"); + if (media == null) { + Log.e(TAG, TAG + " was called without media"); } } @@ -98,11 +91,13 @@ public class CoverFragment extends Fragment implements MediaplayerInfoContentFra @Override public void onMediaChanged(Playable media) { - if(!isAdded() || this.media == media) { + if(this.media == media) { return; } this.media = media; - loadMediaInfo(); + if (isAdded()) { + loadMediaInfo(); + } } } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java new file mode 100644 index 000000000..7c1ec5ec1 --- /dev/null +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FyydSearchFragment.java @@ -0,0 +1,192 @@ +package de.danoeh.antennapod.fragment; + +import android.content.Intent; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.support.v4.view.MenuItemCompat; +import android.support.v7.widget.SearchView; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.GridView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; + +import de.danoeh.antennapod.R; +import de.danoeh.antennapod.activity.OnlineFeedViewActivity; +import de.danoeh.antennapod.adapter.itunes.ItunesAdapter; +import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; +import de.danoeh.antennapod.menuhandler.MenuItemUtils; +import de.mfietz.fyydlin.FyydClient; +import de.mfietz.fyydlin.FyydResponse; +import de.mfietz.fyydlin.SearchHit; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; + +import static de.danoeh.antennapod.adapter.itunes.ItunesAdapter.Podcast; +import static java.util.Collections.emptyList; + +public class FyydSearchFragment extends Fragment { + + private static final String TAG = "FyydSearchFragment"; + + /** + * Adapter responsible with the search results + */ + private ItunesAdapter adapter; + private GridView gridView; + private ProgressBar progressBar; + private TextView txtvError; + private Button butRetry; + private TextView txtvEmpty; + + private FyydClient client = new FyydClient(AntennapodHttpClient.getHttpClient()); + + /** + * List of podcasts retreived from the search + */ + private List<Podcast> searchResults; + private Subscription subscription; + + /** + * Constructor + */ + public FyydSearchFragment() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setHasOptionsMenu(true); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View root = inflater.inflate(R.layout.fragment_itunes_search, container, false); + gridView = (GridView) root.findViewById(R.id.gridView); + adapter = new ItunesAdapter(getActivity(), new ArrayList<>()); + gridView.setAdapter(adapter); + + //Show information about the podcast when the list item is clicked + gridView.setOnItemClickListener((parent, view1, position, id) -> { + Podcast podcast = searchResults.get(position); + Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class); + intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, podcast.feedUrl); + intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, podcast.title); + startActivity(intent); + }); + progressBar = (ProgressBar) root.findViewById(R.id.progressBar); + txtvError = (TextView) root.findViewById(R.id.txtvError); + butRetry = (Button) root.findViewById(R.id.butRetry); + txtvEmpty = (TextView) root.findViewById(android.R.id.empty); + + return root; + } + + @Override + public void onDestroy() { + super.onDestroy(); + if (subscription != null) { + subscription.unsubscribe(); + } + adapter = null; + } + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + inflater.inflate(R.menu.itunes_search, menu); + MenuItem searchItem = menu.findItem(R.id.action_search); + final SearchView sv = (SearchView) MenuItemCompat.getActionView(searchItem); + MenuItemUtils.adjustTextColor(getActivity(), sv); + sv.setQueryHint(getString(R.string.search_fyyd_label)); + sv.setOnQueryTextListener(new SearchView.OnQueryTextListener() { + @Override + public boolean onQueryTextSubmit(String s) { + sv.clearFocus(); + search(s); + return true; + } + + @Override + public boolean onQueryTextChange(String s) { + return false; + } + }); + MenuItemCompat.setOnActionExpandListener(searchItem, new MenuItemCompat.OnActionExpandListener() { + @Override + public boolean onMenuItemActionExpand(MenuItem item) { + return true; + } + + @Override + public boolean onMenuItemActionCollapse(MenuItem item) { + getActivity().getSupportFragmentManager().popBackStack(); + return true; + } + }); + MenuItemCompat.expandActionView(searchItem); + } + + private void search(String query) { + if (subscription != null) { + subscription.unsubscribe(); + } + showOnlyProgressBar(); + subscription = client.searchPodcasts(query) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + progressBar.setVisibility(View.GONE); + processSearchResult(result); + }, error -> { + Log.e(TAG, Log.getStackTraceString(error)); + progressBar.setVisibility(View.GONE); + txtvError.setText(error.toString()); + txtvError.setVisibility(View.VISIBLE); + butRetry.setOnClickListener(v -> search(query)); + butRetry.setVisibility(View.VISIBLE); + }); + } + + private void showOnlyProgressBar() { + gridView.setVisibility(View.GONE); + txtvError.setVisibility(View.GONE); + butRetry.setVisibility(View.GONE); + txtvEmpty.setVisibility(View.GONE); + progressBar.setVisibility(View.VISIBLE); + } + + void processSearchResult(FyydResponse response) { + adapter.clear(); + if (!response.getData().isEmpty()) { + adapter.clear(); + searchResults = new ArrayList<>(); + for (SearchHit searchHit : response.getData().values()) { + Podcast podcast = Podcast.fromSearch(searchHit); + searchResults.add(podcast); + } + } else { + searchResults = emptyList(); + } + for(Podcast podcast : searchResults) { + adapter.add(podcast); + } + adapter.notifyDataSetInvalidated(); + gridView.setVisibility(!searchResults.isEmpty() ? View.VISIBLE : View.GONE); + txtvEmpty.setVisibility(searchResults.isEmpty() ? View.VISIBLE : View.GONE); + } + +} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java index 89a1a8d50..a0586fe16 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemDescriptionFragment.java @@ -185,8 +185,10 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo super.onViewCreated(view, savedInstanceState); Bundle args = getArguments(); if (args.containsKey(ARG_PLAYABLE)) { - media = args.getParcelable(ARG_PLAYABLE); - shownotesProvider = media; + if (media == null) { + media = args.getParcelable(ARG_PLAYABLE); + shownotesProvider = media; + } load(); } else if (args.containsKey(ARG_FEEDITEM_ID)) { long id = getArguments().getLong(ARG_FEEDITEM_ID); @@ -377,12 +379,14 @@ public class ItemDescriptionFragment extends Fragment implements MediaplayerInfo @Override public void onMediaChanged(Playable media) { - if(this.media == media || webvDescription == null) { + if(this.media == media) { return; } this.media = media; this.shownotesProvider = media; - load(); + if (webvDescription != null) { + load(); + } } } 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 13f5481e9..75f9c0d35 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItemlistFragment.java @@ -67,6 +67,7 @@ import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.LongList; import de.danoeh.antennapod.core.util.gui.MoreContentListFooterUtil; import de.danoeh.antennapod.dialog.EpisodesApplyActionFragment; +import de.danoeh.antennapod.dialog.RenameFeedDialog; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; import de.danoeh.antennapod.menuhandler.MenuItemUtils; @@ -99,6 +100,7 @@ public class ItemlistFragment extends ListFragment { private boolean itemsLoaded = false; private boolean viewsCreated = false; + private boolean headerCreated = false; private List<Downloader> downloaderList; @@ -106,6 +108,7 @@ public class ItemlistFragment extends ListFragment { private boolean isUpdatingFeed; + private TextView txtvTitle; private IconTextView txtvFailure; private TextView txtvInformation; @@ -248,6 +251,9 @@ public class ItemlistFragment extends ListFragment { .newInstance(feed.getItems()); ((MainActivity)getActivity()).loadChildFragment(fragment); return true; + case R.id.rename_item: + new RenameFeedDialog(getActivity(), feed).show(); + return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover( getActivity(), feed) { @@ -415,6 +421,7 @@ public class ItemlistFragment extends ListFragment { public void update(EventDistributor eventDistributor, Integer arg) { if ((EVENTS & arg) != 0) { Log.d(TAG, "Received contentUpdate Intent. arg " + arg); + refreshHeaderView(); loadItems(); updateProgressBarVisibility(); } @@ -460,8 +467,8 @@ public class ItemlistFragment extends ListFragment { } private void refreshHeaderView() { - if (getListView() == null || feed == null) { - Log.e(TAG, "Unable to setup listview: recyclerView = null or feed = null"); + if (getListView() == null || feed == null || !headerCreated) { + Log.e(TAG, "Unable to refresh header view"); return; } if(feed.hasLastUpdateFailed()) { @@ -469,6 +476,7 @@ public class ItemlistFragment extends ListFragment { } else { txtvFailure.setVisibility(View.GONE); } + txtvTitle.setText(feed.getTitle()); if(feed.getItemFilter() != null) { FeedItemFilter filter = feed.getItemFilter(); if(filter.getValues().length > 0) { @@ -498,7 +506,7 @@ public class ItemlistFragment extends ListFragment { View header = inflater.inflate(R.layout.feeditemlist_header, lv, false); lv.addHeaderView(header); - TextView txtvTitle = (TextView) header.findViewById(R.id.txtvTitle); + txtvTitle = (TextView) header.findViewById(R.id.txtvTitle); TextView txtvAuthor = (TextView) header.findViewById(R.id.txtvAuthor); ImageView imgvBackground = (ImageView) header.findViewById(R.id.imgvBackground); ImageView imgvCover = (ImageView) header.findViewById(R.id.imgvCover); @@ -539,6 +547,7 @@ public class ItemlistFragment extends ListFragment { startActivity(startIntent); } }); + headerCreated = true; } diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java index b736688b9..db88c070d 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java @@ -18,9 +18,6 @@ import android.widget.ProgressBar; import android.widget.TextView; import com.afollestad.materialdialogs.MaterialDialog; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; import org.json.JSONArray; import org.json.JSONException; @@ -39,6 +36,9 @@ import de.danoeh.antennapod.adapter.itunes.ItunesAdapter; import de.danoeh.antennapod.core.ClientConfig; import de.danoeh.antennapod.core.service.download.AntennapodHttpClient; import de.danoeh.antennapod.menuhandler.MenuItemUtils; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java index 3ddd5245a..01119bcff 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -26,6 +26,7 @@ import de.danoeh.antennapod.core.service.playback.PlaybackService; import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBWriter; import de.danoeh.antennapod.core.util.FeedItemUtil; +import de.danoeh.antennapod.dialog.RenameFeedDialog; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; @@ -102,7 +103,7 @@ public class SubscriptionFragment extends Fragment { if(subscription != null) { subscription.unsubscribe(); } - subscription = Observable.fromCallable(() -> DBReader.getNavDrawerData()) + subscription = Observable.fromCallable(DBReader::getNavDrawerData) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> { @@ -164,6 +165,9 @@ public class SubscriptionFragment extends Fragment { .subscribe(result -> loadSubscriptions(), error -> Log.e(TAG, Log.getStackTraceString(error))); return true; + case R.id.rename_item: + new RenameFeedDialog(getActivity(), feed).show(); + return true; case R.id.remove_item: final FeedRemover remover = new FeedRemover(getContext(), feed) { @Override diff --git a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java index 4c28b197d..ac703e13e 100644 --- a/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/menuhandler/MenuItemUtils.java @@ -28,6 +28,7 @@ public class MenuItemUtils extends de.danoeh.antennapod.core.menuhandler.MenuIte } } + @SuppressWarnings("ResourceType") public static void refreshLockItem(Context context, Menu menu) { final MenuItem queueLock = menu.findItem(de.danoeh.antennapod.R.id.queue_lock); int[] lockIcons = new int[] { de.danoeh.antennapod.R.attr.ic_lock_open, de.danoeh.antennapod.R.attr.ic_lock_closed }; 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 77764247d..7777af450 100644 --- a/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java +++ b/app/src/main/java/de/danoeh/antennapod/preferences/PreferenceController.java @@ -3,6 +3,7 @@ package de.danoeh.antennapod.preferences; import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; +import android.app.ProgressDialog; import android.app.TimePickerDialog; import android.content.ActivityNotFoundException; import android.content.Context; @@ -42,6 +43,8 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; +import java.util.Comparator; import java.util.GregorianCalendar; import java.util.List; import java.util.concurrent.TimeUnit; @@ -55,7 +58,10 @@ import de.danoeh.antennapod.activity.MediaplayerActivity; import de.danoeh.antennapod.activity.PreferenceActivity; import de.danoeh.antennapod.activity.PreferenceActivityGingerbread; import de.danoeh.antennapod.activity.StatisticsActivity; -import de.danoeh.antennapod.asynctask.OpmlExportWorker; +import de.danoeh.antennapod.asynctask.ExportWorker; +import de.danoeh.antennapod.core.export.ExportWriter; +import de.danoeh.antennapod.core.export.html.HtmlWriter; +import de.danoeh.antennapod.core.export.opml.OpmlWriter; import de.danoeh.antennapod.core.preferences.GpodnetPreferences; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.GpodnetSyncService; @@ -67,6 +73,10 @@ 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 rx.Observable; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; /** * Sets up a preference UI that lets the user change user preferences. @@ -76,55 +86,36 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc private static final String TAG = "PreferenceController"; - public static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings"; - public static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate"; - public static final String PREF_FLATTR_REVOKE = "prefRevokeAccess"; - public static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs"; - public static final String PREF_OPML_EXPORT = "prefOpmlExport"; - public static final String STATISTICS = "statistics"; - public static final String PREF_ABOUT = "prefAbout"; - public static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir"; - public static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings"; - public static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher"; + private static final String PREF_FLATTR_SETTINGS = "prefFlattrSettings"; + private static final String PREF_FLATTR_AUTH = "pref_flattr_authenticate"; + private static final String PREF_FLATTR_REVOKE = "prefRevokeAccess"; + private static final String PREF_AUTO_FLATTR_PREFS = "prefAutoFlattrPrefs"; + private static final String PREF_OPML_EXPORT = "prefOpmlExport"; + private static final String PREF_HTML_EXPORT = "prefHtmlExport"; + private static final String STATISTICS = "statistics"; + private static final String PREF_ABOUT = "prefAbout"; + private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir"; + private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings"; + private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher"; public static final String PREF_PLAYBACK_REWIND_DELTA_LAUNCHER = "prefPlaybackRewindDeltaLauncher"; public static final String PREF_PLAYBACK_FAST_FORWARD_DELTA_LAUNCHER = "prefPlaybackFastForwardDeltaLauncher"; - public static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate"; - public static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information"; - public static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync"; - public static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout"; - public static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname"; - public static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications"; - public static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; - public static final String PREF_PROXY = "prefProxy"; - public static final String PREF_KNOWN_ISSUES = "prefKnownIssues"; - public static final String PREF_FAQ = "prefFaq"; - public static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport"; - - private final PreferenceUI ui; - - private CheckBoxPreference[] selectedNetworks; - + private static final String PREF_GPODNET_LOGIN = "pref_gpodnet_authenticate"; + private static final String PREF_GPODNET_SETLOGIN_INFORMATION = "pref_gpodnet_setlogin_information"; + private static final String PREF_GPODNET_SYNC = "pref_gpodnet_sync"; + private static final String PREF_GPODNET_FORCE_FULL_SYNC = "pref_gpodnet_force_full_sync"; + private static final String PREF_GPODNET_LOGOUT = "pref_gpodnet_logout"; + private static final String PREF_GPODNET_HOSTNAME = "pref_gpodnet_hostname"; + private static final String PREF_GPODNET_NOTIFICATIONS = "pref_gpodnet_notifications"; + private static final String PREF_EXPANDED_NOTIFICATION = "prefExpandNotify"; + private static final String PREF_PROXY = "prefProxy"; + private static final String PREF_KNOWN_ISSUES = "prefKnownIssues"; + private static final String PREF_FAQ = "prefFaq"; + private static final String PREF_SEND_CRASH_REPORT = "prefSendCrashReport"; private static final String[] EXTERNAL_STORAGE_PERMISSIONS = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE }; private static final int PERMISSION_REQUEST_EXTERNAL_STORAGE = 41; - - public PreferenceController(PreferenceUI ui) { - this.ui = ui; - PreferenceManager.getDefaultSharedPreferences(ui.getActivity().getApplicationContext()) - .registerOnSharedPreferenceChangeListener(this); - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if(key.equals(UserPreferences.PREF_SONIC)) { - CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC); - if(prefSonic != null) { - prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false)); - } - } - } - + private final PreferenceUI ui; private final SharedPreferences.OnSharedPreferenceChangeListener gpoddernetListener = (sharedPreferences, key) -> { if (GpodnetPreferences.PREF_LAST_SYNC_ATTEMPT_TIMESTAMP.equals(key)) { @@ -132,6 +123,14 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc GpodnetPreferences.getLastSyncAttemptTimestamp()); } }; + private CheckBoxPreference[] selectedNetworks; + private Subscription subscription; + + public PreferenceController(PreferenceUI ui) { + this.ui = ui; + PreferenceManager.getDefaultSharedPreferences(ui.getActivity().getApplicationContext()) + .registerOnSharedPreferenceChangeListener(this); + } /** * Returns the preference activity that should be used on this device. @@ -146,6 +145,16 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } } + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if(key.equals(UserPreferences.PREF_SONIC)) { + CheckBoxPreference prefSonic = (CheckBoxPreference) ui.findPreference(UserPreferences.PREF_SONIC); + if(prefSonic != null) { + prefSonic.setChecked(sharedPreferences.getBoolean(UserPreferences.PREF_SONIC, false)); + } + } + } + public void onCreate() { final Activity activity = ui.getActivity(); @@ -181,11 +190,9 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc } ); ui.findPreference(PreferenceController.PREF_OPML_EXPORT).setOnPreferenceClickListener( - preference -> { - new OpmlExportWorker(activity).executeAsync(); - return true; - } - ); + preference -> export(new OpmlWriter())); + ui.findPreference(PreferenceController.PREF_HTML_EXPORT).setOnPreferenceClickListener( + preference -> export(new HtmlWriter())); ui.findPreference(PreferenceController.PREF_CHOOSE_DATA_DIR).setOnPreferenceClickListener( preference -> { if (Build.VERSION_CODES.KITKAT <= Build.VERSION.SDK_INT && @@ -361,6 +368,18 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc toast.show(); return true; }); + ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC). + setOnPreferenceClickListener(preference -> { + GpodnetPreferences.setLastSubscriptionSyncTimestamp(0L); + GpodnetPreferences.setLastEpisodeActionsSyncTimestamp(0L); + GpodnetPreferences.setLastSyncAttempt(false, 0); + updateLastGpodnetSyncReport(false, 0); + GpodnetSyncService.sendSyncIntent(ui.getActivity().getApplicationContext()); + Toast toast = Toast.makeText(ui.getActivity(), R.string.pref_gpodnet_sync_started, + Toast.LENGTH_SHORT); + toast.show(); + return true; + }); ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setOnPreferenceClickListener( preference -> { GpodnetPreferences.logout(); @@ -440,6 +459,40 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc setSelectedNetworksEnabled(UserPreferences.isEnableAutodownloadWifiFilter()); } + private boolean export(ExportWriter exportWriter) { + Context context = ui.getActivity(); + final ProgressDialog progressDialog = new ProgressDialog(context); + progressDialog.setMessage(context.getString(R.string.exporting_label)); + progressDialog.setIndeterminate(true); + progressDialog.show(); + final AlertDialog.Builder alert = new AlertDialog.Builder(context) + .setNeutralButton(android.R.string.ok, (dialog, which) -> dialog.dismiss()); + Observable<File> observable = new ExportWorker(exportWriter).exportObservable(); + subscription = observable.subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(output -> { + alert.setTitle(R.string.opml_export_success_title); + String message = context.getString(R.string.opml_export_success_sum) + output.toString(); + alert.setMessage(message); + alert.setPositiveButton(R.string.send_label, (dialog, which) -> { + Uri outputUri = Uri.fromFile(output); + Intent sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.putExtra(Intent.EXTRA_SUBJECT, + context.getResources().getText(R.string.opml_export_label)); + sendIntent.putExtra(Intent.EXTRA_STREAM, outputUri); + sendIntent.setType("text/plain"); + context.startActivity(Intent.createChooser(sendIntent, + context.getResources().getText(R.string.send_label))); + }); + alert.create().show(); + }, error -> { + alert.setTitle(R.string.export_error_label); + alert.setMessage(error.getMessage()); + alert.show(); + }, () -> progressDialog.dismiss()); + return true; + } + private void openInBrowser(String url) { try { Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); @@ -464,6 +517,12 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc GpodnetPreferences.unregisterOnSharedPreferenceChangeListener(gpoddernetListener); } + public void onStop() { + if(subscription != null) { + subscription.unsubscribe(); + } + } + @SuppressLint("NewApi") public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK && @@ -505,6 +564,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc ui.findPreference(PreferenceController.PREF_GPODNET_LOGIN).setEnabled(!loggedIn); ui.findPreference(PreferenceController.PREF_GPODNET_SETLOGIN_INFORMATION).setEnabled(loggedIn); ui.findPreference(PreferenceController.PREF_GPODNET_SYNC).setEnabled(loggedIn); + ui.findPreference(PreferenceController.PREF_GPODNET_FORCE_FULL_SYNC).setEnabled(loggedIn); ui.findPreference(PreferenceController.PREF_GPODNET_LOGOUT).setEnabled(loggedIn); ui.findPreference(PREF_GPODNET_NOTIFICATIONS).setEnabled(loggedIn); if(loggedIn) { @@ -524,7 +584,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc private void updateLastGpodnetSyncReport(boolean successful, long lastTime) { Preference sync = ui.findPreference(PREF_GPODNET_SYNC); if (lastTime != 0) { - sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_sum) + "\n" + + sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum) + "\n" + ui.getActivity().getString(R.string.pref_gpodnet_sync_sum_last_sync_line, ui.getActivity().getString(successful ? R.string.gpodnetsync_pref_report_successful : @@ -535,7 +595,7 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc DateUtils.WEEK_IN_MILLIS, DateUtils.FORMAT_SHOW_TIME))); } else { - sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_sum)); + sync.setSummary(ui.getActivity().getString(R.string.pref_gpodnet_sync_changes_sum)); } } @@ -703,6 +763,12 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc List<WifiConfiguration> networks = wifiservice.getConfiguredNetworks(); if (networks != null) { + Collections.sort(networks, new Comparator<WifiConfiguration>() { + @Override + public int compare(WifiConfiguration x, WifiConfiguration y) { + return x.SSID.compareTo(y.SSID); + } + }); selectedNetworks = new CheckBoxPreference[networks.size()]; List<String> prefValues = Arrays.asList(UserPreferences .getAutodownloadSelectedNetworks()); @@ -787,9 +853,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc hiddenDrawerItems.add(NAV_DRAWER_TAGS[which]); } }); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { - UserPreferences.setHiddenDrawerItems(hiddenDrawerItems); - }); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> + UserPreferences.setHiddenDrawerItems(hiddenDrawerItems)); builder.setNegativeButton(R.string.cancel_label, null); builder.create().show(); } @@ -833,9 +898,8 @@ public class PreferenceController implements SharedPreferences.OnSharedPreferenc preferredButtons.remove((Integer) which); } }); - builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> { - UserPreferences.setCompactNotificationButtons(preferredButtons); - }); + builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> + UserPreferences.setCompactNotificationButtons(preferredButtons)); builder.setNegativeButton(R.string.cancel_label, null); builder.create().show(); } |