Add time-based statistics filter (#5734)
This commit is contained in:
parent
4655fcfc80
commit
b6d2316870
@ -2,15 +2,15 @@ package de.danoeh.antennapod.adapter;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.StatisticsItem;
|
||||
import de.danoeh.antennapod.core.util.Converter;
|
||||
import de.danoeh.antennapod.core.util.DateFormatter;
|
||||
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.
|
||||
@ -18,26 +18,30 @@ import java.util.List;
|
||||
public class PlaybackStatisticsListAdapter extends StatisticsListAdapter {
|
||||
|
||||
private final Fragment fragment;
|
||||
boolean countAll = true;
|
||||
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 setCountAll(boolean countAll) {
|
||||
this.countAll = countAll;
|
||||
public void setTimeFilter(boolean includeMarkedAsPlayed, long timeFilterFrom, long timeFilterTo) {
|
||||
this.includeMarkedAsPlayed = includeMarkedAsPlayed;
|
||||
this.timeFilterFrom = timeFilterFrom;
|
||||
this.timeFilterTo = timeFilterTo;
|
||||
}
|
||||
|
||||
@Override
|
||||
String getHeaderCaption() {
|
||||
long usageCounting = UserPreferences.getUsageCountingDateMillis();
|
||||
if (usageCounting > 0) {
|
||||
String date = DateFormatter.formatAbbrev(context, new Date(usageCounting));
|
||||
return context.getString(R.string.statistics_counting_since, date);
|
||||
} else {
|
||||
return context.getString(R.string.total_time_listened_to_podcasts);
|
||||
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
|
||||
@ -50,14 +54,14 @@ public class PlaybackStatisticsListAdapter extends StatisticsListAdapter {
|
||||
float[] dataValues = new float[statisticsData.size()];
|
||||
for (int i = 0; i < statisticsData.size(); i++) {
|
||||
StatisticsItem item = statisticsData.get(i);
|
||||
dataValues[i] = countAll ? item.timePlayedCountAll : item.timePlayed;
|
||||
dataValues[i] = item.timePlayed;
|
||||
}
|
||||
return new PieChartView.PieChartData(dataValues);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onBindFeedViewHolder(StatisticsHolder holder, StatisticsItem statsItem) {
|
||||
long time = countAll ? statsItem.timePlayedCountAll : statsItem.timePlayed;
|
||||
long time = statsItem.timePlayed;
|
||||
holder.value.setText(Converter.shortLocalizedDuration(context, time));
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
|
@ -48,10 +48,7 @@ public abstract class StatisticsListAdapter extends RecyclerView.Adapter<Recycle
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
LayoutInflater inflater = LayoutInflater.from(context);
|
||||
if (viewType == TYPE_HEADER) {
|
||||
View view = inflater.inflate(R.layout.statistics_listitem_total, parent, false);
|
||||
TextView totalText = view.findViewById(R.id.total_description);
|
||||
totalText.setText(getHeaderCaption());
|
||||
return new HeaderHolder(view);
|
||||
return new HeaderHolder(inflater.inflate(R.layout.statistics_listitem_total, parent, false));
|
||||
}
|
||||
return new StatisticsHolder(inflater.inflate(R.layout.statistics_listitem, parent, false));
|
||||
}
|
||||
@ -62,6 +59,7 @@ public abstract class StatisticsListAdapter extends RecyclerView.Adapter<Recycle
|
||||
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);
|
||||
@ -90,11 +88,13 @@ public abstract class StatisticsListAdapter extends RecyclerView.Adapter<Recycle
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
||||
public class FeedStatisticsFragment extends Fragment {
|
||||
@ -60,8 +60,11 @@ public class FeedStatisticsFragment extends Fragment {
|
||||
private void loadStatistics() {
|
||||
disposable =
|
||||
Observable.fromCallable(() -> {
|
||||
List<StatisticsItem> statisticsData = DBReader.getStatistics();
|
||||
for (StatisticsItem statisticsItem : statisticsData) {
|
||||
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;
|
||||
}
|
||||
@ -77,7 +80,6 @@ public class FeedStatisticsFragment extends Fragment {
|
||||
viewBinding.startedTotalLabel.setText(String.format(Locale.getDefault(), "%d / %d",
|
||||
s.episodesStarted, s.episodes));
|
||||
viewBinding.timePlayedLabel.setText(Converter.shortLocalizedDuration(getContext(), s.timePlayed));
|
||||
viewBinding.durationPlayedLabel.setText(Converter.shortLocalizedDuration(getContext(), s.timePlayedCountAll));
|
||||
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));
|
||||
|
@ -3,6 +3,7 @@ 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;
|
||||
@ -16,14 +17,12 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.adapter.DownloadStatisticsListAdapter;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.StatisticsItem;
|
||||
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.List;
|
||||
|
||||
/**
|
||||
* Displays the 'download statistics' screen
|
||||
@ -38,7 +37,8 @@ public class DownloadStatisticsFragment extends Fragment {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||
@Nullable Bundle savedInstanceState) {
|
||||
View root = inflater.inflate(R.layout.statistics_activity, container, false);
|
||||
downloadStatisticsList = root.findViewById(R.id.statistics_list);
|
||||
progressBar = root.findViewById(R.id.progressBar);
|
||||
@ -54,6 +54,13 @@ public class DownloadStatisticsFragment extends Fragment {
|
||||
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);
|
||||
@ -67,15 +74,16 @@ public class DownloadStatisticsFragment extends Fragment {
|
||||
|
||||
disposable =
|
||||
Observable.fromCallable(() -> {
|
||||
List<StatisticsItem> statisticsData = DBReader.getStatistics();
|
||||
Collections.sort(statisticsData, (item1, item2) ->
|
||||
// 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);
|
||||
listAdapter.update(result.feedTime);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
downloadStatisticsList.setVisibility(View.VISIBLE);
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
|
@ -31,7 +31,6 @@ import de.danoeh.antennapod.core.export.ExportWriter;
|
||||
import de.danoeh.antennapod.core.export.favorites.FavoritesWriter;
|
||||
import de.danoeh.antennapod.core.export.html.HtmlWriter;
|
||||
import de.danoeh.antennapod.core.export.opml.OpmlWriter;
|
||||
import de.danoeh.antennapod.core.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DatabaseExporter;
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Observable;
|
||||
@ -263,7 +262,6 @@ public class ImportExportPreferencesFragment extends PreferenceFragmentCompat {
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(() -> {
|
||||
showDatabaseImportSuccessDialog();
|
||||
UserPreferences.unsetUsageCountingDate();
|
||||
progressDialog.dismiss();
|
||||
}, this::showExportErrorDialog);
|
||||
}
|
||||
|
@ -29,7 +29,6 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat {
|
||||
private static final String PREF_VIEW_FORUM = "prefViewForum";
|
||||
private static final String PREF_SEND_BUG_REPORT = "prefSendBugReport";
|
||||
private static final String PREF_CATEGORY_PROJECT = "project";
|
||||
private static final String STATISTICS = "statistics";
|
||||
private static final String PREF_ABOUT = "prefAbout";
|
||||
private static final String PREF_NOTIFICATION = "notifications";
|
||||
private static final String PREF_CONTRIBUTE = "prefContribute";
|
||||
@ -106,14 +105,6 @@ public class MainPreferencesFragment extends PreferenceFragmentCompat {
|
||||
return true;
|
||||
}
|
||||
);
|
||||
findPreference(STATISTICS).setOnPreferenceClickListener(
|
||||
preference -> {
|
||||
getParentFragmentManager().beginTransaction()
|
||||
.replace(R.id.settingsContainer, new StatisticsFragment())
|
||||
.addToBackStack(getString(R.string.statistics_label)).commit();
|
||||
return true;
|
||||
}
|
||||
);
|
||||
findPreference(PREF_DOCUMENTATION).setOnPreferenceClickListener(preference -> {
|
||||
IntentUtils.openInBrowser(getContext(), "https://antennapod.org/documentation/");
|
||||
return true;
|
||||
|
@ -7,16 +7,16 @@ import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.RadioButton;
|
||||
|
||||
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;
|
||||
@ -24,18 +24,21 @@ 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.preferences.UserPreferences;
|
||||
import de.danoeh.antennapod.core.storage.DBReader;
|
||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
||||
import de.danoeh.antennapod.core.storage.StatisticsItem;
|
||||
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.List;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Displays the 'playback statistics' screen
|
||||
@ -43,20 +46,27 @@ import java.util.List;
|
||||
public class PlaybackStatisticsFragment extends Fragment {
|
||||
private static final String TAG = PlaybackStatisticsFragment.class.getSimpleName();
|
||||
private static final String PREF_NAME = "StatisticsActivityPrefs";
|
||||
private static final String PREF_COUNT_ALL = "countAll";
|
||||
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 countAll = false;
|
||||
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);
|
||||
countAll = prefs.getBoolean(PREF_COUNT_ALL, false);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -68,7 +78,6 @@ public class PlaybackStatisticsFragment extends Fragment {
|
||||
feedStatisticsList = root.findViewById(R.id.statistics_list);
|
||||
progressBar = root.findViewById(R.id.progressBar);
|
||||
listAdapter = new PlaybackStatisticsListAdapter(this);
|
||||
listAdapter.setCountAll(countAll);
|
||||
feedStatisticsList.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||
feedStatisticsList.setAdapter(listAdapter);
|
||||
return root;
|
||||
@ -89,62 +98,129 @@ public class PlaybackStatisticsFragment extends Fragment {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.statistics, menu);
|
||||
menu.findItem(R.id.statistics_reset).setEnabled(!countAll);
|
||||
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_mode) {
|
||||
selectStatisticsMode();
|
||||
if (item.getItemId() == R.id.statistics_filter) {
|
||||
selectStatisticsFilter();
|
||||
return true;
|
||||
}
|
||||
if (item.getItemId() == R.id.statistics_reset) {
|
||||
} else if (item.getItemId() == R.id.statistics_reset) {
|
||||
confirmResetStatistics();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
private void selectStatisticsMode() {
|
||||
View contentView = View.inflate(getContext(), R.layout.statistics_mode_select_dialog, null);
|
||||
private void selectStatisticsFilter() {
|
||||
if (statisticsResult == null) {
|
||||
return;
|
||||
}
|
||||
StatisticsFilterDialogBinding dialogBinding = StatisticsFilterDialogBinding.inflate(getLayoutInflater());
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||
builder.setView(contentView);
|
||||
builder.setTitle(R.string.statistics_mode);
|
||||
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);
|
||||
|
||||
if (countAll) {
|
||||
((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).setChecked(true);
|
||||
} else {
|
||||
((RadioButton) contentView.findViewById(R.id.statistics_mode_normal)).setChecked(true);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
builder.setPositiveButton(android.R.string.ok, (dialog, which) -> {
|
||||
countAll = ((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).isChecked();
|
||||
listAdapter.setCountAll(countAll);
|
||||
prefs.edit().putBoolean(PREF_COUNT_ALL, countAll).apply();
|
||||
refreshStatistics();
|
||||
getActivity().invalidateOptionsMenu();
|
||||
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 void confirmResetStatistics() {
|
||||
if (!countAll) {
|
||||
ConfirmationDialog conDialog = new ConfirmationDialog(
|
||||
getActivity(),
|
||||
R.string.statistics_reset_data,
|
||||
R.string.statistics_reset_data_msg) {
|
||||
|
||||
@Override
|
||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||
dialog.dismiss();
|
||||
doResetStatistics();
|
||||
}
|
||||
};
|
||||
conDialog.createNewDialog().show();
|
||||
private 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() {
|
||||
@ -154,13 +230,19 @@ public class PlaybackStatisticsFragment extends Fragment {
|
||||
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(() -> {
|
||||
refreshStatistics();
|
||||
UserPreferences.resetUsageCountingDate();
|
||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
.subscribe(this::refreshStatistics, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
private void refreshStatistics() {
|
||||
@ -173,25 +255,25 @@ public class PlaybackStatisticsFragment extends Fragment {
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
disposable = Observable.fromCallable(this::fetchStatistics)
|
||||
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 -> {
|
||||
listAdapter.update(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)));
|
||||
}
|
||||
|
||||
private List<StatisticsItem> fetchStatistics() {
|
||||
List<StatisticsItem> statisticsData = DBReader.getStatistics();
|
||||
if (countAll) {
|
||||
Collections.sort(statisticsData, (item1, item2) ->
|
||||
Long.compare(item2.timePlayedCountAll, item1.timePlayedCountAll));
|
||||
} else {
|
||||
Collections.sort(statisticsData, (item1, item2) ->
|
||||
Long.compare(item2.timePlayed, item1.timePlayed));
|
||||
}
|
||||
return statisticsData;
|
||||
}
|
||||
}
|
||||
|
@ -16,11 +16,12 @@ 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 Fragment {
|
||||
public class StatisticsFragment extends PagedToolbarFragment {
|
||||
|
||||
public static final String TAG = "StatisticsFragment";
|
||||
|
||||
@ -28,7 +29,6 @@ public class StatisticsFragment extends Fragment {
|
||||
private static final int POS_SPACE_TAKEN = 1;
|
||||
private static final int TOTAL_COUNT = 2;
|
||||
|
||||
|
||||
private TabLayout tabLayout;
|
||||
private ViewPager2 viewPager;
|
||||
private Toolbar toolbar;
|
||||
@ -42,9 +42,13 @@ public class StatisticsFragment extends Fragment {
|
||||
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_LISTENED_HOURS:
|
||||
@ -57,14 +61,6 @@ public class StatisticsFragment extends Fragment {
|
||||
break;
|
||||
}
|
||||
}).attach();
|
||||
|
||||
if (getActivity().getClass() == PreferenceActivity.class) {
|
||||
rootView.findViewById(R.id.toolbar).setVisibility(View.GONE);
|
||||
} else {
|
||||
toolbar.setTitle(getString(R.string.statistics_label));
|
||||
toolbar.setNavigationOnClickListener(v -> getParentFragmentManager().popBackStack());
|
||||
}
|
||||
|
||||
return rootView;
|
||||
}
|
||||
|
||||
|
@ -39,9 +39,6 @@ public class PreferenceUpgrader {
|
||||
private static void upgrade(int oldVersion, Context context) {
|
||||
if (oldVersion == -1) {
|
||||
//New installation
|
||||
if (UserPreferences.getUsageCountingDateMillis() < 0) {
|
||||
UserPreferences.resetUsageCountingDate();
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (oldVersion < 1070196) {
|
||||
|
@ -40,24 +40,6 @@
|
||||
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:tag="detailed">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_duration_played_episodes" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/durationPlayedLabel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="8dp"
|
||||
android:layout_marginStart="8dp"
|
||||
tools:text="0 min" />
|
||||
|
||||
</TableRow>
|
||||
|
||||
<TableRow
|
||||
android:tag="detailed">
|
||||
|
||||
|
95
app/src/main/res/layout/statistics_filter_dialog.xml
Normal file
95
app/src/main/res/layout/statistics_filter_dialog.xml
Normal file
@ -0,0 +1,95 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/includeMarkedCheckbox"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_include_marked"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/dateSelectionContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_from"
|
||||
android:padding="4dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_to"
|
||||
android:padding="4dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/timeFromSpinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/timeToSpinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/lastYearButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_filter_last_year"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="4dp"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/allTimeButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_filter_all_time"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="4dp"
|
||||
style="@style/Widget.MaterialComponents.Button.OutlinedButton" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_speed_not_counted"
|
||||
android:layout_marginTop="16dp" />
|
||||
|
||||
</LinearLayout>
|
@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -16,33 +17,32 @@
|
||||
android:layout_marginLeft="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/total_description"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textAlignment="center"
|
||||
android:layout_marginLeft="56dp"
|
||||
android:layout_marginRight="56dp"
|
||||
android:maxLines="3"
|
||||
android:layout_above="@id/total_time"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/total_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/total_time"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:gravity="center_horizontal"
|
||||
android:textSize="28sp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:layout_above="@id/total_description"
|
||||
tools:text="10.0 hours" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/total_description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:textAlignment="center"
|
||||
android:maxLines="3"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_alignBottom="@id/pie_chart"
|
||||
tools:text="10.0 hours"/>
|
||||
android:layout_alignBottom="@id/pie_chart" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="?android:attr/dividerVertical"
|
||||
android:layout_below="@+id/pie_chart"/>
|
||||
android:layout_below="@+id/pie_chart" />
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RadioGroup xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:text="@string/statistics_speed_not_counted"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/statistics_mode_normal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_mode_normal"/>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/statistics_mode_count_all"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/statistics_mode_count_all"/>
|
||||
</RadioGroup>
|
@ -5,14 +5,13 @@
|
||||
<item
|
||||
android:id="@+id/statistics_reset"
|
||||
android:title="@string/statistics_reset_data"
|
||||
custom:showAsAction="never"
|
||||
/>
|
||||
custom:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/statistics_mode"
|
||||
android:id="@+id/statistics_filter"
|
||||
android:icon="@drawable/ic_filter"
|
||||
android:title="@string/statistics_mode"
|
||||
custom:showAsAction="never">
|
||||
android:title="@string/filter"
|
||||
custom:showAsAction="always">
|
||||
</item>
|
||||
|
||||
</menu>
|
||||
|
@ -44,11 +44,6 @@
|
||||
android:title="@string/notification_pref_fragment"
|
||||
android:icon="@drawable/ic_notifications"/>
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/chart_box_outline"
|
||||
android:key="statistics"
|
||||
android:title="@string/statistics_label" />
|
||||
|
||||
<PreferenceCategory
|
||||
android:key="project"
|
||||
android:title="@string/project_pref">
|
||||
|
@ -23,7 +23,6 @@ import java.text.DecimalFormat;
|
||||
import java.text.DecimalFormatSymbols;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -1071,22 +1070,6 @@ public class UserPreferences {
|
||||
.apply();
|
||||
}
|
||||
|
||||
public static long getUsageCountingDateMillis() {
|
||||
return prefs.getLong(PREF_USAGE_COUNTING_DATE, -1);
|
||||
}
|
||||
|
||||
private static void setUsageCountingDateMillis(long value) {
|
||||
prefs.edit().putLong(PREF_USAGE_COUNTING_DATE, value).apply();
|
||||
}
|
||||
|
||||
public static void resetUsageCountingDate() {
|
||||
setUsageCountingDateMillis(Calendar.getInstance().getTimeInMillis());
|
||||
}
|
||||
|
||||
public static void unsetUsageCountingDate() {
|
||||
setUsageCountingDateMillis(-1);
|
||||
}
|
||||
|
||||
public static boolean shouldShowSubscriptionTitle() {
|
||||
return prefs.getBoolean(PREF_SUBSCRIPTION_TITLE, false);
|
||||
}
|
||||
|
@ -771,26 +771,29 @@ public final class DBReader {
|
||||
}
|
||||
}
|
||||
|
||||
public static class StatisticsResult {
|
||||
public List<StatisticsItem> feedTime = new ArrayList<>();
|
||||
public long oldestDate = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the DB for statistics.
|
||||
*
|
||||
* @return The list of statistics objects
|
||||
*/
|
||||
@NonNull
|
||||
public static List<StatisticsItem> getStatistics() {
|
||||
public static StatisticsResult getStatistics(boolean includeMarkedAsPlayed,
|
||||
long timeFilterFrom, long timeFilterTo) {
|
||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||
adapter.open();
|
||||
|
||||
List<StatisticsItem> feedTime = new ArrayList<>();
|
||||
|
||||
StatisticsResult result = new StatisticsResult();
|
||||
List<Feed> feeds = getFeedList();
|
||||
for (Feed feed : feeds) {
|
||||
long feedPlayedTimeCountAll = 0;
|
||||
long feedPlayedTime = 0;
|
||||
long feedTotalTime = 0;
|
||||
long episodes = 0;
|
||||
long episodesStarted = 0;
|
||||
long episodesStartedIncludingMarked = 0;
|
||||
long totalDownloadSize = 0;
|
||||
long episodesDownloadCount = 0;
|
||||
List<FeedItem> items = getFeed(feed.getId()).getItems();
|
||||
@ -800,22 +803,24 @@ public final class DBReader {
|
||||
continue;
|
||||
}
|
||||
|
||||
feedPlayedTime += media.getPlayedDuration() / 1000;
|
||||
|
||||
if (item.isPlayed()) {
|
||||
feedPlayedTimeCountAll += media.getDuration() / 1000;
|
||||
} else {
|
||||
feedPlayedTimeCountAll += media.getPosition() / 1000;
|
||||
if (media.getLastPlayedTime() > 0 && media.getPlayedDuration() != 0) {
|
||||
result.oldestDate = Math.min(result.oldestDate, media.getLastPlayedTime());
|
||||
}
|
||||
if (media.getLastPlayedTime() >= timeFilterFrom
|
||||
&& media.getLastPlayedTime() <= timeFilterTo) {
|
||||
if (media.getPlayedDuration() != 0) {
|
||||
feedPlayedTime += media.getPlayedDuration() / 1000;
|
||||
} else if (includeMarkedAsPlayed && item.isPlayed()) {
|
||||
feedPlayedTime += media.getDuration() / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
if (media.getPlaybackCompletionDate() != null || media.getPlayedDuration() > 0) {
|
||||
boolean markedAsStarted = item.isPlayed() || media.getPosition() != 0;
|
||||
boolean hasStatistics = media.getPlaybackCompletionDate() != null || media.getPlayedDuration() > 0;
|
||||
if (hasStatistics || (includeMarkedAsPlayed && markedAsStarted)) {
|
||||
episodesStarted++;
|
||||
}
|
||||
|
||||
if (item.isPlayed() || media.getPosition() != 0) {
|
||||
episodesStartedIncludingMarked++;
|
||||
}
|
||||
|
||||
feedTotalTime += media.getDuration() / 1000;
|
||||
|
||||
if (media.isDownloaded()) {
|
||||
@ -825,13 +830,12 @@ public final class DBReader {
|
||||
|
||||
episodes++;
|
||||
}
|
||||
feedTime.add(new StatisticsItem(
|
||||
feed, feedTotalTime, feedPlayedTime, feedPlayedTimeCountAll, episodes,
|
||||
episodesStarted, episodesStartedIncludingMarked, totalDownloadSize, episodesDownloadCount));
|
||||
result.feedTime.add(new StatisticsItem(feed, feedTotalTime, feedPlayedTime, episodes,
|
||||
episodesStarted, totalDownloadSize, episodesDownloadCount));
|
||||
}
|
||||
|
||||
adapter.close();
|
||||
return feedTime;
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -11,11 +11,6 @@ public class StatisticsItem {
|
||||
*/
|
||||
public final long timePlayed;
|
||||
|
||||
/**
|
||||
* Simply sums up time of podcasts that are marked as played.
|
||||
*/
|
||||
public final long timePlayedCountAll;
|
||||
|
||||
/**
|
||||
* Number of episodes.
|
||||
*/
|
||||
@ -26,11 +21,6 @@ public class StatisticsItem {
|
||||
*/
|
||||
public final long episodesStarted;
|
||||
|
||||
/**
|
||||
* All episodes that are marked as played (or have position != 0).
|
||||
*/
|
||||
public final long episodesStartedIncludingMarked;
|
||||
|
||||
/**
|
||||
* Simply sums up the size of download podcasts.
|
||||
*/
|
||||
@ -41,16 +31,14 @@ public class StatisticsItem {
|
||||
*/
|
||||
public final long episodesDownloadCount;
|
||||
|
||||
public StatisticsItem(Feed feed, long time, long timePlayed, long timePlayedCountAll,
|
||||
long episodes, long episodesStarted, long episodesStartedIncludingMarked,
|
||||
public StatisticsItem(Feed feed, long time, long timePlayed,
|
||||
long episodes, long episodesStarted,
|
||||
long totalDownloadSize, long episodesDownloadCount) {
|
||||
this.feed = feed;
|
||||
this.time = time;
|
||||
this.timePlayed = timePlayed;
|
||||
this.timePlayedCountAll = timePlayedCountAll;
|
||||
this.episodes = episodes;
|
||||
this.episodesStarted = episodesStarted;
|
||||
this.episodesStartedIncludingMarked = episodesStartedIncludingMarked;
|
||||
this.totalDownloadSize = totalDownloadSize;
|
||||
this.episodesDownloadCount = episodesDownloadCount;
|
||||
}
|
||||
|
@ -44,17 +44,20 @@
|
||||
<string name="change_setting">Change</string>
|
||||
|
||||
<!-- Statistics fragment -->
|
||||
<string name="total_time_listened_to_podcasts">Total time of episodes played:</string>
|
||||
<string name="statistics_mode">Statistics mode</string>
|
||||
<string name="statistics_mode_normal">Calculate duration that was actually played. Playing twice is counted twice, while marking as played is not counted</string>
|
||||
<string name="statistics_mode_count_all">Sum up all episodes marked as played</string>
|
||||
<string name="statistics_include_marked">Include duration of episodes that are just marked as played</string>
|
||||
<string name="statistics_speed_not_counted">Notice: Playback speed is never taken into account.</string>
|
||||
<string name="statistics_from">From</string>
|
||||
<string name="statistics_to">To</string>
|
||||
<string name="statistics_today">Today</string>
|
||||
<string name="statistics_filter_all_time">All time</string>
|
||||
<string name="statistics_filter_last_year">Last year</string>
|
||||
<string name="statistics_reset_data">Reset statistics data</string>
|
||||
<string name="statistics_reset_data_msg">This will erase the history of duration played for all episodes. Are you sure you want to proceed?</string>
|
||||
<string name="statistics_counting_since">Since %s,\nyou played</string>
|
||||
<string name="statistics_counting_range">Played between %1$s and %2$s</string>
|
||||
<string name="statistics_counting_total">Played in total</string>
|
||||
|
||||
<!-- Download Statistics fragment -->
|
||||
<string name="total_size_downloaded_podcasts">Total size of episodes on the device:</string>
|
||||
<string name="total_size_downloaded_podcasts">Total size of episodes on the device</string>
|
||||
|
||||
<!-- Main activity -->
|
||||
<string name="drawer_open">Open menu</string>
|
||||
@ -707,7 +710,6 @@
|
||||
<string name="auto_download_disabled_globally">Auto download is disabled in the main AntennaPod settings</string>
|
||||
<string name="statistics_time_played">Time played:</string>
|
||||
<string name="statistics_total_duration">Total duration (estimate):</string>
|
||||
<string name="statistics_duration_played_episodes">Duration of played episodes:</string>
|
||||
<string name="statistics_episodes_on_device">Episodes on the device:</string>
|
||||
<string name="statistics_space_used">Space used:</string>
|
||||
<string name="statistics_episodes_started_total">Episodes started/total:</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user