Add report/solve-recaptcha button in error panel
It will be shown even when nothing could be loaded not due to a network error, and the user can choose to ignore or report it. Also improve error reporting arguments Also completely refactor error activity Also improve some code here and there
This commit is contained in:
parent
bb398189d6
commit
0ea6b4928c
59 changed files with 886 additions and 1262 deletions
|
|
@ -202,19 +202,6 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showError(final String message, final boolean showRetryButton) {
|
||||
super.showError(message, showRetryButton);
|
||||
showListFooter(false);
|
||||
|
||||
if (itemsList != null) {
|
||||
animate(itemsList, false, 200);
|
||||
}
|
||||
if (headerRootBinding != null) {
|
||||
animate(headerRootBinding.getRoot(), false, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showEmptyState() {
|
||||
super.showEmptyState();
|
||||
|
|
@ -249,9 +236,18 @@ public abstract class BaseLocalListFragment<I, N> extends BaseStateFragment<I>
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean onError(final Throwable exception) {
|
||||
public void handleError() {
|
||||
super.handleError();
|
||||
resetFragment();
|
||||
return super.onError(exception);
|
||||
|
||||
showListFooter(false);
|
||||
|
||||
if (itemsList != null) {
|
||||
animate(itemsList, false, 200);
|
||||
}
|
||||
if (headerRootBinding != null) {
|
||||
animate(headerRootBinding.getRoot(), false, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import org.schabi.newpipe.database.LocalItem;
|
|||
import org.schabi.newpipe.database.playlist.PlaylistLocalItem;
|
||||
import org.schabi.newpipe.database.playlist.PlaylistMetadataEntry;
|
||||
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.local.BaseLocalListFragment;
|
||||
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
|
||||
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
|
||||
|
|
@ -206,7 +207,8 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||
|
||||
@Override
|
||||
public void onError(final Throwable exception) {
|
||||
BookmarkFragment.this.onError(exception);
|
||||
showError(new ErrorInfo(exception,
|
||||
UserAction.REQUESTED_BOOKMARK, "Loading playlists"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -237,17 +239,6 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||
// Fragment Error Handling
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected boolean onError(final Throwable exception) {
|
||||
if (super.onError(exception)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
onUnrecoverableError(exception, UserAction.SOMETHING_ELSE,
|
||||
"none", "Bookmark", R.string.general_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resetFragment() {
|
||||
super.resetFragment();
|
||||
|
|
@ -295,8 +286,10 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||
.setPositiveButton(R.string.delete, (dialog, i) ->
|
||||
disposables.add(deleteReactor
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(ignored -> { /*Do nothing on success*/ }, this::onError))
|
||||
)
|
||||
.subscribe(ignored -> { /*Do nothing on success*/ }, throwable ->
|
||||
showError(new ErrorInfo(throwable,
|
||||
UserAction.REQUESTED_BOOKMARK,
|
||||
"Deleting playlist")))))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show();
|
||||
}
|
||||
|
|
@ -314,7 +307,10 @@ public final class BookmarkFragment extends BaseLocalListFragment<List<PlaylistL
|
|||
localPlaylistManager.renamePlaylist(id, name);
|
||||
final Disposable disposable = localPlaylistManager.renamePlaylist(id, name)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(longs -> { /*Do nothing on success*/ }, this::onError);
|
||||
.subscribe(longs -> { /*Do nothing on success*/ }, throwable -> showError(
|
||||
new ErrorInfo(throwable,
|
||||
UserAction.REQUESTED_BOOKMARK,
|
||||
"Changing playlist name")));
|
||||
disposables.add(disposable);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ import icepick.State
|
|||
import org.schabi.newpipe.R
|
||||
import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
||||
import org.schabi.newpipe.databinding.FragmentFeedBinding
|
||||
import org.schabi.newpipe.error.ErrorInfo
|
||||
import org.schabi.newpipe.error.UserAction
|
||||
import org.schabi.newpipe.fragments.list.BaseListFragment
|
||||
import org.schabi.newpipe.ktx.animate
|
||||
|
|
@ -48,7 +49,6 @@ import java.util.Calendar
|
|||
class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
||||
private var _feedBinding: FragmentFeedBinding? = null
|
||||
private val feedBinding get() = _feedBinding!!
|
||||
private val errorBinding get() = _feedBinding!!.errorPanel
|
||||
|
||||
private lateinit var viewModel: FeedViewModel
|
||||
@State
|
||||
|
|
@ -171,50 +171,24 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
override fun showLoading() {
|
||||
super.showLoading()
|
||||
feedBinding.refreshRootView.animate(false, 0)
|
||||
feedBinding.itemsList.animate(false, 0)
|
||||
|
||||
feedBinding.loadingProgressBar.animate(true, 200)
|
||||
feedBinding.loadingProgressText.animate(true, 200)
|
||||
|
||||
feedBinding.emptyStateView.root.animate(false, 0)
|
||||
errorBinding.root.animate(false, 0)
|
||||
}
|
||||
|
||||
override fun hideLoading() {
|
||||
super.hideLoading()
|
||||
feedBinding.refreshRootView.animate(true, 200)
|
||||
feedBinding.itemsList.animate(true, 300)
|
||||
|
||||
feedBinding.loadingProgressBar.animate(false, 0)
|
||||
feedBinding.loadingProgressText.animate(false, 0)
|
||||
|
||||
feedBinding.emptyStateView.root.animate(false, 0)
|
||||
errorBinding.root.animate(false, 0)
|
||||
feedBinding.swiperefresh.isRefreshing = false
|
||||
}
|
||||
|
||||
override fun showEmptyState() {
|
||||
super.showEmptyState()
|
||||
feedBinding.refreshRootView.animate(true, 200)
|
||||
feedBinding.itemsList.animate(false, 0)
|
||||
|
||||
feedBinding.loadingProgressBar.animate(false, 0)
|
||||
feedBinding.loadingProgressText.animate(false, 0)
|
||||
|
||||
feedBinding.emptyStateView.root.animate(true, 800)
|
||||
errorBinding.root.animate(false, 0)
|
||||
}
|
||||
|
||||
override fun showError(message: String, showRetryButton: Boolean) {
|
||||
infoListAdapter.clearStreamItemList()
|
||||
feedBinding.refreshRootView.animate(false, 120)
|
||||
feedBinding.itemsList.animate(false, 120)
|
||||
|
||||
feedBinding.loadingProgressBar.animate(false, 120)
|
||||
feedBinding.loadingProgressText.animate(false, 120)
|
||||
|
||||
errorBinding.errorMessageView.text = message
|
||||
errorBinding.errorButtonRetry.animate(showRetryButton, if (showRetryButton) 600 else 0)
|
||||
errorBinding.root.animate(true, 300)
|
||||
}
|
||||
|
||||
override fun handleResult(result: FeedState) {
|
||||
|
|
@ -227,6 +201,14 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
updateRefreshViewState()
|
||||
}
|
||||
|
||||
override fun handleError() {
|
||||
super.handleError()
|
||||
infoListAdapter.clearStreamItemList()
|
||||
feedBinding.refreshRootView.animate(false, 200)
|
||||
feedBinding.itemsList.animate(false, 200)
|
||||
feedBinding.loadingProgressText.animate(false, 200)
|
||||
}
|
||||
|
||||
private fun handleProgressState(progressState: FeedState.ProgressState) {
|
||||
showLoading()
|
||||
|
||||
|
|
@ -266,13 +248,6 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
)
|
||||
}
|
||||
|
||||
if (loadedState.itemsErrors.isNotEmpty()) {
|
||||
showSnackBarError(
|
||||
loadedState.itemsErrors, UserAction.REQUESTED_FEED,
|
||||
"none", "Loading feed", R.string.general_error
|
||||
)
|
||||
}
|
||||
|
||||
if (loadedState.items.isEmpty()) {
|
||||
showEmptyState()
|
||||
} else {
|
||||
|
|
@ -281,12 +256,13 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
}
|
||||
|
||||
private fun handleErrorState(errorState: FeedState.ErrorState): Boolean {
|
||||
hideLoading()
|
||||
errorState.error?.let {
|
||||
onError(errorState.error)
|
||||
return true
|
||||
return if (errorState.error == null) {
|
||||
hideLoading()
|
||||
false
|
||||
} else {
|
||||
showError(ErrorInfo(errorState.error, UserAction.REQUESTED_FEED, "Loading feed"))
|
||||
true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun updateRelativeTimeViews() {
|
||||
|
|
@ -320,18 +296,6 @@ class FeedFragment : BaseListFragment<FeedState, Unit>() {
|
|||
listState = null
|
||||
}
|
||||
|
||||
override fun onError(exception: Throwable): Boolean {
|
||||
if (super.onError(exception)) return true
|
||||
|
||||
if (useAsFrontPage) {
|
||||
showSnackBarError(exception, UserAction.REQUESTED_FEED, "none", "Loading Feed", 0)
|
||||
return true
|
||||
}
|
||||
|
||||
onUnrecoverableError(exception, UserAction.REQUESTED_FEED, "none", "Loading Feed", 0)
|
||||
return true
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_GROUP_ID = "ARG_GROUP_ID"
|
||||
const val KEY_GROUP_NAME = "ARG_GROUP_NAME"
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ import android.widget.Toast;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.viewbinding.ViewBinding;
|
||||
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
|
@ -27,6 +26,8 @@ import org.schabi.newpipe.database.stream.StreamStatisticsEntry;
|
|||
import org.schabi.newpipe.database.stream.model.StreamEntity;
|
||||
import org.schabi.newpipe.databinding.PlaylistControlBinding;
|
||||
import org.schabi.newpipe.databinding.StatisticPlaylistControlBinding;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.error.UserAction;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
import org.schabi.newpipe.info_list.InfoItemDialog;
|
||||
|
|
@ -34,10 +35,7 @@ import org.schabi.newpipe.local.BaseLocalListFragment;
|
|||
import org.schabi.newpipe.player.helper.PlayerHolder;
|
||||
import org.schabi.newpipe.player.playqueue.PlayQueue;
|
||||
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
|
||||
import org.schabi.newpipe.error.ErrorActivity;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.error.UserAction;
|
||||
import org.schabi.newpipe.settings.SettingsActivity;
|
||||
import org.schabi.newpipe.settings.HistorySettingsFragment;
|
||||
import org.schabi.newpipe.util.KoreUtil;
|
||||
import org.schabi.newpipe.util.NavigationHelper;
|
||||
import org.schabi.newpipe.util.OnClickGesture;
|
||||
|
|
@ -49,6 +47,7 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import icepick.State;
|
||||
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
|
||||
|
|
@ -163,48 +162,11 @@ public class StatisticsPlaylistFragment
|
|||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_history_clear:
|
||||
new AlertDialog.Builder(activity)
|
||||
.setTitle(R.string.delete_view_history_alert)
|
||||
.setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
|
||||
.setPositiveButton(R.string.delete, ((dialog, which) -> {
|
||||
final Disposable onDelete = recordManager.deleteWholeStreamHistory()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
howManyDeleted -> Toast.makeText(getContext(),
|
||||
R.string.watch_history_deleted,
|
||||
Toast.LENGTH_SHORT).show(),
|
||||
throwable -> ErrorActivity.reportError(getContext(),
|
||||
throwable,
|
||||
SettingsActivity.class, null,
|
||||
ErrorInfo.make(
|
||||
UserAction.DELETE_FROM_HISTORY,
|
||||
"none",
|
||||
"Delete view history",
|
||||
R.string.general_error)));
|
||||
|
||||
final Disposable onClearOrphans = recordManager.removeOrphanedRecords()
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
howManyDeleted -> {
|
||||
},
|
||||
throwable -> ErrorActivity.reportError(getContext(),
|
||||
throwable,
|
||||
SettingsActivity.class, null,
|
||||
ErrorInfo.make(
|
||||
UserAction.DELETE_FROM_HISTORY,
|
||||
"none",
|
||||
"Delete search history",
|
||||
R.string.general_error)));
|
||||
disposables.add(onClearOrphans);
|
||||
disposables.add(onDelete);
|
||||
}))
|
||||
.create()
|
||||
.show();
|
||||
break;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
if (item.getItemId() == R.id.action_history_clear) {
|
||||
HistorySettingsFragment
|
||||
.openDeleteWatchHistoryDialog(requireContext(), recordManager, disposables);
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -228,7 +190,7 @@ public class StatisticsPlaylistFragment
|
|||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
itemsListState = itemsList.getLayoutManager().onSaveInstanceState();
|
||||
itemsListState = Objects.requireNonNull(itemsList.getLayoutManager()).onSaveInstanceState();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -287,7 +249,8 @@ public class StatisticsPlaylistFragment
|
|||
|
||||
@Override
|
||||
public void onError(final Throwable exception) {
|
||||
StatisticsPlaylistFragment.this.onError(exception);
|
||||
showError(
|
||||
new ErrorInfo(exception, UserAction.SOMETHING_ELSE, "History Statistics"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -313,7 +276,7 @@ public class StatisticsPlaylistFragment
|
|||
}
|
||||
|
||||
itemListAdapter.addItems(processResult(result));
|
||||
if (itemsListState != null) {
|
||||
if (itemsListState != null && itemsList.getLayoutManager() != null) {
|
||||
itemsList.getLayoutManager().onRestoreInstanceState(itemsListState);
|
||||
itemsListState = null;
|
||||
}
|
||||
|
|
@ -341,17 +304,6 @@ public class StatisticsPlaylistFragment
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onError(final Throwable exception) {
|
||||
if (super.onError(exception)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
onUnrecoverableError(exception, UserAction.SOMETHING_ELSE,
|
||||
"none", "History Statistics", R.string.general_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Utils
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
@ -439,9 +391,8 @@ public class StatisticsPlaylistFragment
|
|||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
},
|
||||
throwable -> showSnackBarError(throwable,
|
||||
UserAction.DELETE_FROM_HISTORY, "none",
|
||||
"Deleting item failed", R.string.general_error));
|
||||
throwable -> showSnackBarError(new ErrorInfo(throwable,
|
||||
UserAction.DELETE_FROM_HISTORY, "Deleting item")));
|
||||
|
||||
disposables.add(onDelete);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import org.schabi.newpipe.database.stream.model.StreamEntity;
|
|||
import org.schabi.newpipe.database.stream.model.StreamStateEntity;
|
||||
import org.schabi.newpipe.databinding.LocalPlaylistHeaderBinding;
|
||||
import org.schabi.newpipe.databinding.PlaylistControlBinding;
|
||||
import org.schabi.newpipe.error.ErrorInfo;
|
||||
import org.schabi.newpipe.error.UserAction;
|
||||
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
|
||||
import org.schabi.newpipe.extractor.stream.StreamType;
|
||||
|
|
@ -110,7 +111,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
@Override
|
||||
public void onCreate(final Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
playlistManager = new LocalPlaylistManager(NewPipeDatabase.getInstance(getContext()));
|
||||
playlistManager = new LocalPlaylistManager(NewPipeDatabase.getInstance(requireContext()));
|
||||
debouncedSaveSignal = PublishSubject.create();
|
||||
|
||||
disposables = new CompositeDisposable();
|
||||
|
|
@ -334,7 +335,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
|
||||
@Override
|
||||
public void onError(final Throwable exception) {
|
||||
LocalPlaylistFragment.this.onError(exception);
|
||||
showError(new ErrorInfo(exception, UserAction.REQUESTED_BOOKMARK,
|
||||
"Loading local playlist"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -344,25 +346,23 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_item_remove_watched:
|
||||
if (!isRemovingWatched) {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setMessage(R.string.remove_watched_popup_warning)
|
||||
.setTitle(R.string.remove_watched_popup_title)
|
||||
.setPositiveButton(R.string.yes,
|
||||
(DialogInterface d, int id) -> removeWatchedStreams(false))
|
||||
.setNeutralButton(
|
||||
R.string.remove_watched_popup_yes_and_partially_watched_videos,
|
||||
(DialogInterface d, int id) -> removeWatchedStreams(true))
|
||||
.setNegativeButton(R.string.cancel,
|
||||
(DialogInterface d, int id) -> d.cancel())
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
if (item.getItemId() == R.id.menu_item_remove_watched) {
|
||||
if (!isRemovingWatched) {
|
||||
new AlertDialog.Builder(requireContext())
|
||||
.setMessage(R.string.remove_watched_popup_warning)
|
||||
.setTitle(R.string.remove_watched_popup_title)
|
||||
.setPositiveButton(R.string.yes,
|
||||
(DialogInterface d, int id) -> removeWatchedStreams(false))
|
||||
.setNeutralButton(
|
||||
R.string.remove_watched_popup_yes_and_partially_watched_videos,
|
||||
(DialogInterface d, int id) -> removeWatchedStreams(true))
|
||||
.setNegativeButton(R.string.cancel,
|
||||
(DialogInterface d, int id) -> d.cancel())
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -455,7 +455,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
|
||||
hideLoading();
|
||||
isRemovingWatched = false;
|
||||
}, this::onError));
|
||||
}, throwable -> showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
|
||||
"Removing watched videos, partially watched=" + removePartiallyWatched))));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -511,17 +512,6 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onError(final Throwable exception) {
|
||||
if (super.onError(exception)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
onUnrecoverableError(exception, UserAction.SOMETHING_ELSE,
|
||||
"none", "Local Playlist", R.string.general_error);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*//////////////////////////////////////////////////////////////////////////
|
||||
// Playlist Metadata/Streams Manipulation
|
||||
//////////////////////////////////////////////////////////////////////////*/
|
||||
|
|
@ -562,7 +552,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
|
||||
final Disposable disposable = playlistManager.renamePlaylist(playlistId, title)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(longs -> { /*Do nothing on success*/ }, this::onError);
|
||||
.subscribe(longs -> { /*Do nothing on success*/ }, throwable ->
|
||||
showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
|
||||
"Renaming playlist")));
|
||||
disposables.add(disposable);
|
||||
}
|
||||
|
||||
|
|
@ -583,7 +575,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
final Disposable disposable = playlistManager
|
||||
.changePlaylistThumbnail(playlistId, thumbnailUrl)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(ignore -> successToast.show(), this::onError);
|
||||
.subscribe(ignore -> successToast.show(), throwable ->
|
||||
showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
|
||||
"Changing playlist thumbnail")));
|
||||
disposables.add(disposable);
|
||||
}
|
||||
|
||||
|
|
@ -632,7 +626,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
return debouncedSaveSignal
|
||||
.debounce(SAVE_DEBOUNCE_MILLIS, TimeUnit.MILLISECONDS)
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(ignored -> saveImmediate(), this::onError);
|
||||
.subscribe(ignored -> saveImmediate(), throwable ->
|
||||
showError(new ErrorInfo(throwable, UserAction.SOMETHING_ELSE,
|
||||
"Debounced saver")));
|
||||
}
|
||||
|
||||
private void saveImmediate() {
|
||||
|
|
@ -669,7 +665,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
isModified.set(false);
|
||||
}
|
||||
},
|
||||
this::onError
|
||||
throwable -> showError(new ErrorInfo(throwable,
|
||||
UserAction.REQUESTED_BOOKMARK, "Saving playlist"))
|
||||
);
|
||||
disposables.add(disposable);
|
||||
}
|
||||
|
|
@ -683,7 +680,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
return new ItemTouchHelper.SimpleCallback(directions,
|
||||
ItemTouchHelper.ACTION_STATE_IDLE) {
|
||||
@Override
|
||||
public int interpolateOutOfBoundsScroll(final RecyclerView recyclerView,
|
||||
public int interpolateOutOfBoundsScroll(@NonNull final RecyclerView recyclerView,
|
||||
final int viewSize,
|
||||
final int viewSizeOutOfBounds,
|
||||
final int totalSize,
|
||||
|
|
@ -696,9 +693,9 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean onMove(final RecyclerView recyclerView,
|
||||
final RecyclerView.ViewHolder source,
|
||||
final RecyclerView.ViewHolder target) {
|
||||
public boolean onMove(@NonNull final RecyclerView recyclerView,
|
||||
@NonNull final RecyclerView.ViewHolder source,
|
||||
@NonNull final RecyclerView.ViewHolder target) {
|
||||
if (source.getItemViewType() != target.getItemViewType()
|
||||
|| itemListAdapter == null) {
|
||||
return false;
|
||||
|
|
@ -724,7 +721,8 @@ public class LocalPlaylistFragment extends BaseLocalListFragment<List<PlaylistSt
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) { }
|
||||
public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder,
|
||||
final int swipeDir) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import org.schabi.newpipe.database.feed.model.FeedGroupEntity
|
|||
import org.schabi.newpipe.databinding.DialogTitleBinding
|
||||
import org.schabi.newpipe.databinding.FeedItemCarouselBinding
|
||||
import org.schabi.newpipe.databinding.FragmentSubscriptionBinding
|
||||
import org.schabi.newpipe.error.ErrorInfo
|
||||
import org.schabi.newpipe.error.UserAction
|
||||
import org.schabi.newpipe.extractor.channel.ChannelInfoItem
|
||||
import org.schabi.newpipe.fragments.BaseStateFragment
|
||||
|
|
@ -288,8 +289,8 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
binding.itemsList.adapter = groupAdapter
|
||||
|
||||
viewModel = ViewModelProvider(this).get(SubscriptionViewModel::class.java)
|
||||
viewModel.stateLiveData.observe(viewLifecycleOwner, { it?.let(this::handleResult) })
|
||||
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner, { it?.let(this::handleFeedGroups) })
|
||||
viewModel.stateLiveData.observe(viewLifecycleOwner) { it?.let(this::handleResult) }
|
||||
viewModel.feedGroupsLiveData.observe(viewLifecycleOwner) { it?.let(this::handleFeedGroups) }
|
||||
}
|
||||
|
||||
private fun showLongTapDialog(selectedItem: ChannelInfoItem) {
|
||||
|
|
@ -381,7 +382,9 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
}
|
||||
}
|
||||
is SubscriptionState.ErrorState -> {
|
||||
result.error?.let { onError(result.error) }
|
||||
result.error?.let {
|
||||
showError(ErrorInfo(result.error, UserAction.SOMETHING_ELSE, "Subscriptions"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -412,17 +415,6 @@ class SubscriptionFragment : BaseStateFragment<SubscriptionState>() {
|
|||
binding.itemsList.animate(true, 200)
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// Fragment Error Handling
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
||||
override fun onError(exception: Throwable): Boolean {
|
||||
if (super.onError(exception)) return true
|
||||
|
||||
onUnrecoverableError(exception, UserAction.SOMETHING_ELSE, "none", "Subscriptions", R.string.general_error)
|
||||
return true
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// Grid Mode
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -84,10 +84,12 @@ public class SubscriptionsImportFragment extends BaseFragment {
|
|||
|
||||
setupServiceVariables();
|
||||
if (supportedSources.isEmpty() && currentServiceId != Constants.NO_SERVICE_ID) {
|
||||
ErrorActivity.reportError(activity, Collections.emptyList(), null, null,
|
||||
ErrorInfo.make(UserAction.SOMETHING_ELSE,
|
||||
ErrorActivity.reportError(activity, null, null,
|
||||
new ErrorInfo(new String[]{}, UserAction.SUBSCRIPTION_IMPORT_EXPORT,
|
||||
NewPipe.getNameOfService(currentServiceId),
|
||||
"Service don't support importing", R.string.general_error));
|
||||
"Service does not support importing subscriptions",
|
||||
R.string.general_error,
|
||||
null));
|
||||
activity.finish();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@ import org.schabi.newpipe.ktx.ExceptionUtils;
|
|||
import org.schabi.newpipe.local.subscription.SubscriptionManager;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
|
@ -152,13 +151,10 @@ public abstract class BaseImportExportService extends Service {
|
|||
postErrorResult(null, null);
|
||||
}
|
||||
|
||||
protected void stopAndReportError(@Nullable final Throwable error, final String request) {
|
||||
protected void stopAndReportError(final Throwable throwable, final String request) {
|
||||
stopService();
|
||||
|
||||
final ErrorInfo errorInfo = ErrorInfo
|
||||
.make(UserAction.SUBSCRIPTION, "unknown", request, R.string.general_error);
|
||||
ErrorActivity.reportError(this, error != null ? Collections.singletonList(error)
|
||||
: Collections.emptyList(), null, null, errorInfo);
|
||||
ErrorActivity.reportError(this, null, null, new ErrorInfo(
|
||||
throwable, UserAction.SUBSCRIPTION_IMPORT_EXPORT, request));
|
||||
}
|
||||
|
||||
protected void postErrorResult(final String title, final String text) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue