diff options
Diffstat (limited to 'app/src')
15 files changed, 640 insertions, 549 deletions
diff --git a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java index edb576249..385201f25 100644 --- a/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java +++ b/app/src/androidTest/java/de/test/antennapod/service/playback/PlaybackServiceTaskManagerTest.java @@ -122,11 +122,21 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { } @Override + public void onSleepTimerAlmostExpired() { + + } + + @Override public void onSleepTimerExpired() { } @Override + public void onSleepTimerReset() { + + } + + @Override public void onWidgetUpdaterTick() { } @@ -170,11 +180,21 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { } @Override + public void onSleepTimerAlmostExpired() { + + } + + @Override public void onSleepTimerExpired() { } @Override + public void onSleepTimerReset() { + + } + + @Override public void onWidgetUpdaterTick() { countDownLatch.countDown(); } @@ -221,7 +241,7 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, defaultPSTM); pstm.startWidgetUpdater(); pstm.startPositionSaver(); - pstm.setSleepTimer(100000); + pstm.setSleepTimer(100000, false, false); pstm.cancelAllTasks(); assertFalse(pstm.isPositionSaverActive()); assertFalse(pstm.isWidgetUpdaterActive()); @@ -241,6 +261,11 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { } @Override + public void onSleepTimerAlmostExpired() { + + } + + @Override public void onSleepTimerExpired() { if (countDownLatch.getCount() == 0) { fail(); @@ -249,6 +274,11 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { } @Override + public void onSleepTimerReset() { + + } + + @Override public void onWidgetUpdaterTick() { } @@ -258,7 +288,7 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { } }); - pstm.setSleepTimer(TIME); + pstm.setSleepTimer(TIME, false, false); countDownLatch.await(TIMEOUT, TimeUnit.MILLISECONDS); pstm.shutdown(); } @@ -275,11 +305,21 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { } @Override + public void onSleepTimerAlmostExpired() { + + } + + @Override public void onSleepTimerExpired() { fail("Sleeptimer expired"); } @Override + public void onSleepTimerReset() { + + } + + @Override public void onWidgetUpdaterTick() { } @@ -289,7 +329,7 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { } }); - pstm.setSleepTimer(TIME); + pstm.setSleepTimer(TIME, false, false); pstm.disableSleepTimer(); assertFalse(countDownLatch.await(TIMEOUT, TimeUnit.MILLISECONDS)); pstm.shutdown(); @@ -298,7 +338,7 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { public void testIsSleepTimerActivePositive() { final Context c = getInstrumentation().getTargetContext(); PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, defaultPSTM); - pstm.setSleepTimer(10000); + pstm.setSleepTimer(10000, false, false); assertTrue(pstm.isSleepTimerActive()); pstm.shutdown(); } @@ -306,7 +346,7 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { public void testIsSleepTimerActiveNegative() { final Context c = getInstrumentation().getTargetContext(); PlaybackServiceTaskManager pstm = new PlaybackServiceTaskManager(c, defaultPSTM); - pstm.setSleepTimer(10000); + pstm.setSleepTimer(10000, false, false); pstm.disableSleepTimer(); assertFalse(pstm.isSleepTimerActive()); pstm.shutdown(); @@ -319,11 +359,21 @@ public class PlaybackServiceTaskManagerTest extends InstrumentationTestCase { } @Override + public void onSleepTimerAlmostExpired() { + + } + + @Override public void onSleepTimerExpired() { } @Override + public void onSleepTimerReset() { + + } + + @Override public void onWidgetUpdaterTick() { } diff --git a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java index 65c962f01..286095210 100644 --- a/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java +++ b/app/src/androidTest/java/de/test/antennapod/ui/MainActivityTest.java @@ -13,8 +13,8 @@ import java.util.Arrays; import java.util.List; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity; import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.core.feed.Feed; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.storage.PodDBAdapter; @@ -79,7 +79,7 @@ public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActiv solo.clickOnText(solo.getString(R.string.add_feed_label)); solo.enterText(0, feed.getDownload_url()); solo.clickOnButton(solo.getString(R.string.confirm_label)); - solo.waitForActivity(DefaultOnlineFeedViewActivity.class); + solo.waitForActivity(OnlineFeedViewActivity.class); solo.waitForView(R.id.butSubscribe); assertEquals(solo.getString(R.string.subscribe_label), solo.getButton(0).getText().toString()); solo.clickOnButton(0); diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 710446885..72e7752b1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -203,7 +203,7 @@ android:value="de.danoeh.antennapod.activity.PreferenceActivity"/> <activity - android:name=".activity.DefaultOnlineFeedViewActivity" + android:name=".activity.OnlineFeedViewActivity" android:configChanges="orientation" android:label="@string/add_feed_label"> <meta-data diff --git a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java index 035ab2f22..6ba84c249 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/AboutActivity.java @@ -1,22 +1,42 @@ package de.danoeh.antennapod.activity; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; +import android.util.Log; +import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.LinearLayout; +import org.apache.commons.io.IOUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; + import de.danoeh.antennapod.R; import de.danoeh.antennapod.core.preferences.UserPreferences; +import rx.Observable; +import rx.Subscriber; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; /** * Displays the 'about' screen */ public class AboutActivity extends ActionBarActivity { + private static final String TAG = AboutActivity.class.getSimpleName(); + private WebView webview; private LinearLayout webviewContainer; + private Subscription subscription; + @Override protected void onCreate(Bundle savedInstanceState) { setTheme(UserPreferences.getTheme()); @@ -25,6 +45,13 @@ public class AboutActivity extends ActionBarActivity { setContentView(R.layout.about); webviewContainer = (LinearLayout) findViewById(R.id.webvContainer); webview = (WebView) findViewById(R.id.webvAbout); + if (UserPreferences.getTheme() == R.style.Theme_AntennaPod_Dark) { + if (Build.VERSION.SDK_INT >= 11 + && Build.VERSION.SDK_INT <= Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) { + webview.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + } + webview.setBackgroundColor(Color.TRANSPARENT); + } webview.setWebViewClient(new WebViewClient() { @Override @@ -34,12 +61,43 @@ public class AboutActivity extends ActionBarActivity { } }); - webview.loadUrl("file:///android_asset/about.html"); + subscription = Observable.create(new Observable.OnSubscribe<String>() { + @Override + public void call(Subscriber<? super String> subscriber) { + InputStream input = null; + try { + TypedArray res = AboutActivity.this.getTheme().obtainStyledAttributes( + new int[] { android.R.attr.textColorPrimary }); + int colorResource = res.getColor(0, 0); + String colorString = String.format("#%06X", 0xFFFFFF & colorResource); + res.recycle(); + input = getAssets().open("about.html"); + String webViewData = IOUtils.toString(input, Charset.defaultCharset()); + webViewData = String.format(webViewData, colorString); + subscriber.onNext(webViewData); + } catch (IOException e) { + subscriber.onError(e); + } finally { + IOUtils.closeQuietly(input); + } + subscriber.onCompleted(); + } + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(webviewData -> { + webview.loadDataWithBaseURL(null, webviewData, "text/html", "utf-8", "about:blank"); + }, error -> { + Log.e(TAG, Log.getStackTraceString(error)); + }); } @Override protected void onDestroy() { super.onDestroy(); + if(subscription != null) { + subscription.unsubscribe(); + } if (webviewContainer != null && webview != null) { webviewContainer.removeAllViews(); webview.destroy(); diff --git a/app/src/main/java/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java deleted file mode 100644 index 0993ed6d6..000000000 --- a/app/src/main/java/de/danoeh/antennapod/activity/DefaultOnlineFeedViewActivity.java +++ /dev/null @@ -1,255 +0,0 @@ -package de.danoeh.antennapod.activity; - -import android.content.Context; -import android.content.Intent; -import android.os.AsyncTask; -import android.os.Bundle; -import android.support.v4.app.NavUtils; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.AdapterView; -import android.widget.ArrayAdapter; -import android.widget.Button; -import android.widget.ImageView; -import android.widget.ListView; -import android.widget.Spinner; -import android.widget.TextView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.load.engine.DiskCacheStrategy; - -import org.apache.commons.lang3.StringUtils; -import org.jsoup.Jsoup; -import org.jsoup.examples.HtmlToPlainText; -import org.jsoup.nodes.Document; - -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import de.danoeh.antennapod.BuildConfig; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.adapter.FeedItemlistDescriptionAdapter; -import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; -import de.danoeh.antennapod.core.feed.EventDistributor; -import de.danoeh.antennapod.core.feed.Feed; -import de.danoeh.antennapod.core.feed.FeedItem; -import de.danoeh.antennapod.core.glide.ApGlideSettings; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DownloadRequestException; -import de.danoeh.antennapod.core.storage.DownloadRequester; - -/** - * Default implementation of OnlineFeedViewActivity. Shows the downloaded feed's items with their descriptions, - * a subscribe button and a spinner for choosing alternate feed URLs. - */ -public class DefaultOnlineFeedViewActivity extends OnlineFeedViewActivity { - private static final String TAG = "DefaultOnlineFeedViewActivity"; - - private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED | EventDistributor.DOWNLOAD_QUEUED | EventDistributor.FEED_LIST_UPDATE; - private volatile List<Feed> feeds; - private Feed feed; - private String selectedDownloadUrl; - - private Button subscribeButton; - - @Override - protected void onCreate(Bundle arg0) { - super.onCreate(arg0); - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - Intent destIntent = new Intent(this, MainActivity.class); - if (NavUtils.shouldUpRecreateTask(this, destIntent)) { - startActivity(destIntent); - } else { - NavUtils.navigateUpFromSameTask(this); - } - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - protected void loadData() { - super.loadData(); - feeds = DBReader.getFeedList(this); - } - - @Override - protected void beforeShowFeedInformation(Feed feed, Map<String, String> alternateFeedUrls) { - super.beforeShowFeedInformation(feed, alternateFeedUrls); - - // remove HTML tags from descriptions - - if (BuildConfig.DEBUG) 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))); - } - } - } - } - - @Override - protected void showFeedInformation(final Feed feed, final Map<String, String> alternateFeedUrls) { - super.showFeedInformation(feed, alternateFeedUrls); - setContentView(R.layout.listview_activity); - - this.feed = feed; - this.selectedDownloadUrl = feed.getDownload_url(); - EventDistributor.getInstance().register(listener); - ListView listView = (ListView) findViewById(R.id.listview); - LayoutInflater inflater = (LayoutInflater) - getSystemService(Context.LAYOUT_INFLATER_SERVICE); - View header = inflater.inflate(R.layout.onlinefeedview_header, listView, false); - listView.addHeaderView(header); - - listView.setAdapter(new FeedItemlistDescriptionAdapter(this, 0, feed.getItems())); - - ImageView cover = (ImageView) header.findViewById(R.id.imgvCover); - TextView title = (TextView) header.findViewById(R.id.txtvTitle); - TextView author = (TextView) header.findViewById(R.id.txtvAuthor); - TextView description = (TextView) header.findViewById(R.id.txtvDescription); - Spinner spAlternateUrls = (Spinner) header.findViewById(R.id.spinnerAlternateUrls); - - subscribeButton = (Button) header.findViewById(R.id.butSubscribe); - - if (feed.getImage() != null && StringUtils.isNotBlank(feed.getImage().getDownload_url())) { - Glide.with(this) - .load(feed.getImage().getDownload_url()) - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate() - .into(cover); - } - - title.setText(feed.getTitle()); - author.setText(feed.getAuthor()); - description.setText(feed.getDescription()); - - subscribeButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - try { - Feed f = new Feed(selectedDownloadUrl, new Date(0), feed.getTitle()); - f.setPreferences(feed.getPreferences()); - DefaultOnlineFeedViewActivity.this.feed = f; - - DownloadRequester.getInstance().downloadFeed( - DefaultOnlineFeedViewActivity.this, - f); - } catch (DownloadRequestException e) { - e.printStackTrace(); - DownloadRequestErrorDialogCreator.newRequestErrorDialog(DefaultOnlineFeedViewActivity.this, - e.getMessage()); - } - setSubscribeButtonState(feed); - } - }); - - if (alternateFeedUrls.isEmpty()) { - spAlternateUrls.setVisibility(View.GONE); - } else { - spAlternateUrls.setVisibility(View.VISIBLE); - - final List<String> alternateUrlsList = new ArrayList<String>(); - final List<String> alternateUrlsTitleList = new ArrayList<String>(); - - alternateUrlsList.add(feed.getDownload_url()); - alternateUrlsTitleList.add(feed.getTitle()); - - - alternateUrlsList.addAll(alternateFeedUrls.keySet()); - for (String url : alternateFeedUrls.keySet()) { - alternateUrlsTitleList.add(alternateFeedUrls.get(url)); - } - ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, alternateUrlsTitleList); - adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spAlternateUrls.setAdapter(adapter); - spAlternateUrls.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { - @Override - public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { - selectedDownloadUrl = alternateUrlsList.get(position); - } - - @Override - public void onNothingSelected(AdapterView<?> parent) { - - } - }); - - - } - setSubscribeButtonState(feed); - - } - - private boolean feedInFeedlist(Feed feed) { - if (feeds == null || feed == null) - return false; - for (Feed f : feeds) { - if (f.getIdentifyingValue().equals(feed.getIdentifyingValue())) { - return true; - } - } - return false; - } - - private void setSubscribeButtonState(Feed feed) { - if (subscribeButton != null && feed != null) { - if (DownloadRequester.getInstance().isDownloadingFile(feed.getDownload_url())) { - subscribeButton.setEnabled(false); - subscribeButton.setText(R.string.downloading_label); - } else if (feedInFeedlist(feed)) { - subscribeButton.setEnabled(false); - subscribeButton.setText(R.string.subscribed_label); - } else { - subscribeButton.setEnabled(true); - subscribeButton.setText(R.string.subscribe_label); - } - } - } - - EventDistributor.EventListener listener = new EventDistributor.EventListener() { - @Override - public void update(EventDistributor eventDistributor, Integer arg) { - if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) { - new AsyncTask<Void, Void, List<Feed>>() { - @Override - protected List<Feed> doInBackground(Void... params) { - return DBReader.getFeedList(DefaultOnlineFeedViewActivity.this); - } - - @Override - protected void onPostExecute(List<Feed> feeds) { - super.onPostExecute(feeds); - DefaultOnlineFeedViewActivity.this.feeds = feeds; - setSubscribeButtonState(feed); - } - }.execute(); - } else if ((arg & EVENTS) != 0) { - setSubscribeButtonState(feed); - } - } - }; - - @Override - protected void onStop() { - super.onStop(); - EventDistributor.getInstance().unregister(listener); - } -} - 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 40a0d1801..e34b4dc67 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java @@ -31,7 +31,7 @@ import de.danoeh.antennapod.core.util.StorageUtils; import de.danoeh.antennapod.core.util.playback.MediaPlayerError; import de.danoeh.antennapod.core.util.playback.Playable; import de.danoeh.antennapod.core.util.playback.PlaybackController; -import de.danoeh.antennapod.dialog.TimeDialog; +import de.danoeh.antennapod.dialog.SleepTimerDialog; /** * Provides general features which are both needed for playing audio and video @@ -323,13 +323,10 @@ public abstract class MediaplayerActivity extends ActionBarActivity break; case R.id.set_sleeptimer_item: if (controller.serviceAvailable()) { - TimeDialog td = new TimeDialog(this, - R.string.set_sleeptimer_label, - R.string.set_sleeptimer_label) { - + SleepTimerDialog td = new SleepTimerDialog(this, 0, 0) { @Override - public void onTimeEntered(long millis) { - controller.setSleepTimer(millis); + public void onTimerSet(long millis, boolean shakeToReset, boolean vibrate) { + controller.setSleepTimer(millis, shakeToReset, vibrate); } }; td.show(); 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 3ab384012..13d5e7acf 100644 --- a/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java +++ b/app/src/main/java/de/danoeh/antennapod/activity/OnlineFeedViewActivity.java @@ -4,18 +4,32 @@ import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; import android.content.Intent; import android.os.Bundle; +import android.os.Looper; +import android.support.v4.app.NavUtils; import android.support.v7.app.ActionBarActivity; import android.util.Log; +import android.view.LayoutInflater; +import android.view.MenuItem; +import android.view.View; +import android.widget.AdapterView; import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.ImageView; import android.widget.LinearLayout; +import android.widget.ListView; import android.widget.ProgressBar; import android.widget.RelativeLayout; +import android.widget.Spinner; +import android.widget.TextView; + +import com.bumptech.glide.Glide; import org.apache.commons.lang3.StringUtils; -import org.xml.sax.SAXException; +import org.jsoup.Jsoup; +import org.jsoup.examples.HtmlToPlainText; +import org.jsoup.nodes.Document; import java.io.File; import java.io.IOException; @@ -24,16 +38,22 @@ import java.util.Date; import java.util.List; import java.util.Map; -import javax.xml.parsers.ParserConfigurationException; - import de.danoeh.antennapod.R; +import de.danoeh.antennapod.adapter.FeedItemlistDescriptionAdapter; +import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator; +import de.danoeh.antennapod.core.feed.EventDistributor; import de.danoeh.antennapod.core.feed.Feed; +import de.danoeh.antennapod.core.feed.FeedItem; import de.danoeh.antennapod.core.feed.FeedPreferences; +import de.danoeh.antennapod.core.glide.ApGlideSettings; import de.danoeh.antennapod.core.preferences.UserPreferences; import de.danoeh.antennapod.core.service.download.DownloadRequest; import de.danoeh.antennapod.core.service.download.DownloadStatus; import de.danoeh.antennapod.core.service.download.Downloader; import de.danoeh.antennapod.core.service.download.HttpDownloader; +import de.danoeh.antennapod.core.storage.DBReader; +import de.danoeh.antennapod.core.storage.DownloadRequestException; +import de.danoeh.antennapod.core.storage.DownloadRequester; import de.danoeh.antennapod.core.syndication.handler.FeedHandler; import de.danoeh.antennapod.core.syndication.handler.FeedHandlerResult; import de.danoeh.antennapod.core.syndication.handler.UnsupportedFeedtypeException; @@ -43,6 +63,11 @@ 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.dialog.AuthenticationDialog; +import rx.Observable; +import rx.Subscriber; +import rx.Subscription; +import rx.android.schedulers.AndroidSchedulers; +import rx.schedulers.Schedulers; /** * Downloads a feed from a feed URL and parses it. Subclasses can display the @@ -52,27 +77,57 @@ import de.danoeh.antennapod.dialog.AuthenticationDialog; * If the feed cannot be downloaded or parsed, an error dialog will be displayed * and the activity will finish as soon as the error dialog is closed. */ -public abstract class OnlineFeedViewActivity extends ActionBarActivity { +public class OnlineFeedViewActivity extends ActionBarActivity { + private static final String TAG = "OnlineFeedViewActivity"; + public static final String ARG_FEEDURL = "arg.feedurl"; - /** - * Optional argument: specify a title for the actionbar. - */ + // Optional argument: specify a title for the actionbar. public static final String ARG_TITLE = "title"; + private static final int EVENTS = EventDistributor.DOWNLOAD_HANDLED | EventDistributor.DOWNLOAD_QUEUED | EventDistributor.FEED_LIST_UPDATE; + public static final int RESULT_ERROR = 2; + private volatile List<Feed> feeds; private Feed feed; - private Map<String, String> alternateFeedUrls; + private String selectedDownloadUrl; private Downloader downloader; private boolean isPaused; + private Dialog dialog; + + private Button subscribeButton; + + private Subscription download; + private Subscription parser; + private Subscription updater; + + private EventDistributor.EventListener listener = new EventDistributor.EventListener() { + @Override + public void update(EventDistributor eventDistributor, Integer arg) { + if ((arg & EventDistributor.FEED_LIST_UPDATE) != 0) { + updater = Observable.defer(() -> Observable.just(DBReader.getFeedList(OnlineFeedViewActivity.this))) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(feeds -> { + OnlineFeedViewActivity.this.feeds = feeds; + setSubscribeButtonState(feed); + } + ); + } else if ((arg & EVENTS) != 0) { + setSubscribeButtonState(feed); + } + } + }; + @Override protected void onCreate(Bundle savedInstanceState) { setTheme(UserPreferences.getTheme()); super.onCreate(savedInstanceState); + getSupportActionBar().setDisplayHomeAsUpEnabled(true); if (getIntent() != null && getIntent().hasExtra(ARG_TITLE)) { getSupportActionBar().setTitle(getIntent().getStringExtra(ARG_TITLE)); @@ -87,7 +142,6 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity { || StringUtils.equals(getIntent().getAction(), Intent.ACTION_VIEW)) { feedUrl = (StringUtils.equals(getIntent().getAction(), Intent.ACTION_SEND)) ? getIntent().getStringExtra(Intent.EXTRA_TEXT) : getIntent().getDataString(); - getSupportActionBar().setTitle(R.string.add_new_feed_label); } else { throw new IllegalArgumentException("Activity must be started with feedurl argument!"); @@ -102,16 +156,63 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity { } } + /** + * Displays a progress indicator. + */ + private void setLoadingLayout() { + RelativeLayout rl = new RelativeLayout(this); + RelativeLayout.LayoutParams rlLayoutParams = new RelativeLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.MATCH_PARENT); + + ProgressBar pb = new ProgressBar(this); + pb.setIndeterminate(true); + RelativeLayout.LayoutParams pbLayoutParams = new RelativeLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + pbLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT); + rl.addView(pb, pbLayoutParams); + addContentView(rl, rlLayoutParams); + } + @Override protected void onResume() { super.onResume(); isPaused = false; + EventDistributor.getInstance().register(listener); + } @Override protected void onPause() { super.onPause(); isPaused = true; + EventDistributor.getInstance().unregister(listener); + } + + @Override + protected void onStop() { + super.onStop(); + if (downloader != null && !downloader.isFinished()) { + downloader.cancel(); + } + if(dialog != null && dialog.isShowing()) { + dialog.dismiss(); + } + } + + @Override + public void onDestroy() { + super.onDestroy(); + if(updater != null) { + updater.unsubscribe(); + } + if(download != null) { + download.unsubscribe(); + } + if(parser != null) { + parser.unsubscribe(); + } } @Override @@ -123,14 +224,6 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity { } } - @Override - protected void onStop() { - super.onStop(); - if (downloader != null && !downloader.isFinished()) { - downloader.cancel(); - } - } - private void resetIntent(String url, String title) { Intent intent = new Intent(); intent.putExtra(ARG_FEEDURL, url); @@ -138,41 +231,19 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity { setIntent(intent); } - - private void onDownloadCompleted(final Downloader downloader) { - runOnUiThread(new Runnable() { - - @Override - public void run() { - Log.d(TAG, "Download was completed"); - DownloadStatus status = downloader.getResult(); - if (status != null) { - if (!status.isCancelled()) { - if (status.isSuccessful()) { - parseFeed(); - } else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) { - if (!isFinishing() && !isPaused) { - Dialog dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this, - R.string.authentication_notification_title, downloader.getDownloadRequest().getSource()); - dialog.show(); - } - } else { - String errorMsg = status.getReason().getErrorString( - OnlineFeedViewActivity.this); - if (errorMsg != null - && status.getReasonDetailed() != null) { - errorMsg += " (" + status.getReasonDetailed() + ")"; - } - showErrorDialog(errorMsg); - } - } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + Intent destIntent = new Intent(this, MainActivity.class); + if (NavUtils.shouldUpRecreateTask(this, destIntent)) { + startActivity(destIntent); } else { - Log.wtf(TAG, "DownloadStatus returned by Downloader was null"); - finish(); + NavUtils.navigateUpFromSameTask(this); } - } - }); - + return true; + } + return super.onOptionsItemSelected(item); } private void startFeedDownload(String url, String username, String password) { @@ -186,133 +257,226 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity { FileNameGenerator.generateFileName(feed.getDownload_url())).toString(); feed.setFile_url(fileUrl); final DownloadRequest request = new DownloadRequest(feed.getFile_url(), - feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED, username, password, true, null); - downloader = new HttpDownloader(request); - new Thread() { - @Override - public void run() { - loadData(); - downloader.call(); - onDownloadCompleted(downloader); - } - }.start(); - - - } + feed.getDownload_url(), "OnlineFeed", 0, Feed.FEEDFILETYPE_FEED, username, password, + true, null); - /** - * Displays a progress indicator. - */ - private void setLoadingLayout() { - RelativeLayout rl = new RelativeLayout(this); - RelativeLayout.LayoutParams rlLayoutParams = new RelativeLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.MATCH_PARENT); - - ProgressBar pb = new ProgressBar(this); - pb.setIndeterminate(true); - RelativeLayout.LayoutParams pbLayoutParams = new RelativeLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT); - pbLayoutParams.addRule(RelativeLayout.CENTER_IN_PARENT); - rl.addView(pb, pbLayoutParams); - addContentView(rl, rlLayoutParams); + download = Observable.create(new Observable.OnSubscribe<DownloadStatus>() { + @Override + public void call(Subscriber<? super DownloadStatus> subscriber) { + feeds = DBReader.getFeedList(OnlineFeedViewActivity.this); + downloader = new HttpDownloader(request); + downloader.call(); + Log.d(TAG, "Download was completed"); + subscriber.onNext(downloader.getResult()); + subscriber.onCompleted(); + } + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(status -> { + if (status != null) { + if (!status.isCancelled()) { + if (status.isSuccessful()) { + parseFeed(); + } else if (status.getReason() == DownloadError.ERROR_UNAUTHORIZED) { + if (!isFinishing() && !isPaused) { + dialog = new FeedViewAuthenticationDialog(OnlineFeedViewActivity.this, + R.string.authentication_notification_title, downloader.getDownloadRequest().getSource()); + dialog.show(); + } + } else { + String errorMsg = status.getReason().getErrorString(OnlineFeedViewActivity.this); + if (errorMsg != null && status.getReasonDetailed() != null) { + errorMsg += " (" + status.getReasonDetailed() + ")"; + } + showErrorDialog(errorMsg); + } + } + } else { + Log.wtf(TAG, "DownloadStatus returned by Downloader was null"); + finish(); + } + }); } private void parseFeed() { if (feed == null || feed.getFile_url() == null && feed.isDownloaded()) { - throw new IllegalStateException( - "feed must be non-null and downloaded when parseFeed is called"); + throw new IllegalStateException("feed must be non-null and downloaded when parseFeed is called"); } - Log.d(TAG, "Parsing feed"); - Thread thread = new Thread() { - + parser = Observable.create(new Observable.OnSubscribe<FeedHandlerResult>() { @Override - public void run() { - String reasonDetailed = ""; - boolean successful = false; - FeedHandler handler = new FeedHandler(); - try { - FeedHandlerResult result = handler.parseFeed(feed); - feed = result.feed; - alternateFeedUrls = result.alternateFeedUrls; - successful = true; - } catch (SAXException e) { - e.printStackTrace(); - reasonDetailed = e.getMessage(); - } catch (IOException e) { - e.printStackTrace(); - reasonDetailed = e.getMessage(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - reasonDetailed = e.getMessage(); - } catch (UnsupportedFeedtypeException e) { - Log.d(TAG, "Unsupported feed type detected"); - if (StringUtils.equalsIgnoreCase("html", e.getRootElement())) { - if (showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url())) { - return; + public void call(Subscriber<? super FeedHandlerResult> subscriber) { + FeedHandler handler = new FeedHandler(); + try { + FeedHandlerResult result = handler.parseFeed(feed); + subscriber.onNext(result); + } catch (UnsupportedFeedtypeException e) { + Log.d(TAG, "Unsupported feed type detected"); + if (StringUtils.equalsIgnoreCase("html", e.getRootElement())) { + showFeedDiscoveryDialog(new File(feed.getFile_url()), feed.getDownload_url()); + } else { + subscriber.onError(e); + } + } catch (Exception e) { + subscriber.onError(e); + } finally { + boolean rc = new File(feed.getFile_url()).delete(); + Log.d(TAG, "Deleted feed source file. Result: " + rc); + subscriber.onCompleted(); } - } else { - e.printStackTrace(); - reasonDetailed = e.getMessage(); } - } finally { - boolean rc = new File(feed.getFile_url()).delete(); - Log.d(TAG, "Deleted feed source file. Result: " + rc); - } - - if (successful) { - beforeShowFeedInformation(feed, alternateFeedUrls); - runOnUiThread(new Runnable() { - @Override - public void run() { - showFeedInformation(feed, alternateFeedUrls); - } - }); - } else { - final String errorMsg = - DownloadError.ERROR_PARSER_EXCEPTION.getErrorString( - OnlineFeedViewActivity.this) - + " (" + reasonDetailed + ")"; - runOnUiThread(new Runnable() { - - @Override - public void run() { - showErrorDialog(errorMsg); - } - }); - } - } - }; - thread.start(); - } - - /** - * Can be used to load data asynchronously. - */ - protected void loadData() { - + }) + .subscribeOn(Schedulers.newThread()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(result -> { + beforeShowFeedInformation(result.feed); + showFeedInformation(result.feed, result.alternateFeedUrls); + }, error -> { + String errorMsg = DownloadError.ERROR_PARSER_EXCEPTION.getErrorString( + OnlineFeedViewActivity.this) + " (" + error.getMessage() + ")"; + showErrorDialog(errorMsg); + }); } /** * Called after the feed has been downloaded and parsed and before showFeedInformation is called. * This method is executed on a background thread */ - protected void beforeShowFeedInformation(Feed feed, Map<String, String> alternateFeedUrls) { - + private void beforeShowFeedInformation(Feed feed) { + // remove HTML tags from descriptions + 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))); + } + } + } } /** * Called when feed parsed successfully. * This method is executed on the GUI thread. */ - protected void showFeedInformation(Feed feed, Map<String, String> alternateFeedUrls) { + private void showFeedInformation(final Feed feed, Map<String, String> alternateFeedUrls) { + setContentView(R.layout.listview_activity); + + this.feed = feed; + this.selectedDownloadUrl = feed.getDownload_url(); + EventDistributor.getInstance().register(listener); + ListView listView = (ListView) findViewById(R.id.listview); + LayoutInflater inflater = (LayoutInflater) + getSystemService(Context.LAYOUT_INFLATER_SERVICE); + View header = inflater.inflate(R.layout.onlinefeedview_header, listView, false); + listView.addHeaderView(header); + + listView.setAdapter(new FeedItemlistDescriptionAdapter(this, 0, feed.getItems())); + + ImageView cover = (ImageView) header.findViewById(R.id.imgvCover); + TextView title = (TextView) header.findViewById(R.id.txtvTitle); + TextView author = (TextView) header.findViewById(R.id.txtvAuthor); + TextView description = (TextView) header.findViewById(R.id.txtvDescription); + Spinner spAlternateUrls = (Spinner) header.findViewById(R.id.spinnerAlternateUrls); + + subscribeButton = (Button) header.findViewById(R.id.butSubscribe); + + if (feed.getImage() != null && StringUtils.isNotBlank(feed.getImage().getDownload_url())) { + Glide.with(this) + .load(feed.getImage().getDownload_url()) + .placeholder(R.color.light_gray) + .error(R.color.light_gray) + .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) + .fitCenter() + .dontAnimate() + .into(cover); + } + + title.setText(feed.getTitle()); + author.setText(feed.getAuthor()); + description.setText(feed.getDescription()); + + subscribeButton.setOnClickListener(v -> { + try { + Feed f = new Feed(selectedDownloadUrl, new Date(0), feed.getTitle()); + f.setPreferences(feed.getPreferences()); + this.feed = f; + + DownloadRequester.getInstance().downloadFeed(this, f); + } catch (DownloadRequestException e) { + e.printStackTrace(); + DownloadRequestErrorDialogCreator.newRequestErrorDialog(OnlineFeedViewActivity.this, + e.getMessage()); + } + setSubscribeButtonState(feed); + }); + + if (alternateFeedUrls.isEmpty()) { + spAlternateUrls.setVisibility(View.GONE); + } else { + spAlternateUrls.setVisibility(View.VISIBLE); + + final List<String> alternateUrlsList = new ArrayList<>(); + final List<String> alternateUrlsTitleList = new ArrayList<>(); + + alternateUrlsList.add(feed.getDownload_url()); + alternateUrlsTitleList.add(feed.getTitle()); + + alternateUrlsList.addAll(alternateFeedUrls.keySet()); + for (String url : alternateFeedUrls.keySet()) { + alternateUrlsTitleList.add(alternateFeedUrls.get(url)); + } + ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, alternateUrlsTitleList); + adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spAlternateUrls.setAdapter(adapter); + spAlternateUrls.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { + selectedDownloadUrl = alternateUrlsList.get(position); + } + + @Override + public void onNothingSelected(AdapterView<?> parent) { + + } + }); + } + setSubscribeButtonState(feed); + } + + private void setSubscribeButtonState(Feed feed) { + if (subscribeButton != null && feed != null) { + if (DownloadRequester.getInstance().isDownloadingFile(feed.getDownload_url())) { + subscribeButton.setEnabled(false); + subscribeButton.setText(R.string.downloading_label); + } else if (feedInFeedlist(feed)) { + subscribeButton.setEnabled(false); + subscribeButton.setText(R.string.subscribed_label); + } else { + subscribeButton.setEnabled(true); + subscribeButton.setText(R.string.subscribe_label); + } + } + } + + private boolean feedInFeedlist(Feed feed) { + if (feeds == null || feed == null) { + return false; + } + for (Feed f : feeds) { + if (f.getIdentifyingValue().equals(feed.getIdentifyingValue())) { + return true; + } + } + return false; } private void showErrorDialog(String errorMsg) { + assert(Looper.myLooper() == Looper.getMainLooper()); // run on UI thread if (!isFinishing() && !isPaused) { AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(R.string.error_label); @@ -322,85 +486,71 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity { builder.setMessage(R.string.error_msg_prefix); } builder.setNeutralButton(android.R.string.ok, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } + (dialog, which) -> { + dialog.cancel(); } ); - builder.setOnCancelListener(new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - setResult(RESULT_ERROR); - finish(); - } + builder.setOnCancelListener(dialog -> { + setResult(RESULT_ERROR); + finish(); }); - builder.show(); + if(dialog != null && dialog.isShowing()) { + dialog.dismiss(); + } + dialog = builder.show(); } } - private boolean showFeedDiscoveryDialog(File feedFile, String baseUrl) { + private void showFeedDiscoveryDialog(File feedFile, String baseUrl) { FeedDiscoverer fd = new FeedDiscoverer(); final Map<String, String> urlsMap; try { urlsMap = fd.findLinks(feedFile, baseUrl); if (urlsMap == null || urlsMap.isEmpty()) { - return false; + return; } } catch (IOException e) { e.printStackTrace(); - return false; + return; } - runOnUiThread(new Runnable() { - @Override - public void run() { - if (isPaused || isFinishing()) { - return; - } + if (isPaused || isFinishing()) { + return; + } - final List<String> titles = new ArrayList<String>(); - final List<String> urls = new ArrayList<String>(); + final List<String> titles = new ArrayList<>(); + final List<String> urls = new ArrayList<>(); - urls.addAll(urlsMap.keySet()); - for (String url : urls) { - titles.add(urlsMap.get(url)); - } + urls.addAll(urlsMap.keySet()); + for (String url : urls) { + titles.add(urlsMap.get(url)); + } - final ArrayAdapter<String> adapter = new ArrayAdapter<String>(OnlineFeedViewActivity.this, R.layout.ellipsize_start_listitem, R.id.txtvTitle, titles); - DialogInterface.OnClickListener onClickListener = new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - String selectedUrl = urls.get(which); - dialog.dismiss(); - resetIntent(selectedUrl, titles.get(which)); - FeedPreferences prefs = feed.getPreferences(); - if(prefs != null) { - startFeedDownload(selectedUrl, prefs.getUsername(), prefs.getPassword()); - } else { - startFeedDownload(selectedUrl, null, null); - } - } - }; - - AlertDialog.Builder ab = new AlertDialog.Builder(OnlineFeedViewActivity.this) - .setTitle(R.string.feeds_label) - .setCancelable(true) - .setOnCancelListener(new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - finish(); - } - }) - .setAdapter(adapter, onClickListener); - ab.show(); + final ArrayAdapter<String> adapter = new ArrayAdapter<>(OnlineFeedViewActivity.this, R.layout.ellipsize_start_listitem, R.id.txtvTitle, titles); + DialogInterface.OnClickListener onClickListener = (dialog, which) -> { + String selectedUrl = urls.get(which); + dialog.dismiss(); + resetIntent(selectedUrl, titles.get(which)); + FeedPreferences prefs = feed.getPreferences(); + if(prefs != null) { + startFeedDownload(selectedUrl, prefs.getUsername(), prefs.getPassword()); + } else { + startFeedDownload(selectedUrl, null, null); } - }); + }; + AlertDialog.Builder ab = new AlertDialog.Builder(OnlineFeedViewActivity.this) + .setTitle(R.string.feeds_label) + .setCancelable(true) + .setOnCancelListener(dialog -> finish()) + .setAdapter(adapter, onClickListener); - return true; + runOnUiThread(() -> { + if(dialog != null && dialog.isShowing()) { + dialog.dismiss(); + } + dialog = ab.show(); + }); } private class FeedViewAuthenticationDialog extends AuthenticationDialog { @@ -423,4 +573,5 @@ public abstract class OnlineFeedViewActivity extends ActionBarActivity { startFeedDownload(feedUrl, username, password); } } + } 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 9f0ba9c92..14853c5ae 100644 --- a/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java +++ b/app/src/main/java/de/danoeh/antennapod/adapter/AdapterUtils.java @@ -1,5 +1,6 @@ package de.danoeh.antennapod.adapter; +import android.util.Log; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; @@ -52,13 +53,16 @@ public class AdapterUtils { txtvPos.setText("{fa-spinner}"); Iconify.addIcons(txtvPos); NetworkUtils.getFeedMediaSizeObservable(media) - .subscribe(size -> { + .subscribe( + size -> { if (size > 0) { txtvPos.setText(Converter.byteToString(size)); } else { txtvPos.setText(""); } - }); + }, error -> { + Log.e(TAG, Log.getStackTraceString(error)); + }); } else { txtvPos.setText(""); } diff --git a/app/src/main/java/de/danoeh/antennapod/dialog/TimeDialog.java b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java index 5c4d4c430..a699706a8 100644 --- a/app/src/main/java/de/danoeh/antennapod/dialog/TimeDialog.java +++ b/app/src/main/java/de/danoeh/antennapod/dialog/SleepTimerDialog.java @@ -2,6 +2,7 @@ package de.danoeh.antennapod.dialog; import android.app.Dialog; import android.content.Context; +import android.content.SharedPreferences; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; @@ -9,100 +10,80 @@ import android.util.Log; import android.view.View; import android.view.Window; import android.view.inputmethod.InputMethodManager; -import android.widget.*; -import de.danoeh.antennapod.core.BuildConfig; -import de.danoeh.antennapod.R; +import android.widget.ArrayAdapter; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.Spinner; +import android.widget.Toast; import java.util.concurrent.TimeUnit; -public abstract class TimeDialog extends Dialog { - private static final String TAG = "TimeDialog"; +import de.danoeh.antennapod.R; + +public abstract class SleepTimerDialog extends Dialog { + + 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 EditText etxtTime; private Spinner spTimeUnit; + private CheckBox cbShakeToReset; + private CheckBox cbVibrate; private Button butConfirm; private Button butCancel; - private TimeUnit[] units = {TimeUnit.SECONDS, TimeUnit.MINUTES, - TimeUnit.HOURS}; + private TimeUnit[] units = { TimeUnit.SECONDS, TimeUnit.MINUTES, TimeUnit.HOURS }; - public TimeDialog(Context context, int titleTextId, int leftButtonTextId) { + public SleepTimerDialog(Context context, int titleTextId, int leftButtonTextId) { super(context); this.context = context; + prefs = context.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); - String[] spinnerContent = new String[]{context.getString(R.string.time_seconds), + String[] spinnerContent = new String[] { + context.getString(R.string.time_seconds), context.getString(R.string.time_minutes), - context.getString(R.string.time_hours)}; + context.getString(R.string.time_hours) }; setContentView(R.layout.time_dialog); etxtTime = (EditText) findViewById(R.id.etxtTime); spTimeUnit = (Spinner) findViewById(R.id.spTimeUnit); + cbShakeToReset = (CheckBox) findViewById(R.id.cbShakeToReset); + cbVibrate = (CheckBox) findViewById(R.id.cbVibrate); butConfirm = (Button) findViewById(R.id.butConfirm); butCancel = (Button) findViewById(R.id.butCancel); - butConfirm.setText(R.string.set_sleeptimer_label); - butCancel.setText(R.string.cancel_label); setTitle(R.string.set_sleeptimer_label); - ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>( - this.getContext(), android.R.layout.simple_spinner_item, - spinnerContent); - spinnerAdapter - .setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - spTimeUnit.setAdapter(spinnerAdapter); - spTimeUnit.setSelection(DEFAULT_SPINNER_POSITION); - butCancel.setOnClickListener(new View.OnClickListener() { - - @Override - public void onClick(View v) { - dismiss(); - } - }); - butConfirm.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - try { - long input = readTimeMillis(); - onTimeEntered(input); - dismiss(); - } catch (NumberFormatException e) { - e.printStackTrace(); - Toast toast = Toast.makeText(context, - R.string.time_dialog_invalid_input, - Toast.LENGTH_LONG); - toast.show(); - } - } - }); + etxtTime.setText(prefs.getString(PREF_VALUE, "15")); etxtTime.addTextChangedListener(new TextWatcher() { - @Override public void afterTextChanged(Editable s) { checkInputLength(s.length()); } @Override - public void beforeTextChanged(CharSequence s, int start, int count, - int after) { - + public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override - public void onTextChanged(CharSequence s, int start, int before, - int count) { - + public void onTextChanged(CharSequence s, int start, int before, int count) { } }); - checkInputLength(etxtTime.getText().length()); etxtTime.postDelayed(new Runnable() { @Override public void run() { @@ -111,23 +92,54 @@ public abstract class TimeDialog extends Dialog { } }, 100); + ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<>(this.getContext(), + 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); + cbShakeToReset.setChecked(prefs.getBoolean(PREF_SHAKE_TO_RESET, true)); + cbVibrate.setChecked(prefs.getBoolean(PREF_VIBRATE, true)); + butConfirm.setText(R.string.set_sleeptimer_label); + butConfirm.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + try { + savePreferences(); + long input = readTimeMillis(); + onTimerSet(input, cbShakeToReset.isChecked(), cbVibrate.isChecked()); + dismiss(); + } catch (NumberFormatException e) { + e.printStackTrace(); + Toast toast = Toast.makeText(context, R.string.time_dialog_invalid_input, + Toast.LENGTH_LONG); + toast.show(); + } + } + }); + + butCancel.setText(R.string.cancel_label); + butCancel.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + dismiss(); + } + }); } private void checkInputLength(int length) { if (length > 0) { - if (BuildConfig.DEBUG) - Log.d(TAG, "Length is larger than 0, enabling confirm button"); + Log.d(TAG, "Length is larger than 0, enabling confirm button"); butConfirm.setEnabled(true); } else { - if (BuildConfig.DEBUG) - Log.d(TAG, "Length is smaller than 0, disabling confirm button"); + Log.d(TAG, "Length is smaller than 0, disabling confirm button"); butConfirm.setEnabled(false); } } - public abstract void onTimeEntered(long millis); + public abstract void onTimerSet(long millis, boolean shakeToReset, boolean vibrate); private long readTimeMillis() { TimeUnit selectedUnit = units[spTimeUnit.getSelectedItemPosition()]; @@ -135,4 +147,13 @@ public abstract class TimeDialog extends Dialog { 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(); + } + } 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 bbe6fab46..f6c80aa7c 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/AddFeedFragment.java @@ -10,7 +10,6 @@ import android.widget.Button; import android.widget.EditText; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.activity.OpmlImportFromPathActivity; @@ -73,7 +72,7 @@ public class AddFeedFragment extends Fragment { butConfirm.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent intent = new Intent(getActivity(), DefaultOnlineFeedViewActivity.class); + Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class); intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, etxtFeedurl.getText().toString()); intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, getString(R.string.add_feed_label)); startActivity(intent); 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 edd4da7fe..72704245f 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/ItunesSearchFragment.java @@ -28,7 +28,6 @@ import java.util.ArrayList; import java.util.List; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity; import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.adapter.itunes.ItunesAdapter; import de.danoeh.antennapod.core.preferences.UserPreferences; @@ -96,13 +95,13 @@ public class ItunesSearchFragment extends Fragment { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Intent intent = new Intent(getActivity(), - DefaultOnlineFeedViewActivity.class); + OnlineFeedViewActivity.class); //Tell the OnlineFeedViewActivity where to go String url = searchResults.get(position).feedUrl; intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, url); - intent.putExtra(DefaultOnlineFeedViewActivity.ARG_TITLE, "iTunes"); + intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, "iTunes"); startActivity(intent); } }); diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java index 623c6faa7..204f36956 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/gpodnet/PodcastListFragment.java @@ -23,7 +23,6 @@ import android.widget.TextView; import java.util.List; import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.DefaultOnlineFeedViewActivity; import de.danoeh.antennapod.activity.MainActivity; import de.danoeh.antennapod.activity.OnlineFeedViewActivity; import de.danoeh.antennapod.adapter.gpodnet.PodcastListAdapter; @@ -104,9 +103,9 @@ public abstract class PodcastListFragment extends Fragment { protected void onPodcastSelected(GpodnetPodcast selection) { Log.d(TAG, "Selected podcast: " + selection.toString()); - Intent intent = new Intent(getActivity(), DefaultOnlineFeedViewActivity.class); + Intent intent = new Intent(getActivity(), OnlineFeedViewActivity.class); intent.putExtra(OnlineFeedViewActivity.ARG_FEEDURL, selection.getUrl()); - intent.putExtra(DefaultOnlineFeedViewActivity.ARG_TITLE, getString(R.string.gpodnet_main_label)); + intent.putExtra(OnlineFeedViewActivity.ARG_TITLE, getString(R.string.gpodnet_main_label)); startActivity(intent); } diff --git a/app/src/main/res/layout-v14/time_dialog.xml b/app/src/main/res/layout-v14/time_dialog.xml index 7fd4309d5..aefb82b8b 100644 --- a/app/src/main/res/layout-v14/time_dialog.xml +++ b/app/src/main/res/layout-v14/time_dialog.xml @@ -2,7 +2,7 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical" > + android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" @@ -31,6 +31,37 @@ android:layout_marginTop="8dp" /> </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center"> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:textSize="16sp" + android:text="@string/timer_about_to_expire_label"/> + + <CheckBox android:id="@+id/cbShakeToReset" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/shake_to_reset_label"/> + + <CheckBox android:id="@+id/cbVibrate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/timer_vibration_label"/> + + </LinearLayout> + + </LinearLayout> + <RelativeLayout android:id="@+id/footer" android:layout_width="fill_parent" diff --git a/app/src/main/res/layout/time_dialog.xml b/app/src/main/res/layout/time_dialog.xml index a42f87781..e387a1689 100644 --- a/app/src/main/res/layout/time_dialog.xml +++ b/app/src/main/res/layout/time_dialog.xml @@ -33,6 +33,37 @@ </LinearLayout> <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center"> + + <LinearLayout + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:textSize="16sp" + android:text="@string/timer_about_to_expire_label"/> + + <CheckBox android:id="@+id/cbShakeToReset" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/shake_to_reset_label"/> + + <CheckBox android:id="@+id/cbVibrate" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/timer_vibration_label"/> + + </LinearLayout> + + </LinearLayout> + + <LinearLayout style="@android:style/ButtonBar" android:layout_width="match_parent" android:layout_height="wrap_content" diff --git a/app/src/main/templates/about.html b/app/src/main/templates/about.html index 887b547f4..e6b47f285 100644 --- a/app/src/main/templates/about.html +++ b/app/src/main/templates/about.html @@ -4,16 +4,22 @@ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <style type="text/css"> + @font-face { + font-family: 'Roboto-Light'; + src: url('file:///android_asset/Roboto-Light.ttf'); + } + * { - font-family: Helvetica + color: %s; + font-family: roboto-Light; + font-size: 12pt; } + header { display: block; margin-left: auto; margin-right: auto; padding-bottom: 500px; - - } versiontag { @@ -39,7 +45,7 @@ </head> <body> <div id="header" align="center"> - <img src="logo.png" alt="Logo" width="100px" height="100px"/> + <img src="file:///android_asset/logo.png" alt="Logo" width="100px" height="100px"/> <p>AntennaPod, Version @versionname@</p> <p>Commit: @commit@</p> |