From 7451da112145f96ecddc314eea7b90fcb03737dd Mon Sep 17 00:00:00 2001 From: ByteHamster Date: Wed, 23 Feb 2022 00:22:51 +0100 Subject: Move statistics screens to new module --- app/build.gradle | 1 + .../adapter/DownloadStatisticsListAdapter.java | 50 ---- .../adapter/PlaybackStatisticsListAdapter.java | 73 ------ .../antennapod/adapter/StatisticsListAdapter.java | 123 --------- .../adapter/YearStatisticsListAdapter.java | 121 --------- .../fragment/CompletedDownloadsFragment.java | 1 + .../antennapod/fragment/DownloadLogFragment.java | 1 + .../antennapod/fragment/DownloadsFragment.java | 1 + .../antennapod/fragment/EpisodesFragment.java | 1 + .../antennapod/fragment/EpisodesListFragment.java | 1 + .../antennapod/fragment/FeedInfoFragment.java | 3 +- .../fragment/FeedStatisticsDialogFragment.java | 42 ---- .../fragment/FeedStatisticsFragment.java | 95 ------- .../antennapod/fragment/PagedToolbarFragment.java | 48 ---- .../antennapod/fragment/SubscriptionFragment.java | 2 +- .../preferences/DownloadStatisticsFragment.java | 91 ------- .../fragment/preferences/StatisticsFragment.java | 104 -------- .../SubscriptionStatisticsFragment.java | 279 --------------------- .../preferences/YearsStatisticsFragment.java | 87 ------- .../de/danoeh/antennapod/view/LineChartView.java | 138 ---------- .../de/danoeh/antennapod/view/PieChartView.java | 149 ----------- app/src/main/res/layout/feed_statistics.xml | 95 ------- app/src/main/res/layout/feed_statistics_dialog.xml | 7 - app/src/main/res/layout/pager_fragment.xml | 31 --- app/src/main/res/layout/statistics_activity.xml | 24 -- .../main/res/layout/statistics_filter_dialog.xml | 95 ------- app/src/main/res/layout/statistics_listitem.xml | 71 ------ .../res/layout/statistics_listitem_linechart.xml | 22 -- .../main/res/layout/statistics_listitem_total.xml | 48 ---- .../main/res/layout/statistics_year_listitem.xml | 32 --- app/src/main/res/menu/statistics.xml | 17 -- 31 files changed, 9 insertions(+), 1844 deletions(-) delete mode 100644 app/src/main/java/de/danoeh/antennapod/adapter/DownloadStatisticsListAdapter.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/adapter/YearStatisticsListAdapter.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/FeedStatisticsDialogFragment.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/FeedStatisticsFragment.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/PagedToolbarFragment.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/DownloadStatisticsFragment.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/SubscriptionStatisticsFragment.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/fragment/preferences/YearsStatisticsFragment.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/view/LineChartView.java delete mode 100644 app/src/main/java/de/danoeh/antennapod/view/PieChartView.java delete mode 100644 app/src/main/res/layout/feed_statistics.xml delete mode 100644 app/src/main/res/layout/feed_statistics_dialog.xml delete mode 100644 app/src/main/res/layout/pager_fragment.xml delete mode 100644 app/src/main/res/layout/statistics_activity.xml delete mode 100644 app/src/main/res/layout/statistics_filter_dialog.xml delete mode 100644 app/src/main/res/layout/statistics_listitem.xml delete mode 100644 app/src/main/res/layout/statistics_listitem_linechart.xml delete mode 100644 app/src/main/res/layout/statistics_listitem_total.xml delete mode 100644 app/src/main/res/layout/statistics_year_listitem.xml delete mode 100644 app/src/main/res/menu/statistics.xml (limited to 'app') diff --git a/app/build.gradle b/app/build.gradle index 1bd916425..01d2e0ef5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -121,6 +121,7 @@ dependencies { implementation project(':ui:app-start-intent') implementation project(':ui:common') implementation project(':ui:i18n') + implementation project(':ui:statistics') annotationProcessor "androidx.annotation:annotation:$annotationVersion" implementation "androidx.appcompat:appcompat:$appcompatVersion" diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadStatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/DownloadStatisticsListAdapter.java deleted file mode 100644 index 684ba281d..000000000 --- a/app/src/main/java/de/danoeh/antennapod/adapter/DownloadStatisticsListAdapter.java +++ /dev/null @@ -1,50 +0,0 @@ -package de.danoeh.antennapod.adapter; - -import android.content.Context; -import android.text.format.Formatter; - -import java.util.List; -import java.util.Locale; - -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.storage.StatisticsItem; -import de.danoeh.antennapod.view.PieChartView; - -/** - * Adapter for the download statistics list. - */ -public class DownloadStatisticsListAdapter extends StatisticsListAdapter { - - public DownloadStatisticsListAdapter(Context context) { - super(context); - } - - @Override - String getHeaderCaption() { - return context.getString(R.string.total_size_downloaded_podcasts); - } - - @Override - String getHeaderValue() { - return Formatter.formatShortFileSize(context, (long) pieChartData.getSum()); - } - - @Override - PieChartView.PieChartData generateChartData(List statisticsData) { - float[] dataValues = new float[statisticsData.size()]; - for (int i = 0; i < statisticsData.size(); i++) { - StatisticsItem item = statisticsData.get(i); - dataValues[i] = item.totalDownloadSize; - } - return new PieChartView.PieChartData(dataValues); - } - - @Override - 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))); - } - -} diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java deleted file mode 100644 index e566836e4..000000000 --- a/app/src/main/java/de/danoeh/antennapod/adapter/PlaybackStatisticsListAdapter.java +++ /dev/null @@ -1,73 +0,0 @@ -package de.danoeh.antennapod.adapter; - -import androidx.fragment.app.Fragment; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.storage.StatisticsItem; -import de.danoeh.antennapod.core.util.Converter; -import de.danoeh.antennapod.fragment.FeedStatisticsDialogFragment; -import de.danoeh.antennapod.view.PieChartView; - -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.Locale; - -/** - * Adapter for the playback statistics list. - */ -public class PlaybackStatisticsListAdapter extends StatisticsListAdapter { - - private final Fragment fragment; - private long timeFilterFrom = 0; - private long timeFilterTo = Long.MAX_VALUE; - private boolean includeMarkedAsPlayed = false; - - public PlaybackStatisticsListAdapter(Fragment fragment) { - super(fragment.getContext()); - this.fragment = fragment; - } - - public void setTimeFilter(boolean includeMarkedAsPlayed, long timeFilterFrom, long timeFilterTo) { - this.includeMarkedAsPlayed = includeMarkedAsPlayed; - this.timeFilterFrom = timeFilterFrom; - this.timeFilterTo = timeFilterTo; - } - - @Override - String getHeaderCaption() { - if (includeMarkedAsPlayed) { - return context.getString(R.string.statistics_counting_total); - } - SimpleDateFormat dateFormat = new SimpleDateFormat("MMM yyyy", Locale.getDefault()); - String dateFrom = dateFormat.format(new Date(timeFilterFrom)); - String dateTo = dateFormat.format(new Date(timeFilterTo)); - return context.getString(R.string.statistics_counting_range, dateFrom, dateTo); - } - - @Override - String getHeaderValue() { - return Converter.shortLocalizedDuration(context, (long) pieChartData.getSum()); - } - - @Override - PieChartView.PieChartData generateChartData(List statisticsData) { - float[] dataValues = new float[statisticsData.size()]; - for (int i = 0; i < statisticsData.size(); i++) { - StatisticsItem item = statisticsData.get(i); - dataValues[i] = item.timePlayed; - } - return new PieChartView.PieChartData(dataValues); - } - - @Override - void onBindFeedViewHolder(StatisticsHolder holder, StatisticsItem statsItem) { - long time = statsItem.timePlayed; - holder.value.setText(Converter.shortLocalizedDuration(context, time)); - - holder.itemView.setOnClickListener(v -> { - FeedStatisticsDialogFragment yourDialogFragment = FeedStatisticsDialogFragment.newInstance( - statsItem.feed.getId(), statsItem.feed.getTitle()); - yourDialogFragment.show(fragment.getChildFragmentManager().beginTransaction(), "DialogFragment"); - }); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java deleted file mode 100644 index f0451e974..000000000 --- a/app/src/main/java/de/danoeh/antennapod/adapter/StatisticsListAdapter.java +++ /dev/null @@ -1,123 +0,0 @@ -package de.danoeh.antennapod.adapter; - -import android.content.Context; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; -import android.widget.TextView; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.request.RequestOptions; - -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.glide.ApGlideSettings; -import de.danoeh.antennapod.core.storage.StatisticsItem; -import de.danoeh.antennapod.view.PieChartView; - -import java.util.List; - -/** - * Parent Adapter for the playback and download statistics list. - */ -public abstract class StatisticsListAdapter extends RecyclerView.Adapter { - private static final int TYPE_HEADER = 0; - private static final int TYPE_FEED = 1; - final Context context; - private List statisticsData; - PieChartView.PieChartData pieChartData; - - StatisticsListAdapter(Context context) { - this.context = context; - } - - @Override - public int getItemCount() { - return statisticsData.size() + 1; - } - - @Override - public int getItemViewType(int position) { - return position == 0 ? TYPE_HEADER : TYPE_FEED; - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - LayoutInflater inflater = LayoutInflater.from(context); - if (viewType == TYPE_HEADER) { - return new HeaderHolder(inflater.inflate(R.layout.statistics_listitem_total, parent, false)); - } - return new StatisticsHolder(inflater.inflate(R.layout.statistics_listitem, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder h, int position) { - if (getItemViewType(position) == TYPE_HEADER) { - HeaderHolder holder = (HeaderHolder) h; - holder.pieChart.setData(pieChartData); - holder.totalTime.setText(getHeaderValue()); - holder.totalText.setText(getHeaderCaption()); - } else { - StatisticsHolder holder = (StatisticsHolder) h; - StatisticsItem statsItem = statisticsData.get(position - 1); - Glide.with(context) - .load(statsItem.feed.getImageUrl()) - .apply(new RequestOptions() - .placeholder(R.color.light_gray) - .error(R.color.light_gray) - .diskCacheStrategy(ApGlideSettings.AP_DISK_CACHE_STRATEGY) - .fitCenter() - .dontAnimate()) - .into(holder.image); - - holder.title.setText(statsItem.feed.getTitle()); - holder.chip.setTextColor(pieChartData.getColorOfItem(position - 1)); - onBindFeedViewHolder(holder, statsItem); - } - } - - public void update(List statistics) { - statisticsData = statistics; - pieChartData = generateChartData(statistics); - notifyDataSetChanged(); - } - - static class HeaderHolder extends RecyclerView.ViewHolder { - TextView totalTime; - PieChartView pieChart; - TextView totalText; - - HeaderHolder(View itemView) { - super(itemView); - totalTime = itemView.findViewById(R.id.total_time); - pieChart = itemView.findViewById(R.id.pie_chart); - totalText = itemView.findViewById(R.id.total_description); - } - } - - static class StatisticsHolder extends RecyclerView.ViewHolder { - ImageView image; - TextView title; - TextView value; - TextView chip; - - StatisticsHolder(View itemView) { - super(itemView); - image = itemView.findViewById(R.id.imgvCover); - title = itemView.findViewById(R.id.txtvTitle); - value = itemView.findViewById(R.id.txtvValue); - chip = itemView.findViewById(R.id.chip); - } - } - - abstract String getHeaderCaption(); - - abstract String getHeaderValue(); - - abstract PieChartView.PieChartData generateChartData(List statisticsData); - - abstract void onBindFeedViewHolder(StatisticsHolder holder, StatisticsItem item); -} diff --git a/app/src/main/java/de/danoeh/antennapod/adapter/YearStatisticsListAdapter.java b/app/src/main/java/de/danoeh/antennapod/adapter/YearStatisticsListAdapter.java deleted file mode 100644 index ad20574b3..000000000 --- a/app/src/main/java/de/danoeh/antennapod/adapter/YearStatisticsListAdapter.java +++ /dev/null @@ -1,121 +0,0 @@ -package de.danoeh.antennapod.adapter; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.util.LongList; -import de.danoeh.antennapod.view.LineChartView; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Locale; - -/** - * Adapter for the yearly playback statistics list. - */ -public class YearStatisticsListAdapter extends RecyclerView.Adapter { - private static final int TYPE_HEADER = 0; - private static final int TYPE_FEED = 1; - final Context context; - private List statisticsData = new ArrayList<>(); - LineChartView.LineChartData lineChartData; - - public YearStatisticsListAdapter(Context context) { - this.context = context; - } - - @Override - public int getItemCount() { - return statisticsData.size() + 1; - } - - @Override - public int getItemViewType(int position) { - return position == 0 ? TYPE_HEADER : TYPE_FEED; - } - - @NonNull - @Override - public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - LayoutInflater inflater = LayoutInflater.from(context); - if (viewType == TYPE_HEADER) { - return new HeaderHolder(inflater.inflate(R.layout.statistics_listitem_linechart, parent, false)); - } - return new StatisticsHolder(inflater.inflate(R.layout.statistics_year_listitem, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder h, int position) { - if (getItemViewType(position) == TYPE_HEADER) { - HeaderHolder holder = (HeaderHolder) h; - holder.lineChart.setData(lineChartData); - } else { - StatisticsHolder holder = (StatisticsHolder) h; - DBReader.MonthlyStatisticsItem statsItem = statisticsData.get(position - 1); - holder.year.setText(String.format(Locale.getDefault(), "%d ", statsItem.year)); - holder.hours.setText(String.format(Locale.getDefault(), "%.1f ", statsItem.timePlayed / 3600000.0f) - + context.getString(R.string.time_hours)); - } - } - - public void update(List statistics) { - int lastYear = statistics.size() > 0 ? statistics.get(0).year : 0; - int lastDataPoint = statistics.size() > 0 ? (statistics.get(0).month - 1) + lastYear * 12 : 0; - long yearSum = 0; - statisticsData.clear(); - LongList lineChartValues = new LongList(); - LongList lineChartHorizontalLines = new LongList(); - for (DBReader.MonthlyStatisticsItem statistic : statistics) { - if (statistic.year != lastYear) { - DBReader.MonthlyStatisticsItem yearAggregate = new DBReader.MonthlyStatisticsItem(); - yearAggregate.year = lastYear; - yearAggregate.timePlayed = yearSum; - statisticsData.add(yearAggregate); - yearSum = 0; - lastYear = statistic.year; - lineChartHorizontalLines.add(lineChartValues.size()); - } - yearSum += statistic.timePlayed; - while (lastDataPoint + 1 < (statistic.month - 1) + statistic.year * 12) { - lineChartValues.add(0); // Compensate for months without playback - lastDataPoint++; - } - lineChartValues.add(statistic.timePlayed); - lastDataPoint = (statistic.month - 1) + statistic.year * 12; - } - DBReader.MonthlyStatisticsItem yearAggregate = new DBReader.MonthlyStatisticsItem(); - yearAggregate.year = lastYear; - yearAggregate.timePlayed = yearSum; - statisticsData.add(yearAggregate); - Collections.reverse(statisticsData); - lineChartData = new LineChartView.LineChartData(lineChartValues.toArray(), lineChartHorizontalLines.toArray()); - notifyDataSetChanged(); - } - - static class HeaderHolder extends RecyclerView.ViewHolder { - LineChartView lineChart; - - HeaderHolder(View itemView) { - super(itemView); - lineChart = itemView.findViewById(R.id.lineChart); - } - } - - static class StatisticsHolder extends RecyclerView.ViewHolder { - TextView year; - TextView hours; - - StatisticsHolder(View itemView) { - super(itemView); - year = itemView.findViewById(R.id.yearLabel); - hours = itemView.findViewById(R.id.hoursLabel); - } - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java index 603a00955..80437abbb 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/CompletedDownloadsFragment.java @@ -35,6 +35,7 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.util.FeedItemUtil; import de.danoeh.antennapod.core.util.download.AutoUpdateManager; import de.danoeh.antennapod.menuhandler.FeedItemMenuHandler; +import de.danoeh.antennapod.ui.common.PagedToolbarFragment; import de.danoeh.antennapod.view.EmptyViewHandler; import de.danoeh.antennapod.view.EpisodeItemListRecyclerView; import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java index 0b4f74f9b..b64458e64 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadLogFragment.java @@ -25,6 +25,7 @@ import de.danoeh.antennapod.core.util.download.AutoUpdateManager; import de.danoeh.antennapod.dialog.DownloadLogDetailsDialog; import de.danoeh.antennapod.model.feed.FeedItem; import de.danoeh.antennapod.model.feed.FeedMedia; +import de.danoeh.antennapod.ui.common.PagedToolbarFragment; import de.danoeh.antennapod.view.EmptyViewHandler; import io.reactivex.Observable; import io.reactivex.android.schedulers.AndroidSchedulers; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java index bc3884b37..4467a0cf0 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/DownloadsFragment.java @@ -19,6 +19,7 @@ import com.google.android.material.tabs.TabLayoutMediator; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.ui.common.PagedToolbarFragment; /** * Shows the CompletedDownloadsFragment and the RunningDownloadsFragment. diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java index cfa226f8f..bb987666e 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesFragment.java @@ -18,6 +18,7 @@ import com.google.android.material.tabs.TabLayoutMediator; import de.danoeh.antennapod.R; import de.danoeh.antennapod.activity.MainActivity; +import de.danoeh.antennapod.ui.common.PagedToolbarFragment; public class EpisodesFragment extends PagedToolbarFragment { diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java index e72e53c30..dd2afeeba 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/EpisodesListFragment.java @@ -27,6 +27,7 @@ import de.danoeh.antennapod.event.playback.PlaybackPositionEvent; import de.danoeh.antennapod.event.PlayerStatusEvent; import de.danoeh.antennapod.event.UnreadItemsUpdateEvent; import de.danoeh.antennapod.core.menuhandler.MenuItemUtils; +import de.danoeh.antennapod.ui.common.PagedToolbarFragment; import de.danoeh.antennapod.view.EpisodeItemListRecyclerView; import de.danoeh.antennapod.view.viewholder.EpisodeItemViewHolder; import org.greenrobot.eventbus.EventBus; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java index ccc4e2e5f..d396a3cd4 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/FeedInfoFragment.java @@ -42,10 +42,11 @@ import de.danoeh.antennapod.core.storage.DBReader; import de.danoeh.antennapod.core.storage.DBTasks; import de.danoeh.antennapod.core.util.IntentUtils; import de.danoeh.antennapod.core.util.syndication.HtmlToPlainText; -import de.danoeh.antennapod.fragment.preferences.StatisticsFragment; import de.danoeh.antennapod.menuhandler.FeedMenuHandler; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.model.feed.FeedFunding; +import de.danoeh.antennapod.ui.statistics.StatisticsFragment; +import de.danoeh.antennapod.ui.statistics.feed.FeedStatisticsFragment; import de.danoeh.antennapod.view.ToolbarIconTintManager; import io.reactivex.Completable; import io.reactivex.Maybe; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedStatisticsDialogFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedStatisticsDialogFragment.java deleted file mode 100644 index 33710b2c4..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedStatisticsDialogFragment.java +++ /dev/null @@ -1,42 +0,0 @@ -package de.danoeh.antennapod.fragment; - -import android.app.Dialog; -import android.os.Bundle; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import androidx.fragment.app.DialogFragment; -import de.danoeh.antennapod.R; - -public class FeedStatisticsDialogFragment extends DialogFragment { - private static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; - private static final String EXTRA_FEED_TITLE = "de.danoeh.antennapod.extra.feedTitle"; - - public static FeedStatisticsDialogFragment newInstance(long feedId, String feedTitle) { - FeedStatisticsDialogFragment fragment = new FeedStatisticsDialogFragment(); - Bundle arguments = new Bundle(); - arguments.putLong(EXTRA_FEED_ID, feedId); - arguments.putString(EXTRA_FEED_TITLE, feedTitle); - fragment.setArguments(arguments); - return fragment; - } - - @NonNull - @Override - public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { - AlertDialog.Builder dialog = new AlertDialog.Builder(getContext()); - dialog.setPositiveButton(android.R.string.ok, null); - dialog.setTitle(getArguments().getString(EXTRA_FEED_TITLE)); - dialog.setView(R.layout.feed_statistics_dialog); - return dialog.create(); - } - - @Override - public void onStart() { - super.onStart(); - long feedId = getArguments().getLong(EXTRA_FEED_ID); - getChildFragmentManager().beginTransaction().replace(R.id.statisticsContainer, - FeedStatisticsFragment.newInstance(feedId, true), "feed_statistics_fragment") - .commitAllowingStateLoss(); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/FeedStatisticsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/FeedStatisticsFragment.java deleted file mode 100644 index d6ab34855..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/FeedStatisticsFragment.java +++ /dev/null @@ -1,95 +0,0 @@ -package de.danoeh.antennapod.fragment; - -import android.os.Bundle; -import android.text.format.Formatter; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.StatisticsItem; -import de.danoeh.antennapod.core.util.Converter; -import de.danoeh.antennapod.databinding.FeedStatisticsBinding; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - -import java.util.Collections; -import java.util.Locale; - -public class FeedStatisticsFragment extends Fragment { - private static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId"; - private static final String EXTRA_DETAILED = "de.danoeh.antennapod.extra.detailed"; - - private long feedId; - private Disposable disposable; - private FeedStatisticsBinding viewBinding; - - public static FeedStatisticsFragment newInstance(long feedId, boolean detailed) { - FeedStatisticsFragment fragment = new FeedStatisticsFragment(); - Bundle arguments = new Bundle(); - arguments.putLong(EXTRA_FEED_ID, feedId); - arguments.putBoolean(EXTRA_DETAILED, detailed); - fragment.setArguments(arguments); - return fragment; - } - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - feedId = getArguments().getLong(EXTRA_FEED_ID); - viewBinding = FeedStatisticsBinding.inflate(inflater); - - if (!getArguments().getBoolean(EXTRA_DETAILED)) { - for (int i = 0; i < viewBinding.getRoot().getChildCount(); i++) { - View child = viewBinding.getRoot().getChildAt(i); - if ("detailed".equals(child.getTag())) { - child.setVisibility(View.GONE); - } - } - } - - loadStatistics(); - return viewBinding.getRoot(); - } - - private void loadStatistics() { - disposable = - Observable.fromCallable(() -> { - DBReader.StatisticsResult statisticsData = DBReader.getStatistics(true, 0, Long.MAX_VALUE); - Collections.sort(statisticsData.feedTime, (item1, item2) -> - Long.compare(item2.timePlayed, item1.timePlayed)); - - for (StatisticsItem statisticsItem : statisticsData.feedTime) { - if (statisticsItem.feed.getId() == feedId) { - return statisticsItem; - } - } - return null; - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(this::showStats, Throwable::printStackTrace); - } - - private void showStats(StatisticsItem s) { - viewBinding.startedTotalLabel.setText(String.format(Locale.getDefault(), "%d / %d", - s.episodesStarted, s.episodes)); - viewBinding.timePlayedLabel.setText(Converter.shortLocalizedDuration(getContext(), s.timePlayed)); - viewBinding.totalDurationLabel.setText(Converter.shortLocalizedDuration(getContext(), s.time)); - viewBinding.onDeviceLabel.setText(String.format(Locale.getDefault(), "%d", s.episodesDownloadCount)); - viewBinding.spaceUsedLabel.setText(Formatter.formatShortFileSize(getContext(), s.totalDownloadSize)); - } - - @Override - public void onDestroy() { - super.onDestroy(); - if (disposable != null) { - disposable.dispose(); - } - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/PagedToolbarFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/PagedToolbarFragment.java deleted file mode 100644 index f79bffabc..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/PagedToolbarFragment.java +++ /dev/null @@ -1,48 +0,0 @@ -package de.danoeh.antennapod.fragment; - -import androidx.annotation.NonNull; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; -import androidx.viewpager2.widget.ViewPager2; - -/** - * Fragment with a ViewPager where the displayed items influence the top toolbar's menu. - * All items share the same general menu items and are just allowed to show/hide them. - */ -public abstract class PagedToolbarFragment extends Fragment { - private Toolbar toolbar; - private ViewPager2 viewPager; - - /** - * Invalidate the toolbar menu if the current child fragment is visible. - * @param child The fragment to invalidate - */ - void invalidateOptionsMenuIfActive(@NonNull Fragment child) { - Fragment visibleChild = getChildFragmentManager().findFragmentByTag("f" + viewPager.getCurrentItem()); - if (visibleChild == child) { - visibleChild.onPrepareOptionsMenu(toolbar.getMenu()); - } - } - - protected void setupPagedToolbar(Toolbar toolbar, ViewPager2 viewPager) { - this.toolbar = toolbar; - this.viewPager = viewPager; - - toolbar.setOnMenuItemClickListener(item -> { - Fragment child = getChildFragmentManager().findFragmentByTag("f" + viewPager.getCurrentItem()); - if (child != null) { - return child.onOptionsItemSelected(item); - } - return false; - }); - viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { - @Override - public void onPageSelected(int position) { - Fragment child = getChildFragmentManager().findFragmentByTag("f" + position); - if (child != null) { - child.onPrepareOptionsMenu(toolbar.getMenu()); - } - } - }); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java index 42b6580a2..75d8aea82 100644 --- a/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java +++ b/app/src/main/java/de/danoeh/antennapod/fragment/SubscriptionFragment.java @@ -28,6 +28,7 @@ import com.joanzapata.iconify.Iconify; import com.leinardi.android.speeddial.SpeedDialView; import de.danoeh.antennapod.dialog.TagSettingsDialog; +import de.danoeh.antennapod.ui.statistics.StatisticsFragment; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -57,7 +58,6 @@ import de.danoeh.antennapod.dialog.RemoveFeedDialog; import de.danoeh.antennapod.dialog.RenameItemDialog; import de.danoeh.antennapod.dialog.SubscriptionsFilterDialog; import de.danoeh.antennapod.fragment.actions.FeedMultiSelectActionHandler; -import de.danoeh.antennapod.fragment.preferences.StatisticsFragment; import de.danoeh.antennapod.model.feed.Feed; import de.danoeh.antennapod.view.EmptyViewHandler; import io.reactivex.Observable; diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/DownloadStatisticsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/DownloadStatisticsFragment.java deleted file mode 100644 index f8f489fc4..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/DownloadStatisticsFragment.java +++ /dev/null @@ -1,91 +0,0 @@ -package de.danoeh.antennapod.fragment.preferences; - -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.adapter.DownloadStatisticsListAdapter; -import de.danoeh.antennapod.core.storage.DBReader; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - -import java.util.Collections; - -/** - * Displays the 'download statistics' screen - */ -public class DownloadStatisticsFragment extends Fragment { - private static final String TAG = DownloadStatisticsFragment.class.getSimpleName(); - - private Disposable disposable; - private RecyclerView downloadStatisticsList; - private ProgressBar progressBar; - private DownloadStatisticsListAdapter listAdapter; - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - View root = inflater.inflate(R.layout.statistics_activity, container, false); - downloadStatisticsList = root.findViewById(R.id.statistics_list); - progressBar = root.findViewById(R.id.progressBar); - listAdapter = new DownloadStatisticsListAdapter(getContext()); - downloadStatisticsList.setLayoutManager(new LinearLayoutManager(getContext())); - downloadStatisticsList.setAdapter(listAdapter); - return root; - } - - @Override - public void onStart() { - super.onStart(); - refreshDownloadStatistics(); - } - - @Override - public void onPrepareOptionsMenu(@NonNull Menu menu) { - super.onPrepareOptionsMenu(menu); - menu.findItem(R.id.statistics_reset).setVisible(false); - menu.findItem(R.id.statistics_filter).setVisible(false); - } - - private void refreshDownloadStatistics() { - progressBar.setVisibility(View.VISIBLE); - downloadStatisticsList.setVisibility(View.GONE); - loadStatistics(); - } - - private void loadStatistics() { - if (disposable != null) { - disposable.dispose(); - } - - disposable = - Observable.fromCallable(() -> { - // Filters do not matter here - DBReader.StatisticsResult statisticsData = DBReader.getStatistics(false, 0, Long.MAX_VALUE); - Collections.sort(statisticsData.feedTime, (item1, item2) -> - Long.compare(item2.totalDownloadSize, item1.totalDownloadSize)); - return statisticsData; - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - listAdapter.update(result.feedTime); - progressBar.setVisibility(View.GONE); - downloadStatisticsList.setVisibility(View.VISIBLE); - }, error -> Log.e(TAG, Log.getStackTraceString(error))); - } -} 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 deleted file mode 100644 index 1c5a6acd4..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/StatisticsFragment.java +++ /dev/null @@ -1,104 +0,0 @@ -package de.danoeh.antennapod.fragment.preferences; - -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; -import androidx.viewpager2.adapter.FragmentStateAdapter; -import androidx.viewpager2.widget.ViewPager2; - -import com.google.android.material.tabs.TabLayout; -import com.google.android.material.tabs.TabLayoutMediator; - -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.activity.PreferenceActivity; -import de.danoeh.antennapod.fragment.PagedToolbarFragment; - -/** - * Displays the 'statistics' screen - */ -public class StatisticsFragment extends PagedToolbarFragment { - - public static final String TAG = "StatisticsFragment"; - - private static final int POS_SUBSCRIPTIONS = 0; - private static final int POS_YEARS = 1; - private static final int POS_SPACE_TAKEN = 2; - private static final int TOTAL_COUNT = 3; - - private TabLayout tabLayout; - private ViewPager2 viewPager; - private Toolbar toolbar; - - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - super.onCreateView(inflater, container, savedInstanceState); - setHasOptionsMenu(true); - - View rootView = inflater.inflate(R.layout.pager_fragment, container, false); - viewPager = rootView.findViewById(R.id.viewpager); - toolbar = rootView.findViewById(R.id.toolbar); - toolbar.setTitle(getString(R.string.statistics_label)); - toolbar.inflateMenu(R.menu.statistics); - toolbar.setNavigationOnClickListener(v -> getParentFragmentManager().popBackStack()); - viewPager.setAdapter(new StatisticsPagerAdapter(this)); - // Give the TabLayout the ViewPager - tabLayout = rootView.findViewById(R.id.sliding_tabs); - super.setupPagedToolbar(toolbar, viewPager); - new TabLayoutMediator(tabLayout, viewPager, (tab, position) -> { - switch (position) { - case POS_SUBSCRIPTIONS: - tab.setText(R.string.subscriptions_label); - break; - case POS_YEARS: - tab.setText(R.string.years_statistics_label); - break; - case POS_SPACE_TAKEN: - tab.setText(R.string.downloads_label); - break; - default: - break; - } - }).attach(); - return rootView; - } - - @Override - public void onStart() { - super.onStart(); - if (getActivity().getClass() == PreferenceActivity.class) { - ((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.statistics_label); - } - } - - public static class StatisticsPagerAdapter extends FragmentStateAdapter { - - StatisticsPagerAdapter(@NonNull Fragment fragment) { - super(fragment); - } - - @NonNull - @Override - public Fragment createFragment(int position) { - switch (position) { - case POS_SUBSCRIPTIONS: - return new SubscriptionStatisticsFragment(); - case POS_YEARS: - return new YearsStatisticsFragment(); - default: - case POS_SPACE_TAKEN: - return new DownloadStatisticsFragment(); - } - } - - @Override - public int getItemCount() { - return TOTAL_COUNT; - } - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/SubscriptionStatisticsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/SubscriptionStatisticsFragment.java deleted file mode 100644 index ef701d35c..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/SubscriptionStatisticsFragment.java +++ /dev/null @@ -1,279 +0,0 @@ -package de.danoeh.antennapod.fragment.preferences; - -import android.content.Context; -import android.content.DialogInterface; -import android.content.SharedPreferences; -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ProgressBar; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.AlertDialog; -import androidx.core.util.Pair; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; - -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.adapter.PlaybackStatisticsListAdapter; -import de.danoeh.antennapod.core.dialog.ConfirmationDialog; -import de.danoeh.antennapod.core.storage.DBReader; -import de.danoeh.antennapod.core.storage.DBWriter; -import de.danoeh.antennapod.databinding.StatisticsFilterDialogBinding; -import io.reactivex.Completable; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.Locale; - -/** - * Displays the 'playback statistics' screen - */ -public class SubscriptionStatisticsFragment extends Fragment { - private static final String TAG = SubscriptionStatisticsFragment.class.getSimpleName(); - private static final String PREF_NAME = "StatisticsActivityPrefs"; - private static final String PREF_INCLUDE_MARKED_PLAYED = "countAll"; - private static final String PREF_FILTER_FROM = "filterFrom"; - private static final String PREF_FILTER_TO = "filterTo"; - - private Disposable disposable; - private RecyclerView feedStatisticsList; - private ProgressBar progressBar; - private PlaybackStatisticsListAdapter listAdapter; - private boolean includeMarkedAsPlayed = false; - private long timeFilterFrom = 0; - private long timeFilterTo = Long.MAX_VALUE; - private SharedPreferences prefs; - private DBReader.StatisticsResult statisticsResult; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - prefs = getContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); - includeMarkedAsPlayed = prefs.getBoolean(PREF_INCLUDE_MARKED_PLAYED, false); - timeFilterFrom = prefs.getLong(PREF_FILTER_FROM, 0); - timeFilterTo = prefs.getLong(PREF_FILTER_TO, Long.MAX_VALUE); - setHasOptionsMenu(true); - } - - @Nullable - @Override - 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); - listAdapter = new PlaybackStatisticsListAdapter(this); - feedStatisticsList.setLayoutManager(new LinearLayoutManager(getContext())); - feedStatisticsList.setAdapter(listAdapter); - return root; - } - - @Override - public void onStart() { - super.onStart(); - refreshStatistics(); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - if (disposable != null) { - disposable.dispose(); - } - } - - @Override - public void onPrepareOptionsMenu(@NonNull Menu menu) { - super.onPrepareOptionsMenu(menu); - menu.findItem(R.id.statistics_reset).setVisible(true); - menu.findItem(R.id.statistics_filter).setVisible(true); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.statistics_filter) { - selectStatisticsFilter(); - return true; - } else if (item.getItemId() == R.id.statistics_reset) { - confirmResetStatistics(); - return true; - } - return super.onOptionsItemSelected(item); - } - - private void selectStatisticsFilter() { - if (statisticsResult == null) { - return; - } - StatisticsFilterDialogBinding dialogBinding = StatisticsFilterDialogBinding.inflate(getLayoutInflater()); - AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); - builder.setView(dialogBinding.getRoot()); - builder.setTitle(R.string.filter); - dialogBinding.includeMarkedCheckbox.setOnCheckedChangeListener((compoundButton, checked) -> { - dialogBinding.timeToSpinner.setEnabled(!checked); - dialogBinding.timeFromSpinner.setEnabled(!checked); - dialogBinding.lastYearButton.setEnabled(!checked); - dialogBinding.allTimeButton.setEnabled(!checked); - dialogBinding.dateSelectionContainer.setAlpha(checked ? 0.5f : 1f); - }); - dialogBinding.includeMarkedCheckbox.setChecked(includeMarkedAsPlayed); - - Pair filterDates = makeMonthlyList(statisticsResult.oldestDate); - - ArrayAdapter adapterFrom = new ArrayAdapter<>(getContext(), - android.R.layout.simple_spinner_item, filterDates.first); - adapterFrom.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - dialogBinding.timeFromSpinner.setAdapter(adapterFrom); - for (int i = 0; i < filterDates.second.length; i++) { - if (filterDates.second[i] >= timeFilterFrom) { - dialogBinding.timeFromSpinner.setSelection(i); - break; - } - } - - ArrayAdapter adapterTo = new ArrayAdapter<>(getContext(), - android.R.layout.simple_spinner_item, filterDates.first); - adapterTo.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); - dialogBinding.timeToSpinner.setAdapter(adapterTo); - for (int i = 0; i < filterDates.second.length; i++) { - if (filterDates.second[i] >= timeFilterTo) { - dialogBinding.timeToSpinner.setSelection(i); - break; - } - } - - dialogBinding.allTimeButton.setOnClickListener(v -> { - dialogBinding.timeFromSpinner.setSelection(0); - dialogBinding.timeToSpinner.setSelection(filterDates.first.length - 1); - }); - dialogBinding.lastYearButton.setOnClickListener(v -> { - dialogBinding.timeFromSpinner.setSelection(Math.max(0, filterDates.first.length - 14)); - dialogBinding.timeToSpinner.setSelection(filterDates.first.length - 2); - }); - - builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { - includeMarkedAsPlayed = dialogBinding.includeMarkedCheckbox.isChecked(); - if (includeMarkedAsPlayed) { - // We do not know the date at which something was marked as played, so filtering does not make sense - timeFilterFrom = 0; - timeFilterTo = Long.MAX_VALUE; - } else { - timeFilterFrom = filterDates.second[dialogBinding.timeFromSpinner.getSelectedItemPosition()]; - timeFilterTo = filterDates.second[dialogBinding.timeToSpinner.getSelectedItemPosition()]; - } - prefs.edit() - .putBoolean(PREF_INCLUDE_MARKED_PLAYED, includeMarkedAsPlayed) - .putLong(PREF_FILTER_FROM, timeFilterFrom) - .putLong(PREF_FILTER_TO, timeFilterTo) - .apply(); - refreshStatistics(); - }); - builder.show(); - } - - private Pair makeMonthlyList(long oldestDate) { - Calendar date = Calendar.getInstance(); - date.setTimeInMillis(oldestDate); - date.set(Calendar.DAY_OF_MONTH, 1); - ArrayList names = new ArrayList<>(); - ArrayList timestamps = new ArrayList<>(); - SimpleDateFormat dateFormat = new SimpleDateFormat("MMM yyyy", Locale.getDefault()); - while (date.getTimeInMillis() < System.currentTimeMillis()) { - names.add(dateFormat.format(new Date(date.getTimeInMillis()))); - timestamps.add(date.getTimeInMillis()); - if (date.get(Calendar.MONTH) == Calendar.DECEMBER) { - date.set(Calendar.MONTH, Calendar.JANUARY); - date.set(Calendar.YEAR, date.get(Calendar.YEAR) + 1); - } else { - date.set(Calendar.MONTH, date.get(Calendar.MONTH) + 1); - } - } - names.add(getString(R.string.statistics_today)); - timestamps.add(Long.MAX_VALUE); - return new Pair<>(names.toArray(new String[0]), timestamps.toArray(new Long[0])); - } - - private void confirmResetStatistics() { - 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(); - } - - includeMarkedAsPlayed = false; - timeFilterFrom = 0; - timeFilterTo = Long.MAX_VALUE; - prefs.edit() - .putBoolean(PREF_INCLUDE_MARKED_PLAYED, includeMarkedAsPlayed) - .putLong(PREF_FILTER_FROM, timeFilterFrom) - .putLong(PREF_FILTER_TO, timeFilterTo) - .apply(); - - 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); - loadStatistics(); - } - - private void loadStatistics() { - if (disposable != null) { - disposable.dispose(); - } - disposable = Observable.fromCallable( - () -> { - DBReader.StatisticsResult statisticsData = DBReader.getStatistics( - includeMarkedAsPlayed, timeFilterFrom, timeFilterTo); - Collections.sort(statisticsData.feedTime, (item1, item2) -> - Long.compare(item2.timePlayed, item1.timePlayed)); - return statisticsData; - }) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - statisticsResult = result; - // When "from" is "today", set it to today - listAdapter.setTimeFilter(includeMarkedAsPlayed, Math.max( - Math.min(timeFilterFrom, System.currentTimeMillis()), result.oldestDate), - Math.min(timeFilterTo, System.currentTimeMillis())); - listAdapter.update(result.feedTime); - progressBar.setVisibility(View.GONE); - feedStatisticsList.setVisibility(View.VISIBLE); - }, error -> Log.e(TAG, Log.getStackTraceString(error))); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/YearsStatisticsFragment.java b/app/src/main/java/de/danoeh/antennapod/fragment/preferences/YearsStatisticsFragment.java deleted file mode 100644 index c58a59801..000000000 --- a/app/src/main/java/de/danoeh/antennapod/fragment/preferences/YearsStatisticsFragment.java +++ /dev/null @@ -1,87 +0,0 @@ -package de.danoeh.antennapod.fragment.preferences; - -import android.os.Bundle; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ProgressBar; -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.RecyclerView; -import de.danoeh.antennapod.R; -import de.danoeh.antennapod.adapter.YearStatisticsListAdapter; -import de.danoeh.antennapod.core.storage.DBReader; -import io.reactivex.Observable; -import io.reactivex.android.schedulers.AndroidSchedulers; -import io.reactivex.disposables.Disposable; -import io.reactivex.schedulers.Schedulers; - -/** - * Displays the yearly statistics screen - */ -public class YearsStatisticsFragment extends Fragment { - private static final String TAG = YearsStatisticsFragment.class.getSimpleName(); - - private Disposable disposable; - private RecyclerView yearStatisticsList; - private ProgressBar progressBar; - private YearStatisticsListAdapter listAdapter; - - @Nullable - @Override - public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, - @Nullable Bundle savedInstanceState) { - View root = inflater.inflate(R.layout.statistics_activity, container, false); - yearStatisticsList = root.findViewById(R.id.statistics_list); - progressBar = root.findViewById(R.id.progressBar); - listAdapter = new YearStatisticsListAdapter(getContext()); - yearStatisticsList.setLayoutManager(new LinearLayoutManager(getContext())); - yearStatisticsList.setAdapter(listAdapter); - return root; - } - - @Override - public void onStart() { - super.onStart(); - refreshStatistics(); - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - if (disposable != null) { - disposable.dispose(); - } - } - - @Override - public void onPrepareOptionsMenu(@NonNull Menu menu) { - super.onPrepareOptionsMenu(menu); - menu.findItem(R.id.statistics_reset).setVisible(false); - menu.findItem(R.id.statistics_filter).setVisible(false); - } - - private void refreshStatistics() { - progressBar.setVisibility(View.VISIBLE); - yearStatisticsList.setVisibility(View.GONE); - loadStatistics(); - } - - private void loadStatistics() { - if (disposable != null) { - disposable.dispose(); - } - disposable = Observable.fromCallable(DBReader::getMonthlyTimeStatistics) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(result -> { - listAdapter.update(result); - progressBar.setVisibility(View.GONE); - yearStatisticsList.setVisibility(View.VISIBLE); - }, error -> Log.e(TAG, Log.getStackTraceString(error))); - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/view/LineChartView.java b/app/src/main/java/de/danoeh/antennapod/view/LineChartView.java deleted file mode 100644 index 0eb225e8e..000000000 --- a/app/src/main/java/de/danoeh/antennapod/view/LineChartView.java +++ /dev/null @@ -1,138 +0,0 @@ -package de.danoeh.antennapod.view; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.DashPathEffect; -import android.graphics.LinearGradient; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PixelFormat; -import android.graphics.Shader; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import androidx.annotation.NonNull; -import androidx.appcompat.widget.AppCompatImageView; -import androidx.appcompat.widget.ThemeUtils; -import de.danoeh.antennapod.R; -import io.reactivex.annotations.Nullable; - -public class LineChartView extends AppCompatImageView { - private LineChartDrawable drawable; - - public LineChartView(Context context) { - super(context); - setup(); - } - - public LineChartView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - setup(); - } - - public LineChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - setup(); - } - - @SuppressLint("ClickableViewAccessibility") - private void setup() { - drawable = new LineChartDrawable(); - setImageDrawable(drawable); - } - - /** - * Set of data values to display. - */ - public void setData(LineChartData data) { - drawable.data = data; - } - - public static class LineChartData { - private final long valueMax; - private final long[] values; - private final long[] verticalLines; - - public LineChartData(long[] values, long[] verticalLines) { - this.values = values; - long valueMax = 0; - for (long datum : values) { - valueMax = Math.max(datum, valueMax); - } - this.valueMax = valueMax; - this.verticalLines = verticalLines; - } - - public float getHeight(int item) { - return (float) values[item] / valueMax; - } - } - - private class LineChartDrawable extends Drawable { - private LineChartData data; - private final Paint paintLine; - private final Paint paintBackground; - private final Paint paintVerticalLines; - - private LineChartDrawable() { - paintLine = new Paint(); - paintLine.setFlags(Paint.ANTI_ALIAS_FLAG); - paintLine.setStyle(Paint.Style.STROKE); - paintLine.setStrokeJoin(Paint.Join.ROUND); - paintLine.setStrokeCap(Paint.Cap.ROUND); - paintLine.setColor(ThemeUtils.getThemeAttrColor(getContext(), R.attr.colorAccent)); - paintBackground = new Paint(); - paintBackground.setStyle(Paint.Style.FILL); - paintVerticalLines = new Paint(); - paintVerticalLines.setStyle(Paint.Style.STROKE); - paintVerticalLines.setPathEffect(new DashPathEffect(new float[] {10f, 10f}, 0f)); - paintVerticalLines.setColor(0x66777777); - } - - @Override - public void draw(@NonNull Canvas canvas) { - float width = getBounds().width(); - float height = getBounds().height(); - float usableHeight = height * 0.9f; - float stepSize = width / (data.values.length + 1); - - paintVerticalLines.setStrokeWidth(height * 0.005f); - for (long line : data.verticalLines) { - canvas.drawLine((line + 1) * stepSize, 0, (line + 1) * stepSize, height, paintVerticalLines); - } - - paintLine.setStrokeWidth(height * 0.015f); - Path path = new Path(); - for (int i = 0; i < data.values.length; i++) { - if (i == 0) { - path.moveTo((i + 1) * stepSize, (1 - data.getHeight(i)) * usableHeight + height * 0.05f); - } else { - path.lineTo((i + 1) * stepSize, (1 - data.getHeight(i)) * usableHeight + height * 0.05f); - } - } - canvas.drawPath(path, paintLine); - - path.lineTo(data.values.length * stepSize, height); - path.lineTo(stepSize, height); - paintBackground.setShader(new LinearGradient(0, 0, 0, height, - (ThemeUtils.getThemeAttrColor(getContext(), R.attr.colorAccent) & 0xffffff) + 0x66000000, - Color.TRANSPARENT, Shader.TileMode.CLAMP)); - canvas.drawPath(path, paintBackground); - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } - - @Override - public void setAlpha(int alpha) { - } - - @Override - public void setColorFilter(ColorFilter cf) { - } - } -} diff --git a/app/src/main/java/de/danoeh/antennapod/view/PieChartView.java b/app/src/main/java/de/danoeh/antennapod/view/PieChartView.java deleted file mode 100644 index ab4920119..000000000 --- a/app/src/main/java/de/danoeh/antennapod/view/PieChartView.java +++ /dev/null @@ -1,149 +0,0 @@ -package de.danoeh.antennapod.view; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.ColorFilter; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import androidx.annotation.NonNull; -import androidx.appcompat.widget.AppCompatImageView; -import io.reactivex.annotations.Nullable; - -public class PieChartView extends AppCompatImageView { - private PieChartDrawable drawable; - - public PieChartView(Context context) { - super(context); - setup(); - } - - public PieChartView(Context context, @Nullable AttributeSet attrs) { - super(context, attrs); - setup(); - } - - public PieChartView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - setup(); - } - - @SuppressLint("ClickableViewAccessibility") - private void setup() { - drawable = new PieChartDrawable(); - setImageDrawable(drawable); - } - - /** - * Set of data values to display. - */ - public void setData(PieChartData data) { - drawable.data = data; - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - int width = getMeasuredWidth(); - setMeasuredDimension(width, width / 2); - } - - public static class PieChartData { - private static final int[] COLOR_VALUES = new int[]{0xFF3775E6, 0xffe51c23, 0xffff9800, 0xff259b24, 0xff9c27b0, - 0xff0099c6, 0xffdd4477, 0xff66aa00, 0xffb82e2e, 0xff316395, - 0xff994499, 0xff22aa99, 0xffaaaa11, 0xff6633cc, 0xff0073e6}; - - private final float valueSum; - private final float[] values; - - public PieChartData(float[] values) { - this.values = values; - float valueSum = 0; - for (float datum : values) { - valueSum += datum; - } - this.valueSum = valueSum; - } - - public float getSum() { - return valueSum; - } - - public float getPercentageOfItem(int index) { - if (valueSum == 0) { - return 0; - } - return values[index] / valueSum; - } - - public boolean isLargeEnoughToDisplay(int index) { - return getPercentageOfItem(index) > 0.04; - } - - public int getColorOfItem(int index) { - if (!isLargeEnoughToDisplay(index)) { - return Color.GRAY; - } - return COLOR_VALUES[index % COLOR_VALUES.length]; - } - } - - private static class PieChartDrawable extends Drawable { - private static final float PADDING_DEGREES = 3f; - private PieChartData data; - private final Paint paint; - - private PieChartDrawable() { - paint = new Paint(); - paint.setFlags(Paint.ANTI_ALIAS_FLAG); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeJoin(Paint.Join.ROUND); - paint.setStrokeCap(Paint.Cap.ROUND); - } - - @Override - public void draw(@NonNull Canvas canvas) { - final float strokeSize = getBounds().height() / 30f; - paint.setStrokeWidth(strokeSize); - - float radius = getBounds().height() - strokeSize; - float center = getBounds().width() / 2.f; - RectF arcBounds = new RectF(center - radius, strokeSize, center + radius, strokeSize + radius * 2); - - float startAngle = 180; - for (int i = 0; i < data.values.length; i++) { - if (!data.isLargeEnoughToDisplay(i)) { - break; - } - paint.setColor(data.getColorOfItem(i)); - float padding = i == 0 ? PADDING_DEGREES / 2 : PADDING_DEGREES; - float sweepAngle = (180f - PADDING_DEGREES) * data.getPercentageOfItem(i); - canvas.drawArc(arcBounds, startAngle + padding, sweepAngle - padding, false, paint); - startAngle = startAngle + sweepAngle; - } - - paint.setColor(Color.GRAY); - float sweepAngle = 360 - startAngle - PADDING_DEGREES / 2; - if (sweepAngle > PADDING_DEGREES) { - canvas.drawArc(arcBounds, startAngle + PADDING_DEGREES, sweepAngle - PADDING_DEGREES, false, paint); - } - } - - @Override - public int getOpacity() { - return PixelFormat.TRANSLUCENT; - } - - @Override - public void setAlpha(int alpha) { - } - - @Override - public void setColorFilter(ColorFilter cf) { - } - } -} diff --git a/app/src/main/res/layout/feed_statistics.xml b/app/src/main/res/layout/feed_statistics.xml deleted file mode 100644 index 7897a7d5f..000000000 --- a/app/src/main/res/layout/feed_statistics.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/feed_statistics_dialog.xml b/app/src/main/res/layout/feed_statistics_dialog.xml deleted file mode 100644 index fcd36fe7a..000000000 --- a/app/src/main/res/layout/feed_statistics_dialog.xml +++ /dev/null @@ -1,7 +0,0 @@ - - diff --git a/app/src/main/res/layout/pager_fragment.xml b/app/src/main/res/layout/pager_fragment.xml deleted file mode 100644 index ea007892a..000000000 --- a/app/src/main/res/layout/pager_fragment.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - diff --git a/app/src/main/res/layout/statistics_activity.xml b/app/src/main/res/layout/statistics_activity.xml deleted file mode 100644 index 9d9cad438..000000000 --- a/app/src/main/res/layout/statistics_activity.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - diff --git a/app/src/main/res/layout/statistics_filter_dialog.xml b/app/src/main/res/layout/statistics_filter_dialog.xml deleted file mode 100644 index d37226c07..000000000 --- a/app/src/main/res/layout/statistics_filter_dialog.xml +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - -