loadResult(final boolean forceLoad) {
// Contract
//////////////////////////////////////////////////////////////////////////*/
- @Override
- public void showLoading() {
- super.showLoading();
- }
-
@Override
public void handleResult(@NonNull final CommentsInfo result) {
super.handleResult(result);
-
ViewUtils.slideUp(requireView(), 120, 150, 0.06f);
-
- if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(), UserAction.REQUESTED_COMMENTS,
- NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
- }
-
disposables.clear();
}
- @Override
- public void handleNextItems(final ListExtractor.InfoItemsPage result) {
- super.handleNextItems(result);
-
- if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(), UserAction.REQUESTED_COMMENTS,
- NewPipe.getNameOfService(serviceId), "Get next page of: " + url,
- R.string.general_error);
- }
- }
-
- /*//////////////////////////////////////////////////////////////////////////
- // OnError
- //////////////////////////////////////////////////////////////////////////*/
-
- @Override
- protected boolean onError(final Throwable exception) {
- if (super.onError(exception)) {
- return true;
- }
-
- hideLoading();
- showSnackBarError(exception, UserAction.REQUESTED_COMMENTS,
- NewPipe.getNameOfService(serviceId), url, R.string.error_unable_to_load_comments);
- return true;
- }
-
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/DefaultKioskFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/DefaultKioskFragment.java
index 1797191b64b..d0b9e3a3dd2 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/DefaultKioskFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/DefaultKioskFragment.java
@@ -2,14 +2,16 @@
import android.os.Bundle;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.kiosk.KioskList;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.ServiceHelper;
public class DefaultKioskFragment extends KioskFragment {
+
@Override
public void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -46,8 +48,8 @@ private void updateSelectedDefaultKiosk() {
currentInfo = null;
currentNextPage = null;
} catch (final ExtractionException e) {
- onUnrecoverableError(e, UserAction.REQUESTED_KIOSK, "none",
- "Loading default kiosk from selected service", 0);
+ showError(new ErrorInfo(e, UserAction.REQUESTED_KIOSK,
+ "Loading default kiosk for selected service"));
}
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java
index 2e5e6453953..882bb021dc0 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/kiosk/KioskFragment.java
@@ -12,6 +12,8 @@
import androidx.appcompat.app.ActionBar;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
@@ -20,7 +22,6 @@
import org.schabi.newpipe.extractor.linkhandler.ListLinkHandlerFactory;
import org.schabi.newpipe.extractor.localization.ContentCountry;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.Localization;
@@ -28,8 +29,6 @@
import icepick.State;
import io.reactivex.rxjava3.core.Single;
-import static org.schabi.newpipe.ktx.ViewUtils.animate;
-
/**
* Created by Christian Schabesberger on 23.09.17.
*
@@ -82,6 +81,10 @@ public static KioskFragment getInstance(final int serviceId, final String kioskI
return instance;
}
+ public KioskFragment() {
+ super(UserAction.REQUESTED_KIOSK);
+ }
+
/*//////////////////////////////////////////////////////////////////////////
// LifeCycle
//////////////////////////////////////////////////////////////////////////*/
@@ -102,9 +105,7 @@ public void setUserVisibleHint(final boolean isVisibleToUser) {
try {
setTitle(kioskTranslatedName);
} catch (final Exception e) {
- onUnrecoverableError(e, UserAction.UI_ERROR,
- "none",
- "none", R.string.app_ui_crash);
+ showSnackBarError(new ErrorInfo(e, UserAction.UI_ERROR, "Setting kiosk title"));
}
}
}
@@ -157,34 +158,11 @@ public Single loadMoreItemsLogic() {
// Contract
//////////////////////////////////////////////////////////////////////////*/
- @Override
- public void showLoading() {
- super.showLoading();
- animate(itemsList, false, 100);
- }
-
@Override
public void handleResult(@NonNull final KioskInfo result) {
super.handleResult(result);
name = kioskTranslatedName;
setTitle(kioskTranslatedName);
-
- if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(),
- UserAction.REQUESTED_KIOSK,
- NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
- }
- }
-
- @Override
- public void handleNextItems(final ListExtractor.InfoItemsPage result) {
- super.handleNextItems(result);
-
- if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(),
- UserAction.REQUESTED_PLAYLIST, NewPipe.getNameOfService(serviceId),
- "Get next page of: " + url, 0);
- }
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
index 85dea83dcee..11494792319 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/playlist/PlaylistFragment.java
@@ -14,7 +14,6 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.viewbinding.ViewBinding;
@@ -25,11 +24,12 @@
import org.schabi.newpipe.database.playlist.model.PlaylistRemoteEntity;
import org.schabi.newpipe.databinding.PlaylistControlBinding;
import org.schabi.newpipe.databinding.PlaylistHeaderBinding;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
-import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.ServiceList;
-import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.services.youtube.YoutubeParsingHelper;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
@@ -40,8 +40,6 @@
import org.schabi.newpipe.player.helper.PlayerHolder;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.PlaylistPlayQueue;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ExtractorHelper;
import org.schabi.newpipe.util.ImageDisplayConstants;
import org.schabi.newpipe.util.KoreUtil;
@@ -62,6 +60,7 @@
import io.reactivex.rxjava3.disposables.Disposable;
import static org.schabi.newpipe.ktx.ViewUtils.animate;
+import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling;
import static org.schabi.newpipe.util.ThemeHelper.resolveResourceIdFromAttr;
public class PlaylistFragment extends BaseListInfoFragment {
@@ -87,6 +86,10 @@ public static PlaylistFragment getInstance(final int serviceId, final String url
return instance;
}
+ public PlaylistFragment() {
+ super(UserAction.REQUESTED_PLAYLIST);
+ }
+
/*//////////////////////////////////////////////////////////////////////////
// LifeCycle
//////////////////////////////////////////////////////////////////////////*/
@@ -262,7 +265,7 @@ public boolean onOptionsItemSelected(final MenuItem item) {
public void showLoading() {
super.showLoading();
animate(headerBinding.getRoot(), false, 200);
- animate(itemsList, false, 100);
+ animateHideRecyclerViewAllowingScrolling(itemsList);
IMAGE_LOADER.cancelDisplayTask(headerBinding.uploaderAvatarView);
animate(headerBinding.uploaderLayout, false, 200);
@@ -284,7 +287,7 @@ public void handleResult(@NonNull final PlaylistInfo result) {
NavigationHelper.openChannelFragment(getFM(), result.getServiceId(),
result.getUploaderUrl(), result.getUploaderName());
} catch (final Exception e) {
- ErrorActivity.reportUiError((AppCompatActivity) getActivity(), e);
+ ErrorActivity.reportUiErrorInSnackbar(this, "Opening channel fragment", e);
}
});
}
@@ -315,8 +318,8 @@ public void handleResult(@NonNull final PlaylistInfo result) {
.localizeStreamCount(getContext(), result.getStreamCount()));
if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(), UserAction.REQUESTED_PLAYLIST,
- NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
+ showSnackBarError(new ErrorInfo(result.getErrors(), UserAction.REQUESTED_PLAYLIST,
+ result.getUrl(), result));
}
remotePlaylistManager.getPlaylist(result)
@@ -363,33 +366,6 @@ private PlayQueue getPlayQueue(final int index) {
);
}
- @Override
- public void handleNextItems(final ListExtractor.InfoItemsPage result) {
- super.handleNextItems(result);
-
- if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(), UserAction.REQUESTED_PLAYLIST,
- NewPipe.getNameOfService(serviceId), "Get next page of: " + url, 0);
- }
- }
-
- /*//////////////////////////////////////////////////////////////////////////
- // OnError
- //////////////////////////////////////////////////////////////////////////*/
-
- @Override
- protected boolean onError(final Throwable exception) {
- if (super.onError(exception)) {
- return true;
- }
-
- final int errorId = exception instanceof ExtractionException
- ? R.string.parsing_error : R.string.general_error;
- onUnrecoverableError(exception, UserAction.REQUESTED_PLAYLIST,
- NewPipe.getNameOfService(serviceId), url, errorId);
- return true;
- }
-
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
@@ -434,8 +410,9 @@ public void onNext(final List playlist) {
}
@Override
- public void onError(final Throwable t) {
- PlaylistFragment.this.onError(t);
+ public void onError(final Throwable throwable) {
+ showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
+ "Get playlist bookmarks"));
}
@Override
@@ -460,12 +437,16 @@ private void onBookmarkClicked() {
if (currentInfo != null && playlistEntity == null) {
action = remotePlaylistManager.onBookmark(currentInfo)
.observeOn(AndroidSchedulers.mainThread())
- .subscribe(ignored -> { /* Do nothing */ }, this::onError);
+ .subscribe(ignored -> { /* Do nothing */ }, throwable ->
+ showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
+ "Adding playlist bookmark")));
} else if (playlistEntity != null) {
action = remotePlaylistManager.deletePlaylist(playlistEntity.getUid())
.observeOn(AndroidSchedulers.mainThread())
.doFinally(() -> playlistEntity = null)
- .subscribe(ignored -> { /* Do nothing */ }, this::onError);
+ .subscribe(ignored -> { /* Do nothing */ }, throwable ->
+ showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
+ "Deleting playlist bookmark")));
} else {
action = Disposable.empty();
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
index 5273fd396df..26360137e9c 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/search/SearchFragment.java
@@ -35,16 +35,18 @@
import androidx.recyclerview.widget.RecyclerView;
import org.schabi.newpipe.R;
-import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.database.history.model.SearchHistoryEntry;
import org.schabi.newpipe.databinding.FragmentSearchBinding;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.ReCaptchaActivity;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor;
import org.schabi.newpipe.extractor.MetaInfo;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.Page;
import org.schabi.newpipe.extractor.StreamingService;
-import org.schabi.newpipe.extractor.exceptions.ParsingException;
import org.schabi.newpipe.extractor.search.SearchExtractor;
import org.schabi.newpipe.extractor.search.SearchInfo;
import org.schabi.newpipe.extractor.services.peertube.linkHandler.PeertubeSearchQueryHandlerFactory;
@@ -54,9 +56,6 @@
import org.schabi.newpipe.ktx.AnimationType;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.local.history.HistoryRecordManager;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ExtractorHelper;
@@ -162,11 +161,6 @@ public class SearchFragment extends BaseListFragment suggestionPublisher
.onNext(searchEditText.getText().toString()),
- 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 failed")));
disposables.add(onDelete);
})
.show();
@@ -733,14 +721,12 @@ private void initSuggestionObserver() {
suggestionDisposable.dispose();
}
- final Observable observable = suggestionPublisher
+ suggestionDisposable = suggestionPublisher
.debounce(SUGGESTIONS_DEBOUNCE, TimeUnit.MILLISECONDS)
.startWithItem(searchString != null
? searchString
: "")
- .filter(ss -> isSuggestionsEnabled);
-
- suggestionDisposable = observable
+ .filter(ss -> isSuggestionsEnabled)
.switchMap(query -> {
final Flowable> flowable = historyRecordManager
.getRelatedSearches(query, 3, 25);
@@ -763,8 +749,8 @@ private void initSuggestionObserver() {
.suggestionsFor(serviceId, query)
.onErrorReturn(throwable -> {
if (!ExceptionUtils.isNetworkRelated(throwable)) {
- showSnackBarError(throwable, UserAction.GET_SUGGESTIONS,
- NewPipe.getNameOfService(serviceId), searchString, 0);
+ showSnackBarError(new ErrorInfo(throwable,
+ UserAction.GET_SUGGESTIONS, searchString, serviceId));
}
return new ArrayList<>();
})
@@ -800,7 +786,8 @@ private void initSuggestionObserver() {
if (listNotification.isOnNext()) {
handleSuggestions(listNotification.getValue());
} else if (listNotification.isOnError()) {
- onSuggestionError(listNotification.getError());
+ showError(new ErrorInfo(listNotification.getError(),
+ UserAction.GET_SUGGESTIONS, searchString, serviceId));
}
});
}
@@ -832,8 +819,7 @@ private void search(final String theSearchString,
.subscribe(intent -> {
getFM().popBackStackImmediate();
activity.startActivity(intent);
- }, throwable ->
- showError(getString(R.string.unsupported_url), false)));
+ }, throwable -> showTextError(getString(R.string.unsupported_url))));
return;
}
} catch (final Exception ignored) {
@@ -844,15 +830,16 @@ private void search(final String theSearchString,
this.searchString = theSearchString;
infoListAdapter.clearStreamItemList();
hideSuggestionsPanel();
+ showMetaInfoInTextView(null, searchBinding.searchMetaInfoTextView,
+ searchBinding.searchMetaInfoSeparator);
hideKeyboardSearch();
disposables.add(historyRecordManager.onSearched(serviceId, theSearchString)
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
- ignored -> {
- },
- error -> showSnackBarError(error, UserAction.SEARCHED,
- NewPipe.getNameOfService(serviceId), theSearchString, 0)
+ ignored -> { },
+ throwable -> showSnackBarError(new ErrorInfo(throwable, UserAction.SEARCHED,
+ theSearchString, serviceId))
));
suggestionPublisher.onNext(theSearchString);
startLoading(false);
@@ -872,7 +859,7 @@ public void startLoading(final boolean forceLoad) {
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnEvent((searchResult, throwable) -> isLoading.set(false))
- .subscribe(this::handleResult, this::onError);
+ .subscribe(this::handleResult, this::onItemError);
}
@@ -895,7 +882,7 @@ protected void loadMoreItems() {
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnEvent((nextItemsResult, throwable) -> isLoading.set(false))
- .subscribe(this::handleNextItems, this::onError);
+ .subscribe(this::handleNextItems, this::onItemError);
}
@Override
@@ -909,6 +896,15 @@ protected void onItemSelected(final InfoItem selectedItem) {
hideKeyboardSearch();
}
+ private void onItemError(final Throwable exception) {
+ if (exception instanceof SearchExtractor.NothingFoundException) {
+ infoListAdapter.clearStreamItemList();
+ showEmptyState();
+ } else {
+ showError(new ErrorInfo(exception, UserAction.SEARCHED, searchString, serviceId));
+ }
+ }
+
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
@@ -945,26 +941,11 @@ public void handleSuggestions(@NonNull final List suggestions) {
searchBinding.suggestionsList.smoothScrollToPosition(0);
searchBinding.suggestionsList.post(() -> suggestionListAdapter.setItems(suggestions));
- if (suggestionsPanelVisible && errorPanelRoot.getVisibility() == View.VISIBLE) {
+ if (suggestionsPanelVisible && isErrorPanelVisible()) {
hideLoading();
}
}
- public void onSuggestionError(final Throwable exception) {
- if (DEBUG) {
- Log.d(TAG, "onSuggestionError() called with: exception = [" + exception + "]");
- }
- if (super.onError(exception)) {
- return;
- }
-
- final int errorId = exception instanceof ParsingException
- ? R.string.parsing_error
- : R.string.general_error;
- onUnrecoverableError(exception, UserAction.GET_SUGGESTIONS,
- NewPipe.getNameOfService(serviceId), searchString, errorId);
- }
-
/*//////////////////////////////////////////////////////////////////////////
// Contract
//////////////////////////////////////////////////////////////////////////*/
@@ -975,13 +956,6 @@ public void hideLoading() {
showListFooter(false);
}
- @Override
- public void showError(final String message, final boolean showRetryButton) {
- super.showError(message, showRetryButton);
- hideSuggestionsPanel();
- hideKeyboardSearch();
- }
-
/*//////////////////////////////////////////////////////////////////////////
// Search Results
//////////////////////////////////////////////////////////////////////////*/
@@ -992,8 +966,8 @@ public void handleResult(@NonNull final SearchInfo result) {
if (!exceptions.isEmpty()
&& !(exceptions.size() == 1
&& exceptions.get(0) instanceof SearchExtractor.NothingFoundException)) {
- showSnackBarError(result.getErrors(), UserAction.SEARCHED,
- NewPipe.getNameOfService(serviceId), searchString, 0);
+ showSnackBarError(new ErrorInfo(result.getErrors(), UserAction.SEARCHED,
+ searchString, serviceId));
}
searchSuggestion = result.getSearchSuggestion();
@@ -1002,8 +976,8 @@ public void handleResult(@NonNull final SearchInfo result) {
// List cannot be bundled without creating some containers
metaInfo = new MetaInfo[result.getMetaInfo().size()];
metaInfo = result.getMetaInfo().toArray(metaInfo);
- disposables.add(showMetaInfoInTextView(result.getMetaInfo(), metaInfoTextView,
- metaInfoSeparator));
+ disposables.add(showMetaInfoInTextView(result.getMetaInfo(),
+ searchBinding.searchMetaInfoTextView, searchBinding.searchMetaInfoSeparator));
handleSearchSuggestion();
@@ -1061,33 +1035,20 @@ public void handleNextItems(final ListExtractor.InfoItemsPage> result) {
nextPage = result.getNextPage();
if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(), UserAction.SEARCHED,
- NewPipe.getNameOfService(serviceId),
+ showSnackBarError(new ErrorInfo(result.getErrors(), UserAction.SEARCHED,
"\"" + searchString + "\" → pageUrl: " + nextPage.getUrl() + ", "
+ "pageIds: " + nextPage.getIds() + ", "
- + "pageCookies: " + nextPage.getCookies(), 0);
+ + "pageCookies: " + nextPage.getCookies(),
+ serviceId));
}
super.handleNextItems(result);
}
@Override
- protected boolean onError(final Throwable exception) {
- if (super.onError(exception)) {
- return true;
- }
-
- if (exception instanceof SearchExtractor.NothingFoundException) {
- infoListAdapter.clearStreamItemList();
- showEmptyState();
- } else {
- final int errorId = exception instanceof ParsingException
- ? R.string.parsing_error
- : R.string.general_error;
- onUnrecoverableError(exception, UserAction.SEARCHED,
- NewPipe.getNameOfService(serviceId), searchString, errorId);
- }
-
- return true;
+ public void handleError() {
+ super.handleError();
+ hideSuggestionsPanel();
+ hideKeyboardSearch();
}
/*//////////////////////////////////////////////////////////////////////////
@@ -1113,9 +1074,8 @@ public void onSuggestionItemSwiped(@NonNull final RecyclerView.ViewHolder viewHo
.subscribe(
howManyDeleted -> suggestionPublisher
.onNext(searchEditText.getText().toString()),
- 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 failed")));
disposables.add(onDelete);
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java
index 7afe6971699..902df94bc1d 100644
--- a/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/fragments/list/videos/RelatedVideosFragment.java
@@ -16,12 +16,11 @@
import org.schabi.newpipe.R;
import org.schabi.newpipe.databinding.RelatedStreamsHeaderBinding;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.ListExtractor;
-import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.fragments.list.BaseListInfoFragment;
import org.schabi.newpipe.ktx.ViewUtils;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.RelatedStreamInfo;
import java.io.Serializable;
@@ -47,6 +46,10 @@ public static RelatedVideosFragment getInstance(final StreamInfo info) {
return instance;
}
+ public RelatedVideosFragment() {
+ super(UserAction.REQUESTED_STREAM);
+ }
+
/*//////////////////////////////////////////////////////////////////////////
// LifeCycle
//////////////////////////////////////////////////////////////////////////*/
@@ -125,43 +128,9 @@ public void handleResult(@NonNull final RelatedStreamInfo result) {
}
ViewUtils.slideUp(requireView(), 120, 96, 0.06f);
- if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(), UserAction.REQUESTED_STREAM,
- NewPipe.getNameOfService(result.getServiceId()), result.getUrl(), 0);
- }
-
disposables.clear();
}
- @Override
- public void handleNextItems(final ListExtractor.InfoItemsPage result) {
- super.handleNextItems(result);
-
- if (!result.getErrors().isEmpty()) {
- showSnackBarError(result.getErrors(),
- UserAction.REQUESTED_STREAM,
- NewPipe.getNameOfService(serviceId),
- "Get next page of: " + url,
- R.string.general_error);
- }
- }
-
- /*//////////////////////////////////////////////////////////////////////////
- // OnError
- //////////////////////////////////////////////////////////////////////////*/
-
- @Override
- protected boolean onError(final Throwable exception) {
- if (super.onError(exception)) {
- return true;
- }
-
- hideLoading();
- showSnackBarError(exception, UserAction.REQUESTED_STREAM,
- NewPipe.getNameOfService(serviceId), url, R.string.general_error);
- return true;
- }
-
/*//////////////////////////////////////////////////////////////////////////
// Utils
//////////////////////////////////////////////////////////////////////////*/
@@ -190,11 +159,9 @@ public void onSaveInstanceState(@NonNull final Bundle outState) {
@Override
protected void onRestoreInstanceState(@NonNull final Bundle savedState) {
super.onRestoreInstanceState(savedState);
- if (savedState != null) {
- final Serializable serializable = savedState.getSerializable(INFO_KEY);
- if (serializable instanceof RelatedStreamInfo) {
- this.relatedStreamInfo = (RelatedStreamInfo) serializable;
- }
+ final Serializable serializable = savedState.getSerializable(INFO_KEY);
+ if (serializable instanceof RelatedStreamInfo) {
+ this.relatedStreamInfo = (RelatedStreamInfo) serializable;
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
index fe35a18c404..b106e029dbd 100644
--- a/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
+++ b/app/src/main/java/org/schabi/newpipe/info_list/holder/CommentsMiniInfoItemHolder.java
@@ -14,11 +14,11 @@
import androidx.preference.PreferenceManager;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.error.ErrorActivity;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.comments.CommentsInfoItem;
import org.schabi.newpipe.info_list.InfoItemBuilder;
import org.schabi.newpipe.local.history.HistoryRecordManager;
-import org.schabi.newpipe.report.ErrorActivity;
import org.schabi.newpipe.util.CommentTextOnTouchListener;
import org.schabi.newpipe.util.DeviceUtils;
import org.schabi.newpipe.util.ImageDisplayConstants;
@@ -171,15 +171,15 @@ private void openCommentAuthor(final CommentsInfoItem item) {
if (TextUtils.isEmpty(item.getUploaderUrl())) {
return;
}
+ final AppCompatActivity activity = (AppCompatActivity) itemBuilder.getContext();
try {
- final AppCompatActivity activity = (AppCompatActivity) itemBuilder.getContext();
NavigationHelper.openChannelFragment(
activity.getSupportFragmentManager(),
item.getServiceId(),
item.getUploaderUrl(),
item.getUploaderName());
} catch (final Exception e) {
- ErrorActivity.reportUiError((AppCompatActivity) itemBuilder.getContext(), e);
+ ErrorActivity.reportUiErrorInSnackbar(activity, "Opening channel fragment", e);
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/ktx/View.kt b/app/src/main/java/org/schabi/newpipe/ktx/View.kt
index 2b1f36bc7aa..2fd80703c23 100644
--- a/app/src/main/java/org/schabi/newpipe/ktx/View.kt
+++ b/app/src/main/java/org/schabi/newpipe/ktx/View.kt
@@ -319,6 +319,16 @@ fun View.slideUp(duration: Long, delay: Long, @FloatRange(from = 0.0, to = 1.0)
.start()
}
+/**
+ * Instead of hiding normally using [animate], which would make
+ * the recycler view unable to capture touches after being hidden, this just animates the alpha
+ * value setting it to `0.0` after `200` milliseconds.
+ */
+fun View.animateHideRecyclerViewAllowingScrolling() {
+ // not hiding normally because the view needs to still capture touches and allow scroll
+ animate().alpha(0.0f).setDuration(200).start()
+}
+
enum class AnimationType {
ALPHA, SCALE_AND_ALPHA, LIGHT_SCALE_AND_ALPHA, SLIDE_AND_ALPHA, LIGHT_SLIDE_AND_ALPHA
}
diff --git a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java
index 84908e41a05..78fb200298c 100644
--- a/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/local/BaseLocalListFragment.java
@@ -24,6 +24,7 @@
import org.schabi.newpipe.fragments.list.ListViewContract;
import static org.schabi.newpipe.ktx.ViewUtils.animate;
+import static org.schabi.newpipe.ktx.ViewUtils.animateHideRecyclerViewAllowingScrolling;
/**
* This fragment is design to be used with persistent data such as
@@ -184,7 +185,7 @@ public void startLoading(final boolean forceLoad) {
public void showLoading() {
super.showLoading();
if (itemsList != null) {
- animate(itemsList, false, 200);
+ animateHideRecyclerViewAllowingScrolling(itemsList);
}
if (headerRootBinding != null) {
animate(headerRootBinding.getRoot(), false, 200);
@@ -202,19 +203,6 @@ public void hideLoading() {
}
}
- @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 +237,18 @@ protected void resetFragment() {
}
@Override
- protected boolean onError(final Throwable exception) {
+ public void handleError() {
+ super.handleError();
resetFragment();
- return super.onError(exception);
+
+ showListFooter(false);
+
+ if (itemsList != null) {
+ animateHideRecyclerViewAllowingScrolling(itemsList);
+ }
+ if (headerRootBinding != null) {
+ animate(headerRootBinding.getRoot(), false, 200);
+ }
}
@Override
diff --git a/app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java b/app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java
index ee77db89f19..e9032a1c661 100644
--- a/app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/local/bookmark/BookmarkFragment.java
@@ -23,10 +23,11 @@
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.error.UserAction;
import org.schabi.newpipe.local.BaseLocalListFragment;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.OnClickGesture;
@@ -206,7 +207,8 @@ public void onNext(final List subscriptions) {
@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 void handleResult(@NonNull final List result) {
// 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 @@ private void showDeleteDialog(final String name, final Single deleteRea
.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 @@ private void changeLocalPlaylistName(final long id, final String name) {
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);
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
index 04090abc67e..33bed7d7ef2 100644
--- a/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/feed/FeedFragment.kt
@@ -38,17 +38,18 @@ 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
+import org.schabi.newpipe.ktx.animateHideRecyclerViewAllowingScrolling
import org.schabi.newpipe.local.feed.service.FeedLoadService
-import org.schabi.newpipe.report.UserAction
import org.schabi.newpipe.util.Localization
import java.util.Calendar
class FeedFragment : BaseListFragment() {
private var _feedBinding: FragmentFeedBinding? = null
private val feedBinding get() = _feedBinding!!
- private val errorBinding get() = _feedBinding!!.errorPanel
private lateinit var viewModel: FeedViewModel
@State
@@ -106,7 +107,7 @@ class FeedFragment : BaseListFragment() {
override fun initListeners() {
super.initListeners()
feedBinding.refreshRootView.setOnClickListener { reloadContent() }
- feedBinding.swiperefresh.setOnRefreshListener { reloadContent() }
+ feedBinding.swipeRefreshLayout.setOnRefreshListener { reloadContent() }
}
// /////////////////////////////////////////////////////////////////////////
@@ -171,50 +172,26 @@ class FeedFragment : BaseListFragment() {
// /////////////////////////////////////////////////////////////////////////
override fun showLoading() {
+ super.showLoading()
+ feedBinding.itemsList.animateHideRecyclerViewAllowingScrolling()
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)
+ feedBinding.swipeRefreshLayout.isRefreshing = true
}
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
+ feedBinding.swipeRefreshLayout.isRefreshing = false
}
override fun showEmptyState() {
+ super.showEmptyState()
+ feedBinding.itemsList.animateHideRecyclerViewAllowingScrolling()
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)
+ feedBinding.swipeRefreshLayout.isRefreshing = false
}
override fun handleResult(result: FeedState) {
@@ -227,6 +204,15 @@ class FeedFragment : BaseListFragment() {
updateRefreshViewState()
}
+ override fun handleError() {
+ super.handleError()
+ infoListAdapter.clearStreamItemList()
+ feedBinding.itemsList.animateHideRecyclerViewAllowingScrolling()
+ feedBinding.refreshRootView.animate(false, 0)
+ feedBinding.loadingProgressText.animate(false, 0)
+ feedBinding.swipeRefreshLayout.isRefreshing = false
+ }
+
private fun handleProgressState(progressState: FeedState.ProgressState) {
showLoading()
@@ -266,13 +252,6 @@ class FeedFragment : BaseListFragment() {
)
}
- 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 +260,13 @@ class FeedFragment : BaseListFragment() {
}
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 +300,6 @@ class FeedFragment : BaseListFragment() {
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"
diff --git a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java
index f9aa38054eb..1bece369b73 100644
--- a/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/local/history/StatisticsPlaylistFragment.java
@@ -14,7 +14,6 @@
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.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.player.helper.PlayerHolder;
import org.schabi.newpipe.player.playqueue.PlayQueue;
import org.schabi.newpipe.player.playqueue.SinglePlayQueue;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.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.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 void held(final LocalItem selectedItem) {
@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 void startLoading(final boolean forceLoad) {
@Override
public void onPause() {
super.onPause();
- itemsListState = itemsList.getLayoutManager().onSaveInstanceState();
+ itemsListState = Objects.requireNonNull(itemsList.getLayoutManager()).onSaveInstanceState();
}
@Override
@@ -287,7 +249,8 @@ public void onNext(final List streams) {
@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 void handleResult(@NonNull final List result) {
}
itemListAdapter.addItems(processResult(result));
- if (itemsListState != null) {
+ if (itemsListState != null && itemsList.getLayoutManager() != null) {
itemsList.getLayoutManager().onRestoreInstanceState(itemsListState);
itemsListState = null;
}
@@ -341,17 +304,6 @@ protected void resetFragment() {
}
}
- @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 @@ private void deleteEntry(final int index) {
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);
}
diff --git a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java
index 3137de9e6f7..5dbb67cd1d0 100644
--- a/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/local/playlist/LocalPlaylistFragment.java
@@ -34,6 +34,8 @@
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;
import org.schabi.newpipe.info_list.InfoItemDialog;
@@ -42,7 +44,6 @@
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.report.UserAction;
import org.schabi.newpipe.util.KoreUtil;
import org.schabi.newpipe.util.Localization;
import org.schabi.newpipe.util.NavigationHelper;
@@ -110,7 +111,7 @@ public static LocalPlaylistFragment getInstance(final long playlistId, final Str
@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 void onNext(final List streams) {
@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 void onComplete() { }
@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 void removeWatchedStreams(final boolean removePartiallyWatched) {
hideLoading();
isRemovingWatched = false;
- }, this::onError));
+ }, throwable -> showError(new ErrorInfo(throwable, UserAction.REQUESTED_BOOKMARK,
+ "Removing watched videos, partially watched=" + removePartiallyWatched))));
}
@Override
@@ -511,17 +512,6 @@ protected void resetFragment() {
}
}
- @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 @@ private void changePlaylistName(final String title) {
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 @@ private void changeThumbnailUrl(final String thumbnailUrl) {
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 @@ private Disposable getDebouncedSaver() {
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 @@ private void saveImmediate() {
isModified.set(false);
}
},
- this::onError
+ throwable -> showError(new ErrorInfo(throwable,
+ UserAction.REQUESTED_BOOKMARK, "Saving playlist"))
);
disposables.add(disposable);
}
@@ -683,7 +680,7 @@ private ItemTouchHelper.SimpleCallback getItemTouchCallback() {
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 int interpolateOutOfBoundsScroll(final RecyclerView recyclerView,
}
@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 boolean isItemViewSwipeEnabled() {
}
@Override
- public void onSwiped(final RecyclerView.ViewHolder viewHolder, final int swipeDir) { }
+ public void onSwiped(@NonNull final RecyclerView.ViewHolder viewHolder,
+ final int swipeDir) { }
};
}
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
index b74288a340b..d60d82cb422 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionFragment.kt
@@ -34,6 +34,8 @@ 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
import org.schabi.newpipe.ktx.animate
@@ -56,7 +58,6 @@ import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_MODE
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.KEY_VALUE
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService.PREVIOUS_EXPORT_MODE
-import org.schabi.newpipe.report.UserAction
import org.schabi.newpipe.util.FilePickerActivityHelper
import org.schabi.newpipe.util.NavigationHelper
import org.schabi.newpipe.util.OnClickGesture
@@ -288,8 +289,8 @@ class SubscriptionFragment : BaseStateFragment() {
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() {
}
}
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() {
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
// /////////////////////////////////////////////////////////////////////////
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java
index d7a1051e634..f0675da1b79 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/SubscriptionsImportFragment.java
@@ -22,13 +22,13 @@
import org.schabi.newpipe.BaseFragment;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
import org.schabi.newpipe.local.subscription.services.SubscriptionsImportService;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.Constants;
import org.schabi.newpipe.util.FilePickerActivityHelper;
import org.schabi.newpipe.util.ServiceHelper;
@@ -84,10 +84,12 @@ public void onCreate(final Bundle savedInstanceState) {
setupServiceVariables();
if (supportedSources.isEmpty() && currentServiceId != Constants.NO_SERVICE_ID) {
- ErrorActivity.reportError(activity, Collections.emptyList(), null, null,
- ErrorInfo.make(UserAction.SOMETHING_ELSE,
+ ErrorActivity.reportErrorInSnackbar(activity,
+ 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();
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt
index 6f821f43267..5bd13356d1d 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupDialog.kt
@@ -42,7 +42,6 @@ import org.schabi.newpipe.local.subscription.item.PickerSubscriptionItem
import org.schabi.newpipe.util.DeviceUtils
import org.schabi.newpipe.util.ThemeHelper
import java.io.Serializable
-import kotlin.collections.contains
class FeedGroupDialog : DialogFragment(), BackPressable {
private var _feedGroupCreateBinding: DialogFeedGroupCreateBinding? = null
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt
index 2b09a3b3bbc..57815ea9003 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/dialog/FeedGroupReorderDialog.kt
@@ -24,6 +24,10 @@ import org.schabi.newpipe.local.subscription.dialog.FeedGroupReorderDialogViewMo
import org.schabi.newpipe.local.subscription.item.FeedGroupReorderItem
import org.schabi.newpipe.util.ThemeHelper
import java.util.Collections
+import kotlin.collections.ArrayList
+import kotlin.collections.List
+import kotlin.collections.map
+import kotlin.collections.sortedBy
class FeedGroupReorderDialog : DialogFragment() {
private var _binding: DialogFeedGroupReorderBinding? = null
diff --git a/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java b/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java
index f573f4679a1..901eabf4453 100644
--- a/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java
+++ b/app/src/main/java/org/schabi/newpipe/local/subscription/services/BaseImportExportService.java
@@ -35,15 +35,14 @@
import org.reactivestreams.Publisher;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.subscription.SubscriptionExtractor;
import org.schabi.newpipe.ktx.ExceptionUtils;
import org.schabi.newpipe.local.subscription.SubscriptionManager;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import java.io.FileNotFoundException;
-import java.util.Collections;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
@@ -152,13 +151,10 @@ protected void stopService() {
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, new ErrorInfo(
+ throwable, UserAction.SUBSCRIPTION_IMPORT_EXPORT, request));
}
protected void postErrorResult(final String title, final String text) {
diff --git a/app/src/main/java/org/schabi/newpipe/report/ErrorInfo.kt b/app/src/main/java/org/schabi/newpipe/report/ErrorInfo.kt
deleted file mode 100644
index 4947d79500c..00000000000
--- a/app/src/main/java/org/schabi/newpipe/report/ErrorInfo.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-package org.schabi.newpipe.report
-
-import android.os.Parcelable
-import androidx.annotation.StringRes
-import kotlinx.android.parcel.Parcelize
-
-@Parcelize
-class ErrorInfo(
- val userAction: UserAction?,
- val serviceName: String,
- val request: String,
- @field:StringRes @param:StringRes val message: Int
-) : Parcelable {
- companion object {
- @JvmStatic
- fun make(
- userAction: UserAction?,
- serviceName: String,
- request: String,
- @StringRes message: Int
- ) = ErrorInfo(userAction, serviceName, request, message)
- }
-}
diff --git a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
index c0639131c08..dbe05bbd2f0 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/ContentSettingsFragment.java
@@ -21,13 +21,11 @@
import org.schabi.newpipe.DownloaderImpl;
import org.schabi.newpipe.NewPipeDatabase;
import org.schabi.newpipe.R;
-import org.schabi.newpipe.ReCaptchaActivity;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ReCaptchaActivity;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.localization.ContentCountry;
import org.schabi.newpipe.extractor.localization.Localization;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.FilePickerActivityHelper;
import org.schabi.newpipe.util.ZipHelper;
@@ -198,7 +196,7 @@ private void exportDatabase(final String path) {
Toast.makeText(getContext(), R.string.export_complete_toast, Toast.LENGTH_SHORT).show();
} catch (final Exception e) {
- onError(e);
+ ErrorActivity.reportUiErrorInSnackbar(this, "Exporting database", e);
}
}
@@ -243,20 +241,7 @@ private void importDatabase(final String filePath) {
System.exit(0);
}
} catch (final Exception e) {
- onError(e);
+ ErrorActivity.reportUiErrorInSnackbar(this, "Importing database", e);
}
}
-
- /*//////////////////////////////////////////////////////////////////////////
- // Error
- //////////////////////////////////////////////////////////////////////////*/
-
- protected void onError(final Throwable e) {
- final Activity activity = getActivity();
- ErrorActivity.reportError(activity, e,
- activity.getClass(),
- null,
- ErrorInfo.make(UserAction.UI_ERROR,
- "none", "", R.string.app_ui_crash));
- }
}
diff --git a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java
index 98c1ffc30a8..89fabbdde3b 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/HistorySettingsFragment.java
@@ -1,17 +1,19 @@
package org.schabi.newpipe.settings;
+import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.local.history.HistoryRecordManager;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.InfoCache;
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
@@ -46,120 +48,103 @@ public void onCreatePreferences(final Bundle savedInstanceState, final String ro
public boolean onPreferenceTreeClick(final Preference preference) {
if (preference.getKey().equals(cacheWipeKey)) {
InfoCache.getInstance().clearCache();
- Toast.makeText(preference.getContext(), R.string.metadata_cache_wipe_complete_notice,
- Toast.LENGTH_SHORT).show();
+ Toast.makeText(requireContext(),
+ R.string.metadata_cache_wipe_complete_notice, Toast.LENGTH_SHORT).show();
+ } else if (preference.getKey().equals(viewsHistoryClearKey)) {
+ openDeleteWatchHistoryDialog(requireContext(), recordManager, disposables);
+ } else if (preference.getKey().equals(playbackStatesClearKey)) {
+ openDeletePlaybackStatesDialog(requireContext(), recordManager, disposables);
+ } else if (preference.getKey().equals(searchHistoryClearKey)) {
+ openDeleteSearchHistoryDialog(requireContext(), recordManager, disposables);
+ } else {
+ return super.onPreferenceTreeClick(preference);
}
+ return true;
+ }
- if (preference.getKey().equals(viewsHistoryClearKey)) {
- new AlertDialog.Builder(getActivity())
- .setTitle(R.string.delete_view_history_alert)
- .setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
- .setPositiveButton(R.string.delete, ((dialog, which) -> {
- final Disposable onDeletePlaybackStates
- = recordManager.deleteCompleteStreamStateHistory()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(
- howManyDeleted -> Toast.makeText(getActivity(),
- R.string.watch_history_states_deleted,
- Toast.LENGTH_SHORT).show(),
- throwable -> ErrorActivity.reportError(getContext(),
- throwable,
- SettingsActivity.class, null,
- ErrorInfo.make(
- UserAction.DELETE_FROM_HISTORY,
- "none",
- "Delete playback states",
- R.string.general_error)));
-
- final Disposable onDelete = recordManager.deleteWholeStreamHistory()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(
- howManyDeleted -> Toast.makeText(getActivity(),
- 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)));
+ private static Disposable getDeletePlaybackStatesDisposable(
+ @NonNull final Context context, final HistoryRecordManager recordManager) {
+ return recordManager.deleteCompleteStreamStateHistory()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(
+ howManyDeleted -> Toast.makeText(context,
+ R.string.watch_history_states_deleted, Toast.LENGTH_SHORT).show(),
+ throwable -> ErrorActivity.reportError(context,
+ new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY,
+ "Delete playback states")));
+ }
- 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(onDeletePlaybackStates);
- disposables.add(onClearOrphans);
- disposables.add(onDelete);
- }))
- .create()
- .show();
- }
+ private static Disposable getWholeStreamHistoryDisposable(
+ @NonNull final Context context, final HistoryRecordManager recordManager) {
+ return recordManager.deleteWholeStreamHistory()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(
+ howManyDeleted -> Toast.makeText(context,
+ R.string.watch_history_deleted, Toast.LENGTH_SHORT).show(),
+ throwable -> ErrorActivity.reportError(context,
+ new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY,
+ "Delete from history")));
+ }
- if (preference.getKey().equals(playbackStatesClearKey)) {
- new AlertDialog.Builder(getActivity())
- .setTitle(R.string.delete_playback_states_alert)
- .setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
- .setPositiveButton(R.string.delete, ((dialog, which) -> {
+ private static Disposable getRemoveOrphanedRecordsDisposable(
+ @NonNull final Context context, final HistoryRecordManager recordManager) {
+ return recordManager.removeOrphanedRecords()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(
+ howManyDeleted -> { },
+ throwable -> ErrorActivity.reportError(context,
+ new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY,
+ "Clear orphaned records")));
+ }
- final Disposable onDeletePlaybackStates
- = recordManager.deleteCompleteStreamStateHistory()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(
- howManyDeleted -> Toast.makeText(getActivity(),
- R.string.watch_history_states_deleted,
- Toast.LENGTH_SHORT).show(),
- throwable -> ErrorActivity.reportError(getContext(),
- throwable,
- SettingsActivity.class, null,
- ErrorInfo.make(
- UserAction.DELETE_FROM_HISTORY,
- "none",
- "Delete playback states",
- R.string.general_error)));
+ private static Disposable getDeleteSearchHistoryDisposable(
+ @NonNull final Context context, final HistoryRecordManager recordManager) {
+ return recordManager.deleteCompleteSearchHistory()
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(
+ howManyDeleted -> Toast.makeText(context,
+ R.string.search_history_deleted, Toast.LENGTH_SHORT).show(),
+ throwable -> ErrorActivity.reportError(context,
+ new ErrorInfo(throwable, UserAction.DELETE_FROM_HISTORY,
+ "Delete search history")));
+ }
- disposables.add(onDeletePlaybackStates);
- }))
- .create()
- .show();
- }
+ public static void openDeleteWatchHistoryDialog(@NonNull final Context context,
+ final HistoryRecordManager recordManager,
+ final CompositeDisposable disposables) {
+ new AlertDialog.Builder(context)
+ .setTitle(R.string.delete_view_history_alert)
+ .setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
+ .setPositiveButton(R.string.delete, ((dialog, which) -> {
+ disposables.add(getDeletePlaybackStatesDisposable(context, recordManager));
+ disposables.add(getWholeStreamHistoryDisposable(context, recordManager));
+ disposables.add(getRemoveOrphanedRecordsDisposable(context, recordManager));
+ }))
+ .create()
+ .show();
+ }
- if (preference.getKey().equals(searchHistoryClearKey)) {
- new AlertDialog.Builder(getActivity())
- .setTitle(R.string.delete_search_history_alert)
- .setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
- .setPositiveButton(R.string.delete, ((dialog, which) -> {
- final Disposable onDelete = recordManager.deleteCompleteSearchHistory()
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe(
- howManyDeleted -> Toast.makeText(getActivity(),
- R.string.search_history_deleted,
- Toast.LENGTH_SHORT).show(),
- throwable -> ErrorActivity.reportError(getContext(),
- throwable,
- SettingsActivity.class, null,
- ErrorInfo.make(
- UserAction.DELETE_FROM_HISTORY,
- "none",
- "Delete search history",
- R.string.general_error)));
- disposables.add(onDelete);
- }))
- .create()
- .show();
- }
+ public static void openDeletePlaybackStatesDialog(@NonNull final Context context,
+ final HistoryRecordManager recordManager,
+ final CompositeDisposable disposables) {
+ new AlertDialog.Builder(context)
+ .setTitle(R.string.delete_playback_states_alert)
+ .setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
+ .setPositiveButton(R.string.delete, ((dialog, which) ->
+ disposables.add(getDeletePlaybackStatesDisposable(context, recordManager))))
+ .create()
+ .show();
+ }
- return super.onPreferenceTreeClick(preference);
+ public static void openDeleteSearchHistoryDialog(@NonNull final Context context,
+ final HistoryRecordManager recordManager,
+ final CompositeDisposable disposables) {
+ new AlertDialog.Builder(context)
+ .setTitle(R.string.delete_search_history_alert)
+ .setNegativeButton(R.string.cancel, ((dialog, which) -> dialog.dismiss()))
+ .setPositiveButton(R.string.delete, ((dialog, which) ->
+ disposables.add(getDeleteSearchHistoryDisposable(context, recordManager))))
+ .create()
+ .show();
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java
index afe42d5d812..7f706be779e 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/SelectChannelFragment.java
@@ -1,6 +1,5 @@
package org.schabi.newpipe.settings;
-import android.app.Activity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -20,10 +19,8 @@
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.subscription.SubscriptionEntity;
+import org.schabi.newpipe.error.ErrorActivity;
import org.schabi.newpipe.local.subscription.SubscriptionManager;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.ThemeHelper;
import java.util.List;
@@ -108,7 +105,7 @@ public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup
emptyView.setVisibility(View.GONE);
- final SubscriptionManager subscriptionManager = new SubscriptionManager(getContext());
+ final SubscriptionManager subscriptionManager = new SubscriptionManager(requireContext());
subscriptionManager.subscriptions().toObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
@@ -122,7 +119,7 @@ public View onCreateView(@NonNull final LayoutInflater inflater, final ViewGroup
//////////////////////////////////////////////////////////////////////////*/
@Override
- public void onCancel(final DialogInterface dialogInterface) {
+ public void onCancel(@NonNull final DialogInterface dialogInterface) {
super.onCancel(dialogInterface);
if (onCancelListener != null) {
onCancelListener.onCancel();
@@ -156,16 +153,17 @@ private void displayChannels(final List newSubscriptions) {
private Observer> getSubscriptionObserver() {
return new Observer>() {
@Override
- public void onSubscribe(final Disposable d) { }
+ public void onSubscribe(@NonNull final Disposable disposable) { }
@Override
- public void onNext(final List newSubscriptions) {
+ public void onNext(@NonNull final List newSubscriptions) {
displayChannels(newSubscriptions);
}
@Override
- public void onError(final Throwable exception) {
- SelectChannelFragment.this.onError(exception);
+ public void onError(@NonNull final Throwable exception) {
+ ErrorActivity.reportUiErrorInSnackbar(SelectChannelFragment.this,
+ "Loading subscription", exception);
}
@Override
@@ -173,16 +171,6 @@ public void onComplete() { }
};
}
- /*//////////////////////////////////////////////////////////////////////////
- // Error
- //////////////////////////////////////////////////////////////////////////*/
-
- protected void onError(final Throwable e) {
- final Activity activity = getActivity();
- ErrorActivity.reportError(activity, e, activity.getClass(), null, ErrorInfo
- .make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash));
- }
-
/*//////////////////////////////////////////////////////////////////////////
// Interfaces
//////////////////////////////////////////////////////////////////////////*/
@@ -197,6 +185,7 @@ public interface OnCancelListener {
private class SelectChannelAdapter
extends RecyclerView.Adapter {
+ @NonNull
@Override
public SelectChannelItemHolder onCreateViewHolder(final ViewGroup parent,
final int viewType) {
diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java
index fc974607b18..5c20b752ccb 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/SelectKioskFragment.java
@@ -1,6 +1,5 @@
package org.schabi.newpipe.settings;
-import android.app.Activity;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -16,11 +15,9 @@
import androidx.recyclerview.widget.RecyclerView;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.error.ErrorActivity;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.ThemeHelper;
@@ -83,7 +80,7 @@ public View onCreateView(final LayoutInflater inflater, final ViewGroup containe
try {
selectKioskAdapter = new SelectKioskAdapter();
} catch (final Exception e) {
- onError(e);
+ ErrorActivity.reportUiErrorInSnackbar(this, "Selecting kiosk", e);
}
recyclerView.setAdapter(selectKioskAdapter);
@@ -109,16 +106,6 @@ private void clickedItem(final SelectKioskAdapter.Entry entry) {
dismiss();
}
- /*//////////////////////////////////////////////////////////////////////////
- // Error
- //////////////////////////////////////////////////////////////////////////*/
-
- protected void onError(final Throwable e) {
- final Activity activity = getActivity();
- ErrorActivity.reportError(activity, e, activity.getClass(), null, ErrorInfo
- .make(UserAction.UI_ERROR, "none", "", R.string.app_ui_crash));
- }
-
/*//////////////////////////////////////////////////////////////////////////
// Interfaces
//////////////////////////////////////////////////////////////////////////*/
diff --git a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java
index 16ccd0953e4..63da3274f39 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/SelectPlaylistFragment.java
@@ -24,11 +24,11 @@
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.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.local.playlist.LocalPlaylistManager;
import org.schabi.newpipe.local.playlist.RemotePlaylistManager;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import java.util.List;
import java.util.Vector;
@@ -115,8 +115,8 @@ private void displayPlaylists(final List newPlaylists) {
protected void onError(final Throwable e) {
final Activity activity = requireActivity();
- ErrorActivity.reportError(activity, e, activity.getClass(), null, ErrorInfo
- .make(UserAction.UI_ERROR, "none", "load_playlists", R.string.app_ui_crash));
+ ErrorActivity.reportErrorInSnackbar(activity, new ErrorInfo(e,
+ UserAction.UI_ERROR, "Loading playlists"));
}
/*//////////////////////////////////////////////////////////////////////////
diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java
index 9042559c970..c5974642831 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/SettingMigrations.java
@@ -7,9 +7,9 @@
import androidx.preference.PreferenceManager;
import org.schabi.newpipe.R;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import static org.schabi.newpipe.MainActivity.DEBUG;
@@ -95,15 +95,13 @@ public static void initMigrations(final Context context, final boolean isFirstRu
} catch (final Exception e) {
// save the version with the last successful migration and report the error
sp.edit().putInt(lastPrefVersionKey, currentVersion).apply();
- final ErrorInfo errorInfo = ErrorInfo.make(
+ ErrorActivity.reportError(context, new ErrorInfo(
+ e,
UserAction.PREFERENCES_MIGRATION,
- "none",
"Migrating preferences from version " + lastPrefVersion + " to "
+ VERSION + ". "
- + "Error at " + currentVersion + " => " + ++currentVersion,
- 0
- );
- ErrorActivity.reportError(context, e, SettingMigrations.class, null, errorInfo);
+ + "Error at " + currentVersion + " => " + ++currentVersion
+ ));
return;
}
}
diff --git a/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java b/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java
index cbc47392b9f..572741d03a8 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/tabs/ChooseTabsFragment.java
@@ -27,10 +27,10 @@
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import org.schabi.newpipe.R;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.NewPipe;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.settings.SelectChannelFragment;
import org.schabi.newpipe.settings.SelectKioskFragment;
import org.schabi.newpipe.settings.SelectPlaylistFragment;
@@ -183,10 +183,9 @@ private void addTab(final int tabId) {
final Tab.Type type = typeFrom(tabId);
if (type == null) {
- ErrorActivity.reportError(requireContext(),
- new IllegalStateException("Tab id not found: " + tabId), null, null,
- ErrorInfo.make(UserAction.SOMETHING_ELSE, "none",
- "Choosing tabs on settings", 0));
+ ErrorActivity.reportErrorInSnackbar(this,
+ new ErrorInfo(new IllegalStateException("Tab id not found: " + tabId),
+ UserAction.SOMETHING_ELSE, "Choosing tabs on settings"));
return;
}
diff --git a/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java b/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java
index ce3874f3975..0ffda2261c1 100644
--- a/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java
+++ b/app/src/main/java/org/schabi/newpipe/settings/tabs/Tab.java
@@ -12,6 +12,9 @@
import org.schabi.newpipe.R;
import org.schabi.newpipe.database.LocalItem.LocalItemType;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.extractor.NewPipe;
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.exceptions.ExtractionException;
@@ -25,9 +28,6 @@
import org.schabi.newpipe.local.history.StatisticsPlaylistFragment;
import org.schabi.newpipe.local.playlist.LocalPlaylistFragment;
import org.schabi.newpipe.local.subscription.SubscriptionFragment;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import org.schabi.newpipe.util.KioskTranslator;
import org.schabi.newpipe.util.ServiceHelper;
import org.schabi.newpipe.util.ThemeHelper;
@@ -483,9 +483,8 @@ private String getDefaultKioskId(final Context context) {
final StreamingService service = NewPipe.getService(kioskServiceId);
kioskId = service.getKioskList().getDefaultKioskId();
} catch (final ExtractionException e) {
- ErrorActivity.reportError(context, e, null, null,
- ErrorInfo.make(UserAction.REQUESTED_KIOSK, "none",
- "Loading default kiosk from selected service", 0));
+ ErrorActivity.reportErrorInSnackbar(context, new ErrorInfo(e,
+ UserAction.REQUESTED_KIOSK, "Loading default kiosk for selected service"));
}
return kioskId;
}
diff --git a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java
index d6e3a0e8066..af7cafc1518 100644
--- a/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java
+++ b/app/src/main/java/org/schabi/newpipe/util/ExtractorHelper.java
@@ -20,12 +20,9 @@
package org.schabi.newpipe.util;
import android.content.Context;
-import android.content.Intent;
-import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.widget.TextView;
-import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.core.text.HtmlCompat;
@@ -33,7 +30,6 @@
import org.schabi.newpipe.MainActivity;
import org.schabi.newpipe.R;
-import org.schabi.newpipe.ReCaptchaActivity;
import org.schabi.newpipe.extractor.Info;
import org.schabi.newpipe.extractor.InfoItem;
import org.schabi.newpipe.extractor.ListExtractor.InfoItemsPage;
@@ -44,29 +40,14 @@
import org.schabi.newpipe.extractor.StreamingService;
import org.schabi.newpipe.extractor.channel.ChannelInfo;
import org.schabi.newpipe.extractor.comments.CommentsInfo;
-import org.schabi.newpipe.extractor.exceptions.AgeRestrictedContentException;
-import org.schabi.newpipe.extractor.exceptions.ContentNotAvailableException;
-import org.schabi.newpipe.extractor.exceptions.ContentNotSupportedException;
-import org.schabi.newpipe.extractor.exceptions.GeographicRestrictionException;
-import org.schabi.newpipe.extractor.exceptions.PaidContentException;
-import org.schabi.newpipe.extractor.exceptions.ParsingException;
-import org.schabi.newpipe.extractor.exceptions.PrivateContentException;
-import org.schabi.newpipe.extractor.exceptions.ReCaptchaException;
-import org.schabi.newpipe.extractor.exceptions.SoundCloudGoPlusContentException;
-import org.schabi.newpipe.extractor.exceptions.YoutubeMusicPremiumContentException;
import org.schabi.newpipe.extractor.feed.FeedExtractor;
import org.schabi.newpipe.extractor.feed.FeedInfo;
import org.schabi.newpipe.extractor.kiosk.KioskInfo;
import org.schabi.newpipe.extractor.playlist.PlaylistInfo;
import org.schabi.newpipe.extractor.search.SearchInfo;
-import org.schabi.newpipe.extractor.services.youtube.extractors.YoutubeStreamExtractor;
import org.schabi.newpipe.extractor.stream.StreamInfo;
import org.schabi.newpipe.extractor.stream.StreamInfoItem;
import org.schabi.newpipe.extractor.suggestion.SuggestionExtractor;
-import org.schabi.newpipe.ktx.ExceptionUtils;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
import java.util.Collections;
import java.util.List;
@@ -280,65 +261,6 @@ public static boolean isCached(final int serviceId, final String url,
return null != loadFromCache(serviceId, url, infoType).blockingGet();
}
- /**
- * A simple and general error handler that show a Toast for known exceptions,
- * and for others, opens the report error activity with the (optional) error message.
- *
- * @param context Android app context
- * @param serviceId the service the exception happened in
- * @param url the URL where the exception happened
- * @param exception the exception to be handled
- * @param userAction the action of the user that caused the exception
- * @param optionalErrorMessage the optional error message
- */
- public static void handleGeneralException(final Context context, final int serviceId,
- final String url, final Throwable exception,
- final UserAction userAction,
- final String optionalErrorMessage) {
- final Handler handler = new Handler(context.getMainLooper());
-
- handler.post(() -> {
- if (exception instanceof ReCaptchaException) {
- Toast.makeText(context, R.string.recaptcha_request_toast, Toast.LENGTH_LONG).show();
- // Starting ReCaptcha Challenge Activity
- final Intent intent = new Intent(context, ReCaptchaActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- context.startActivity(intent);
- } else if (ExceptionUtils.isNetworkRelated(exception)) {
- Toast.makeText(context, R.string.network_error, Toast.LENGTH_LONG).show();
- } else if (exception instanceof AgeRestrictedContentException) {
- Toast.makeText(context, R.string.restricted_video_no_stream,
- Toast.LENGTH_LONG).show();
- } else if (exception instanceof GeographicRestrictionException) {
- Toast.makeText(context, R.string.georestricted_content, Toast.LENGTH_LONG).show();
- } else if (exception instanceof PaidContentException) {
- Toast.makeText(context, R.string.paid_content, Toast.LENGTH_LONG).show();
- } else if (exception instanceof PrivateContentException) {
- Toast.makeText(context, R.string.private_content, Toast.LENGTH_LONG).show();
- } else if (exception instanceof SoundCloudGoPlusContentException) {
- Toast.makeText(context, R.string.soundcloud_go_plus_content,
- Toast.LENGTH_LONG).show();
- } else if (exception instanceof YoutubeMusicPremiumContentException) {
- Toast.makeText(context, R.string.youtube_music_premium_content,
- Toast.LENGTH_LONG).show();
- } else if (exception instanceof ContentNotAvailableException) {
- Toast.makeText(context, R.string.content_not_available, Toast.LENGTH_LONG).show();
- } else if (exception instanceof ContentNotSupportedException) {
- Toast.makeText(context, R.string.content_not_supported, Toast.LENGTH_LONG).show();
- } else {
- final int errorId = exception instanceof YoutubeStreamExtractor.DeobfuscateException
- ? R.string.youtube_signature_deobfuscation_error
- : exception instanceof ParsingException
- ? R.string.parsing_error : R.string.general_error;
- ErrorActivity.reportError(handler, context, exception, MainActivity.class, null,
- ErrorInfo.make(userAction, serviceId == -1 ? "none"
- : NewPipe.getNameOfService(serviceId),
- url + (optionalErrorMessage == null ? ""
- : optionalErrorMessage), errorId));
- }
- });
- }
-
/**
* Formats the text contained in the meta info list as HTML and puts it into the text view,
* while also making the separator visible. If the list is null or empty, or the user chose not
@@ -352,10 +274,9 @@ public static Disposable showMetaInfoInTextView(@Nullable final List m
final TextView metaInfoTextView,
final View metaInfoSeparator) {
final Context context = metaInfoTextView.getContext();
- final boolean showMetaInfo = PreferenceManager.getDefaultSharedPreferences(context)
- .getBoolean(context.getString(R.string.show_meta_info_key), true);
-
- if (!showMetaInfo || metaInfos == null || metaInfos.isEmpty()) {
+ if (metaInfos == null || metaInfos.isEmpty()
+ || !PreferenceManager.getDefaultSharedPreferences(context).getBoolean(
+ context.getString(R.string.show_meta_info_key), true)) {
metaInfoTextView.setVisibility(View.GONE);
metaInfoSeparator.setVisibility(View.GONE);
return Disposable.empty();
diff --git a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
index bea4b6f9420..41a254b4976 100644
--- a/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
+++ b/app/src/main/java/us/shandian/giga/ui/adapter/MissionAdapter.java
@@ -41,9 +41,9 @@
import org.schabi.newpipe.BuildConfig;
import org.schabi.newpipe.R;
import org.schabi.newpipe.extractor.NewPipe;
-import org.schabi.newpipe.report.ErrorActivity;
-import org.schabi.newpipe.report.ErrorInfo;
-import org.schabi.newpipe.report.UserAction;
+import org.schabi.newpipe.error.ErrorActivity;
+import org.schabi.newpipe.error.ErrorInfo;
+import org.schabi.newpipe.error.UserAction;
import org.schabi.newpipe.util.NavigationHelper;
import org.schabi.newpipe.util.ShareUtils;
@@ -583,16 +583,12 @@ private void showError(DownloadMission mission, UserAction action, @StringRes in
try {
service = NewPipe.getServiceByUrl(mission.source).getServiceInfo().getName();
} catch (Exception e) {
- service = "-";
+ service = ErrorInfo.SERVICE_NONE;
}
- ErrorActivity.reportError(
- mContext,
- mission.errObject,
- null,
- null,
- ErrorInfo.make(action, service, request.toString(), reason)
- );
+ ErrorActivity.reportError(mContext,
+ new ErrorInfo(ErrorInfo.Companion.throwableToStringList(mission.errObject), action,
+ service, request.toString(), reason, null));
}
public void clearFinishedDownloads(boolean delete) {
diff --git a/app/src/main/res/layout-large-land/fragment_video_detail.xml b/app/src/main/res/layout-large-land/fragment_video_detail.xml
index 14459b49489..a3d947f6f1a 100644
--- a/app/src/main/res/layout-large-land/fragment_video_detail.xml
+++ b/app/src/main/res/layout-large-land/fragment_video_detail.xml
@@ -219,7 +219,7 @@
+ tools:context=".error.ErrorActivity">
+
+
Press \"Done\" when solved
reCAPTCHA challenge requested
+ Solve
Done
Download
diff --git a/app/src/test/java/org/schabi/newpipe/report/ErrorActivityTest.java b/app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.java
similarity index 97%
rename from app/src/test/java/org/schabi/newpipe/report/ErrorActivityTest.java
rename to app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.java
index 6c40df42dea..f77c7b2681c 100644
--- a/app/src/test/java/org/schabi/newpipe/report/ErrorActivityTest.java
+++ b/app/src/test/java/org/schabi/newpipe/error/ErrorActivityTest.java
@@ -1,4 +1,4 @@
-package org.schabi.newpipe.report;
+package org.schabi.newpipe.error;
import android.app.Activity;
diff --git a/app/src/test/java/org/schabi/newpipe/ReCaptchaActivityTest.kt b/app/src/test/java/org/schabi/newpipe/error/ReCaptchaActivityTest.kt
similarity index 83%
rename from app/src/test/java/org/schabi/newpipe/ReCaptchaActivityTest.kt
rename to app/src/test/java/org/schabi/newpipe/error/ReCaptchaActivityTest.kt
index b9f6887f9db..7b2ec52f7f9 100644
--- a/app/src/test/java/org/schabi/newpipe/ReCaptchaActivityTest.kt
+++ b/app/src/test/java/org/schabi/newpipe/error/ReCaptchaActivityTest.kt
@@ -1,8 +1,7 @@
-package org.schabi.newpipe
+package org.schabi.newpipe.error
import org.junit.Assert.assertEquals
import org.junit.Test
-import org.schabi.newpipe.ReCaptchaActivity.YT_URL
class ReCaptchaActivityTest {
private fun assertSanitized(expected: String, actual: String?) {
@@ -10,9 +9,9 @@ class ReCaptchaActivityTest {
}
@Test fun `null, empty or blank url is sanitized correctly`() {
- assertSanitized(YT_URL, null)
- assertSanitized(YT_URL, "")
- assertSanitized(YT_URL, " \n \t ")
+ assertSanitized(ReCaptchaActivity.YT_URL, null)
+ assertSanitized(ReCaptchaActivity.YT_URL, "")
+ assertSanitized(ReCaptchaActivity.YT_URL, " \n \t ")
}
@Test fun `YouTube url containing pbj=1 is sanitized correctly`() {