summaryrefslogtreecommitdiff
path: root/ui
diff options
context:
space:
mode:
authorByteHamster <info@bytehamster.com>2024-02-18 23:59:46 +0100
committerByteHamster <info@bytehamster.com>2024-02-18 23:59:46 +0100
commit7a40a505f3700c5e2fe812cba9ef626579409c83 (patch)
tree139617b459e3f9ed6de50fc25a76e31f64ec4ee0 /ui
parentdc63386e8992f3430e82748282a7843c519a4865 (diff)
parent0d29e44de5ac97f2285aca241e4f4290c26ea0f9 (diff)
downloadAntennaPod-7a40a505f3700c5e2fe812cba9ef626579409c83.zip
Merge branch 'develop'
Diffstat (limited to 'ui')
-rw-r--r--ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java94
-rw-r--r--ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/FinalShareScreen.java44
-rw-r--r--ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/WavesScreen.java38
-rw-r--r--ui/i18n/src/main/res/values/strings.xml34
-rw-r--r--ui/png-icons/src/main/res/drawable/ic_notification_next_chapter.xml7
-rw-r--r--ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/downloads/DownloadStatisticsListAdapter.java9
-rw-r--r--ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/PlaybackStatisticsListAdapter.java4
-rw-r--r--ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/StatisticsFilterDialog.java4
8 files changed, 158 insertions, 76 deletions
diff --git a/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java b/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java
index 50b34b6e3..758eaeac7 100644
--- a/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java
+++ b/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/EchoActivity.java
@@ -10,8 +10,8 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
+import android.text.format.DateFormat;
import android.util.Log;
-import android.util.Pair;
import android.view.KeyEvent;
import android.view.View;
import androidx.annotation.NonNull;
@@ -35,6 +35,7 @@ import de.danoeh.antennapod.ui.echo.screens.FinalShareScreen;
import de.danoeh.antennapod.ui.echo.screens.RotatingSquaresScreen;
import de.danoeh.antennapod.ui.echo.screens.StripesScreen;
import de.danoeh.antennapod.ui.echo.screens.WaveformScreen;
+import de.danoeh.antennapod.ui.echo.screens.WavesScreen;
import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
@@ -53,6 +54,7 @@ import java.util.Locale;
import java.util.concurrent.TimeUnit;
public class EchoActivity extends AppCompatActivity {
+ public static final int RELEASE_YEAR = 2023;
private static final String TAG = "EchoActivity";
private static final int NUM_SCREENS = 7;
private static final int SHARE_SIZE = 1000;
@@ -67,6 +69,7 @@ public class EchoActivity extends AppCompatActivity {
private long timeTouchDown;
private long timeLastFrame;
private Disposable disposable;
+ private Disposable disposableFavorite;
private long totalTime = 0;
private int totalActivePodcasts = 0;
@@ -77,7 +80,8 @@ public class EchoActivity extends AppCompatActivity {
private long queueSecondsLeft = 0;
private long timeBetweenReleaseAndPlay = 0;
private long oldestDate = 0;
- private final ArrayList<Pair<String, Drawable>> favoritePods = new ArrayList<>();
+ private final ArrayList<String> favoritePodNames = new ArrayList<>();
+ private final ArrayList<Drawable> favoritePodImages = new ArrayList<>();
@SuppressLint("ClickableViewAccessibility")
@Override
@@ -134,7 +138,7 @@ public class EchoActivity extends AppCompatActivity {
new ShareCompat.IntentBuilder(this)
.setType("image/png")
.addStream(fileUri)
- .setText(getString(R.string.echo_share, 2023))
+ .setText(getString(R.string.echo_share, RELEASE_YEAR))
.setChooserTitle(R.string.share_file_label)
.startChooser();
} catch (Exception e) {
@@ -176,6 +180,9 @@ public class EchoActivity extends AppCompatActivity {
if (disposable != null) {
disposable.dispose();
}
+ if (disposableFavorite != null) {
+ disposableFavorite.dispose();
+ }
}
private void loadScreen(int screen, boolean force) {
@@ -190,7 +197,7 @@ public class EchoActivity extends AppCompatActivity {
switch (currentScreen) {
case 0:
viewBinding.aboveLabel.setText(R.string.echo_intro_your_year);
- viewBinding.largeLabel.setText(String.format(getEchoLanguage(), "%d", 2023));
+ viewBinding.largeLabel.setText(String.format(getEchoLanguage(), "%d", RELEASE_YEAR));
viewBinding.belowLabel.setText(R.string.echo_intro_in_podcasts);
viewBinding.smallLabel.setText(R.string.echo_intro_locally);
currentDrawable = new BubbleScreen(this);
@@ -207,20 +214,27 @@ public class EchoActivity extends AppCompatActivity {
viewBinding.largeLabel.setText(String.format(getEchoLanguage(), "%d", queueSecondsLeft / 3600));
viewBinding.belowLabel.setText(getResources().getQuantityString(
R.plurals.echo_queue_hours_waiting, queueNumEpisodes, queueNumEpisodes));
- int daysUntil2024 = Math.max(356 - Calendar.getInstance().get(Calendar.DAY_OF_YEAR) + 1, 1);
- long secondsPerDay = queueSecondsLeft / daysUntil2024;
+ Calendar dec31 = Calendar.getInstance();
+ dec31.set(Calendar.DAY_OF_MONTH, 31);
+ dec31.set(Calendar.MONTH, Calendar.DECEMBER);
+ int daysUntilNextYear = Math.max(1,
+ dec31.get(Calendar.DAY_OF_YEAR) - Calendar.getInstance().get(Calendar.DAY_OF_YEAR) + 1);
+ long secondsPerDay = queueSecondsLeft / daysUntilNextYear;
String timePerDay = Converter.getDurationStringLocalized(
getLocalizedResources(this, getEchoLanguage()), secondsPerDay * 1000, true);
double hoursPerDay = (double) (secondsPerDay / 3600);
+ int nextYear = RELEASE_YEAR + 1;
if (hoursPerDay < 1.5) {
viewBinding.aboveLabel.setText(R.string.echo_queue_title_clean);
- viewBinding.smallLabel.setText(getString(R.string.echo_queue_hours_clean, timePerDay, 2024));
+ viewBinding.smallLabel.setText(
+ getString(R.string.echo_queue_hours_clean, timePerDay, nextYear));
} else if (hoursPerDay <= 24) {
viewBinding.aboveLabel.setText(R.string.echo_queue_title_many);
- viewBinding.smallLabel.setText(getString(R.string.echo_queue_hours_normal, timePerDay, 2024));
+ viewBinding.smallLabel.setText(
+ getString(R.string.echo_queue_hours_normal, timePerDay, nextYear));
} else {
viewBinding.aboveLabel.setText(R.string.echo_queue_title_many);
- viewBinding.smallLabel.setText(getString(R.string.echo_queue_hours_much, timePerDay, 2024));
+ viewBinding.smallLabel.setText(getString(R.string.echo_queue_hours_much, timePerDay, nextYear));
}
currentDrawable = new StripesScreen(this);
break;
@@ -257,13 +271,14 @@ public class EchoActivity extends AppCompatActivity {
viewBinding.smallLabel.setText(getString(R.string.echo_hoarder_comment_clean,
percentagePlayed, totalActivePodcasts));
}
- currentDrawable = new StripesScreen(this);
+ currentDrawable = new WavesScreen(this);
break;
case 5:
viewBinding.aboveLabel.setText("");
viewBinding.largeLabel.setText(R.string.echo_thanks_large);
if (oldestDate < jan1()) {
- SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM yyyy", getEchoLanguage());
+ String skeleton = DateFormat.getBestDateTimePattern(getEchoLanguage(), "MMMM yyyy");
+ SimpleDateFormat dateFormat = new SimpleDateFormat(skeleton, getEchoLanguage());
String dateFrom = dateFormat.format(new Date(oldestDate));
viewBinding.belowLabel.setText(getString(R.string.echo_thanks_we_are_glad_old, dateFrom));
} else {
@@ -277,7 +292,7 @@ public class EchoActivity extends AppCompatActivity {
viewBinding.largeLabel.setText("");
viewBinding.belowLabel.setText("");
viewBinding.smallLabel.setText("");
- currentDrawable = new FinalShareScreen(this, favoritePods);
+ currentDrawable = new FinalShareScreen(this, favoritePodNames, favoritePodImages);
break;
default: // Keep
}
@@ -312,7 +327,7 @@ public class EchoActivity extends AppCompatActivity {
date.set(Calendar.MILLISECOND, 0);
date.set(Calendar.DAY_OF_MONTH, 1);
date.set(Calendar.MONTH, 0);
- date.set(Calendar.YEAR, 2023);
+ date.set(Calendar.YEAR, RELEASE_YEAR);
return date.getTimeInMillis();
}
@@ -329,25 +344,11 @@ public class EchoActivity extends AppCompatActivity {
Collections.sort(statisticsData.feedTime, (item1, item2) ->
Long.compare(item2.timePlayed, item1.timePlayed));
- favoritePods.clear();
+ favoritePodNames.clear();
for (int i = 0; i < 5 && i < statisticsData.feedTime.size(); i++) {
- BitmapDrawable cover = new BitmapDrawable(getResources(), (Bitmap) null);
- try {
- final int size = SHARE_SIZE / 3;
- final int radius = (i == 0) ? (size / 16) : (size / 8);
- cover = new BitmapDrawable(getResources(), Glide.with(this)
- .asBitmap()
- .load(statisticsData.feedTime.get(i).feed.getImageUrl())
- .apply(new RequestOptions()
- .fitCenter()
- .transform(new RoundedCorners(radius)))
- .submit(size, size)
- .get(1, TimeUnit.SECONDS));
- } catch (Exception e) {
- e.printStackTrace();
- }
- favoritePods.add(new Pair<>(statisticsData.feedTime.get(i).feed.getTitle(), cover));
+ favoritePodNames.add(statisticsData.feedTime.get(i).feed.getTitle());
}
+ loadFavoritePodImages(statisticsData);
totalActivePodcasts = 0;
playedActivePodcasts = 0;
@@ -396,4 +397,37 @@ public class EchoActivity extends AppCompatActivity {
.subscribe(result -> loadScreen(currentScreen, true),
error -> Log.e(TAG, Log.getStackTraceString(error)));
}
+
+ void loadFavoritePodImages(DBReader.StatisticsResult statisticsData) {
+ if (disposableFavorite != null) {
+ disposableFavorite.dispose();
+ }
+ disposableFavorite = Observable.fromCallable(
+ () -> {
+ favoritePodImages.clear();
+ for (int i = 0; i < 5 && i < statisticsData.feedTime.size(); i++) {
+ BitmapDrawable cover = new BitmapDrawable(getResources(), (Bitmap) null);
+ try {
+ final int size = SHARE_SIZE / 3;
+ final int radius = (i == 0) ? (size / 16) : (size / 8);
+ cover = new BitmapDrawable(getResources(), Glide.with(this)
+ .asBitmap()
+ .load(statisticsData.feedTime.get(i).feed.getImageUrl())
+ .apply(new RequestOptions()
+ .fitCenter()
+ .transform(new RoundedCorners(radius)))
+ .submit(size, size)
+ .get(5, TimeUnit.SECONDS));
+ } catch (Exception e) {
+ Log.d(TAG, "Loading cover: " + e.getMessage());
+ }
+ favoritePodImages.add(cover);
+ }
+ return statisticsData;
+ })
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(result -> { },
+ error -> Log.e(TAG, Log.getStackTraceString(error)));
+ }
}
diff --git a/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/FinalShareScreen.java b/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/FinalShareScreen.java
index 87b9cbd53..4af8941d0 100644
--- a/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/FinalShareScreen.java
+++ b/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/FinalShareScreen.java
@@ -7,9 +7,9 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
-import android.util.Pair;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.core.content.res.ResourcesCompat;
+import de.danoeh.antennapod.ui.echo.EchoActivity;
import de.danoeh.antennapod.ui.echo.R;
import java.util.ArrayList;
@@ -19,16 +19,21 @@ public class FinalShareScreen extends BubbleScreen {
private final Paint paintTextMain;
private final Paint paintCoverBorder;
private final String heading;
+ private final String year;
private final Drawable logo;
- private final ArrayList<Pair<String, Drawable>> favoritePods;
+ private final ArrayList<String> favoritePodNames;
+ private final ArrayList<Drawable> favoritePodImages;
private final Typeface typefaceNormal;
private final Typeface typefaceBold;
- public FinalShareScreen(Context context, ArrayList<Pair<String, Drawable>> favoritePods) {
+ public FinalShareScreen(Context context,
+ ArrayList<String> favoritePodNames, ArrayList<Drawable> favoritePodImages) {
super(context);
this.heading = context.getString(R.string.echo_share_heading);
this.logo = AppCompatResources.getDrawable(context, R.drawable.echo);
- this.favoritePods = favoritePods;
+ this.favoritePodNames = favoritePodNames;
+ this.favoritePodImages = favoritePodImages;
+ this.year = String.valueOf(EchoActivity.RELEASE_YEAR);
typefaceNormal = ResourcesCompat.getFont(context, R.font.sarabun_regular);
typefaceBold = ResourcesCompat.getFont(context, R.font.sarabun_semi_bold);
paintTextMain = new Paint();
@@ -49,12 +54,11 @@ public class FinalShareScreen extends BubbleScreen {
paintTextMain.setTextSize(headingSize);
canvas.drawText(heading, innerBoxX + 0.5f * innerBoxSize, innerBoxY + headingSize, paintTextMain);
paintTextMain.setTextSize(0.12f * innerBoxSize);
- canvas.drawText("2023", innerBoxX + 0.8f * innerBoxSize, innerBoxY + 0.25f * innerBoxSize, paintTextMain);
+ canvas.drawText(year, innerBoxX + 0.8f * innerBoxSize, innerBoxY + 0.25f * innerBoxSize, paintTextMain);
- paintTextMain.setTextAlign(Paint.Align.LEFT);
float fontSizePods = innerBoxSize / 18; // First one only
float textY = innerBoxY + 0.62f * innerBoxSize;
- for (int i = 0; i < favoritePods.size(); i++) {
+ for (int i = 0; i < favoritePodNames.size(); i++) {
float coverSize = (i == 0) ? (0.4f * innerBoxSize) : (0.2f * innerBoxSize);
float coverX = COVER_POSITIONS[i][0];
float coverY = COVER_POSITIONS[i][1];
@@ -68,12 +72,20 @@ public class FinalShareScreen extends BubbleScreen {
logo1Pos.inset((int) (0.003f * innerBoxSize), (int) (0.003f * innerBoxSize));
Rect pos = new Rect();
logo1Pos.round(pos);
- favoritePods.get(i).second.setBounds(pos);
- favoritePods.get(i).second.draw(canvas);
+ if (favoritePodImages.size() > i) {
+ favoritePodImages.get(i).setBounds(pos);
+ favoritePodImages.get(i).draw(canvas);
+ } else {
+ canvas.drawText(" ...", pos.left, pos.centerY(), paintTextMain);
+ }
+ paintTextMain.setTextAlign(Paint.Align.CENTER);
paintTextMain.setTextSize(fontSizePods);
- canvas.drawText((i + 1) + ".", innerBoxX, textY, paintTextMain);
- canvas.drawText(favoritePods.get(i).first, innerBoxX + 0.055f * innerBoxSize, textY, paintTextMain);
+ final float numberWidth = 0.06f * innerBoxSize;
+ canvas.drawText((i + 1) + ".", innerBoxX + numberWidth / 2, textY, paintTextMain);
+ paintTextMain.setTextAlign(Paint.Align.LEFT);
+ String ellipsizedTitle = ellipsize(favoritePodNames.get(i), paintTextMain, innerBoxSize - numberWidth);
+ canvas.drawText(ellipsizedTitle, innerBoxX + numberWidth, textY, paintTextMain);
fontSizePods = innerBoxSize / 24; // Starting with second text is smaller
textY += 1.3f * fontSizePods;
paintTextMain.setTypeface(typefaceNormal);
@@ -86,4 +98,14 @@ public class FinalShareScreen extends BubbleScreen {
(int) (innerBoxY + innerBoxSize));
logo.draw(canvas);
}
+
+ String ellipsize(String string, Paint paint, float maxWidth) {
+ if (paint.measureText(string) <= maxWidth) {
+ return string;
+ }
+ while (paint.measureText(string + "…") > maxWidth || string.endsWith(" ")) {
+ string = string.substring(0, string.length() - 1);
+ }
+ return string + "…";
+ }
}
diff --git a/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/WavesScreen.java b/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/WavesScreen.java
new file mode 100644
index 000000000..eb521f0a2
--- /dev/null
+++ b/ui/echo/src/main/java/de/danoeh/antennapod/ui/echo/screens/WavesScreen.java
@@ -0,0 +1,38 @@
+package de.danoeh.antennapod.ui.echo.screens;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import androidx.annotation.NonNull;
+
+public class WavesScreen extends BaseScreen {
+ protected static final int NUM_PARTICLES = 10;
+
+ public WavesScreen(Context context) {
+ super(context);
+ paintParticles.setStyle(Paint.Style.STROKE);
+ for (int i = 0; i < NUM_PARTICLES; i++) {
+ particles.add(new Particle(0, 0, 1.0f * i / NUM_PARTICLES, 0));
+ }
+ }
+
+ @Override
+ public void draw(@NonNull Canvas canvas) {
+ paintParticles.setStrokeWidth(0.05f * getBounds().height());
+ super.draw(canvas);
+ }
+
+ @Override
+ protected void drawParticle(@NonNull Canvas canvas, Particle p, float width, float height,
+ float innerBoxX, float innerBoxY, float innerBoxSize) {
+ canvas.drawCircle(width / 2, 1.1f * height, (float) (p.positionZ * 1.2f * height), paintParticles);
+ }
+
+ @Override
+ protected void particleTick(Particle p, long timeSinceLastFrame) {
+ p.positionZ += 0.00005 * timeSinceLastFrame;
+ if (p.positionZ > 1f) {
+ p.positionZ -= 1f;
+ }
+ }
+}
diff --git a/ui/i18n/src/main/res/values/strings.xml b/ui/i18n/src/main/res/values/strings.xml
index c1872969a..e40e03035 100644
--- a/ui/i18n/src/main/res/values/strings.xml
+++ b/ui/i18n/src/main/res/values/strings.xml
@@ -26,7 +26,7 @@
<string name="episode_cache_full_message">The episode cache limit has been reached. You can increase the cache size in the Settings.</string>
<string name="years_statistics_label">Years</string>
<string name="notification_pref_fragment">Notifications</string>
- <string name="recently_played_episodes">Recently played episodes</string>
+ <string name="current_playing_episode">Current</string>
<string name="antennapod_echo" translatable="false">AntennaPod Echo</string>
<string name="antennapod_echo_year" translatable="false">AntennaPod Echo %d</string>
@@ -123,7 +123,6 @@
<string name="description_label">Description</string>
<string name="shownotes_label">Shownotes</string>
<string name="shownotes_contentdescription">swipe up to read shownotes</string>
- <string name="episodes_suffix">\u0020episodes</string>
<string name="close_label">Close</string>
<string name="retry_label">Retry</string>
<string name="auto_download_label">Include in auto downloads</string>
@@ -185,7 +184,6 @@
<string name="remove_feed_label">Remove podcast</string>
<string name="share_label">Share</string>
<string name="share_file_label">Share file</string>
- <string name="share_rss_address_label">RSS address:</string>
<string name="feed_delete_confirmation_msg">Please confirm that you want to delete the podcast \"%1$s\", ALL its episodes (including downloaded episodes), and its statistics.</string>
<string name="feed_delete_confirmation_msg_batch">Please confirm that you want to remove the selected podcasts, ALL their episodes (including downloaded episodes), and its statistics.</string>
<string name="feed_delete_confirmation_local_msg">Please confirm that you want to remove the podcast \"%1$s\" and its statistics. The files in the local source folder will not be deleted.</string>
@@ -490,10 +488,9 @@
<string name="pref_expandNotify_sum">This usually expands the notification to show playback buttons.</string>
<string name="pref_persistNotify_title">Persistent playback controls</string>
<string name="pref_persistNotify_sum">Keep notification and lockscreen controls when playback is paused</string>
- <string name="pref_compact_notification_buttons_title">Set compact notification buttons</string>
- <string name="pref_compact_notification_buttons_sum">Change the playback buttons when the notification is collapsed. The play/pause button is always included.</string>
- <string name="pref_compact_notification_buttons_dialog_title">Select a maximum of %1$d items</string>
- <string name="pref_compact_notification_buttons_dialog_error">You can only select a maximum of %1$d items.</string>
+ <string name="pref_compact_notification_buttons_dialog_error_exact">You must select exactly %1$d items.</string>
+ <string name="pref_full_notification_buttons_title">Set notification buttons</string>
+ <string name="pref_full_notification_buttons_sum">Change the playback buttons on the playback notification.</string>
<string name="pref_enqueue_location_title">Enqueue location</string>
<string name="pref_enqueue_location_sum">Add episodes to: %1$s</string>
<string name="enqueue_location_back">Back</string>
@@ -579,7 +576,7 @@
<string name="database_import_summary">Import AntennaPod database from another device</string>
<string name="opml_import_label">OPML import</string>
<string name="opml_add_podcast_label">Import podcast list (OPML)</string>
- <string name="opml_reader_error">An error has occurred while reading the OPML document:</string>
+ <string name="opml_reader_error">An error has occurred while reading the file. Make sure that you have actually selected an OPML file and that the file is valid.</string>
<string name="opml_import_error_no_file">No file selected!</string>
<string name="select_all_label">Select all</string>
<string name="deselect_all_label">Deselect all</string>
@@ -773,25 +770,7 @@
<string name="not_paused">Not paused</string>
<string name="hide_played_episodes_label">Played</string>
<string name="not_played">Not played</string>
-
- <!-- Sort -->
- <string name="sort_title_a_z">Title (A \u2192 Z)</string>
- <string name="sort_title_z_a">Title (Z \u2192 A)</string>
- <string name="sort_date_new_old">Date (New \u2192 Old)</string>
- <string name="sort_date_old_new">Date (Old \u2192 New)</string>
- <string name="sort_duration_short_long">Duration (Short \u2192 Long)</string>
- <string name="sort_duration_long_short">Duration (Long \u2192 Short)</string>
- <string name="sort_filename_a_z">File Name (A \u2192 Z)</string>
- <string name="sort_filename_z_a">File Name (Z \u2192 A)</string>
-
- <string name="sort_a_z">A \u2192 Z</string>
- <string name="sort_z_a">Z \u2192 A</string>
- <string name="sort_new_old">New \u2192 Old</string>
- <string name="sort_old_new">Old \u2192 New</string>
- <string name="sort_short_long">Short \u2192 Long</string>
- <string name="sort_long_short">Long \u2192 Short</string>
- <string name="sort_small_large">Small \u2192 Large</string>
- <string name="sort_large_small">Large \u2192 Small</string>
+ <string name="filename">File name</string>
<!-- Share episode dialog -->
<string name="share_playback_position_dialog_label">Include playback position</string>
@@ -804,7 +783,6 @@
<!-- Audio controls -->
<string name="audio_controls">Audio controls</string>
<string name="playback_speed">Playback speed</string>
- <string name="audio_effects">Audio effects</string>
<string name="player_switch_to_audio_only">Switch to audio only</string>
<!-- proxy settings -->
diff --git a/ui/png-icons/src/main/res/drawable/ic_notification_next_chapter.xml b/ui/png-icons/src/main/res/drawable/ic_notification_next_chapter.xml
new file mode 100644
index 000000000..cb55e93a9
--- /dev/null
+++ b/ui/png-icons/src/main/res/drawable/ic_notification_next_chapter.xml
@@ -0,0 +1,7 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24dp"
+ android:width="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path android:fillColor="#fff" android:pathData="M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4M8,8V16L13,12M14,8V16H16V8" />
+</vector>
diff --git a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/downloads/DownloadStatisticsListAdapter.java b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/downloads/DownloadStatisticsListAdapter.java
index 4839aa891..083a87514 100644
--- a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/downloads/DownloadStatisticsListAdapter.java
+++ b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/downloads/DownloadStatisticsListAdapter.java
@@ -10,7 +10,6 @@ import de.danoeh.antennapod.ui.statistics.StatisticsListAdapter;
import de.danoeh.antennapod.ui.statistics.feed.FeedStatisticsDialogFragment;
import java.util.List;
-import java.util.Locale;
/**
* Adapter for the download statistics list.
@@ -45,10 +44,10 @@ public class DownloadStatisticsListAdapter extends StatisticsListAdapter {
@Override
protected void onBindFeedViewHolder(StatisticsHolder holder, StatisticsItem item) {
- holder.value.setText(Formatter.formatShortFileSize(context, item.totalDownloadSize)
- + " • "
- + String.format(Locale.getDefault(), "%d%s",
- item.episodesDownloadCount, context.getString(R.string.episodes_suffix)));
+ int numEpisodes = (int) item.episodesDownloadCount;
+ String text = Formatter.formatShortFileSize(context, item.totalDownloadSize);
+ text += " • " + context.getResources().getQuantityString(R.plurals.num_episodes, numEpisodes, numEpisodes);
+ holder.value.setText(text);
holder.itemView.setOnClickListener(v -> {
FeedStatisticsDialogFragment yourDialogFragment = FeedStatisticsDialogFragment.newInstance(
diff --git a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/PlaybackStatisticsListAdapter.java b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/PlaybackStatisticsListAdapter.java
index 3936118ca..9b1f234c8 100644
--- a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/PlaybackStatisticsListAdapter.java
+++ b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/PlaybackStatisticsListAdapter.java
@@ -1,5 +1,6 @@
package de.danoeh.antennapod.ui.statistics.subscriptions;
+import android.text.format.DateFormat;
import androidx.fragment.app.Fragment;
import de.danoeh.antennapod.core.storage.StatisticsItem;
import de.danoeh.antennapod.core.util.Converter;
@@ -39,7 +40,8 @@ public class PlaybackStatisticsListAdapter extends StatisticsListAdapter {
if (includeMarkedAsPlayed) {
return context.getString(R.string.statistics_counting_total);
}
- SimpleDateFormat dateFormat = new SimpleDateFormat("MMM yyyy", Locale.getDefault());
+ String skeleton = DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMM yyyy");
+ SimpleDateFormat dateFormat = new SimpleDateFormat(skeleton, Locale.getDefault());
String dateFrom = dateFormat.format(new Date(timeFilterFrom));
// FilterTo is first day of next month => Subtract one day
String dateTo = dateFormat.format(new Date(timeFilterTo - 24L * 3600000L));
diff --git a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/StatisticsFilterDialog.java b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/StatisticsFilterDialog.java
index 077883321..e46e48240 100644
--- a/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/StatisticsFilterDialog.java
+++ b/ui/statistics/src/main/java/de/danoeh/antennapod/ui/statistics/subscriptions/StatisticsFilterDialog.java
@@ -2,6 +2,7 @@ package de.danoeh.antennapod.ui.statistics.subscriptions;
import android.content.Context;
import android.content.SharedPreferences;
+import android.text.format.DateFormat;
import android.view.LayoutInflater;
import android.widget.ArrayAdapter;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
@@ -114,7 +115,8 @@ public class StatisticsFilterDialog {
date.set(Calendar.DAY_OF_MONTH, 1);
ArrayList<String> names = new ArrayList<>();
ArrayList<Long> timestamps = new ArrayList<>();
- SimpleDateFormat dateFormat = new SimpleDateFormat("MMM yyyy", Locale.getDefault());
+ String skeleton = DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMM yyyy");
+ SimpleDateFormat dateFormat = new SimpleDateFormat(skeleton, Locale.getDefault());
while (date.getTimeInMillis() < System.currentTimeMillis()) {
names.add(dateFormat.format(new Date(date.getTimeInMillis())));
if (!inclusive) {