mirror of
https://github.com/AntennaPod/AntennaPod.git
synced 2025-12-01 12:31:45 +00:00
Open podcast or episode from download log details (#7867)
This commit is contained in:
@ -0,0 +1,126 @@
|
||||
package de.test.antennapod.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import androidx.test.espresso.intent.rule.IntentsTestRule;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.activity.MainActivity;
|
||||
import de.danoeh.antennapod.model.download.DownloadError;
|
||||
import de.danoeh.antennapod.model.download.DownloadResult;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.model.feed.FeedItem;
|
||||
import de.danoeh.antennapod.model.feed.FeedMedia;
|
||||
import de.danoeh.antennapod.storage.database.DBWriter;
|
||||
import de.danoeh.antennapod.storage.database.FeedDatabaseWriter;
|
||||
import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
|
||||
import de.danoeh.antennapod.ui.screen.download.CompletedDownloadsFragment;
|
||||
import de.test.antennapod.EspressoTestUtils;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import static androidx.test.espresso.Espresso.onView;
|
||||
import static androidx.test.espresso.action.ViewActions.click;
|
||||
import static androidx.test.espresso.assertion.ViewAssertions.matches;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.isRoot;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
|
||||
import static androidx.test.espresso.matcher.ViewMatchers.withText;
|
||||
import static de.test.antennapod.EspressoTestUtils.waitForView;
|
||||
import static de.test.antennapod.EspressoTestUtils.waitForViewGlobally;
|
||||
import static org.hamcrest.CoreMatchers.not;
|
||||
import static org.hamcrest.Matchers.allOf;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class DownloadLogTest {
|
||||
@Rule
|
||||
public IntentsTestRule<MainActivity> activityRule = new IntentsTestRule<>(MainActivity.class, false, false);
|
||||
private Context context;
|
||||
private Intent completedDownloadsIntent;
|
||||
private Feed feed;
|
||||
private FeedMedia media;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
EspressoTestUtils.clearPreferences();
|
||||
EspressoTestUtils.clearDatabase();
|
||||
context = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
completedDownloadsIntent = new Intent(context, MainActivity.class);
|
||||
completedDownloadsIntent.putExtra(MainActivityStarter.EXTRA_FRAGMENT_TAG, CompletedDownloadsFragment.TAG);
|
||||
|
||||
feed = new Feed(0, "last modified", "@@Feed title@@", "link", "description", "payment link",
|
||||
"@author@", "language", "type", "feedIdentifier", "http://localhost/cover.png",
|
||||
"/sdcard/abc", "http://localhost/feed.xml", 0);
|
||||
FeedItem item = new FeedItem(0, "title", "identifier", "link", new Date(), FeedItem.UNPLAYED, feed);
|
||||
media = new FeedMedia(item, "http://localhost/media.mp3", 10000, "mime type");
|
||||
item.setMedia(media);
|
||||
feed.setItems(Collections.singletonList(item));
|
||||
feed = FeedDatabaseWriter.updateFeed(context, feed, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingSubscribedFeed() {
|
||||
DownloadResult result = new DownloadResult("@@Title@@", feed.getId(),
|
||||
Feed.FEEDFILETYPE_FEED, false, DownloadError.ERROR_IO_ERROR, "@@reason@@");
|
||||
openDialog(result);
|
||||
// Open feed
|
||||
onView(withText(R.string.download_log_open_feed)).perform(click());
|
||||
waitForViewGlobally(withText(feed.getAuthor()), 2000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingNonSubscribedFeed() throws InterruptedException, ExecutionException {
|
||||
DBWriter.setFeedState(context, feed, Feed.STATE_NOT_SUBSCRIBED).get();
|
||||
DownloadResult result = new DownloadResult("@@Title@@", feed.getId(),
|
||||
Feed.FEEDFILETYPE_FEED, false, DownloadError.ERROR_IO_ERROR, "@@reason@@");
|
||||
openDialog(result);
|
||||
// Opens online feed view
|
||||
onView(withText(R.string.download_log_open_feed)).perform(click());
|
||||
waitForViewGlobally(withText(feed.getAuthor()), 2000);
|
||||
onView(isRoot()).perform(waitForView(allOf(withText(R.string.subscribe_label), isDisplayed()), 2000));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonExistingFeed() {
|
||||
DownloadResult result = new DownloadResult("@@Title@@", feed.getId() + 1,
|
||||
Feed.FEEDFILETYPE_FEED, false, DownloadError.ERROR_IO_ERROR, "@@reason@@");
|
||||
openDialog(result);
|
||||
// Does not have button
|
||||
onView(withText(R.string.download_log_open_feed)).check(matches(not(isDisplayed())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingMedia() {
|
||||
DownloadResult result = new DownloadResult("@@Title@@", media.getId(),
|
||||
FeedMedia.FEEDFILETYPE_FEEDMEDIA, false, DownloadError.ERROR_IO_ERROR, "@@reason@@");
|
||||
openDialog(result);
|
||||
// Opens feed
|
||||
onView(withText(R.string.download_log_open_feed)).perform(click());
|
||||
waitForViewGlobally(withText(feed.getAuthor()), 2000);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNonExistingMedia() {
|
||||
DownloadResult result = new DownloadResult("@@Title@@", media.getId() + 1,
|
||||
FeedMedia.FEEDFILETYPE_FEEDMEDIA, false, DownloadError.ERROR_IO_ERROR, "@@reason@@");
|
||||
openDialog(result);
|
||||
// Does not have button
|
||||
onView(withText(R.string.download_log_open_feed)).check(matches(not(isDisplayed())));
|
||||
}
|
||||
|
||||
void openDialog(DownloadResult result) {
|
||||
DBWriter.addDownloadStatus(result);
|
||||
activityRule.launchActivity(completedDownloadsIntent);
|
||||
onView(withContentDescription(R.string.downloads_log_label)).perform(click());
|
||||
onView(isRoot()).perform(waitForView(allOf(withText(result.getTitle()), isDisplayed()), 1000));
|
||||
onView(withText(result.getTitle())).perform(click());
|
||||
onView(isRoot()).perform(waitForView(allOf(withText(result.getReasonDetailed()), isDisplayed()), 1000));
|
||||
}
|
||||
}
|
||||
@ -707,7 +707,7 @@ public class MainActivity extends CastEnabledActivity {
|
||||
drawerLayout.open();
|
||||
}
|
||||
if (intent.getBooleanExtra(MainActivityStarter.EXTRA_OPEN_DOWNLOAD_LOGS, false)) {
|
||||
new DownloadLogFragment().show(getSupportFragmentManager(), null);
|
||||
new DownloadLogFragment().show(getSupportFragmentManager(), DownloadLogFragment.TAG);
|
||||
}
|
||||
if (intent.getBooleanExtra(EXTRA_REFRESH_ON_START, false)) {
|
||||
FeedUpdateManager.getInstance().runOnceOrAsk(this);
|
||||
|
||||
@ -131,7 +131,7 @@ public class CompletedDownloadsFragment extends Fragment
|
||||
return true;
|
||||
});
|
||||
if (getArguments() != null && getArguments().getBoolean(ARG_SHOW_LOGS, false)) {
|
||||
new DownloadLogFragment().show(getChildFragmentManager(), null);
|
||||
new DownloadLogFragment().show(getChildFragmentManager(), DownloadLogFragment.TAG);
|
||||
}
|
||||
|
||||
addEmptyView();
|
||||
@ -176,7 +176,7 @@ public class CompletedDownloadsFragment extends Fragment
|
||||
FeedUpdateManager.getInstance().runOnceOrAsk(requireContext());
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_download_logs) {
|
||||
new DownloadLogFragment().show(getChildFragmentManager(), null);
|
||||
new DownloadLogFragment().show(getChildFragmentManager(), DownloadLogFragment.TAG);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.action_search) {
|
||||
((MainActivity) getActivity()).loadChildFragment(SearchFragment.newInstance());
|
||||
|
||||
@ -1,71 +1,169 @@
|
||||
package de.danoeh.antennapod.ui.screen.download;
|
||||
|
||||
import android.content.ClipData;
|
||||
import android.content.ClipboardManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.Spannable;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.widget.TextView;
|
||||
import android.app.Dialog;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.databinding.DownloadLogDetailsDialogBinding;
|
||||
import de.danoeh.antennapod.model.download.DownloadResult;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.event.MessageEvent;
|
||||
import de.danoeh.antennapod.model.feed.Feed;
|
||||
import de.danoeh.antennapod.model.feed.FeedMedia;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.ui.appstartintent.MainActivityStarter;
|
||||
import de.danoeh.antennapod.ui.appstartintent.OnlineFeedviewActivityStarter;
|
||||
import de.danoeh.antennapod.ui.common.ClipboardUtils;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Single;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
|
||||
public class DownloadLogDetailsDialog extends MaterialAlertDialogBuilder {
|
||||
/**
|
||||
* Shows a dialog with Feed title (and FeedItem title if possible).
|
||||
* Can show a button to jump to the feed details view.
|
||||
*/
|
||||
public class DownloadLogDetailsDialog extends DialogFragment {
|
||||
public static final String TAG = "DownloadLogDetails";
|
||||
private static final String EXTRA_IS_JUMP_TO_FEED = "isJumpToFeed";
|
||||
private static final String EXTRA_DOWNLOAD_RESULT = "downloadResult";
|
||||
private DownloadLogDetailsDialogBinding viewBinding;
|
||||
private Disposable disposable;
|
||||
private boolean isJumpToFeed;
|
||||
private DownloadResult downloadResult;
|
||||
private Feed feed = null;
|
||||
private String podcastName = null;
|
||||
private String episodeName = null;
|
||||
private String url = "unknown";
|
||||
private String clipboardContent = "";
|
||||
|
||||
public DownloadLogDetailsDialog(@NonNull Context context, DownloadResult status) {
|
||||
super(context);
|
||||
|
||||
String url = "unknown";
|
||||
if (status.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
|
||||
FeedMedia media = DBReader.getFeedMedia(status.getFeedfileId());
|
||||
if (media != null) {
|
||||
url = media.getDownloadUrl();
|
||||
}
|
||||
} else if (status.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
|
||||
Feed feed = DBReader.getFeed(status.getFeedfileId(), false, 0, 0);
|
||||
if (feed != null) {
|
||||
url = feed.getDownloadUrl();
|
||||
}
|
||||
}
|
||||
|
||||
String message = context.getString(R.string.download_successful);
|
||||
if (!status.isSuccessful()) {
|
||||
message = status.getReasonDetailed();
|
||||
}
|
||||
|
||||
String humanReadableReason = context.getString(DownloadErrorLabel.from(status.getReason()));
|
||||
SpannableString errorMessage = new SpannableString(context.getString(R.string.download_log_details_message,
|
||||
humanReadableReason, message, url));
|
||||
errorMessage.setSpan(new ForegroundColorSpan(0x88888888),
|
||||
humanReadableReason.length(), errorMessage.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
setTitle(R.string.download_error_details);
|
||||
setMessage(errorMessage);
|
||||
setPositiveButton(android.R.string.ok, null);
|
||||
setNeutralButton(R.string.copy_to_clipboard, (dialog, which) -> {
|
||||
ClipboardManager clipboard = (ClipboardManager) getContext()
|
||||
.getSystemService(Context.CLIPBOARD_SERVICE);
|
||||
ClipData clip = ClipData.newPlainText(context.getString(R.string.download_error_details), errorMessage);
|
||||
clipboard.setPrimaryClip(clip);
|
||||
if (Build.VERSION.SDK_INT < 32) {
|
||||
EventBus.getDefault().post(new MessageEvent(context.getString(R.string.copied_to_clipboard)));
|
||||
}
|
||||
});
|
||||
public static DownloadLogDetailsDialog newInstance(DownloadResult downloadResult, boolean isJumpToFeed) {
|
||||
DownloadLogDetailsDialog dialog = new DownloadLogDetailsDialog();
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(EXTRA_DOWNLOAD_RESULT, downloadResult);
|
||||
args.putBoolean(EXTRA_IS_JUMP_TO_FEED, isJumpToFeed);
|
||||
dialog.setArguments(args);
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AlertDialog show() {
|
||||
AlertDialog dialog = super.show();
|
||||
((TextView) dialog.findViewById(android.R.id.message)).setTextIsSelectable(true);
|
||||
return dialog;
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
downloadResult = (DownloadResult) getArguments().getSerializable(EXTRA_DOWNLOAD_RESULT);
|
||||
isJumpToFeed = getArguments().getBoolean(EXTRA_IS_JUMP_TO_FEED, true);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||
MaterialAlertDialogBuilder dialog = new MaterialAlertDialogBuilder(getContext());
|
||||
dialog.setTitle(R.string.download_error_details);
|
||||
dialog.setPositiveButton(android.R.string.ok, null);
|
||||
dialog.setNeutralButton(R.string.copy_to_clipboard, (copyDialog, which) ->
|
||||
ClipboardUtils.copyText(viewBinding.getRoot(), R.string.download_error_details, clipboardContent));
|
||||
|
||||
viewBinding = DownloadLogDetailsDialogBinding.inflate(getLayoutInflater());
|
||||
dialog.setView(viewBinding.getRoot());
|
||||
|
||||
viewBinding.goToPodcastButton.setVisibility(View.GONE);
|
||||
viewBinding.goToPodcastButton.setOnClickListener(v -> {
|
||||
goToFeed();
|
||||
dismiss();
|
||||
Fragment downloadLog = getParentFragmentManager().findFragmentByTag(DownloadLogFragment.TAG);
|
||||
if (downloadLog instanceof DownloadLogFragment) {
|
||||
((DownloadLogFragment) downloadLog).dismiss();
|
||||
}
|
||||
});
|
||||
viewBinding.fileUrlLabel.setOnClickListener(v ->
|
||||
ClipboardUtils.copyText(viewBinding.fileUrlLabel, R.string.download_log_details_file_url_title));
|
||||
viewBinding.technicalReasonLabel.setOnClickListener(v ->
|
||||
ClipboardUtils.copyText(viewBinding.technicalReasonLabel,
|
||||
R.string.download_log_details_technical_reason_title));
|
||||
|
||||
loadData();
|
||||
return dialog.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
if (disposable != null) {
|
||||
disposable.dispose();
|
||||
}
|
||||
disposable = Single.create(emitter -> {
|
||||
if (downloadResult.getFeedfileType() == FeedMedia.FEEDFILETYPE_FEEDMEDIA) {
|
||||
FeedMedia media = DBReader.getFeedMedia(downloadResult.getFeedfileId());
|
||||
if (media != null) {
|
||||
if (media.getItem() != null && media.getItem().getFeed() != null) {
|
||||
feed = media.getItem().getFeed();
|
||||
podcastName = feed.getTitle();
|
||||
}
|
||||
episodeName = media.getEpisodeTitle();
|
||||
url = media.getDownloadUrl();
|
||||
} else {
|
||||
episodeName = downloadResult.getTitle();
|
||||
}
|
||||
} else if (downloadResult.getFeedfileType() == Feed.FEEDFILETYPE_FEED) {
|
||||
feed = DBReader.getFeed(downloadResult.getFeedfileId(), false, 0, 0);
|
||||
if (feed != null) {
|
||||
podcastName = feed.getTitle();
|
||||
url = feed.getDownloadUrl();
|
||||
} else {
|
||||
podcastName = downloadResult.getTitle();
|
||||
}
|
||||
}
|
||||
emitter.onSuccess(true);
|
||||
})
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(obj -> updateUi(),
|
||||
error -> Log.e(TAG, Log.getStackTraceString(error)));
|
||||
}
|
||||
|
||||
private void updateUi() {
|
||||
String message = getString(R.string.download_successful);
|
||||
if (!downloadResult.isSuccessful()) {
|
||||
message = downloadResult.getReasonDetailed();
|
||||
}
|
||||
viewBinding.goToPodcastButton.setVisibility((isJumpToFeed && feed != null) ? View.VISIBLE : View.GONE);
|
||||
viewBinding.podcastNameLabel.setText(podcastName);
|
||||
viewBinding.podcastContainer.setVisibility(podcastName == null ? View.GONE : View.VISIBLE);
|
||||
viewBinding.episodeNameLabel.setText(episodeName);
|
||||
viewBinding.episodeContainer.setVisibility(episodeName == null ? View.GONE : View.VISIBLE);
|
||||
|
||||
final String humanReadableReason = getString(DownloadErrorLabel.from(downloadResult.getReason()));
|
||||
viewBinding.humanReadableReasonLabel.setText(humanReadableReason);
|
||||
viewBinding.technicalReasonLabel.setText(message);
|
||||
viewBinding.fileUrlLabel.setText(url);
|
||||
|
||||
final String humanReadableReasonTitle = getString(R.string.download_log_details_human_readable_reason_title);
|
||||
final String technicalReasonTitle = getString(R.string.download_log_details_technical_reason_title);
|
||||
final String urlTitle = getString(R.string.download_log_details_file_url_title);
|
||||
clipboardContent = String.format("%s: \n%s \n\n%s: \n%s \n\n%s: \n%s",
|
||||
humanReadableReasonTitle, humanReadableReason, technicalReasonTitle, message, urlTitle, url);
|
||||
}
|
||||
|
||||
void goToFeed() {
|
||||
if (feed == null) {
|
||||
return;
|
||||
}
|
||||
Intent intent;
|
||||
if (feed.getState() == Feed.STATE_SUBSCRIBED) {
|
||||
intent = new MainActivityStarter(getContext()).withOpenFeed(feed.getId()).getIntent();
|
||||
} else {
|
||||
intent = new OnlineFeedviewActivityStarter(getContext(), feed.getDownloadUrl()).getIntent();
|
||||
}
|
||||
getContext().startActivity(intent);
|
||||
}
|
||||
}
|
||||
@ -12,14 +12,14 @@ import androidx.annotation.Nullable;
|
||||
import com.google.android.material.appbar.MaterialToolbar;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
import de.danoeh.antennapod.R;
|
||||
import de.danoeh.antennapod.databinding.DownloadLogFragmentBinding;
|
||||
import de.danoeh.antennapod.event.DownloadLogEvent;
|
||||
import de.danoeh.antennapod.model.download.DownloadResult;
|
||||
import de.danoeh.antennapod.storage.database.DBReader;
|
||||
import de.danoeh.antennapod.storage.database.DBWriter;
|
||||
import de.danoeh.antennapod.databinding.DownloadLogFragmentBinding;
|
||||
import de.danoeh.antennapod.model.download.DownloadResult;
|
||||
import de.danoeh.antennapod.ui.view.EmptyViewHandler;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.rxjava3.core.Observable;
|
||||
import io.reactivex.rxjava3.disposables.Disposable;
|
||||
import io.reactivex.rxjava3.schedulers.Schedulers;
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
@ -33,7 +33,7 @@ import java.util.List;
|
||||
*/
|
||||
public class DownloadLogFragment extends BottomSheetDialogFragment
|
||||
implements AdapterView.OnItemClickListener, MaterialToolbar.OnMenuItemClickListener {
|
||||
private static final String TAG = "DownloadLogFragment";
|
||||
public static final String TAG = "DownloadLogFragment";
|
||||
|
||||
private List<DownloadResult> downloadLog = new ArrayList<>();
|
||||
private DownloadLogAdapter adapter;
|
||||
@ -86,7 +86,8 @@ public class DownloadLogFragment extends BottomSheetDialogFragment
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final DownloadResult item = adapter.getItem(position);
|
||||
if (item != null) {
|
||||
new DownloadLogDetailsDialog(getContext(), item).show();
|
||||
DownloadLogDetailsDialog.newInstance(item, true)
|
||||
.show(getParentFragmentManager(), DownloadLogDetailsDialog.TAG);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -624,9 +624,10 @@ public class FeedItemlistFragment extends Fragment implements AdapterView.OnItem
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
downloadStatus -> new DownloadLogDetailsDialog(getContext(), downloadStatus).show(),
|
||||
downloadStatus -> DownloadLogDetailsDialog.newInstance(downloadStatus, false)
|
||||
.show(getChildFragmentManager(), DownloadLogDetailsDialog.TAG),
|
||||
error -> error.printStackTrace(),
|
||||
() -> new DownloadLogFragment().show(getChildFragmentManager(), null));
|
||||
() -> new DownloadLogFragment().show(getChildFragmentManager(), DownloadLogFragment.TAG));
|
||||
}
|
||||
|
||||
private void showFeedInfo() {
|
||||
|
||||
154
app/src/main/res/layout/download_log_details_dialog.xml
Normal file
154
app/src/main/res/layout/download_log_details_dialog.xml
Normal file
@ -0,0 +1,154 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
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:orientation="vertical"
|
||||
android:padding="?dialogPreferredPadding">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Podcast header, podcast title, button to jump to podcast -->
|
||||
<LinearLayout
|
||||
android:id="@+id/podcastContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_weight="1">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/feed"
|
||||
android:layout_marginEnd="4dp"
|
||||
style="@style/TextAppearance.Material3.TitleMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/podcastNameLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="end"
|
||||
tools:text="Podcast name" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/goToPodcastButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="0dp"
|
||||
android:text="@string/download_log_open_feed"
|
||||
android:layout_marginStart="8dp"
|
||||
style="@style/Widget.Material3.Button.TextButton" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Episode header, episode title -->
|
||||
<LinearLayout
|
||||
android:id="@+id/episodeContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/episode"
|
||||
android:layout_marginEnd="4dp"
|
||||
style="@style/TextAppearance.Material3.TitleMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/episodeNameLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="middle"
|
||||
tools:text="Episode Name" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Human readable reason for the message/error -->
|
||||
<LinearLayout
|
||||
android:id="@+id/humanReadableReasonContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/download_log_details_human_readable_reason_title"
|
||||
android:layout_marginEnd="4dp"
|
||||
style="@style/TextAppearance.Material3.TitleMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/humanReadableReasonLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="@string/download_error_not_found" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Technical details/reason -->
|
||||
<LinearLayout
|
||||
android:id="@+id/technicalReasonContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/download_log_details_technical_reason_title"
|
||||
android:layout_marginEnd="4dp"
|
||||
style="@style/TextAppearance.Material3.TitleMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/technicalReasonLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
tools:text="Http error 404" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- File URL -->
|
||||
<LinearLayout
|
||||
android:id="@+id/fileUrlContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/download_log_details_file_url_title"
|
||||
android:layout_marginEnd="4dp"
|
||||
style="@style/TextAppearance.Material3.TitleMedium" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fileUrlLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
tools:text="http://example.com/feed.xml" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
@ -2,12 +2,15 @@ package de.danoeh.antennapod.model.download;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Contains status attributes for one download
|
||||
*/
|
||||
public class DownloadResult {
|
||||
public class DownloadResult implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* Downloaders should use this constant for the size attribute if necessary
|
||||
* so that the listadapters etc. can react properly.
|
||||
|
||||
@ -304,6 +304,10 @@
|
||||
<string name="download_running">Download running</string>
|
||||
<string name="download_error_details">Details</string>
|
||||
<string name="download_log_details_message">%1$s \n\nTechnical reason: \n%2$s \n\nFile URL:\n%3$s</string>
|
||||
<string name="download_log_details_human_readable_reason_title">Status</string>
|
||||
<string name="download_log_details_technical_reason_title">Technical details</string>
|
||||
<string name="download_log_details_file_url_title">File URL</string>
|
||||
<string name="download_log_open_feed">Open</string>
|
||||
<string name="download_error_retrying">Download of \"%1$s\" failed. Will be retried later.</string>
|
||||
<string name="download_error_not_retrying">Download of \"%1$s\" failed.</string>
|
||||
<string name="download_error_tap_for_details">Tap to view details.</string>
|
||||
@ -387,7 +391,9 @@
|
||||
<string name="keep_sorted">Keep sorted</string>
|
||||
<string name="date">Date</string>
|
||||
<string name="duration">Duration</string>
|
||||
<string name="episode">Episode</string>
|
||||
<string name="episode_title">Episode title</string>
|
||||
<string name="feed">Podcast</string>
|
||||
<string name="feed_title">Podcast title</string>
|
||||
<string name="random">Random</string>
|
||||
<string name="smart_shuffle">Smart shuffle</string>
|
||||
|
||||
Reference in New Issue
Block a user