summaryrefslogtreecommitdiff
path: root/core/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/main')
-rw-r--r--core/src/main/AndroidManifest.xml2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java5
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java3
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/EpisodeDownloadWorker.java21
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java31
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java36
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java2
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java128
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java12
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/sync/queue/SynchronizationQueueSink.java8
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java10
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/FeedUtil.java13
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java16
-rw-r--r--core/src/main/res/drawable/bg_rounded_corners.xml6
-rw-r--r--core/src/main/res/drawable/ic_close_white.xml11
-rw-r--r--core/src/main/res/drawable/ic_disc_full.xml9
-rw-r--r--core/src/main/res/drawable/ic_error.xml5
-rw-r--r--core/src/main/res/layout/more_content_list_footer.xml6
-rw-r--r--core/src/main/res/values/arrays.xml18
-rw-r--r--core/src/main/res/values/dimens.xml3
-rw-r--r--core/src/main/res/values/styles.xml36
23 files changed, 268 insertions, 121 deletions
diff --git a/core/src/main/AndroidManifest.xml b/core/src/main/AndroidManifest.xml
index e186a856f..71cf676a0 100644
--- a/core/src/main/AndroidManifest.xml
+++ b/core/src/main/AndroidManifest.xml
@@ -1,5 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools" package="de.danoeh.antennapod.core">
+ xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
diff --git a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
index eae7a8426..d63fd50f2 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/feed/LocalFeedUpdater.java
@@ -38,7 +38,6 @@ import de.danoeh.antennapod.model.download.DownloadError;
import de.danoeh.antennapod.model.feed.Feed;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedMedia;
-import de.danoeh.antennapod.model.feed.FeedPreferences;
import de.danoeh.antennapod.model.playback.MediaType;
import de.danoeh.antennapod.parser.feed.util.MimeTypeUtils;
import de.danoeh.antennapod.parser.media.id3.ID3ReaderException;
@@ -125,13 +124,9 @@ public class LocalFeedUpdater {
feed.setImageUrl(getImageUrl(allFiles, folderUri));
feed.getPreferences().setAutoDownload(false);
- feed.getPreferences().setAutoDeleteAction(FeedPreferences.AutoDeleteAction.NEVER);
feed.setDescription(context.getString(R.string.local_feed_description));
feed.setAuthor(context.getString(R.string.local_folder));
- if (newItems.isEmpty()) {
- throw new IOException("Empty folder. Make sure that the folder is accessible and contains media files.");
- }
DBTasks.updateFeed(context, feed, true);
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java b/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
index 659650bc1..eea4d2082 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/FeedUpdateWorker.java
@@ -199,7 +199,8 @@ public class FeedUpdateWorker extends Worker {
newEpisodesNotification.showIfNeeded(getApplicationContext(), feedSyncTask.getSavedFeed());
if (downloader.permanentRedirectUrl != null) {
DBWriter.updateFeedDownloadURL(request.getSource(), downloader.permanentRedirectUrl);
- } else if (feedSyncTask.getRedirectUrl() != null) {
+ } else if (feedSyncTask.getRedirectUrl() != null
+ && !feedSyncTask.getRedirectUrl().equals(request.getSource())) {
DBWriter.updateFeedDownloadURL(request.getSource(), feedSyncTask.getRedirectUrl());
}
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/EpisodeDownloadWorker.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/EpisodeDownloadWorker.java
index 976b3504a..e80f9b47f 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/EpisodeDownloadWorker.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/EpisodeDownloadWorker.java
@@ -158,11 +158,7 @@ public class EpisodeDownloadWorker extends Worker {
downloader.call();
} catch (Exception e) {
DBWriter.addDownloadStatus(downloader.getResult());
- if (EventBus.getDefault().hasSubscriberForEvent(MessageEvent.class)) {
- sendMessage(request.getTitle(), true);
- } else {
- sendErrorNotification();
- }
+ sendErrorNotification(request.getTitle());
return Result.failure();
}
@@ -195,11 +191,7 @@ public class EpisodeDownloadWorker extends Worker {
|| status.getReason() == DownloadError.ERROR_UNAUTHORIZED
|| status.getReason() == DownloadError.ERROR_IO_BLOCKED) {
// Fail fast, these are probably unrecoverable
- if (EventBus.getDefault().hasSubscriberForEvent(MessageEvent.class)) {
- sendMessage(request.getTitle(), true);
- } else {
- sendErrorNotification();
- }
+ sendErrorNotification(request.getTitle());
return Result.failure();
}
sendMessage(request.getTitle(), false);
@@ -208,7 +200,7 @@ public class EpisodeDownloadWorker extends Worker {
private Result retry3times() {
if (isLastRunAttempt()) {
- sendErrorNotification();
+ sendErrorNotification(downloader.getDownloadRequest().getTitle());
return Result.failure();
} else {
return Result.retry();
@@ -243,7 +235,12 @@ public class EpisodeDownloadWorker extends Worker {
PendingIntent.FLAG_UPDATE_CURRENT | (Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
}
- private void sendErrorNotification() {
+ private void sendErrorNotification(String title) {
+ if (EventBus.getDefault().hasSubscriberForEvent(MessageEvent.class)) {
+ sendMessage(title, false);
+ return;
+ }
+
NotificationCompat.Builder builder = new NotificationCompat.Builder(getApplicationContext(),
NotificationUtils.CHANNEL_ID_DOWNLOAD_ERROR);
builder.setTicker(getApplicationContext().getString(R.string.download_report_title))
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java
index c0cf9e077..01038435d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/download/NewEpisodesNotification.java
@@ -94,7 +94,7 @@ public class NewEpisodesNotification {
intent.setAction("NewEpisodes");
intent.setComponent(new ComponentName(context, "de.danoeh.antennapod.activity.MainActivity"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- intent.putExtra("fragment_tag", "EpisodesFragment");
+ intent.putExtra("fragment_tag", "NewEpisodesFragment");
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent,
(Build.VERSION.SDK_INT >= 23 ? PendingIntent.FLAG_IMMUTABLE : 0));
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
index e0c5da00b..c275444d9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/ExoPlayerWrapper.java
@@ -1,6 +1,7 @@
package de.danoeh.antennapod.core.service.playback;
import android.content.Context;
+import android.media.audiofx.LoudnessEnhancer;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
@@ -68,6 +69,8 @@ public class ExoPlayerWrapper {
private PlaybackParameters playbackParameters;
private DefaultTrackSelector trackSelector;
+ private LoudnessEnhancer loudnessEnhancer;
+
ExoPlayerWrapper(Context context) {
this.context = context;
createPlayer();
@@ -133,7 +136,14 @@ public class ExoPlayerWrapper {
audioSeekCompleteListener.run();
}
}
+
+ @Override
+ public void onAudioSessionIdChanged(int audioSessionId) {
+ initLoudnessEnhancer(audioSessionId);
+ }
});
+
+ initLoudnessEnhancer(exoPlayer.getAudioSessionId());
}
public int getCurrentPosition() {
@@ -235,7 +245,14 @@ public class ExoPlayerWrapper {
}
public void setVolume(float v, float v1) {
- exoPlayer.setVolume(v);
+ if (v > 1) {
+ exoPlayer.setVolume(1f);
+ loudnessEnhancer.setEnabled(true);
+ loudnessEnhancer.setTargetGain((int) (1000 * (v - 1)));
+ } else {
+ exoPlayer.setVolume(v);
+ loudnessEnhancer.setEnabled(false);
+ }
}
public void start() {
@@ -335,4 +352,16 @@ public class ExoPlayerWrapper {
void setOnBufferingUpdateListener(Consumer<Integer> bufferingUpdateListener) {
this.bufferingUpdateListener = bufferingUpdateListener;
}
+
+ private void initLoudnessEnhancer(int audioStreamId) {
+ LoudnessEnhancer newEnhancer = new LoudnessEnhancer(audioStreamId);
+ LoudnessEnhancer oldEnhancer = this.loudnessEnhancer;
+ if (oldEnhancer != null) {
+ newEnhancer.setEnabled(oldEnhancer.getEnabled());
+ newEnhancer.setTargetGain((int) oldEnhancer.getTargetGain());
+ oldEnhancer.release();
+ }
+
+ this.loudnessEnhancer = newEnhancer;
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
index 9dc846cc2..e7d7d10c9 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/LocalPSMP.java
@@ -343,6 +343,12 @@ public class LocalPSMP extends PlaybackServiceMediaPlayer {
t = 0;
}
+ if (t >= getDuration()) {
+ Log.d(TAG, "Seek reached end of file, skipping to next episode");
+ skip();
+ return;
+ }
+
if (playerStatus == PlayerStatus.PLAYING
|| playerStatus == PlayerStatus.PAUSED
|| playerStatus == PlayerStatus.PREPARED) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
index 6fc9035ca..c41ec93b1 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/service/playback/PlaybackService.java
@@ -20,7 +20,9 @@ import android.net.Uri;
import android.os.Binder;
import android.os.Build;
import android.os.Bundle;
+import android.os.Handler;
import android.os.IBinder;
+import android.os.Looper;
import android.os.Vibrator;
import android.service.quicksettings.TileService;
import android.support.v4.media.MediaBrowserCompat;
@@ -33,6 +35,7 @@ import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.SurfaceHolder;
+import android.view.ViewConfiguration;
import android.webkit.URLUtil;
import android.widget.Toast;
@@ -65,6 +68,7 @@ import de.danoeh.antennapod.core.storage.DBWriter;
import de.danoeh.antennapod.core.storage.FeedSearcher;
import de.danoeh.antennapod.core.sync.queue.SynchronizationQueueSink;
import de.danoeh.antennapod.core.util.FeedItemUtil;
+import de.danoeh.antennapod.core.util.FeedUtil;
import de.danoeh.antennapod.core.util.IntentUtils;
import de.danoeh.antennapod.core.util.NetworkUtils;
import de.danoeh.antennapod.core.util.gui.NotificationUtils;
@@ -150,6 +154,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
private CastStateListener castStateListener;
private String autoSkippedFeedMediaId = null;
+ private int clickCount = 0;
+ private final Handler clickHandler = new Handler(Looper.getMainLooper());
/**
* Used for Lollipop notifications, Android Wear, and Android Auto.
@@ -556,6 +562,12 @@ public class PlaybackService extends MediaBrowserServiceCompat {
@SuppressLint("LaunchActivityFromNotification")
private void displayStreamingNotAllowedNotification(Intent originalIntent) {
+ if (EventBus.getDefault().hasSubscriberForEvent(MessageEvent.class)) {
+ EventBus.getDefault().post(new MessageEvent(
+ getString(R.string.confirm_mobile_streaming_notification_message)));
+ return;
+ }
+
Intent intentAllowThisTime = new Intent(originalIntent);
intentAllowThisTime.setAction(PlaybackServiceInterface.EXTRA_ALLOW_STREAM_THIS_TIME);
intentAllowThisTime.putExtra(PlaybackServiceInterface.EXTRA_ALLOW_STREAM_THIS_TIME, true);
@@ -1098,7 +1110,8 @@ public class PlaybackService extends MediaBrowserServiceCompat {
FeedPreferences.AutoDeleteAction action =
item.getFeed().getPreferences().getCurrentAutoDelete();
boolean shouldAutoDelete = action == FeedPreferences.AutoDeleteAction.ALWAYS
- || (action == FeedPreferences.AutoDeleteAction.GLOBAL && UserPreferences.isAutoDelete());
+ || (action == FeedPreferences.AutoDeleteAction.GLOBAL
+ && FeedUtil.shouldAutoDeleteItemsOnThatFeed(item.getFeed()));
if (shouldAutoDelete && (!item.isTagged(FeedItem.TAG_FAVORITE)
|| !UserPreferences.shouldFavoriteKeepEpisode())) {
DBWriter.deleteFeedMediaOfItem(PlaybackService.this, media.getId());
@@ -1761,7 +1774,7 @@ public class PlaybackService extends MediaBrowserServiceCompat {
public void onPause() {
Log.d(TAG, "onPause()");
if (getStatus() == PlayerStatus.PLAYING) {
- pause(!UserPreferences.isPersistNotify(), true);
+ pause(!UserPreferences.isPersistNotify(), false);
}
}
@@ -1823,7 +1836,24 @@ public class PlaybackService extends MediaBrowserServiceCompat {
if (keyEvent != null &&
keyEvent.getAction() == KeyEvent.ACTION_DOWN &&
keyEvent.getRepeatCount() == 0) {
- return handleKeycode(keyEvent.getKeyCode(), false);
+ int keyCode = keyEvent.getKeyCode();
+ if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
+ clickCount++;
+ clickHandler.removeCallbacksAndMessages(null);
+ clickHandler.postDelayed(() -> {
+ if (clickCount == 1) {
+ handleKeycode(KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, false);
+ } else if (clickCount == 2) {
+ onFastForward();
+ } else if (clickCount == 3) {
+ onRewind();
+ }
+ clickCount = 0;
+ }, ViewConfiguration.getDoubleTapTimeout());
+ return true;
+ } else {
+ return handleKeycode(keyCode, false);
+ }
}
}
return false;
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
index d42f14591..d6a4fa1cb 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBTasks.java
@@ -281,7 +281,7 @@ public final class DBTasks {
if (oldItem != null) {
oldItem.updateFromOther(item);
} else {
- // item is new
+ Log.d(TAG, "Found new item: " + item.getTitle());
item.setFeed(savedFeed);
if (idx >= savedFeed.getItems().size()) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
index b2cc46ee0..1453f701d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java
@@ -2,15 +2,22 @@ package de.danoeh.antennapod.core.storage;
import android.app.backup.BackupManager;
import android.content.Context;
+import android.net.Uri;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.NotificationManagerCompat;
+import androidx.documentfile.provider.DocumentFile;
+import com.google.common.util.concurrent.Futures;
+
+import de.danoeh.antennapod.core.event.DownloadLogEvent;
+import de.danoeh.antennapod.core.feed.LocalFeedUpdater;
import de.danoeh.antennapod.net.download.serviceinterface.DownloadServiceInterface;
import de.danoeh.antennapod.core.service.playback.PlaybackServiceInterface;
import de.danoeh.antennapod.storage.database.PodDBAdapter;
+
import org.greenrobot.eventbus.EventBus;
import java.io.File;
@@ -25,7 +32,6 @@ import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import de.danoeh.antennapod.core.R;
-import de.danoeh.antennapod.core.event.DownloadLogEvent;
import de.danoeh.antennapod.event.FavoritesEvent;
import de.danoeh.antennapod.event.FeedItemEvent;
import de.danoeh.antennapod.event.FeedListUpdateEvent;
@@ -94,7 +100,7 @@ public class DBWriter {
*/
public static Future<?> deleteFeedMediaOfItem(@NonNull final Context context,
final long mediaId) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final FeedMedia media = DBReader.getFeedMedia(mediaId);
if (media != null) {
boolean result = deleteFeedMediaSynchronous(context, media);
@@ -106,10 +112,10 @@ public class DBWriter {
});
}
- private static boolean deleteFeedMediaSynchronous(
- @NonNull Context context, @NonNull FeedMedia media) {
+ private static boolean deleteFeedMediaSynchronous(@NonNull Context context, @NonNull FeedMedia media) {
Log.i(TAG, String.format(Locale.US, "Requested to delete FeedMedia [id=%d, title=%s, downloaded=%s",
media.getId(), media.getEpisodeTitle(), media.isDownloaded()));
+ boolean localDelete = false;
if (media.isDownloaded() || media.getFile_url() != null) {
// delete downloaded media file
File mediaFile = new File(media.getFile_url());
@@ -125,23 +131,38 @@ public class DBWriter {
adapter.open();
adapter.setMedia(media);
adapter.close();
+ } else if (media.getFile_url().startsWith("content://")) {
+ // Local feed
+ DocumentFile documentFile = DocumentFile.fromSingleUri(
+ context, Uri.parse(media.getFile_url()));
+ if (documentFile == null || !documentFile.exists() || !documentFile.delete()) {
+ EventBus.getDefault().post(new MessageEvent(context.getString(R.string.delete_local_failed)));
+ return false;
+ }
+ localDelete = true;
+ }
- if (media.getId() == PlaybackPreferences.getCurrentlyPlayingFeedMediaId()) {
- PlaybackPreferences.writeNoMediaPlaying();
- IntentUtils.sendLocalBroadcast(context, PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
+ if (media.getId() == PlaybackPreferences.getCurrentlyPlayingFeedMediaId()) {
+ PlaybackPreferences.writeNoMediaPlaying();
+ IntentUtils.sendLocalBroadcast(context, PlaybackServiceInterface.ACTION_SHUTDOWN_PLAYBACK_SERVICE);
- NotificationManagerCompat nm = NotificationManagerCompat.from(context);
- nm.cancel(R.id.notification_playing);
- }
+ NotificationManagerCompat nm = NotificationManagerCompat.from(context);
+ nm.cancel(R.id.notification_playing);
+ }
+ if (localDelete) {
+ // Do full update of this feed to get rid of the item
+ LocalFeedUpdater.updateFeed(media.getItem().getFeed(), context.getApplicationContext(), null);
+ } else {
// Gpodder: queue delete action for synchronization
FeedItem item = media.getItem();
EpisodeAction action = new EpisodeAction.Builder(item, EpisodeAction.DELETE)
.currentTimestamp()
.build();
SynchronizationQueueSink.enqueueEpisodeActionIfSynchronizationIsActive(context, action);
+
+ EventBus.getDefault().post(FeedItemEvent.updated(media.getItem()));
}
- EventBus.getDefault().post(FeedItemEvent.updated(media.getItem()));
return true;
}
@@ -152,7 +173,7 @@ public class DBWriter {
* @param feedId ID of the Feed that should be deleted.
*/
public static Future<?> deleteFeed(final Context context, final long feedId) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final Feed feed = DBReader.getFeed(feedId);
if (feed == null) {
return;
@@ -183,7 +204,7 @@ public class DBWriter {
*/
@NonNull
public static Future<?> deleteFeedItems(@NonNull Context context, @NonNull List<FeedItem> items) {
- return dbExec.submit(() -> deleteFeedItemsSynchronous(context, items));
+ return runOnDbThread(() -> deleteFeedItemsSynchronous(context, items));
}
/**
@@ -235,7 +256,7 @@ public class DBWriter {
* Deletes the entire playback history.
*/
public static Future<?> clearPlaybackHistory() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.clearPlaybackHistory();
@@ -248,7 +269,7 @@ public class DBWriter {
* Deletes the entire download log.
*/
public static Future<?> clearDownloadLog() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.clearDownloadLog();
@@ -281,7 +302,7 @@ public class DBWriter {
* @param date PlaybackCompletionDate for <code>media</code>
*/
public static Future<?> addItemToPlaybackHistory(final FeedMedia media, Date date) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
Log.d(TAG, "Adding item to playback history");
media.setPlaybackCompletionDate(date);
@@ -300,7 +321,7 @@ public class DBWriter {
* @param status The DownloadStatus object.
*/
public static Future<?> addDownloadStatus(final DownloadResult status) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setDownloadStatus(status);
@@ -322,7 +343,7 @@ public class DBWriter {
*/
public static Future<?> addQueueItemAt(final Context context, final long itemId,
final int index, final boolean performAutoDownload) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
final List<FeedItem> queue = DBReader.getQueue(adapter);
@@ -393,7 +414,7 @@ public class DBWriter {
*/
public static Future<?> addQueueItem(final Context context, final boolean performAutoDownload,
final boolean markAsUnplayed, final long... itemIds) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
if (itemIds.length < 1) {
return;
}
@@ -476,7 +497,7 @@ public class DBWriter {
* Removes all FeedItem objects from the queue.
*/
public static Future<?> clearQueue() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.clearQueue();
@@ -495,12 +516,12 @@ public class DBWriter {
*/
public static Future<?> removeQueueItem(final Context context,
final boolean performAutoDownload, final FeedItem item) {
- return dbExec.submit(() -> removeQueueItemSynchronous(context, performAutoDownload, item.getId()));
+ return runOnDbThread(() -> removeQueueItemSynchronous(context, performAutoDownload, item.getId()));
}
public static Future<?> removeQueueItem(final Context context, final boolean performAutoDownload,
final long... itemIds) {
- return dbExec.submit(() -> removeQueueItemSynchronous(context, performAutoDownload, itemIds));
+ return runOnDbThread(() -> removeQueueItemSynchronous(context, performAutoDownload, itemIds));
}
private static void removeQueueItemSynchronous(final Context context,
@@ -562,7 +583,7 @@ public class DBWriter {
}
public static Future<?> addFavoriteItem(final FeedItem item) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance().open();
adapter.addFavoriteItem(item);
adapter.close();
@@ -573,7 +594,7 @@ public class DBWriter {
}
public static Future<?> removeFavoriteItem(final FeedItem item) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance().open();
adapter.removeFavoriteItem(item);
adapter.close();
@@ -590,7 +611,7 @@ public class DBWriter {
* @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
*/
public static Future<?> moveQueueItemToTop(final long itemId, final boolean broadcastUpdate) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
LongList queueIdList = DBReader.getQueueIDList();
int index = queueIdList.indexOf(itemId);
if (index >= 0) {
@@ -609,7 +630,7 @@ public class DBWriter {
*/
public static Future<?> moveQueueItemToBottom(final long itemId,
final boolean broadcastUpdate) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
LongList queueIdList = DBReader.getQueueIDList();
int index = queueIdList.indexOf(itemId);
if (index >= 0) {
@@ -632,7 +653,7 @@ public class DBWriter {
*/
public static Future<?> moveQueueItem(final int from,
final int to, final boolean broadcastUpdate) {
- return dbExec.submit(() -> moveQueueItemHelper(from, to, broadcastUpdate));
+ return runOnDbThread(() -> moveQueueItemHelper(from, to, broadcastUpdate));
}
/**
@@ -669,7 +690,7 @@ public class DBWriter {
}
public static Future<?> resetPagedFeedPage(Feed feed) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.resetPagedFeedPage(feed);
@@ -699,7 +720,7 @@ public class DBWriter {
*/
public static Future<?> markItemPlayed(final int played, final boolean broadcastUpdate,
final long... itemIds) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItemRead(played, itemIds);
@@ -729,7 +750,7 @@ public class DBWriter {
final int played,
final long mediaId,
final boolean resetMediaPosition) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItemRead(played, itemId, mediaId,
@@ -746,7 +767,7 @@ public class DBWriter {
* @param feedId ID of the Feed.
*/
public static Future<?> removeFeedNewFlag(final long feedId) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED, feedId);
@@ -760,7 +781,7 @@ public class DBWriter {
* Sets the 'read'-attribute of all NEW FeedItems to UNPLAYED.
*/
public static Future<?> removeAllNewFlags() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItems(FeedItem.NEW, FeedItem.UNPLAYED);
@@ -771,7 +792,7 @@ public class DBWriter {
}
static Future<?> addNewFeed(final Context context, final Feed... feeds) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setCompleteFeed(feeds);
@@ -789,7 +810,7 @@ public class DBWriter {
}
static Future<?> setCompleteFeed(final Feed... feeds) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setCompleteFeed(feeds);
@@ -798,7 +819,7 @@ public class DBWriter {
}
public static Future<?> setItemList(final List<FeedItem> items) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.storeFeedItemlist(items);
@@ -814,7 +835,7 @@ public class DBWriter {
* @param media The FeedMedia object.
*/
public static Future<?> setFeedMedia(final FeedMedia media) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setMedia(media);
@@ -828,7 +849,7 @@ public class DBWriter {
* @param media The FeedMedia object.
*/
public static Future<?> setFeedMediaPlaybackInformation(final FeedMedia media) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedMediaPlaybackInformation(media);
@@ -843,7 +864,7 @@ public class DBWriter {
* @param item The FeedItem object.
*/
public static Future<?> setFeedItem(final FeedItem item) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setSingleFeedItem(item);
@@ -857,7 +878,7 @@ public class DBWriter {
*/
public static Future<?> updateFeedDownloadURL(final String original, final String updated) {
Log.d(TAG, "updateFeedDownloadURL(original: " + original + ", updated: " + updated + ")");
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedDownloadUrl(original, updated);
@@ -871,7 +892,7 @@ public class DBWriter {
* @param preferences The FeedPreferences object.
*/
public static Future<?> setFeedPreferences(final FeedPreferences preferences) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedPreferences(preferences);
@@ -901,7 +922,7 @@ public class DBWriter {
*/
public static Future<?> setFeedLastUpdateFailed(final long feedId,
final boolean lastUpdateFailed) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedLastUpdateFailed(feedId, lastUpdateFailed);
@@ -911,7 +932,7 @@ public class DBWriter {
}
public static Future<?> setFeedCustomTitle(Feed feed) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedCustomTitle(feed.getId(), feed.getCustomTitle());
@@ -930,10 +951,10 @@ public class DBWriter {
public static Future<?> reorderQueue(@Nullable SortOrder sortOrder, final boolean broadcastUpdate) {
if (sortOrder == null) {
Log.w(TAG, "reorderQueue() - sortOrder is null. Do nothing.");
- return dbExec.submit(() -> { });
+ return runOnDbThread(() -> { });
}
final Permutor<FeedItem> permutor = FeedItemPermutors.getPermutor(sortOrder);
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
final PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
final List<FeedItem> queue = DBReader.getQueue(adapter);
@@ -960,7 +981,7 @@ public class DBWriter {
public static Future<?> setFeedItemsFilter(final long feedId,
final Set<String> filterValues) {
Log.d(TAG, "setFeedItemsFilter() called with: " + "feedId = [" + feedId + "], filterValues = [" + filterValues + "]");
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItemFilter(feedId, filterValues);
@@ -974,7 +995,7 @@ public class DBWriter {
*
*/
public static Future<?> setFeedItemSortOrder(long feedId, @Nullable SortOrder sortOrder) {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.setFeedItemSortOrder(feedId, sortOrder);
@@ -988,11 +1009,24 @@ public class DBWriter {
*/
@NonNull
public static Future<?> resetStatistics() {
- return dbExec.submit(() -> {
+ return runOnDbThread(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
adapter.resetAllMediaPlayedDuration();
adapter.close();
});
}
+
+ /**
+ * Submit to the DB thread only if caller is not already on the DB thread. Otherwise,
+ * just execute synchronously
+ */
+ private static Future<?> runOnDbThread(Runnable runnable) {
+ if ("DatabaseExecutor".equals(Thread.currentThread().getName())) {
+ runnable.run();
+ return Futures.immediateFuture(null);
+ } else {
+ return dbExec.submit(runnable);
+ }
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
index 7fe0c5e46..dc6b7ff80 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/SyncService.java
@@ -22,6 +22,7 @@ import androidx.work.WorkerParameters;
import de.danoeh.antennapod.core.util.download.FeedUpdateManager;
import de.danoeh.antennapod.event.FeedUpdateRunningEvent;
+import de.danoeh.antennapod.event.MessageEvent;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.model.feed.SortOrder;
import org.apache.commons.lang3.StringUtils;
@@ -298,13 +299,18 @@ public class SyncService extends Worker {
}
private void updateErrorNotification(Exception exception) {
+ Log.d(TAG, "Posting sync error notification");
+ final String description = getApplicationContext().getString(R.string.gpodnetsync_error_descr)
+ + exception.getMessage();
+
if (!UserPreferences.gpodnetNotificationsEnabled()) {
Log.d(TAG, "Skipping sync error notification because of user setting");
return;
}
- Log.d(TAG, "Posting sync error notification");
- final String description = getApplicationContext().getString(R.string.gpodnetsync_error_descr)
- + exception.getMessage();
+ if (EventBus.getDefault().hasSubscriberForEvent(MessageEvent.class)) {
+ EventBus.getDefault().post(new MessageEvent(description));
+ return;
+ }
Intent intent = getApplicationContext().getPackageManager().getLaunchIntentForPackage(
getApplicationContext().getPackageName());
diff --git a/core/src/main/java/de/danoeh/antennapod/core/sync/queue/SynchronizationQueueSink.java b/core/src/main/java/de/danoeh/antennapod/core/sync/queue/SynchronizationQueueSink.java
index 55c415153..cfe3798a7 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/sync/queue/SynchronizationQueueSink.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/sync/queue/SynchronizationQueueSink.java
@@ -19,6 +19,12 @@ public class SynchronizationQueueSink {
serviceStarterImpl.run();
}
+ public static void syncNowIfNotSyncedRecently() {
+ if (System.currentTimeMillis() - SynchronizationSettings.getLastSyncAttempt() > 1000 * 60 * 10) {
+ syncNow();
+ }
+ }
+
public static void clearQueue(Context context) {
LockingAsyncExecutor.executeLockedAsync(new SynchronizationQueueStorage(context)::clearQueue);
}
@@ -58,7 +64,7 @@ public class SynchronizationQueueSink {
if (!SynchronizationSettings.isProviderConnected()) {
return;
}
- if (media.getItem() == null) {
+ if (media.getItem() == null || media.getItem().getFeed().isLocalFeed()) {
return;
}
if (media.getStartPosition() < 0 || (!completed && media.getStartPosition() >= media.getPosition())) {
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java
index 12377791e..ec9c9e55e 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/FeedItemPermutors.java
@@ -72,6 +72,12 @@ public class FeedItemPermutors {
case SMART_SHUFFLE_NEW_OLD:
permutor = (queue) -> smartShuffle(queue, false);
break;
+ case SIZE_SMALL_LARGE:
+ comparator = (f1, f2) -> Long.compare(size(f1), size(f2));
+ break;
+ case SIZE_LARGE_SMALL:
+ comparator = (f1, f2) -> Long.compare(size(f2), size(f1));
+ break;
}
if (comparator != null) {
@@ -97,6 +103,10 @@ public class FeedItemPermutors {
return (item != null && item.getMedia() != null) ? item.getMedia().getDuration() : 0;
}
+ private static long size(@Nullable FeedItem item) {
+ return (item != null && item.getMedia() != null) ? item.getMedia().getSize() : 0;
+ }
+
@NonNull
private static String itemLink(@Nullable FeedItem item) {
return (item != null && item.getLink() != null)
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/FeedUtil.java b/core/src/main/java/de/danoeh/antennapod/core/util/FeedUtil.java
new file mode 100644
index 000000000..201207816
--- /dev/null
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/FeedUtil.java
@@ -0,0 +1,13 @@
+package de.danoeh.antennapod.core.util;
+
+import de.danoeh.antennapod.model.feed.Feed;
+import de.danoeh.antennapod.storage.preferences.UserPreferences;
+
+public abstract class FeedUtil {
+ public static boolean shouldAutoDeleteItemsOnThatFeed(Feed feed) {
+ if (!UserPreferences.isAutoDelete()) {
+ return false;
+ }
+ return !feed.isLocalFeed() || UserPreferences.isAutoDeleteLocal();
+ }
+}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java b/core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java
index 79732ff32..d870cb1f8 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/util/gui/NotificationUtils.java
@@ -18,7 +18,6 @@ public class NotificationUtils {
public static final String CHANNEL_ID_PLAYING = "playing";
public static final String CHANNEL_ID_DOWNLOAD_ERROR = "error";
public static final String CHANNEL_ID_SYNC_ERROR = "sync_error";
- public static final String CHANNEL_ID_AUTO_DOWNLOAD = "auto_download";
public static final String CHANNEL_ID_EPISODE_NOTIFICATIONS = "episode_notifications";
public static final String GROUP_ID_ERRORS = "group_errors";
@@ -38,7 +37,6 @@ public class NotificationUtils {
createChannelPlaying(context),
createChannelError(context),
createChannelSyncError(context),
- createChannelAutoDownload(context),
createChannelEpisodeNotification(context));
mNotificationManager.createNotificationChannelsCompat(channels);
}
@@ -98,20 +96,6 @@ public class NotificationUtils {
return notificationChannel.build();
}
- private static NotificationChannelCompat createChannelAutoDownload(final Context c) {
- final NotificationChannelCompat.Builder notificationChannel = new NotificationChannelCompat.Builder(
- CHANNEL_ID_AUTO_DOWNLOAD, NotificationManagerCompat.IMPORTANCE_NONE)
- .setName(c.getString(R.string.notification_channel_auto_download))
- .setDescription(c.getString(R.string.notification_channel_episode_auto_download))
- .setGroup(GROUP_ID_NEWS);
-
- if (UserPreferences.getShowAutoDownloadReportRaw()) {
- // Migration from app managed setting: enable notification
- notificationChannel.setImportance(NotificationManagerCompat.IMPORTANCE_DEFAULT);
- }
- return notificationChannel.build();
- }
-
private static NotificationChannelCompat createChannelEpisodeNotification(final Context c) {
return new NotificationChannelCompat.Builder(
CHANNEL_ID_EPISODE_NOTIFICATIONS, NotificationManagerCompat.IMPORTANCE_DEFAULT)
diff --git a/core/src/main/res/drawable/bg_rounded_corners.xml b/core/src/main/res/drawable/bg_rounded_corners.xml
new file mode 100644
index 000000000..11b7710c4
--- /dev/null
+++ b/core/src/main/res/drawable/bg_rounded_corners.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="rectangle">
+ <corners android:radius="8dp" />
+</shape>
diff --git a/core/src/main/res/drawable/ic_close_white.xml b/core/src/main/res/drawable/ic_close_white.xml
new file mode 100644
index 000000000..d37d3f963
--- /dev/null
+++ b/core/src/main/res/drawable/ic_close_white.xml
@@ -0,0 +1,11 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:pathData="M17.656,6.343L12,12M12,12L6.343,17.656M12,12L17.656,17.656M12,12L6.343,6.343"
+ android:strokeWidth="2"
+ android:fillColor="#00000000"
+ android:strokeColor="#ffffff"/>
+</vector>
diff --git a/core/src/main/res/drawable/ic_disc_full.xml b/core/src/main/res/drawable/ic_disc_full.xml
new file mode 100644
index 000000000..2aba1bc53
--- /dev/null
+++ b/core/src/main/res/drawable/ic_disc_full.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="20dp"
+ android:height="16dp"
+ android:viewportWidth="20"
+ android:viewportHeight="16">
+ <path
+ android:pathData="M17.1 11.5s0-1.7 0-1.7s1.8 0 1.8 0s0 1.7 0 1.7s-1.8 0-1.8 0zm0-8s1.8 0 1.8 0s0 4.5 0 4.5s-1.8 0-1.8 0s0-4.5 0-4.5zm-8.9-2.6c2 0 3.6 0.7 5 2.1s2.1 3 2.1 5s-0.7 3.7-2.1 5s-3 2.1-5 2.1c-1.9 0-3.6-0.7-5-2.1s-2.1-3-2.1-5s0.7-3.6 2.1-5s3.1-2.1 5-2.1zm0 8.9c0.5 0 0.9-0.2 1.3-0.5s0.5-0.8 0.5-1.3s-0.2-0.9-0.5-1.3s-0.8-0.5-1.3-0.5s-0.9 0.2-1.2 0.5s-0.6 0.8-0.6 1.3s0.2 0.9 0.6 1.3s0.7 0.5 1.2 0.5z"
+ android:fillColor="?android:attr/textColorPrimary" />
+</vector> \ No newline at end of file
diff --git a/core/src/main/res/drawable/ic_error.xml b/core/src/main/res/drawable/ic_error.xml
index 402f224b2..fc4fa2b9a 100644
--- a/core/src/main/res/drawable/ic_error.xml
+++ b/core/src/main/res/drawable/ic_error.xml
@@ -4,6 +4,9 @@
android:viewportWidth="24"
android:viewportHeight="24">
<path
- android:fillColor="#FFFFFF"
+ android:fillColor="?android:attr/colorBackground"
+ android:pathData="M12 1C5.9 1 1 5.9 1 12s4.9 11 11 11 11-4.9 11-11S18.1 1 12 1z" />
+ <path
+ android:fillColor="?attr/icon_red"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM13,17h-2v-2h2v2zM13,13h-2L11,7h2v6z" />
</vector>
diff --git a/core/src/main/res/layout/more_content_list_footer.xml b/core/src/main/res/layout/more_content_list_footer.xml
index 2869ef7de..a3fcd5489 100644
--- a/core/src/main/res/layout/more_content_list_footer.xml
+++ b/core/src/main/res/layout/more_content_list_footer.xml
@@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:foreground="?attr/selectableItemBackground"
- android:background="?android:attr/windowBackground"
+ android:background="?android:attr/colorBackground"
android:gravity="center"
android:padding="8dp">
@@ -31,6 +31,6 @@
android:text="@string/load_next_page_label"
android:textColor="?android:attr/textColorPrimary"
android:layout_marginLeft="8dp"
- android:layout_marginRight="8dp"/>
+ android:layout_marginRight="8dp" />
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/core/src/main/res/values/arrays.xml b/core/src/main/res/values/arrays.xml
index 7749c6f3c..50afe630b 100644
--- a/core/src/main/res/values/arrays.xml
+++ b/core/src/main/res/values/arrays.xml
@@ -13,16 +13,22 @@
<item>never</item>
</string-array>
- <string-array name="spnVolumeReductionItems">
- <item>@string/feed_volume_reduction_off</item>
- <item>@string/feed_volume_reduction_light</item>
+ <string-array name="spnVolumeAdaptationItems">
<item>@string/feed_volume_reduction_heavy</item>
+ <item>@string/feed_volume_reduction_light</item>
+ <item>@string/feed_volume_reduction_off</item>
+ <item>@string/feed_volume_boost_light</item>
+ <item>@string/feed_volume_boost_medium</item>
+ <item>@string/feed_volume_boost_heavy</item>
</string-array>
- <string-array name="spnVolumeReductionValues">
- <item>off</item>
- <item>light</item>
+ <string-array name="spnVolumeAdaptationValues">
<item>heavy</item>
+ <item>light</item>
+ <item>off</item>
+ <item>light_boost</item>
+ <item>medium_boost</item>
+ <item>heavy_boost</item>
</string-array>
<string-array name="feed_refresh_interval_entries">
diff --git a/core/src/main/res/values/dimens.xml b/core/src/main/res/values/dimens.xml
index cddff1c47..68d0e59ab 100644
--- a/core/src/main/res/values/dimens.xml
+++ b/core/src/main/res/values/dimens.xml
@@ -6,11 +6,10 @@
<dimen name="text_size_micro">12sp</dimen>
<dimen name="text_size_small">14sp</dimen>
<dimen name="text_size_navdrawer">16sp</dimen>
- <dimen name="text_size_medium">18sp</dimen>
<dimen name="text_size_large">22sp</dimen>
<dimen name="thumbnail_length_itemlist">56dp</dimen>
<dimen name="thumbnail_length_queue_item">56dp</dimen>
- <dimen name="thumbnail_length_onlinefeedview">100dp</dimen>
+ <dimen name="thumbnail_length_onlinefeedview">92dp</dimen>
<dimen name="feeditemlist_header_height">132dp</dimen>
<dimen name="thumbnail_length_navlist">40dp</dimen>
<dimen name="listitem_iconwithtext_height">48dp</dimen>
diff --git a/core/src/main/res/values/styles.xml b/core/src/main/res/values/styles.xml
index f1dcd3200..da227d163 100644
--- a/core/src/main/res/values/styles.xml
+++ b/core/src/main/res/values/styles.xml
@@ -31,6 +31,7 @@
</style>
<style name="Theme.AntennaPod.Light" parent="Theme.AntennaPod.Dynamic.Light">
+ <item name="isMaterial3DynamicColorApplied">false</item>
<item name="colorPrimary">@color/accent_light</item>
<item name="colorOnPrimary">@color/white</item>
<item name="colorAccent">@color/accent_light</item>
@@ -39,9 +40,9 @@
<item name="colorPrimaryDark">@color/accent_light</item>
<item name="colorPrimaryContainer">@color/accent_light</item>
<item name="colorOnPrimaryContainer">@color/white</item>
- <item name="android:windowBackground">@color/background_light</item>
+ <item name="android:colorBackground">@color/background_light</item>
<item name="colorSurface">@color/background_light</item>
- <item name="colorSurfaceVariant">#B8E4FF</item>
+ <item name="colorSurfaceVariant">#D3DCE0</item>
</style>
<style name="Theme.AntennaPod.Dynamic.Dark" parent="Theme.Base.AntennaPod.Dynamic.Dark">
@@ -73,6 +74,7 @@
</style>
<style name="Theme.AntennaPod.Dark" parent="Theme.AntennaPod.Dynamic.Dark">
+ <item name="isMaterial3DynamicColorApplied">false</item>
<item name="colorPrimary">@color/accent_dark</item>
<item name="colorOnPrimary">@color/black</item>
<item name="colorAccent">@color/accent_dark</item>
@@ -81,15 +83,15 @@
<item name="colorPrimaryDark">@color/accent_dark</item>
<item name="colorPrimaryContainer">@color/accent_dark</item>
<item name="colorOnPrimaryContainer">@color/black</item>
- <item name="android:windowBackground">@color/background_darktheme</item>
+ <item name="android:colorBackground">@color/background_darktheme</item>
<item name="colorSurface">@color/background_darktheme</item>
- <item name="colorSurfaceVariant">#1B3B6A</item>
+ <item name="colorSurfaceVariant">#2F3B4F</item>
</style>
<style name="Theme.AntennaPod.Dynamic.TrueBlack" parent="Theme.AntennaPod.Dynamic.Dark">
<item name="android:textColorPrimary">@color/white</item>
<item name="android:color">@color/white</item>
- <item name="android:windowBackground">@color/black</item>
+ <item name="android:colorBackground">@color/black</item>
<item name="colorSurface">@color/black</item>
<item name="background_color">@color/black</item>
<item name="background_elevated">@color/black</item>
@@ -99,7 +101,7 @@
<style name="Theme.AntennaPod.TrueBlack" parent="Theme.AntennaPod.Dark">
<item name="android:textColorPrimary">@color/white</item>
<item name="android:color">@color/white</item>
- <item name="android:windowBackground">@color/black</item>
+ <item name="android:colorBackground">@color/black</item>
<item name="colorSurface">@color/black</item>
<item name="background_color">@color/black</item>
<item name="background_elevated">@color/black</item>
@@ -235,24 +237,24 @@
<item name="android:fontFamily">sans-serif-light</item>
</style>
- <style name="AntennaPod.TextView.ListItemPrimaryTitle" parent="@android:style/TextAppearance.Small">
- <item name="android:textSize">16sp</item>
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <style name="AntennaPod.TextView.ListItemPrimaryTitle" parent="@style/TextAppearance.Material3.BodyLarge">
+ <item name="android:textColor">?attr/colorOnSurface</item>
<item name="android:maxLines">2</item>
<item name="android:ellipsize">end</item>
+ <item name="lineHeight">20sp</item>
+ <item name="android:lineHeight" tools:targetApi="p">20sp</item>
</style>
- <style name="AntennaPod.TextView.ListItemPrimaryTitle2" parent="@android:style/TextAppearance.Small">
- <item name="android:textSize">16sp</item>
- <item name="android:textColor">?android:attr/textColorPrimary</item>
+ <style name="AntennaPod.TextView.ListItemSecondaryTitle" parent="@style/TextAppearance.Material3.BodyMedium">
+ <item name="android:textColor">?attr/colorOnSurfaceVariant</item>
+ <item name="android:lines">1</item>
<item name="android:ellipsize">end</item>
</style>
- <style name="AntennaPod.TextView.ListItemSecondaryTitle" parent="@android:style/TextAppearance.Small">
- <item name="android:textSize">14sp</item>
- <item name="android:textColor">?android:attr/textColorSecondary</item>
- <item name="android:lines">1</item>
- <item name="android:ellipsize">end</item>
+ <style name="AntennaPod.TextView.ListItemBody" parent="@style/TextAppearance.Material3.BodyMedium">
+ <item name="android:textColor">?attr/colorOnSurfaceVariant</item>
+ <item name="lineHeight">18sp</item>
+ <item name="android:lineHeight" tools:targetApi="p">18sp</item>
</style>
<style name="OutlinedButtonBetterContrast" parent="Widget.Material3.Button.OutlinedButton">