Merge pull request #3523 from wseemann/develop
Show storage size of downloaded episodes
This commit is contained in:
commit
2f0c627b15
|
@ -0,0 +1,45 @@
|
||||||
|
package de.danoeh.antennapod.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
|
import de.danoeh.antennapod.core.util.Converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter for the download statistics list
|
||||||
|
*/
|
||||||
|
public class DownloadStatisticsListAdapter extends StatisticsListAdapter {
|
||||||
|
|
||||||
|
public DownloadStatisticsListAdapter(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getHeaderCaptionResourceId() {
|
||||||
|
return R.string.total_size_downloaded_podcasts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onBindHeaderViewHolder(HeaderHolder holder) {
|
||||||
|
long totalDownloadSize = 0;
|
||||||
|
|
||||||
|
for (DBReader.StatisticsItem item: statisticsData.feeds) {
|
||||||
|
totalDownloadSize = totalDownloadSize + item.totalDownloadSize;
|
||||||
|
}
|
||||||
|
holder.totalTime.setText(Converter.byteToString(totalDownloadSize));
|
||||||
|
float[] dataValues = new float[statisticsData.feeds.size()];
|
||||||
|
for (int i = 0; i < statisticsData.feeds.size(); i++) {
|
||||||
|
DBReader.StatisticsItem item = statisticsData.feeds.get(i);
|
||||||
|
dataValues[i] = item.totalDownloadSize;
|
||||||
|
}
|
||||||
|
holder.pieChart.setData(dataValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onBindFeedViewHolder(StatisticsHolder holder, int position) {
|
||||||
|
DBReader.StatisticsItem statsItem = statisticsData.feeds.get(position - 1);
|
||||||
|
holder.value.setText(Converter.byteToString(statsItem.totalDownloadSize));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package de.danoeh.antennapod.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
|
import de.danoeh.antennapod.core.util.Converter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter for the playback statistics list
|
||||||
|
*/
|
||||||
|
public class PlaybackStatisticsListAdapter extends StatisticsListAdapter {
|
||||||
|
|
||||||
|
boolean countAll = true;
|
||||||
|
|
||||||
|
public PlaybackStatisticsListAdapter(Context context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCountAll(boolean countAll) {
|
||||||
|
this.countAll = countAll;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
int getHeaderCaptionResourceId() {
|
||||||
|
return R.string.total_time_listened_to_podcasts;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onBindHeaderViewHolder(HeaderHolder holder) {
|
||||||
|
long time = countAll ? statisticsData.totalTimeCountAll : statisticsData.totalTime;
|
||||||
|
holder.totalTime.setText(Converter.shortLocalizedDuration(context, time));
|
||||||
|
float[] dataValues = new float[statisticsData.feeds.size()];
|
||||||
|
for (int i = 0; i < statisticsData.feeds.size(); i++) {
|
||||||
|
DBReader.StatisticsItem item = statisticsData.feeds.get(i);
|
||||||
|
dataValues[i] = countAll ? item.timePlayedCountAll : item.timePlayed;
|
||||||
|
}
|
||||||
|
holder.pieChart.setData(dataValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void onBindFeedViewHolder(StatisticsHolder holder, int position) {
|
||||||
|
DBReader.StatisticsItem statsItem = statisticsData.feeds.get(position - 1);
|
||||||
|
long time = countAll ? statsItem.timePlayedCountAll : statsItem.timePlayed;
|
||||||
|
holder.value.setText(Converter.shortLocalizedDuration(context, time));
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> {
|
||||||
|
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
||||||
|
dialog.setTitle(statsItem.feed.getTitle());
|
||||||
|
dialog.setMessage(context.getString(R.string.statistics_details_dialog,
|
||||||
|
countAll ? statsItem.episodesStartedIncludingMarked : statsItem.episodesStarted,
|
||||||
|
statsItem.episodes, Converter.shortLocalizedDuration(context,
|
||||||
|
countAll ? statsItem.timePlayedCountAll : statsItem.timePlayed),
|
||||||
|
Converter.shortLocalizedDuration(context, statsItem.time)));
|
||||||
|
dialog.setPositiveButton(android.R.string.ok, null);
|
||||||
|
dialog.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,49 +2,44 @@ package de.danoeh.antennapod.adapter;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
import com.bumptech.glide.request.RequestOptions;
|
import com.bumptech.glide.request.RequestOptions;
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
import de.danoeh.antennapod.core.glide.ApGlideSettings;
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
import de.danoeh.antennapod.core.storage.DBReader;
|
||||||
import de.danoeh.antennapod.core.util.Converter;
|
|
||||||
import de.danoeh.antennapod.view.PieChartView;
|
import de.danoeh.antennapod.view.PieChartView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter for the statistics list
|
* Parent Adapter for the playback and download statistics list
|
||||||
*/
|
*/
|
||||||
public class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
public abstract class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||||
private static final int TYPE_HEADER = 0;
|
private static final int TYPE_HEADER = 0;
|
||||||
private static final int TYPE_FEED = 1;
|
private static final int TYPE_FEED = 1;
|
||||||
private final Context context;
|
final Context context;
|
||||||
private DBReader.StatisticsData statisticsData;
|
DBReader.StatisticsData statisticsData;
|
||||||
private boolean countAll = true;
|
|
||||||
|
|
||||||
public StatisticsListAdapter(Context context) {
|
StatisticsListAdapter(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCountAll(boolean countAll) {
|
|
||||||
this.countAll = countAll;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return statisticsData.feedTime.size() + 1;
|
return statisticsData.feeds.size() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public DBReader.StatisticsItem getItem(int position) {
|
public DBReader.StatisticsItem getItem(int position) {
|
||||||
if (position == 0) {
|
if (position == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return statisticsData.feedTime.get(position - 1);
|
return statisticsData.feeds.get(position - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -57,7 +52,10 @@ public class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.Vie
|
||||||
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
LayoutInflater inflater = LayoutInflater.from(context);
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
if (viewType == TYPE_HEADER) {
|
if (viewType == TYPE_HEADER) {
|
||||||
return new HeaderHolder(inflater.inflate(R.layout.statistics_listitem_total_time, parent, false));
|
View view = inflater.inflate(R.layout.statistics_listitem_total, parent, false);
|
||||||
|
TextView totalText = view.findViewById(R.id.total_description);
|
||||||
|
totalText.setText(getHeaderCaptionResourceId());
|
||||||
|
return new HeaderHolder(view);
|
||||||
}
|
}
|
||||||
return new StatisticsHolder(inflater.inflate(R.layout.statistics_listitem, parent, false));
|
return new StatisticsHolder(inflater.inflate(R.layout.statistics_listitem, parent, false));
|
||||||
}
|
}
|
||||||
|
@ -65,18 +63,10 @@ public class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.Vie
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder h, int position) {
|
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder h, int position) {
|
||||||
if (getItemViewType(position) == TYPE_HEADER) {
|
if (getItemViewType(position) == TYPE_HEADER) {
|
||||||
HeaderHolder holder = (HeaderHolder) h;
|
onBindHeaderViewHolder((HeaderHolder) h);
|
||||||
long time = countAll ? statisticsData.totalTimeCountAll : statisticsData.totalTime;
|
|
||||||
holder.totalTime.setText(Converter.shortLocalizedDuration(context, time));
|
|
||||||
float[] dataValues = new float[statisticsData.feedTime.size()];
|
|
||||||
for (int i = 0; i < statisticsData.feedTime.size(); i++) {
|
|
||||||
DBReader.StatisticsItem item = statisticsData.feedTime.get(i);
|
|
||||||
dataValues[i] = countAll ? item.timePlayedCountAll : item.timePlayed;
|
|
||||||
}
|
|
||||||
holder.pieChart.setData(dataValues);
|
|
||||||
} else {
|
} else {
|
||||||
StatisticsHolder holder = (StatisticsHolder) h;
|
StatisticsHolder holder = (StatisticsHolder) h;
|
||||||
DBReader.StatisticsItem statsItem = statisticsData.feedTime.get(position - 1);
|
DBReader.StatisticsItem statsItem = statisticsData.feeds.get(position - 1);
|
||||||
Glide.with(context)
|
Glide.with(context)
|
||||||
.load(statsItem.feed.getImageLocation())
|
.load(statsItem.feed.getImageLocation())
|
||||||
.apply(new RequestOptions()
|
.apply(new RequestOptions()
|
||||||
|
@ -88,20 +78,7 @@ public class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.Vie
|
||||||
.into(holder.image);
|
.into(holder.image);
|
||||||
|
|
||||||
holder.title.setText(statsItem.feed.getTitle());
|
holder.title.setText(statsItem.feed.getTitle());
|
||||||
long time = countAll ? statsItem.timePlayedCountAll : statsItem.timePlayed;
|
onBindFeedViewHolder(holder, position);
|
||||||
holder.time.setText(Converter.shortLocalizedDuration(context, time));
|
|
||||||
|
|
||||||
holder.itemView.setOnClickListener(v -> {
|
|
||||||
AlertDialog.Builder dialog = new AlertDialog.Builder(context);
|
|
||||||
dialog.setTitle(statsItem.feed.getTitle());
|
|
||||||
dialog.setMessage(context.getString(R.string.statistics_details_dialog,
|
|
||||||
countAll ? statsItem.episodesStartedIncludingMarked : statsItem.episodesStarted,
|
|
||||||
statsItem.episodes, Converter.shortLocalizedDuration(context,
|
|
||||||
countAll ? statsItem.timePlayedCountAll : statsItem.timePlayed),
|
|
||||||
Converter.shortLocalizedDuration(context, statsItem.time)));
|
|
||||||
dialog.setPositiveButton(android.R.string.ok, null);
|
|
||||||
dialog.show();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,14 +101,19 @@ public class StatisticsListAdapter extends RecyclerView.Adapter<RecyclerView.Vie
|
||||||
static class StatisticsHolder extends RecyclerView.ViewHolder {
|
static class StatisticsHolder extends RecyclerView.ViewHolder {
|
||||||
ImageView image;
|
ImageView image;
|
||||||
TextView title;
|
TextView title;
|
||||||
TextView time;
|
TextView value;
|
||||||
|
|
||||||
StatisticsHolder(View itemView) {
|
StatisticsHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
image = itemView.findViewById(R.id.imgvCover);
|
image = itemView.findViewById(R.id.imgvCover);
|
||||||
title = itemView.findViewById(R.id.txtvTitle);
|
title = itemView.findViewById(R.id.txtvTitle);
|
||||||
time = itemView.findViewById(R.id.txtvTime);
|
value = itemView.findViewById(R.id.txtvValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract int getHeaderCaptionResourceId();
|
||||||
|
|
||||||
|
abstract void onBindHeaderViewHolder(HeaderHolder holder);
|
||||||
|
|
||||||
|
abstract void onBindFeedViewHolder(StatisticsHolder holder, int position);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
package de.danoeh.antennapod.fragment.preferences;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
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 de.danoeh.antennapod.core.util.comparator.CompareCompat;
|
||||||
|
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;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshDownloadStatistics() {
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
downloadStatisticsList.setVisibility(View.GONE);
|
||||||
|
loadStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadStatistics() {
|
||||||
|
if (disposable != null) {
|
||||||
|
disposable.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
disposable =
|
||||||
|
Observable.fromCallable(() -> {
|
||||||
|
DBReader.StatisticsData statisticsData = DBReader.getStatistics();
|
||||||
|
Collections.sort(statisticsData.feeds, (item1, item2) ->
|
||||||
|
CompareCompat.compareLong(item1.totalDownloadSize, item2.totalDownloadSize));
|
||||||
|
return statisticsData;
|
||||||
|
})
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(result -> {
|
||||||
|
listAdapter.update(result);
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
downloadStatisticsList.setVisibility(View.VISIBLE);
|
||||||
|
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
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.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
import android.widget.RadioButton;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||||
|
import de.danoeh.antennapod.adapter.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.core.util.comparator.CompareCompat;
|
||||||
|
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.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the 'playback statistics' screen
|
||||||
|
*/
|
||||||
|
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 Disposable disposable;
|
||||||
|
private RecyclerView feedStatisticsList;
|
||||||
|
private ProgressBar progressBar;
|
||||||
|
private PlaybackStatisticsListAdapter listAdapter;
|
||||||
|
private boolean countAll = false;
|
||||||
|
private SharedPreferences prefs;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
prefs = getContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
||||||
|
countAll = prefs.getBoolean(PREF_COUNT_ALL, false);
|
||||||
|
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(getContext());
|
||||||
|
listAdapter.setCountAll(countAll);
|
||||||
|
feedStatisticsList.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
|
feedStatisticsList.setAdapter(listAdapter);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStart() {
|
||||||
|
super.onStart();
|
||||||
|
((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.statistics_label);
|
||||||
|
refreshStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
if (disposable != null) {
|
||||||
|
disposable.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.statistics, menu);
|
||||||
|
menu.findItem(R.id.statistics_reset).setEnabled(!countAll);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
if (item.getItemId() == R.id.statistics_mode) {
|
||||||
|
selectStatisticsMode();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
||||||
|
builder.setView(contentView);
|
||||||
|
builder.setTitle(R.string.statistics_mode);
|
||||||
|
|
||||||
|
if (countAll) {
|
||||||
|
((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).setChecked(true);
|
||||||
|
} else {
|
||||||
|
((RadioButton) contentView.findViewById(R.id.statistics_mode_normal)).setChecked(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void confirmResetStatistics() {
|
||||||
|
if (!countAll) {
|
||||||
|
ConfirmationDialog conDialog = new ConfirmationDialog(
|
||||||
|
getActivity(),
|
||||||
|
R.string.statistics_reset_data,
|
||||||
|
R.string.statistics_reset_data_msg) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onConfirmButtonPressed(DialogInterface dialog) {
|
||||||
|
dialog.dismiss();
|
||||||
|
doResetStatistics();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
conDialog.createNewDialog().show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void doResetStatistics() {
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
feedStatisticsList.setVisibility(View.GONE);
|
||||||
|
if (disposable != null) {
|
||||||
|
disposable.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
disposable = Completable.fromFuture(DBWriter.resetStatistics())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(this::refreshStatistics, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void refreshStatistics() {
|
||||||
|
progressBar.setVisibility(View.VISIBLE);
|
||||||
|
feedStatisticsList.setVisibility(View.GONE);
|
||||||
|
loadStatistics();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadStatistics() {
|
||||||
|
if (disposable != null) {
|
||||||
|
disposable.dispose();
|
||||||
|
}
|
||||||
|
disposable = Observable.fromCallable(this::fetchStatistics)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(result -> {
|
||||||
|
listAdapter.update(result);
|
||||||
|
progressBar.setVisibility(View.GONE);
|
||||||
|
feedStatisticsList.setVisibility(View.VISIBLE);
|
||||||
|
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DBReader.StatisticsData fetchStatistics() {
|
||||||
|
DBReader.StatisticsData statisticsData = DBReader.getStatistics();
|
||||||
|
if (countAll) {
|
||||||
|
Collections.sort(statisticsData.feeds, (item1, item2) ->
|
||||||
|
CompareCompat.compareLong(item1.timePlayedCountAll, item2.timePlayedCountAll));
|
||||||
|
} else {
|
||||||
|
Collections.sort(statisticsData.feeds, (item1, item2) ->
|
||||||
|
CompareCompat.compareLong(item1.timePlayed, item2.timePlayed));
|
||||||
|
}
|
||||||
|
return statisticsData;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,180 +1,96 @@
|
||||||
package de.danoeh.antennapod.fragment.preferences;
|
package de.danoeh.antennapod.fragment.preferences;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.res.Resources;
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.RadioButton;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.fragment.app.FragmentPagerAdapter;
|
||||||
|
import androidx.viewpager.widget.ViewPager;
|
||||||
|
|
||||||
|
import com.google.android.material.tabs.TabLayout;
|
||||||
|
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.activity.PreferenceActivity;
|
import de.danoeh.antennapod.activity.PreferenceActivity;
|
||||||
import de.danoeh.antennapod.adapter.StatisticsListAdapter;
|
|
||||||
import de.danoeh.antennapod.core.dialog.ConfirmationDialog;
|
|
||||||
import de.danoeh.antennapod.core.storage.DBReader;
|
|
||||||
import de.danoeh.antennapod.core.storage.DBWriter;
|
|
||||||
import io.reactivex.Completable;
|
|
||||||
import io.reactivex.Observable;
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
||||||
import io.reactivex.disposables.Disposable;
|
|
||||||
import io.reactivex.schedulers.Schedulers;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the 'statistics' screen
|
* Displays the 'statistics' screen
|
||||||
*/
|
*/
|
||||||
public class StatisticsFragment extends Fragment {
|
public class StatisticsFragment extends Fragment {
|
||||||
private static final String TAG = StatisticsFragment.class.getSimpleName();
|
|
||||||
private static final String PREF_NAME = "StatisticsActivityPrefs";
|
|
||||||
private static final String PREF_COUNT_ALL = "countAll";
|
|
||||||
|
|
||||||
private Disposable disposable;
|
public static final String TAG = "StatisticsFragment";
|
||||||
private RecyclerView feedStatisticsList;
|
|
||||||
private ProgressBar progressBar;
|
private static final int POS_LISTENED_HOURS = 0;
|
||||||
private StatisticsListAdapter listAdapter;
|
private static final int POS_SPACE_TAKEN = 1;
|
||||||
private boolean countAll = false;
|
private static final int TOTAL_COUNT = 2;
|
||||||
private SharedPreferences prefs;
|
|
||||||
|
|
||||||
|
private TabLayout tabLayout;
|
||||||
|
private ViewPager viewPager;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
prefs = getContext().getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE);
|
|
||||||
countAll = prefs.getBoolean(PREF_COUNT_ALL, false);
|
|
||||||
setHasOptionsMenu(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
@Override
|
Bundle savedInstanceState) {
|
||||||
public View onCreateView(
|
super.onCreateView(inflater, container, savedInstanceState);
|
||||||
@NonNull LayoutInflater inflater,
|
setHasOptionsMenu(true);
|
||||||
@Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
|
||||||
View root = inflater.inflate(R.layout.statistics_activity, container, false);
|
View rootView = inflater.inflate(R.layout.pager_fragment, container, false);
|
||||||
feedStatisticsList = root.findViewById(R.id.statistics_list);
|
viewPager = rootView.findViewById(R.id.viewpager);
|
||||||
progressBar = root.findViewById(R.id.progressBar);
|
viewPager.setAdapter(new StatisticsPagerAdapter(getChildFragmentManager(), getResources()));
|
||||||
listAdapter = new StatisticsListAdapter(getContext());
|
|
||||||
listAdapter.setCountAll(countAll);
|
// Give the TabLayout the ViewPager
|
||||||
feedStatisticsList.setLayoutManager(new LinearLayoutManager(getContext()));
|
tabLayout = rootView.findViewById(R.id.sliding_tabs);
|
||||||
feedStatisticsList.setAdapter(listAdapter);
|
tabLayout.setupWithViewPager(viewPager);
|
||||||
return root;
|
|
||||||
|
return rootView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStart() {
|
public void onStart() {
|
||||||
super.onStart();
|
super.onStart();
|
||||||
((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.statistics_label);
|
((PreferenceActivity) getActivity()).getSupportActionBar().setTitle(R.string.statistics_label);
|
||||||
refreshStatistics();
|
}
|
||||||
|
|
||||||
|
public static class StatisticsPagerAdapter extends FragmentPagerAdapter {
|
||||||
|
|
||||||
|
private final Resources resources;
|
||||||
|
|
||||||
|
public StatisticsPagerAdapter(FragmentManager fm, Resources resources) {
|
||||||
|
super(fm);
|
||||||
|
this.resources = resources;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public Fragment getItem(int position) {
|
||||||
super.onDestroyView();
|
if (position == 0) {
|
||||||
if (disposable != null) {
|
return new PlaybackStatisticsFragment();
|
||||||
disposable.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
||||||
inflater.inflate(R.menu.statistics, menu);
|
|
||||||
menu.findItem(R.id.statistics_reset).setEnabled(!countAll);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
if (item.getItemId() == R.id.statistics_mode) {
|
|
||||||
selectStatisticsMode();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
|
|
||||||
builder.setView(contentView);
|
|
||||||
builder.setTitle(R.string.statistics_mode);
|
|
||||||
|
|
||||||
if (countAll) {
|
|
||||||
((RadioButton) contentView.findViewById(R.id.statistics_mode_count_all)).setChecked(true);
|
|
||||||
} else {
|
} else {
|
||||||
((RadioButton) contentView.findViewById(R.id.statistics_mode_normal)).setChecked(true);
|
return new DownloadStatisticsFragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
|
||||||
});
|
|
||||||
|
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void confirmResetStatistics() {
|
|
||||||
if (!countAll) {
|
|
||||||
ConfirmationDialog conDialog = new ConfirmationDialog(
|
|
||||||
getActivity(),
|
|
||||||
R.string.statistics_reset_data,
|
|
||||||
R.string.statistics_reset_data_msg) {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConfirmButtonPressed(DialogInterface dialog) {
|
public int getCount() {
|
||||||
dialog.dismiss();
|
return TOTAL_COUNT;
|
||||||
doResetStatistics();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
conDialog.createNewDialog().show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doResetStatistics() {
|
@Override
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
public CharSequence getPageTitle(int position) {
|
||||||
feedStatisticsList.setVisibility(View.GONE);
|
switch (position) {
|
||||||
if (disposable != null) {
|
case POS_LISTENED_HOURS:
|
||||||
disposable.dispose();
|
return resources.getString(R.string.playback_statistics_label);
|
||||||
}
|
case POS_SPACE_TAKEN:
|
||||||
|
return resources.getString(R.string.download_statistics_label);
|
||||||
disposable = Completable.fromFuture(DBWriter.resetStatistics())
|
default:
|
||||||
.subscribeOn(Schedulers.io())
|
return super.getPageTitle(position);
|
||||||
.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.getStatistics(countAll))
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(result -> {
|
|
||||||
listAdapter.update(result);
|
|
||||||
progressBar.setVisibility(View.GONE);
|
|
||||||
feedStatisticsList.setVisibility(View.VISIBLE);
|
|
||||||
}, error -> Log.e(TAG, Log.getStackTraceString(error)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/sliding_tabs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:tabGravity="fill"
|
||||||
|
app:tabMode="fixed" />
|
||||||
|
|
||||||
|
<androidx.viewpager.widget.ViewPager
|
||||||
|
android:id="@+id/viewpager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0px"
|
||||||
|
android:layout_weight="1" />
|
||||||
|
</LinearLayout>
|
|
@ -41,7 +41,7 @@
|
||||||
tools:text="Feed title"/>
|
tools:text="Feed title"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txtvTime"
|
android:id="@+id/txtvValue"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
|
|
|
@ -15,9 +15,8 @@
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/total_time_description"
|
android:id="@+id/total_description"
|
||||||
android:textSize="14sp"
|
android:textSize="14sp"
|
||||||
android:text="@string/total_time_listened_to_podcasts"
|
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:layout_above="@+id/total_time"/>
|
android:layout_above="@+id/total_time"/>
|
||||||
|
|
|
@ -868,12 +868,10 @@ public final class DBReader {
|
||||||
/**
|
/**
|
||||||
* Searches the DB for statistics
|
* Searches the DB for statistics
|
||||||
*
|
*
|
||||||
* @param sortByCountAll If true, the statistic items will be sorted according to the
|
|
||||||
* countAll calculation time
|
|
||||||
* @return The StatisticsInfo object
|
* @return The StatisticsInfo object
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
public static StatisticsData getStatistics(boolean sortByCountAll) {
|
public static StatisticsData getStatistics() {
|
||||||
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
PodDBAdapter adapter = PodDBAdapter.getInstance();
|
||||||
adapter.open();
|
adapter.open();
|
||||||
|
|
||||||
|
@ -889,6 +887,7 @@ public final class DBReader {
|
||||||
long episodes = 0;
|
long episodes = 0;
|
||||||
long episodesStarted = 0;
|
long episodesStarted = 0;
|
||||||
long episodesStartedIncludingMarked = 0;
|
long episodesStartedIncludingMarked = 0;
|
||||||
|
long totalDownloadSize = 0;
|
||||||
List<FeedItem> items = getFeed(feed.getId()).getItems();
|
List<FeedItem> items = getFeed(feed.getId()).getItems();
|
||||||
for (FeedItem item : items) {
|
for (FeedItem item : items) {
|
||||||
FeedMedia media = item.getMedia();
|
FeedMedia media = item.getMedia();
|
||||||
|
@ -913,43 +912,24 @@ public final class DBReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
feedTotalTime += media.getDuration() / 1000;
|
feedTotalTime += media.getDuration() / 1000;
|
||||||
|
|
||||||
|
if (media.isDownloaded()) {
|
||||||
|
totalDownloadSize = totalDownloadSize + media.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
episodes++;
|
episodes++;
|
||||||
}
|
}
|
||||||
feedTime.add(new StatisticsItem(
|
feedTime.add(new StatisticsItem(
|
||||||
feed, feedTotalTime, feedPlayedTime, feedPlayedTimeCountAll, episodes,
|
feed, feedTotalTime, feedPlayedTime, feedPlayedTimeCountAll, episodes,
|
||||||
episodesStarted, episodesStartedIncludingMarked));
|
episodesStarted, episodesStartedIncludingMarked, totalDownloadSize));
|
||||||
totalTime += feedPlayedTime;
|
totalTime += feedPlayedTime;
|
||||||
totalTimeCountAll += feedPlayedTimeCountAll;
|
totalTimeCountAll += feedPlayedTimeCountAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortByCountAll) {
|
|
||||||
Collections.sort(feedTime, (item1, item2) ->
|
|
||||||
compareLong(item1.timePlayedCountAll, item2.timePlayedCountAll));
|
|
||||||
} else {
|
|
||||||
Collections.sort(feedTime, (item1, item2) ->
|
|
||||||
compareLong(item1.timePlayed, item2.timePlayed));
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.close();
|
adapter.close();
|
||||||
return new StatisticsData(totalTime, totalTimeCountAll, feedTime);
|
return new StatisticsData(totalTime, totalTimeCountAll, feedTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares two {@code long} values. Long.compare() is not available before API 19
|
|
||||||
*
|
|
||||||
* @return 0 if long1 = long2, less than 0 if long1 < long2,
|
|
||||||
* and greater than 0 if long1 > long2.
|
|
||||||
*/
|
|
||||||
private static int compareLong(long long1, long long2) {
|
|
||||||
if (long1 > long2) {
|
|
||||||
return -1;
|
|
||||||
} else if (long1 < long2) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class StatisticsData {
|
public static class StatisticsData {
|
||||||
/**
|
/**
|
||||||
* Simply sums up time of podcasts that are marked as played
|
* Simply sums up time of podcasts that are marked as played
|
||||||
|
@ -961,12 +941,12 @@ public final class DBReader {
|
||||||
*/
|
*/
|
||||||
public final long totalTime;
|
public final long totalTime;
|
||||||
|
|
||||||
public final List<StatisticsItem> feedTime;
|
public final List<StatisticsItem> feeds;
|
||||||
|
|
||||||
public StatisticsData(long totalTime, long totalTimeCountAll, List<StatisticsItem> feedTime) {
|
public StatisticsData(long totalTime, long totalTimeCountAll, List<StatisticsItem> feeds) {
|
||||||
this.totalTime = totalTime;
|
this.totalTime = totalTime;
|
||||||
this.totalTimeCountAll = totalTimeCountAll;
|
this.totalTimeCountAll = totalTimeCountAll;
|
||||||
this.feedTime = feedTime;
|
this.feeds = feeds;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,9 +971,14 @@ public final class DBReader {
|
||||||
* All episodes that are marked as played (or have position != 0)
|
* All episodes that are marked as played (or have position != 0)
|
||||||
*/
|
*/
|
||||||
public final long episodesStartedIncludingMarked;
|
public final long episodesStartedIncludingMarked;
|
||||||
|
/**
|
||||||
|
* Simply sums up the size of download podcasts
|
||||||
|
*/
|
||||||
|
public final long totalDownloadSize;
|
||||||
|
|
||||||
public StatisticsItem(Feed feed, long time, long timePlayed, long timePlayedCountAll,
|
public StatisticsItem(Feed feed, long time, long timePlayed, long timePlayedCountAll,
|
||||||
long episodes, long episodesStarted, long episodesStartedIncludingMarked) {
|
long episodes, long episodesStarted, long episodesStartedIncludingMarked,
|
||||||
|
long totalDownloadSize) {
|
||||||
this.feed = feed;
|
this.feed = feed;
|
||||||
this.time = time;
|
this.time = time;
|
||||||
this.timePlayed = timePlayed;
|
this.timePlayed = timePlayed;
|
||||||
|
@ -1001,6 +986,7 @@ public final class DBReader {
|
||||||
this.episodes = episodes;
|
this.episodes = episodes;
|
||||||
this.episodesStarted = episodesStarted;
|
this.episodesStarted = episodesStarted;
|
||||||
this.episodesStartedIncludingMarked = episodesStartedIncludingMarked;
|
this.episodesStartedIncludingMarked = episodesStartedIncludingMarked;
|
||||||
|
this.totalDownloadSize = totalDownloadSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package de.danoeh.antennapod.core.util.comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some compare() methods are not available before API 19.
|
||||||
|
* This class provides fallbacks
|
||||||
|
*/
|
||||||
|
public class CompareCompat {
|
||||||
|
|
||||||
|
private CompareCompat() {
|
||||||
|
// Must not be instantiated
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two {@code long} values. Long.compare() is not available before API 19
|
||||||
|
*
|
||||||
|
* @return 0 if long1 = long2, less than 0 if long1 < long2,
|
||||||
|
* and greater than 0 if long1 > long2.
|
||||||
|
*/
|
||||||
|
public static int compareLong(long long1, long long2) {
|
||||||
|
//noinspection UseCompareMethod
|
||||||
|
if (long1 > long2) {
|
||||||
|
return -1;
|
||||||
|
} else if (long1 < long2) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -29,6 +29,8 @@
|
||||||
<string name="gpodnet_auth_label">gpodder.net Login</string>
|
<string name="gpodnet_auth_label">gpodder.net Login</string>
|
||||||
<string name="episode_cache_full_title">Episode cache full</string>
|
<string name="episode_cache_full_title">Episode cache full</string>
|
||||||
<string name="episode_cache_full_message">The episode cache limit has been reached. You can increase the cache size in the Settings.</string>
|
<string name="episode_cache_full_message">The episode cache limit has been reached. You can increase the cache size in the Settings.</string>
|
||||||
|
<string name="playback_statistics_label">Playback</string>
|
||||||
|
<string name="download_statistics_label">Downloads</string>
|
||||||
|
|
||||||
<!-- Statistics fragment -->
|
<!-- Statistics fragment -->
|
||||||
<string name="total_time_listened_to_podcasts">Total time of podcasts played:</string>
|
<string name="total_time_listened_to_podcasts">Total time of podcasts played:</string>
|
||||||
|
@ -40,6 +42,9 @@
|
||||||
<string name="statistics_reset_data">Reset statistics data</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_reset_data_msg">This will erase the history of duration played for all episodes. Are you sure you want to proceed?</string>
|
||||||
|
|
||||||
|
<!-- Download Statistics fragment -->
|
||||||
|
<string name="total_size_downloaded_podcasts">Total size of downloaded podcasts:</string>
|
||||||
|
|
||||||
<!-- Main activity -->
|
<!-- Main activity -->
|
||||||
<string name="drawer_open">Open menu</string>
|
<string name="drawer_open">Open menu</string>
|
||||||
<string name="drawer_close">Close menu</string>
|
<string name="drawer_close">Close menu</string>
|
||||||
|
|
Loading…
Reference in New Issue