Added on-demand configuration for stream vs download
This commit is contained in:
parent
b233f4dcb7
commit
8be147c603
|
@ -171,6 +171,7 @@ dependencies {
|
||||||
implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
|
implementation "com.github.AntennaPod:AntennaPod-AudioPlayer:$audioPlayerVersion"
|
||||||
implementation 'com.github.mfietz:fyydlin:v0.5.0'
|
implementation 'com.github.mfietz:fyydlin:v0.5.0'
|
||||||
implementation 'com.github.ByteHamster:SearchPreference:v2.0.0'
|
implementation 'com.github.ByteHamster:SearchPreference:v2.0.0'
|
||||||
|
implementation "com.github.skydoves:balloon:1.1.5"
|
||||||
|
|
||||||
androidTestImplementation "org.awaitility:awaitility:$awaitilityVersion"
|
androidTestImplementation "org.awaitility:awaitility:$awaitilityVersion"
|
||||||
androidTestImplementation 'com.nanohttpd:nanohttpd:2.1.1'
|
androidTestImplementation 'com.nanohttpd:nanohttpd:2.1.1'
|
||||||
|
|
|
@ -12,6 +12,7 @@ import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
import de.danoeh.antennapod.core.dialog.DownloadRequestErrorDialogCreator;
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UsageStatistics;
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||||
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
import de.danoeh.antennapod.core.storage.DownloadRequestException;
|
||||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||||
|
@ -50,6 +51,8 @@ public class DownloadActionButton extends ItemActionButton {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UsageStatistics.logAction(UsageStatistics.ACTION_DOWNLOAD);
|
||||||
|
|
||||||
if (NetworkUtils.isEpisodeDownloadAllowed() || MobileDownloadHelper.userAllowedMobileDownloads()) {
|
if (NetworkUtils.isEpisodeDownloadAllowed() || MobileDownloadHelper.userAllowedMobileDownloads()) {
|
||||||
downloadEpisode(context);
|
downloadEpisode(context);
|
||||||
} else if (MobileDownloadHelper.userChoseAddToQueue() && !isInQueue) {
|
} else if (MobileDownloadHelper.userChoseAddToQueue() && !isInQueue) {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import androidx.annotation.AttrRes;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageButton;
|
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
|
@ -47,7 +46,7 @@ public abstract class ItemActionButton {
|
||||||
return new PlayActionButton(item);
|
return new PlayActionButton(item);
|
||||||
} else if (isDownloadingMedia) {
|
} else if (isDownloadingMedia) {
|
||||||
return new CancelDownloadActionButton(item);
|
return new CancelDownloadActionButton(item);
|
||||||
} else if (UserPreferences.streamOverDownload() && allowStream) {
|
} else if (UserPreferences.isStreamOverDownload() && allowStream) {
|
||||||
return new StreamActionButton(item);
|
return new StreamActionButton(item);
|
||||||
} else if (MobileDownloadHelper.userAllowedMobileDownloads()
|
} else if (MobileDownloadHelper.userAllowedMobileDownloads()
|
||||||
|| !MobileDownloadHelper.userChoseAddToQueue() || isInQueue) {
|
|| !MobileDownloadHelper.userChoseAddToQueue() || isInQueue) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.core.feed.FeedItem;
|
import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
import de.danoeh.antennapod.core.feed.MediaType;
|
import de.danoeh.antennapod.core.feed.MediaType;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UsageStatistics;
|
||||||
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
import de.danoeh.antennapod.core.service.playback.PlaybackService;
|
||||||
import de.danoeh.antennapod.core.util.NetworkUtils;
|
import de.danoeh.antennapod.core.util.NetworkUtils;
|
||||||
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
|
import de.danoeh.antennapod.core.util.playback.PlaybackServiceStarter;
|
||||||
|
@ -38,6 +39,8 @@ public class StreamActionButton extends ItemActionButton {
|
||||||
if (media == null) {
|
if (media == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
UsageStatistics.logAction(UsageStatistics.ACTION_STREAM);
|
||||||
|
|
||||||
if (!NetworkUtils.isStreamingAllowed()) {
|
if (!NetworkUtils.isStreamingAllowed()) {
|
||||||
new StreamingConfirmationDialog(context, media).show();
|
new StreamingConfirmationDialog(context, media).show();
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -11,18 +11,25 @@ import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.core.text.TextUtilsCompat;
|
||||||
import androidx.core.util.ObjectsCompat;
|
import androidx.core.util.ObjectsCompat;
|
||||||
|
import androidx.core.view.ViewCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.load.resource.bitmap.FitCenter;
|
import com.bumptech.glide.load.resource.bitmap.FitCenter;
|
||||||
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.skydoves.balloon.ArrowOrientation;
|
||||||
|
import com.skydoves.balloon.Balloon;
|
||||||
|
import com.skydoves.balloon.BalloonAnimation;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.MainActivity;
|
import de.danoeh.antennapod.activity.MainActivity;
|
||||||
import de.danoeh.antennapod.adapter.actionbutton.CancelDownloadActionButton;
|
import de.danoeh.antennapod.adapter.actionbutton.CancelDownloadActionButton;
|
||||||
|
@ -43,11 +50,14 @@ import de.danoeh.antennapod.core.feed.FeedItem;
|
||||||
import de.danoeh.antennapod.core.feed.FeedMedia;
|
import de.danoeh.antennapod.core.feed.FeedMedia;
|
||||||
import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
|
import de.danoeh.antennapod.core.feed.util.ImageResourceUtils;
|
||||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UsageStatistics;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.service.download.Downloader;
|
import de.danoeh.antennapod.core.service.download.Downloader;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
import de.danoeh.antennapod.core.storage.DownloadRequester;
|
||||||
import de.danoeh.antennapod.core.util.Converter;
|
import de.danoeh.antennapod.core.util.Converter;
|
||||||
import de.danoeh.antennapod.core.util.DateUtils;
|
import de.danoeh.antennapod.core.util.DateUtils;
|
||||||
|
import de.danoeh.antennapod.core.util.ThemeUtils;
|
||||||
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
import de.danoeh.antennapod.core.util.playback.PlaybackController;
|
||||||
import de.danoeh.antennapod.core.util.playback.Timeline;
|
import de.danoeh.antennapod.core.util.playback.Timeline;
|
||||||
import de.danoeh.antennapod.view.ShownotesWebView;
|
import de.danoeh.antennapod.view.ShownotesWebView;
|
||||||
|
@ -61,6 +71,7 @@ import org.greenrobot.eventbus.Subscribe;
|
||||||
import org.greenrobot.eventbus.ThreadMode;
|
import org.greenrobot.eventbus.ThreadMode;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays information about a FeedItem and actions.
|
* Displays information about a FeedItem and actions.
|
||||||
|
@ -158,11 +169,60 @@ public class ItemFragment extends Fragment {
|
||||||
butAction2Icon = layout.findViewById(R.id.butAction2Icon);
|
butAction2Icon = layout.findViewById(R.id.butAction2Icon);
|
||||||
butAction1Text = layout.findViewById(R.id.butAction1Text);
|
butAction1Text = layout.findViewById(R.id.butAction1Text);
|
||||||
butAction2Text = layout.findViewById(R.id.butAction2Text);
|
butAction2Text = layout.findViewById(R.id.butAction2Text);
|
||||||
butAction1.setOnClickListener(v -> actionButton1.onClick(getContext()));
|
|
||||||
butAction2.setOnClickListener(v -> actionButton2.onClick(getContext()));
|
butAction1.setOnClickListener(v -> {
|
||||||
|
if (actionButton1 instanceof StreamActionButton && !UserPreferences.isStreamOverDownload()
|
||||||
|
&& UsageStatistics.hasSignificantBiasTo(UsageStatistics.ACTION_STREAM)) {
|
||||||
|
showOnDemandConfigBalloon(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
actionButton1.onClick(getContext());
|
||||||
|
});
|
||||||
|
butAction2.setOnClickListener(v -> {
|
||||||
|
if (actionButton2 instanceof DownloadActionButton && UserPreferences.isStreamOverDownload()
|
||||||
|
&& UsageStatistics.hasSignificantBiasTo(UsageStatistics.ACTION_DOWNLOAD)) {
|
||||||
|
showOnDemandConfigBalloon(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
actionButton2.onClick(getContext());
|
||||||
|
});
|
||||||
return layout;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showOnDemandConfigBalloon(boolean offerStreaming) {
|
||||||
|
boolean isLocaleRtl = TextUtilsCompat.getLayoutDirectionFromLocale(Locale.getDefault())
|
||||||
|
== ViewCompat.LAYOUT_DIRECTION_RTL;
|
||||||
|
Balloon balloon = new Balloon.Builder(getContext())
|
||||||
|
.setArrowOrientation(ArrowOrientation.TOP)
|
||||||
|
.setArrowPosition(0.25f + ((isLocaleRtl ^ offerStreaming) ? 0f : 0.5f))
|
||||||
|
.setWidthRatio(1.0f)
|
||||||
|
.isRtlSupport(true)
|
||||||
|
.setBackgroundColor(ThemeUtils.getColorFromAttr(getContext(), R.attr.colorSecondary))
|
||||||
|
.setBalloonAnimation(BalloonAnimation.OVERSHOOT)
|
||||||
|
.setLayout(R.layout.popup_bubble_view)
|
||||||
|
.setDismissWhenTouchOutside(true)
|
||||||
|
.setLifecycleOwner(this)
|
||||||
|
.build();
|
||||||
|
Button positiveButton = balloon.getContentView().findViewById(R.id.balloon_button_positive);
|
||||||
|
Button negativeButton = balloon.getContentView().findViewById(R.id.balloon_button_negative);
|
||||||
|
TextView message = balloon.getContentView().findViewById(R.id.balloon_message);
|
||||||
|
message.setText(offerStreaming
|
||||||
|
? R.string.on_demand_config_stream_text : R.string.on_demand_config_download_text);
|
||||||
|
positiveButton.setOnClickListener(v1 -> {
|
||||||
|
UserPreferences.setStreamOverDownload(offerStreaming);
|
||||||
|
// Update all visible lists to reflect new streaming action button
|
||||||
|
EventBus.getDefault().post(new UnreadItemsUpdateEvent());
|
||||||
|
((MainActivity) getActivity()).showSnackbarAbovePlayer(
|
||||||
|
R.string.on_demand_config_setting_changed, Snackbar.LENGTH_SHORT);
|
||||||
|
balloon.dismiss();
|
||||||
|
});
|
||||||
|
negativeButton.setOnClickListener(v1 -> {
|
||||||
|
UsageStatistics.askAgainLater(UsageStatistics.ACTION_STREAM); // Type does not matter. Both are silenced.
|
||||||
|
balloon.dismiss();
|
||||||
|
});
|
||||||
|
balloon.showAlignBottom(butAction1, 0, (int) (-12 * getResources().getDisplayMetrics().density));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import androidx.preference.PreferenceFragmentCompat;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.PreferenceActivity;
|
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||||
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
import de.danoeh.antennapod.core.event.UnreadItemsUpdateEvent;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UsageStatistics;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil;
|
import de.danoeh.antennapod.core.util.gui.PictureInPictureUtil;
|
||||||
import de.danoeh.antennapod.dialog.SkipPreferenceDialog;
|
import de.danoeh.antennapod.dialog.SkipPreferenceDialog;
|
||||||
|
@ -63,6 +64,7 @@ public class PlaybackPreferencesFragment extends PreferenceFragmentCompat {
|
||||||
findPreference(PREF_PLAYBACK_PREFER_STREAMING).setOnPreferenceChangeListener((preference, newValue) -> {
|
findPreference(PREF_PLAYBACK_PREFER_STREAMING).setOnPreferenceChangeListener((preference, newValue) -> {
|
||||||
// Update all visible lists to reflect new streaming action button
|
// Update all visible lists to reflect new streaming action button
|
||||||
EventBus.getDefault().post(new UnreadItemsUpdateEvent());
|
EventBus.getDefault().post(new UnreadItemsUpdateEvent());
|
||||||
|
UsageStatistics.askAgainLater(UsageStatistics.ACTION_STREAM);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ public class PreferenceUpgrader {
|
||||||
}
|
}
|
||||||
|
|
||||||
UserPreferences.setQueueLocked(false);
|
UserPreferences.setQueueLocked(false);
|
||||||
prefs.edit().putBoolean(UserPreferences.PREF_STREAM_OVER_DOWNLOAD, false).apply();
|
UserPreferences.setStreamOverDownload(false);
|
||||||
|
|
||||||
if (!prefs.contains(UserPreferences.PREF_ENQUEUE_LOCATION)) {
|
if (!prefs.contains(UserPreferences.PREF_ENQUEUE_LOCATION)) {
|
||||||
final String keyOldPrefEnqueueFront = "prefQueueAddToFront";
|
final String keyOldPrefEnqueueFront = "prefQueueAddToFront";
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
||||||
|
|
||||||
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
||||||
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
|
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UsageStatistics;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||||
|
@ -42,6 +43,7 @@ public class ClientConfig {
|
||||||
}
|
}
|
||||||
PodDBAdapter.init(context);
|
PodDBAdapter.init(context);
|
||||||
UserPreferences.init(context);
|
UserPreferences.init(context);
|
||||||
|
UsageStatistics.init(context);
|
||||||
PlaybackPreferences.init(context);
|
PlaybackPreferences.init(context);
|
||||||
NetworkUtils.init(context);
|
NetworkUtils.init(context);
|
||||||
AntennapodHttpClient.setCacheDirectory(new File(context.getCacheDir(), "okhttp"));
|
AntennapodHttpClient.setCacheDirectory(new File(context.getCacheDir(), "okhttp"));
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package de.danoeh.antennapod.core.preferences;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collects statistics about the app usage. The statistics are used to allow on-demand configuration:
|
||||||
|
* "Looks like you stream a lot. Do you want to toggle the 'Prefer streaming' setting?".
|
||||||
|
* The data is only stored locally on the device. It is NOT used for analytics/tracking.
|
||||||
|
* A private instance of this class must first be instantiated via
|
||||||
|
* init() or otherwise every public method will throw an Exception
|
||||||
|
* when called.
|
||||||
|
*/
|
||||||
|
public class UsageStatistics {
|
||||||
|
private UsageStatistics() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String PREF_DB_NAME = "UsageStatistics";
|
||||||
|
private static final float MOVING_AVERAGE_WEIGHT = 0.8f;
|
||||||
|
private static final float MOVING_AVERAGE_BIAS_THRESHOLD = 0.1f;
|
||||||
|
private static final long ASK_AGAIN_LATER_DELAY = 1000 * 3600 * 24 * 10; // 10 days
|
||||||
|
private static final String SUFFIX_HIDDEN_UNTIL = "_hiddenUntil";
|
||||||
|
private static SharedPreferences prefs;
|
||||||
|
|
||||||
|
public static final StatsAction ACTION_STREAM = new StatsAction("downloadVsStream", 0);
|
||||||
|
public static final StatsAction ACTION_DOWNLOAD = new StatsAction("downloadVsStream", 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the UsageStatistics class.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if context is null
|
||||||
|
*/
|
||||||
|
public static void init(@NonNull Context context) {
|
||||||
|
prefs = context.getSharedPreferences(PREF_DB_NAME, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void logAction(StatsAction action) {
|
||||||
|
int numExecutions = prefs.getInt(action.type + action.value, 0);
|
||||||
|
float movingAverage = prefs.getFloat(action.type, 0.5f);
|
||||||
|
prefs.edit()
|
||||||
|
.putInt(action.type + action.value, numExecutions + 1)
|
||||||
|
.putFloat(action.type, MOVING_AVERAGE_WEIGHT * movingAverage
|
||||||
|
+ (1 - MOVING_AVERAGE_WEIGHT) * action.value)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean hasSignificantBiasTo(StatsAction action) {
|
||||||
|
final float movingAverage = prefs.getFloat(action.type, 0.5f);
|
||||||
|
final long askAfter = prefs.getLong(action.type + SUFFIX_HIDDEN_UNTIL, 0);
|
||||||
|
return Math.abs(action.value - movingAverage) < MOVING_AVERAGE_BIAS_THRESHOLD
|
||||||
|
&& Calendar.getInstance().getTimeInMillis() > askAfter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void askAgainLater(StatsAction action) {
|
||||||
|
prefs.edit().putLong(action.type + SUFFIX_HIDDEN_UNTIL,
|
||||||
|
Calendar.getInstance().getTimeInMillis() + ASK_AGAIN_LATER_DELAY)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final class StatsAction {
|
||||||
|
public final String type;
|
||||||
|
public final int value;
|
||||||
|
|
||||||
|
public StatsAction(String type, int value) {
|
||||||
|
this.type = type;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -996,10 +996,14 @@ public class UserPreferences {
|
||||||
return prefs.getBoolean(PREF_TIME_RESPECTS_SPEED, false);
|
return prefs.getBoolean(PREF_TIME_RESPECTS_SPEED, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean streamOverDownload() {
|
public static boolean isStreamOverDownload() {
|
||||||
return prefs.getBoolean(PREF_STREAM_OVER_DOWNLOAD, false);
|
return prefs.getBoolean(PREF_STREAM_OVER_DOWNLOAD, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setStreamOverDownload(boolean stream) {
|
||||||
|
prefs.edit().putBoolean(PREF_STREAM_OVER_DOWNLOAD, stream).apply();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns if the queue is in keep sorted mode.
|
* Returns if the queue is in keep sorted mode.
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="16dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:textColor="?attr/colorOnSecondary"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:lines="3"
|
||||||
|
android:id="@+id/balloon_message"/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:gravity="end">
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:textColor="?attr/colorOnSecondary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/no"
|
||||||
|
android:id="@+id/balloon_button_negative"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
style="@style/Widget.MaterialComponents.Button.TextButton"
|
||||||
|
android:textColor="?attr/colorOnSecondary"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/yes"
|
||||||
|
android:id="@+id/balloon_button_positive"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
|
@ -810,4 +810,9 @@
|
||||||
<string name="widget_settings">Widget settings</string>
|
<string name="widget_settings">Widget settings</string>
|
||||||
<string name="widget_create_button">Create widget</string>
|
<string name="widget_create_button">Create widget</string>
|
||||||
<string name="widget_opacity">Opacity</string>
|
<string name="widget_opacity">Opacity</string>
|
||||||
|
|
||||||
|
<!-- On-Demand configuration -->
|
||||||
|
<string name="on_demand_config_setting_changed">Setting updated successfully.</string>
|
||||||
|
<string name="on_demand_config_stream_text">Looks like you stream a lot. Do you want episode lists to show stream buttons?</string>
|
||||||
|
<string name="on_demand_config_download_text">Looks like you download a lot. Do you want episode lists to show download buttons?</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import com.google.android.gms.security.ProviderInstaller;
|
||||||
import de.danoeh.antennapod.core.cast.CastManager;
|
import de.danoeh.antennapod.core.cast.CastManager;
|
||||||
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
import de.danoeh.antennapod.core.preferences.PlaybackPreferences;
|
||||||
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
|
import de.danoeh.antennapod.core.preferences.SleepTimerPreferences;
|
||||||
|
import de.danoeh.antennapod.core.preferences.UsageStatistics;
|
||||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
import de.danoeh.antennapod.core.service.download.AntennapodHttpClient;
|
||||||
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
import de.danoeh.antennapod.core.storage.PodDBAdapter;
|
||||||
|
@ -51,6 +52,7 @@ public class ClientConfig {
|
||||||
}
|
}
|
||||||
PodDBAdapter.init(context);
|
PodDBAdapter.init(context);
|
||||||
UserPreferences.init(context);
|
UserPreferences.init(context);
|
||||||
|
UsageStatistics.init(context);
|
||||||
PlaybackPreferences.init(context);
|
PlaybackPreferences.init(context);
|
||||||
NetworkUtils.init(context);
|
NetworkUtils.init(context);
|
||||||
// Don't initialize Cast-related logic unless it is enabled, to avoid the unnecessary
|
// Don't initialize Cast-related logic unless it is enabled, to avoid the unnecessary
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
include ':app', ':sync', ':core'
|
include ':app', ':core'
|
||||||
|
|
Loading…
Reference in New Issue