summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java66
-rw-r--r--app/src/main/res/menu/statistics.xml6
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/DBWriter.java74
-rw-r--r--core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java14
-rw-r--r--core/src/main/res/values/strings.xml2
5 files changed, 127 insertions, 35 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java
index 2b5310837..7e1fdf2b9 100644
--- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java
+++ b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java
@@ -1,14 +1,9 @@
package de.danoeh.antennapod.fragment.preferences;
import android.content.Context;
+import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.fragment.app.Fragment;
-import androidx.appcompat.app.AlertDialog;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -18,10 +13,21 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.RadioButton;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.app.AlertDialog;
+import androidx.fragment.app.Fragment;
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
import de.danoeh.antennapod.R;
import de.danoeh.antennapod.activity.PreferenceActivity;
import de.danoeh.antennapod.adapter.StatisticsListAdapter;
+import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBWriter;
+import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
@@ -52,7 +58,9 @@ public class StatisticsFragment extends Fragment {
@Nullable
@Override
- public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ public View onCreateView(
+ @NonNull LayoutInflater inflater,
+ @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.statistics_activity, container, false);
feedStatisticsList = root.findViewById(R.id.statistics_list);
progressBar = root.findViewById(R.id.progressBar);
@@ -71,8 +79,17 @@ public class StatisticsFragment extends Fragment {
}
@Override
+ public void onDestroyView() {
+ super.onDestroyView();
+ if (disposable != null) {
+ disposable.dispose();
+ }
+ }
+
+ @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.statistics, menu);
+ menu.findItem(R.id.statistics_reset).setEnabled(!countAll);
}
@Override
@@ -81,6 +98,10 @@ public class StatisticsFragment extends Fragment {
selectStatisticsMode();
return true;
}
+ if (item.getItemId() == R.id.statistics_reset) {
+ confirmResetStatistics();
+ return true;
+ }
return super.onOptionsItemSelected(item);
}
@@ -101,11 +122,42 @@ public class StatisticsFragment extends Fragment {
listAdapter.setCountAll(countAll);
prefs.edit().putBoolean(PREF_COUNT_ALL, countAll).apply();
refreshStatistics();
+ getActivity().invalidateOptionsMenu();
});
builder.show();
}
+ private void confirmResetStatistics() {
+ if (!countAll) {
+ ConfirmationDialog conDialog = new ConfirmationDialog(
+ getActivity(),
+ R.string.statistics_reset_data,
+ R.string.statistics_reset_data_msg) {
+
+ @Override
+ public void onConfirmButtonPressed(DialogInterface dialog) {
+ dialog.dismiss();
+ doResetStatistics();
+ }
+ };
+ conDialog.createNewDialog().show();
+ }
+ }
+
+ private void doResetStatistics() {
+ progressBar.setVisibility(View.VISIBLE);
+ feedStatisticsList.setVisibility(View.GONE);
+ if (disposable != null) {
+ disposable.dispose();
+ }
+
+ disposable = Completable.fromFuture(DBWriter.resetStatistics())
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(this::refreshStatistics, error -> Log.e(TAG, Log.getStackTraceString(error)));
+ }
+
private void refreshStatistics() {
progressBar.setVisibility(View.VISIBLE);
feedStatisticsList.setVisibility(View.GONE);
diff --git a/app/src/main/res/menu/statistics.xml b/app/src/main/res/menu/statistics.xml
index 6ecc70707..eb2a51550 100644
--- a/app/src/main/res/menu/statistics.xml
+++ b/app/src/main/res/menu/statistics.xml
@@ -3,6 +3,12 @@
xmlns:custom="http://schemas.android.com/apk/res-auto">
<item
+ android:id="@+id/statistics_reset"
+ android:title="@string/statistics_reset_data"
+ custom:showAsAction="never"
+ />
+
+ <item
android:id="@+id/statistics_mode"
android:icon="?attr/ic_filter"
android:title="@string/statistics_mode"
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 11d90e57c..e0e15c1ff 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,9 +2,10 @@ package de.danoeh.antennapod.core.storage;
import android.app.backup.BackupManager;
import android.content.Context;
-import androidx.annotation.NonNull;
import android.util.Log;
+import androidx.annotation.NonNull;
+
import org.greenrobot.eventbus.EventBus;
import java.io.File;
@@ -86,7 +87,8 @@ 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("Requested to delete FeedMedia [id=%d, title=%s, downloaded=%s",
media.getId(), media.getEpisodeTitle(), String.valueOf(media.isDownloaded())));
if (media.isDownloaded()) {
@@ -111,7 +113,7 @@ public class DBWriter {
}
// Gpodder: queue delete action for synchronization
- if(GpodnetPreferences.loggedIn()) {
+ if (GpodnetPreferences.loggedIn()) {
FeedItem item = media.getItem();
GpodnetEpisodeAction action = new GpodnetEpisodeAction.Builder(item, GpodnetEpisodeAction.Action.DELETE)
.currentDeviceId()
@@ -159,7 +161,7 @@ public class DBWriter {
adapter.open();
if (removed.size() > 0) {
adapter.setQueue(queue);
- for(FeedItem item : removed) {
+ for (FeedItem item : removed) {
EventBus.getDefault().post(QueueEvent.irreversibleRemoved(item));
}
}
@@ -184,7 +186,6 @@ public class DBWriter {
/**
* Deletes the entire playback history.
- *
*/
public static Future<?> clearPlaybackHistory() {
return dbExec.submit(() -> {
@@ -215,7 +216,7 @@ public class DBWriter {
* its playback completion date is set to a non-null value. This method will set the playback completion date to the
* current date regardless of the current value.
*
- * @param media FeedMedia that should be added to the playback history.
+ * @param media FeedMedia that should be added to the playback history.
*/
public static Future<?> addItemToPlaybackHistory(final FeedMedia media) {
return dbExec.submit(() -> {
@@ -234,7 +235,7 @@ public class DBWriter {
/**
* Adds a Download status object to the download log.
*
- * @param status The DownloadStatus object.
+ * @param status The DownloadStatus object.
*/
public static Future<?> addDownloadStatus(final DownloadStatus status) {
return dbExec.submit(() -> {
@@ -304,9 +305,9 @@ public class DBWriter {
* Appends FeedItem objects to the end of the queue. The 'read'-attribute of all items will be set to true.
* If a FeedItem is already in the queue, the FeedItem will not change its position in the queue.
*
- * @param context A context that is used for opening a database connection.
+ * @param context A context that is used for opening a database connection.
* @param performAutoDownload true if an auto-download process should be started after the operation.
- * @param itemIds IDs of the FeedItem objects that should be added to the queue.
+ * @param itemIds IDs of the FeedItem objects that should be added to the queue.
*/
public static Future<?> addQueueItem(final Context context, final boolean performAutoDownload,
final long... itemIds) {
@@ -394,7 +395,6 @@ public class DBWriter {
/**
* Removes all FeedItem objects from the queue.
- *
*/
public static Future<?> clearQueue() {
return dbExec.submit(() -> {
@@ -409,7 +409,8 @@ public class DBWriter {
/**
* Removes a FeedItem object from the queue.
- * @param context A context that is used for opening a database connection.
+ *
+ * @param context A context that is used for opening a database connection.
* @param performAutoDownload true if an auto-download process should be started after the operation.
* @param item FeedItem that should be removed.
*/
@@ -497,14 +498,15 @@ public class DBWriter {
/**
* Moves the specified item to the top of the queue.
- * @param itemId The item to move to the top of the queue
+ *
+ * @param itemId The item to move to the top of the queue
* @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(() -> {
LongList queueIdList = DBReader.getQueueIDList();
int index = queueIdList.indexOf(itemId);
- if (index >=0) {
+ if (index >= 0) {
moveQueueItemHelper(index, 0, broadcastUpdate);
} else {
Log.e(TAG, "moveQueueItemToTop: item not found");
@@ -514,7 +516,8 @@ public class DBWriter {
/**
* Moves the specified item to the bottom of the queue.
- * @param itemId The item to move to the bottom of the queue
+ *
+ * @param itemId The item to move to the bottom of the queue
* @param broadcastUpdate true if this operation should trigger a QueueUpdateBroadcast. This option should be set to
*/
public static Future<?> moveQueueItemToBottom(final long itemId,
@@ -524,7 +527,7 @@ public class DBWriter {
int index = queueIdList.indexOf(itemId);
if (index >= 0) {
moveQueueItemHelper(index, queueIdList.size() - 1,
- broadcastUpdate);
+ broadcastUpdate);
} else {
Log.e(TAG, "moveQueueItemToBottom: item not found");
}
@@ -605,7 +608,7 @@ public class DBWriter {
adapter.open();
adapter.setFeedItemRead(played, itemIds);
adapter.close();
- if(broadcastUpdate) {
+ if (broadcastUpdate) {
EventDistributor.getInstance().sendUnreadItemsUpdateBroadcast();
}
});
@@ -614,7 +617,8 @@ public class DBWriter {
/**
* Sets the 'read'-attribute of a FeedItem to the specified value.
- * @param item The FeedItem object
+ *
+ * @param item The FeedItem object
* @param played New value of the 'read'-attribute one of FeedItem.PLAYED,
* FeedItem.NEW, FeedItem.UNPLAYED
* @param resetMediaPosition true if this method should also reset the position of the FeedItem's FeedMedia object.
@@ -644,7 +648,7 @@ public class DBWriter {
/**
* Sets the 'read'-attribute of all NEW FeedItems of a specific Feed to UNPLAYED.
*
- * @param feedId ID of the Feed.
+ * @param feedId ID of the Feed.
*/
public static Future<?> removeFeedNewFlag(final long feedId) {
return dbExec.submit(() -> {
@@ -660,7 +664,7 @@ public class DBWriter {
/**
* Sets the 'read'-attribute of all FeedItems of a specific Feed to PLAYED.
*
- * @param feedId ID of the Feed.
+ * @param feedId ID of the Feed.
*/
public static Future<?> markFeedRead(final long feedId) {
return dbExec.submit(() -> {
@@ -732,7 +736,7 @@ public class DBWriter {
* Saves a FeedMedia object in the database. This method will save all attributes of the FeedMedia object. The
* contents of FeedComponent-attributes (e.g. the FeedMedia's 'item'-attribute) will not be saved.
*
- * @param media The FeedMedia object.
+ * @param media The FeedMedia object.
*/
public static Future<?> setFeedMedia(final FeedMedia media) {
return dbExec.submit(() -> {
@@ -746,7 +750,7 @@ public class DBWriter {
/**
* Saves the 'position', 'duration' and 'last played time' attributes of a FeedMedia object
*
- * @param media The FeedMedia object.
+ * @param media The FeedMedia object.
*/
public static Future<?> setFeedMediaPlaybackInformation(final FeedMedia media) {
return dbExec.submit(() -> {
@@ -761,7 +765,7 @@ public class DBWriter {
* Saves a FeedItem object in the database. This method will save all attributes of the FeedItem object including
* the content of FeedComponent-attributes.
*
- * @param item The FeedItem object.
+ * @param item The FeedItem object.
*/
public static Future<?> setFeedItem(final FeedItem item) {
return dbExec.submit(() -> {
@@ -777,7 +781,7 @@ public class DBWriter {
* Updates download URL of a feed
*/
public static Future<?> updateFeedDownloadURL(final String original, final String updated) {
- Log.d(TAG, "updateFeedDownloadURL(original: " + original + ", updated: " + updated +")");
+ Log.d(TAG, "updateFeedDownloadURL(original: " + original + ", updated: " + updated + ")");
return dbExec.submit(() -> {
PodDBAdapter adapter = PodDBAdapter.getInstance();
adapter.open();
@@ -802,11 +806,11 @@ public class DBWriter {
}
private static boolean itemListContains(List<FeedItem> items, long itemId) {
- return indexInItemList(items, itemId) >= 0;
+ return indexInItemList(items, itemId) >= 0;
}
private static int indexInItemList(List<FeedItem> items, long itemId) {
- for (int i = 0; i < items.size(); i ++) {
+ for (int i = 0; i < items.size(); i++) {
FeedItem item = items.get(i);
if (item.getId() == itemId) {
return i;
@@ -870,7 +874,7 @@ public class DBWriter {
/**
* Sets the 'auto_download'-attribute of specific FeedItem.
*
- * @param feedItem FeedItem.
+ * @param feedItem FeedItem.
* @param autoDownload true enables auto download, false disables it
*/
public static Future<?> setFeedItemAutoDownload(final FeedItem feedItem,
@@ -888,7 +892,7 @@ public class DBWriter {
return dbExec.submit(() -> {
int failedAttempts = feedItem.getFailedAutoDownloadAttempts() + 1;
long autoDownload;
- if(!feedItem.getAutoDownload() || failedAttempts >= 10) {
+ if (!feedItem.getAutoDownload() || failedAttempts >= 10) {
autoDownload = 0; // giving up, disable auto download
feedItem.setAutoDownload(false);
} else {
@@ -924,7 +928,8 @@ public class DBWriter {
/**
* Set filter of the feed
- * @param feedId The feed's ID
+ *
+ * @param feedId The feed's ID
* @param filterValues Values that represent properties to filter by
*/
public static Future<?> setFeedItemsFilter(final long feedId,
@@ -939,4 +944,17 @@ public class DBWriter {
});
}
+
+ /**
+ * Reset the statistics in DB
+ */
+ @NonNull
+ public static Future<?> resetStatistics() {
+ return dbExec.submit(() -> {
+ PodDBAdapter adapter = PodDBAdapter.getInstance();
+ adapter.open();
+ adapter.resetAllMediaPlayedDuration();
+ adapter.close();
+ });
+ }
}
diff --git a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
index 5feedcebf..66f6d223d 100644
--- a/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
+++ b/core/src/main/java/de/danoeh/antennapod/core/storage/PodDBAdapter.java
@@ -476,6 +476,20 @@ public class PodDBAdapter {
}
}
+ public void resetAllMediaPlayedDuration() {
+ try {
+ db.beginTransactionNonExclusive();
+ ContentValues values = new ContentValues();
+ values.put(KEY_PLAYED_DURATION, 0);
+ db.update(TABLE_NAME_FEED_MEDIA, values, null, new String[0]);
+ db.setTransactionSuccessful();
+ } catch (SQLException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ } finally {
+ db.endTransaction();
+ }
+ }
+
/**
* Insert all FeedItems of a feed and the feed object itself in a single
* transaction
diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml
index 0d61e30cd..5a0267232 100644
--- a/core/src/main/res/values/strings.xml
+++ b/core/src/main/res/values/strings.xml
@@ -37,6 +37,8 @@
<string name="statistics_mode_normal">Calculate duration that was actually played. Playing twice is counted twice, while marking as played is not counted</string>
<string name="statistics_mode_count_all">Sum up all podcasts marked as played</string>
<string name="statistics_speed_not_counted">Notice: Playback speed is never taken into account.</string>
+ <string name="statistics_reset_data">Reset statistics data</string>
+ <string name="statistics_reset_data_msg">This will erase the history of duration played for all episodes. Are you sure you want to proceed?</string>
<!-- Main activity -->
<string name="drawer_open">Open menu</string>