diff options
author | ByteHamster <ByteHamster@users.noreply.github.com> | 2022-02-27 11:05:05 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-27 11:05:05 +0100 |
commit | 8ff8ac2d5db6c71dea50fee89516d7ab2be88b29 (patch) | |
tree | 437ad8df931d422eb0c5deebf19d6a9e93c0310c /app/src/main/java/de/danoeh/antennapod/fragment | |
parent | 0d7555da8c291457cd8fe7b97036fd05c515bbd2 (diff) | |
parent | 7451da112145f96ecddc314eea7b90fcb03737dd (diff) | |
download | AntennaPod-8ff8ac2d5db6c71dea50fee89516d7ab2be88b29.zip |
Merge pull request #5747 from ByteHamster/decouple-statistics
Move statistics screens to new module
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod/fragment')
14 files changed, 8 insertions, 748 deletions
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<String[], Long[]> filterDates = makeMonthlyList(statisticsResult.oldestDate); - - ArrayAdapter<String> 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<String> 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<String[], Long[]> makeMonthlyList(long oldestDate) { - Calendar date = Calendar.getInstance(); - date.setTimeInMillis(oldestDate); - date.set(Calendar.DAY_OF_MONTH, 1); - ArrayList<String> names = new ArrayList<>(); - ArrayList<Long> timestamps = new ArrayList<>(); - SimpleDateFormat dateFormat = new SimpleDateFormat("MMM yyyy", Locale.getDefault()); - 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))); - } -} |