Modernize feed details design (#7402)

This commit is contained in:
ByteHamster 2024-09-15 10:26:13 +02:00 committed by GitHub
parent 43902d7234
commit dafe821775
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 188 additions and 192 deletions

View File

@ -41,6 +41,7 @@ import de.danoeh.antennapod.model.feed.FeedFunding;
import de.danoeh.antennapod.ui.glide.FastBlurTransformation;
import de.danoeh.antennapod.ui.screen.feed.preferences.EditUrlSettingsDialog;
import de.danoeh.antennapod.ui.statistics.StatisticsFragment;
import de.danoeh.antennapod.ui.statistics.feed.FeedStatisticsDialogFragment;
import de.danoeh.antennapod.ui.statistics.feed.FeedStatisticsFragment;
import io.reactivex.Completable;
import io.reactivex.Maybe;
@ -120,6 +121,9 @@ public class FeedInfoFragment extends Fragment implements MaterialToolbar.OnMenu
getParentFragmentManager().beginTransaction().replace(R.id.statisticsFragmentContainer,
FeedStatisticsFragment.newInstance(feedId, false), "feed_statistics_fragment")
.commitAllowingStateLoss();
viewBinding.statisticsFragmentContainer.setOnClickListener(v ->
FeedStatisticsDialogFragment.newInstance(feedId, feed.getTitle())
.show(getChildFragmentManager().beginTransaction(), "FeedStatistics"));
viewBinding.statisticsButton.setOnClickListener(view -> {
StatisticsFragment fragment = new StatisticsFragment();
@ -239,12 +243,10 @@ public class FeedInfoFragment extends Fragment implements MaterialToolbar.OnMenu
((MainActivity) getActivity()).loadChildFragment(fragment, TransitionEffect.SLIDE);
});
} else {
viewBinding.statisticsButton.setVisibility(View.GONE);
viewBinding.statisticsHeading.setVisibility(View.GONE);
viewBinding.statisticsFragmentContainer.setVisibility(View.GONE);
viewBinding.statisticsHeadingLabel.setVisibility(View.GONE);
viewBinding.supportHeadingLabel.setVisibility(View.GONE);
viewBinding.supportUrl.setVisibility(View.GONE);
viewBinding.descriptionHeadingLabel.setVisibility(View.GONE);
}
refreshToolbarState();

View File

@ -54,8 +54,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingHorizontal="8dp"
android:paddingBottom="8dp"
android:scrollbarStyle="outsideOverlay"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
@ -65,82 +64,93 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="16dp"
android:paddingHorizontal="@dimen/additional_horizontal_spacing">
<TextView
android:id="@+id/statisticsHeadingLabel"
android:layout_width="wrap_content"
<LinearLayout
android:id="@+id/statisticsHeading"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginBottom="8dp"
android:text="@string/statistics_label"
android:textColor="?android:attr/textColorPrimary"
tools:background="@android:color/holo_red_light" />
android:paddingHorizontal="8dp"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<TextView
android:id="@+id/statisticsHeadingLabel"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/statistics_label"
android:layout_weight="1"
style="@style/TextAppearance.Material3.TitleMedium" />
<Button
android:id="@+id/statisticsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:minWidth="0dp"
android:minHeight="0dp"
android:text="@string/statistics_view_all"
style="@style/Widget.MaterialComponents.Button.TextButton" />
</LinearLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@+id/statisticsFragmentContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/statisticsButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="0dp"
android:minHeight="0dp"
android:layout_marginBottom="16dp"
android:text="@string/statistics_view_all"
style="@style/Widget.MaterialComponents.Button.TextButton" />
android:paddingHorizontal="4dp"
tools:layout_height="20dp"
tools:background="@color/image_readability_tint" />
<TextView
android:id="@+id/supportHeadingLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="4dp"
android:paddingHorizontal="8dp"
android:text="@string/support_funding_label"
android:textColor="?android:attr/textColorPrimary"
android:textSize="18sp"
tools:background="@android:color/holo_red_light" />
style="@style/TextAppearance.Material3.TitleMedium" />
<TextView
android:id="@+id/supportUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="8"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingHorizontal="8dp"
android:linksClickable="true"
android:autoLink="web"
tools:background="@android:color/holo_green_dark" />
style="@style/TextAppearance.Material3.BodyMedium"
tools:text="Support this podcast" />
<TextView
android:id="@+id/descriptionHeadingLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginTop="16dp"
android:paddingHorizontal="8dp"
android:layout_marginBottom="4dp"
android:text="@string/description_label"
android:textColor="?android:attr/textColorPrimary"
tools:background="@android:color/holo_red_light" />
style="@style/TextAppearance.Material3.TitleMedium" />
<TextView
android:id="@+id/descriptionLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textIsSelectable="true"
tools:background="@android:color/holo_green_dark" />
android:paddingHorizontal="8dp"
style="@style/TextAppearance.Material3.BodyMedium"
tools:text="Description" />
<TextView
android:id="@+id/urlHeadingLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
android:layout_marginTop="16dp"
android:layout_marginBottom="4dp"
android:paddingHorizontal="8dp"
android:text="@string/url_label"
android:textColor="?android:attr/textColorPrimary"
tools:background="@android:color/holo_red_light" />
style="@style/TextAppearance.Material3.TitleMedium" />
<TextView
android:id="@+id/urlLabel"
@ -150,8 +160,9 @@
android:maxLines="4"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:paddingHorizontal="8dp"
android:drawablePadding="4dp"
tools:background="@android:color/holo_green_dark"
style="@style/TextAppearance.Material3.BodyMedium"
tools:text="http://www.example.com/feed" />
</LinearLayout>

View File

@ -736,15 +736,16 @@
<string name="keep_updated">Keep updated</string>
<string name="keep_updated_summary">Include this podcast when (auto-)refreshing all podcasts</string>
<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_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>
<string name="statistics_expected_next_episode">Expected next episode:</string>
<string name="statistics_episodes_started">started</string>
<string name="statistics_episodes_total">total</string>
<string name="statistics_episodes_played">played</string>
<string name="statistics_episodes_downloaded">downloaded</string>
<string name="statistics_episodes_space">space taken</string>
<string name="statistics_release_schedule">release schedule</string>
<string name="statistics_release_next">next episode (estimate)</string>
<string name="statistics_expected_next_episode_any_day">Any day now</string>
<string name="statistics_expected_next_episode_unknown">Unknown</string>
<string name="statistics_view_all">View for all podcasts »</string>
<string name="statistics_view_all">All podcasts »</string>
<string name="wait_icon" translatable="false"></string>
<string name="edit_url_menu">Edit feed URL</string>
<string name="edit_url_confirmation_msg">Changing the RSS address can easily break the playback state and episode listings of the podcast. We do NOT recommend changing it and will NOT provide support if anything goes wrong. This cannot be undone. The broken subscription CANNOT be repaired by simply changing the address back. We recommend creating a backup before continuing.</string>

View File

@ -49,11 +49,9 @@ public class DownloadStatisticsListAdapter extends StatisticsListAdapter {
text += "" + context.getResources().getQuantityString(R.plurals.num_episodes, numEpisodes, numEpisodes);
holder.value.setText(text);
holder.itemView.setOnClickListener(v -> {
FeedStatisticsDialogFragment yourDialogFragment = FeedStatisticsDialogFragment.newInstance(
item.feed.getId(), item.feed.getTitle());
yourDialogFragment.show(fragment.getChildFragmentManager().beginTransaction(), "DialogFragment");
});
holder.itemView.setOnClickListener(v ->
FeedStatisticsDialogFragment.newInstance(item.feed.getId(), item.feed.getTitle())
.show(fragment.getChildFragmentManager().beginTransaction(), "FeedStatistics"));
}
}

View File

@ -17,6 +17,7 @@ import de.danoeh.antennapod.storage.database.ReleaseScheduleGuesser;
import de.danoeh.antennapod.model.feed.FeedItem;
import de.danoeh.antennapod.model.feed.FeedItemFilter;
import de.danoeh.antennapod.model.feed.SortOrder;
import de.danoeh.antennapod.ui.common.ThemeUtils;
import de.danoeh.antennapod.ui.statistics.R;
import de.danoeh.antennapod.ui.statistics.databinding.FeedStatisticsBinding;
import io.reactivex.Observable;
@ -29,7 +30,6 @@ import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;
public class FeedStatisticsFragment extends Fragment {
private static final String EXTRA_FEED_ID = "de.danoeh.antennapod.extra.feedId";
@ -54,17 +54,20 @@ public class FeedStatisticsFragment extends Fragment {
@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();
if (getArguments().getBoolean(EXTRA_DETAILED)) {
viewBinding.secondRowContainer.setVisibility(View.VISIBLE);
int color = ThemeUtils.getColorFromAttr(getContext(), R.attr.colorSurface);
viewBinding.playbackTime.getRoot().setBackgroundColor(color);
viewBinding.episodesStarted.getRoot().setBackgroundColor(color);
viewBinding.spaceDownloaded.getRoot().setBackgroundColor(color);
viewBinding.episodesTotal.getRoot().setBackgroundColor(color);
viewBinding.durationTotal.getRoot().setBackgroundColor(color);
viewBinding.episodesDownloaded.getRoot().setBackgroundColor(color);
viewBinding.expectedNextEpisode.getRoot().setBackgroundColor(color);
viewBinding.episodeSchedule.getRoot().setBackgroundColor(color);
}
return viewBinding.getRoot();
}
@ -148,28 +151,49 @@ public class FeedStatisticsFragment extends Fragment {
private void showStats(Pair<StatisticsItem, ReleaseScheduleGuesser.Guess> p) {
StatisticsItem s = p.first;
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));
viewBinding.episodesStarted.mainLabel.setText(getResources()
.getQuantityString(R.plurals.num_episodes, (int) s.episodesStarted, s.episodesStarted));
viewBinding.episodesStarted.subtitleLabel.setText(R.string.statistics_episodes_started);
viewBinding.episodesTotal.mainLabel.setText(getResources()
.getQuantityString(R.plurals.num_episodes, (int) s.episodes, s.episodes));
viewBinding.episodesTotal.subtitleLabel.setText(R.string.statistics_episodes_total);
viewBinding.playbackTime.mainLabel.setText(Converter.shortLocalizedDuration(getContext(), s.timePlayed));
viewBinding.playbackTime.subtitleLabel.setText(R.string.statistics_episodes_played);
viewBinding.durationTotal.mainLabel.setText(Converter.shortLocalizedDuration(getContext(), s.time));
viewBinding.durationTotal.subtitleLabel.setText(R.string.statistics_episodes_total);
viewBinding.episodesDownloaded.mainLabel.setText(getResources()
.getQuantityString(R.plurals.num_episodes, (int) s.episodesDownloadCount, s.episodesDownloadCount));
viewBinding.episodesDownloaded.subtitleLabel.setText(R.string.statistics_episodes_downloaded);
viewBinding.spaceDownloaded.mainLabel.setText(Formatter.formatShortFileSize(getContext(), s.totalDownloadSize));
viewBinding.spaceDownloaded.subtitleLabel.setText(R.string.statistics_episodes_space);
viewBinding.expectedNextEpisode.subtitleLabel.setText(R.string.statistics_release_next);
viewBinding.episodeSchedule.subtitleLabel.setText(R.string.statistics_release_schedule);
ReleaseScheduleGuesser.Guess guess = p.second;
if (!s.feed.getPreferences().getKeepUpdated()) {
viewBinding.expectedNextEpisodeLabel.setText(R.string.updates_disabled_label);
viewBinding.expectedNextEpisode.subtitleLabel.setText(R.string.statistics_expected_next_episode_unknown);
viewBinding.episodeSchedule.subtitleLabel.setText(R.string.updates_disabled_label);
} else if (guess == null || guess.nextExpectedDate.getTime() <= new Date().getTime() - 7 * 24 * 3600000L) {
// More than 30 days delayed
viewBinding.expectedNextEpisodeLabel.setText(R.string.statistics_expected_next_episode_unknown);
viewBinding.expectedNextEpisode.mainLabel.setText(R.string.statistics_expected_next_episode_unknown);
viewBinding.episodeSchedule.mainLabel.setText(R.string.statistics_expected_next_episode_unknown);
} else {
String text = DateFormatter.formatAbbrev(getContext(), guess.nextExpectedDate);
if (guess.nextExpectedDate.getTime() <= new Date().getTime()) {
text = getString(R.string.statistics_expected_next_episode_any_day);
viewBinding.expectedNextEpisode.mainLabel.setText(R.string.statistics_expected_next_episode_any_day);
} else {
viewBinding.expectedNextEpisode.mainLabel.setText(
DateFormatter.formatAbbrev(getContext(), guess.nextExpectedDate));
}
if (guess.schedule != ReleaseScheduleGuesser.Schedule.UNKNOWN) {
text += " (" + getReadableSchedule(guess) + ")";
if (guess.schedule == ReleaseScheduleGuesser.Schedule.UNKNOWN) {
viewBinding.episodeSchedule.mainLabel.setText(R.string.statistics_expected_next_episode_unknown);
} else {
viewBinding.episodeSchedule.mainLabel.setText(getReadableSchedule(guess));
}
viewBinding.expectedNextEpisodeLabel.setText(text);
}
}

View File

@ -68,10 +68,8 @@ public class PlaybackStatisticsListAdapter extends StatisticsListAdapter {
long time = statsItem.timePlayed;
holder.value.setText(Converter.shortLocalizedDuration(context, time));
holder.itemView.setOnClickListener(v -> {
FeedStatisticsDialogFragment yourDialogFragment = FeedStatisticsDialogFragment.newInstance(
statsItem.feed.getId(), statsItem.feed.getTitle());
yourDialogFragment.show(fragment.getChildFragmentManager().beginTransaction(), "DialogFragment");
});
holder.itemView.setOnClickListener(v ->
FeedStatisticsDialogFragment.newInstance(statsItem.feed.getId(), statsItem.feed.getTitle())
.show(fragment.getChildFragmentManager().beginTransaction(), "FeedStatistics"));
}
}

View File

@ -1,131 +1,65 @@
<?xml version="1.0" encoding="utf-8"?>
<TableLayout
<LinearLayout
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">
android:layout_height="wrap_content"
android:orientation="vertical">
<TableRow
android:tag="detailed">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/statistics_episodes_started_total" />
<include
android:id="@+id/playbackTime"
layout="@layout/feed_statistics_card" />
<TextView
android:id="@+id/startedTotalLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="@string/wait_icon"
tools:text="0 / 0" />
<include
android:id="@+id/episodesStarted"
layout="@layout/feed_statistics_card" />
</TableRow>
<include
android:id="@+id/spaceDownloaded"
layout="@layout/feed_statistics_card" />
<TableRow>
</LinearLayout>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/statistics_time_played" />
<LinearLayout
android:id="@+id/secondRowContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="horizontal"
tools:visibility="visible">
<TextView
android:id="@+id/timePlayedLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="@string/wait_icon"
tools:text="0 min" />
<include
android:id="@+id/episodesTotal"
layout="@layout/feed_statistics_card" />
</TableRow>
<include
android:id="@+id/durationTotal"
layout="@layout/feed_statistics_card" />
<TableRow
android:tag="detailed">
<include
android:id="@+id/episodesDownloaded"
layout="@layout/feed_statistics_card" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/statistics_total_duration" />
</LinearLayout>
<TextView
android:id="@+id/totalDurationLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="@string/wait_icon"
tools:text="0 min" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
</TableRow>
<include
android:id="@+id/expectedNextEpisode"
layout="@layout/feed_statistics_card" />
<TableRow>
<include
android:id="@+id/episodeSchedule"
layout="@layout/feed_statistics_card" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/statistics_episodes_on_device" />
</LinearLayout>
<TextView
android:id="@+id/onDeviceLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="@string/wait_icon"
tools:text="0" />
</TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/statistics_space_used" />
<TextView
android:id="@+id/spaceUsedLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:text="@string/wait_icon"
tools:text="0 MB" />
</TableRow>
<TableRow>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/statistics_expected_next_episode" />
<TextView
android:id="@+id/expectedNextEpisodeLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:lines="2"
android:text="@string/wait_icon"
tools:text="Jan 1st (weekly)" />
</TableRow>
</TableLayout>
</LinearLayout>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_margin="4dp"
android:padding="8dp"
android:background="?attr/colorSurfaceContainer"
android:orientation="vertical">
<TextView
android:id="@+id/mainLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/wait_icon"
style="@style/TextAppearance.Material3.TitleSmall"
tools:text="1 Episode" />
<TextView
android:id="@+id/subtitleLabel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
style="@style/TextAppearance.Material3.BodySmall"
tools:text="on this device" />
</LinearLayout>