From 8ada566bf16bcafb57a1d6920f5610e156b5a495 Mon Sep 17 00:00:00 2001 From: litetex <40789489+litetex@users.noreply.github.com> Date: Wed, 23 Oct 2024 21:28:07 +0200 Subject: [PATCH] Replaced ``Icepick`` with ``Bridge`` and ``Android-State`` * IcePick fails on Java 21 (default in Android Studio 2024.2) * Bridge is the most modern alternative that is currently available. It is backed by ``Android-State`` and can be configured with various frameworks * In the long term this should be replaced with something better --- app/build.gradle | 7 ++- app/proguard-rules.pro | 9 --- app/src/main/java/org/schabi/newpipe/App.java | 2 + .../java/org/schabi/newpipe/BaseFragment.java | 9 +-- .../org/schabi/newpipe/RouterActivity.java | 9 +-- .../org/schabi/newpipe/about/AboutActivity.kt | 8 ++- .../newpipe/download/DownloadDialog.java | 12 ++-- .../newpipe/fragments/BaseStateFragment.java | 5 +- .../fragments/detail/DescriptionFragment.java | 6 +- .../fragments/detail/VideoDetailFragment.java | 2 +- .../fragments/list/BaseListInfoFragment.java | 5 +- .../list/channel/ChannelAboutFragment.java | 6 +- .../list/channel/ChannelFragment.java | 12 ++-- .../list/channel/ChannelTabFragment.java | 6 +- .../list/comments/CommentRepliesFragment.java | 3 +- .../fragments/list/kiosk/KioskFragment.java | 3 +- .../fragments/list/search/SearchFragment.java | 7 ++- .../local/bookmark/BookmarkFragment.java | 7 ++- .../schabi/newpipe/local/feed/FeedFragment.kt | 2 +- .../history/StatisticsPlaylistFragment.java | 3 +- .../local/playlist/LocalPlaylistFragment.java | 8 ++- .../ImportConfirmationDialog.java | 14 ++--- .../subscription/SubscriptionFragment.kt | 2 +- .../SubscriptionsImportFragment.java | 4 +- .../subscription/dialog/FeedGroupDialog.kt | 8 +-- .../dialog/FeedGroupReorderDialog.kt | 12 ++-- .../helper/PlaybackParameterDialog.java | 10 +-- .../newpipe/settings/SettingsActivity.java | 9 ++- .../util/BridgeStateSaverInitializer.java | 61 +++++++++++++++++++ .../schabi/newpipe/views/CollapsibleView.java | 16 ++--- 30 files changed, 167 insertions(+), 100 deletions(-) create mode 100644 app/src/main/java/org/schabi/newpipe/util/BridgeStateSaverInitializer.java diff --git a/app/build.gradle b/app/build.gradle index 51909c6eb..b32109692 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -116,7 +116,7 @@ ext { androidxRoomVersion = '2.6.1' androidxWorkVersion = '2.8.1' - icepickVersion = '3.2.0' + stateSaverVersion = '1.4.1' exoPlayerVersion = '2.18.7' googleAutoServiceVersion = '1.1.1' groupieVersion = '2.10.1' @@ -243,8 +243,9 @@ dependencies { /** Third-party libraries **/ // Instance state boilerplate elimination - implementation "frankiesardo:icepick:${icepickVersion}" - kapt "frankiesardo:icepick-processor:${icepickVersion}" + implementation 'com.github.livefront:bridge:v2.0.2' + implementation "com.evernote:android-state:$stateSaverVersion" + kapt "com.evernote:android-state-processor:$stateSaverVersion" // HTML parser implementation "org.jsoup:jsoup:1.17.2" diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 435c4e29b..215df0da5 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -13,15 +13,6 @@ ## Rules for ExoPlayer -keep class com.google.android.exoplayer2.** { *; } -## Rules for Icepick. Copy pasted from https://github.com/frankiesardo/icepick --dontwarn icepick.** --keep class icepick.** { *; } --keep class **$$Icepick { *; } --keepclasseswithmembernames class * { - @icepick.* ; -} --keepnames class * { @icepick.State *;} - ## Rules for OkHttp. Copy pasted from https://github.com/square/okhttp -dontwarn okhttp3.** -dontwarn okio.** diff --git a/app/src/main/java/org/schabi/newpipe/App.java b/app/src/main/java/org/schabi/newpipe/App.java index f1876c5dd..d271dba0d 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -21,6 +21,7 @@ import org.schabi.newpipe.extractor.NewPipe; import org.schabi.newpipe.extractor.downloader.Downloader; import org.schabi.newpipe.ktx.ExceptionUtils; import org.schabi.newpipe.settings.NewPipeSettings; +import org.schabi.newpipe.util.BridgeStateSaverInitializer; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.StateSaver; @@ -107,6 +108,7 @@ public class App extends Application implements ImageLoaderFactory { Localization.getPreferredContentCountry(this)); Localization.initPrettyTime(Localization.resolvePrettyTime(getApplicationContext())); + BridgeStateSaverInitializer.init(this); StateSaver.init(this); initNotificationChannels(); diff --git a/app/src/main/java/org/schabi/newpipe/BaseFragment.java b/app/src/main/java/org/schabi/newpipe/BaseFragment.java index 7a06771dd..a55a341e6 100644 --- a/app/src/main/java/org/schabi/newpipe/BaseFragment.java +++ b/app/src/main/java/org/schabi/newpipe/BaseFragment.java @@ -10,8 +10,9 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; -import icepick.Icepick; -import icepick.State; +import com.evernote.android.state.State; +import com.livefront.bridge.Bridge; + public abstract class BaseFragment extends Fragment { protected final String TAG = getClass().getSimpleName() + "@" + Integer.toHexString(hashCode()); @@ -48,7 +49,7 @@ public abstract class BaseFragment extends Fragment { + "savedInstanceState = [" + savedInstanceState + "]"); } super.onCreate(savedInstanceState); - Icepick.restoreInstanceState(this, savedInstanceState); + Bridge.restoreInstanceState(this, savedInstanceState); if (savedInstanceState != null) { onRestoreInstanceState(savedInstanceState); } @@ -70,7 +71,7 @@ public abstract class BaseFragment extends Fragment { @Override public void onSaveInstanceState(@NonNull final Bundle outState) { super.onSaveInstanceState(outState); - Icepick.saveInstanceState(this, outState); + Bridge.saveInstanceState(this, outState); } protected void onRestoreInstanceState(@NonNull final Bundle savedInstanceState) { diff --git a/app/src/main/java/org/schabi/newpipe/RouterActivity.java b/app/src/main/java/org/schabi/newpipe/RouterActivity.java index c59dc7532..197c965ba 100644 --- a/app/src/main/java/org/schabi/newpipe/RouterActivity.java +++ b/app/src/main/java/org/schabi/newpipe/RouterActivity.java @@ -41,6 +41,9 @@ import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; import androidx.preference.PreferenceManager; +import com.evernote.android.state.State; +import com.livefront.bridge.Bridge; + import org.schabi.newpipe.database.stream.model.StreamEntity; import org.schabi.newpipe.databinding.ListRadioIconItemBinding; import org.schabi.newpipe.databinding.SingleChoiceDialogViewBinding; @@ -98,8 +101,6 @@ import java.util.List; import java.util.Optional; import java.util.function.Consumer; -import icepick.Icepick; -import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Single; @@ -152,7 +153,7 @@ public class RouterActivity extends AppCompatActivity { getWindow().setAttributes(params); super.onCreate(savedInstanceState); - Icepick.restoreInstanceState(this, savedInstanceState); + Bridge.restoreInstanceState(this, savedInstanceState); // FragmentManager will take care to recreate (Playlist|Download)Dialog when screen rotates // We used to .setOnDismissListener(dialog -> finish()); when creating these DialogFragments @@ -197,7 +198,7 @@ public class RouterActivity extends AppCompatActivity { @Override protected void onSaveInstanceState(@NonNull final Bundle outState) { super.onSaveInstanceState(outState); - Icepick.saveInstanceState(this, outState); + Bridge.saveInstanceState(this, outState); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt index 0d0d0d48d..60a1cff37 100644 --- a/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt +++ b/app/src/main/java/org/schabi/newpipe/about/AboutActivity.kt @@ -138,8 +138,12 @@ class AboutActivity : AppCompatActivity() { "https://github.com/lisawray/groupie", StandardLicenses.MIT ), SoftwareComponent( - "Icepick", "2015", "Frankie Sardo", - "https://github.com/frankiesardo/icepick", StandardLicenses.EPL1 + "Android-State", "2018", "Evernote", + "https://github.com/Evernote/android-state", StandardLicenses.EPL1 + ), + SoftwareComponent( + "Bridge", "2021", "Livefront", + "https://github.com/livefront/bridge", StandardLicenses.APACHE2 ), SoftwareComponent( "Jsoup", "2009 - 2020", "Jonathan Hedley", diff --git a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java index db2066b27..34a4ba022 100644 --- a/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java +++ b/app/src/main/java/org/schabi/newpipe/download/DownloadDialog.java @@ -39,6 +39,8 @@ import androidx.documentfile.provider.DocumentFile; import androidx.fragment.app.DialogFragment; import androidx.preference.PreferenceManager; +import com.evernote.android.state.State; +import com.livefront.bridge.Bridge; import com.nononsenseapps.filepicker.Utils; import org.schabi.newpipe.MainActivity; @@ -59,6 +61,8 @@ import org.schabi.newpipe.settings.NewPipeSettings; import org.schabi.newpipe.streams.io.NoFileManagerSafeGuard; import org.schabi.newpipe.streams.io.StoredDirectoryHelper; import org.schabi.newpipe.streams.io.StoredFileHelper; +import org.schabi.newpipe.util.AudioTrackAdapter; +import org.schabi.newpipe.util.AudioTrackAdapter.AudioTracksWrapper; import org.schabi.newpipe.util.FilePickerActivityHelper; import org.schabi.newpipe.util.FilenameUtils; import org.schabi.newpipe.util.ListHelper; @@ -67,8 +71,6 @@ import org.schabi.newpipe.util.SecondaryStreamHelper; import org.schabi.newpipe.util.SimpleOnSeekBarChangeListener; import org.schabi.newpipe.util.StreamItemAdapter; import org.schabi.newpipe.util.StreamItemAdapter.StreamInfoWrapper; -import org.schabi.newpipe.util.AudioTrackAdapter; -import org.schabi.newpipe.util.AudioTrackAdapter.AudioTracksWrapper; import org.schabi.newpipe.util.ThemeHelper; import java.io.File; @@ -79,8 +81,6 @@ import java.util.Locale; import java.util.Objects; import java.util.Optional; -import icepick.Icepick; -import icepick.State; import io.reactivex.rxjava3.disposables.CompositeDisposable; import us.shandian.giga.get.MissionRecoveryInfo; import us.shandian.giga.postprocessing.Postprocessing; @@ -214,7 +214,7 @@ public class DownloadDialog extends DialogFragment context = getContext(); setStyle(STYLE_NO_TITLE, ThemeHelper.getDialogTheme(context)); - Icepick.restoreInstanceState(this, savedInstanceState); + Bridge.restoreInstanceState(this, savedInstanceState); this.audioTrackAdapter = new AudioTrackAdapter(wrappedAudioTracks); this.subtitleStreamsAdapter = new StreamItemAdapter<>(wrappedSubtitleStreams); @@ -372,7 +372,7 @@ public class DownloadDialog extends DialogFragment @Override public void onSaveInstanceState(@NonNull final Bundle outState) { super.onSaveInstanceState(outState); - Icepick.saveInstanceState(this, outState); + Bridge.saveInstanceState(this, outState); } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java index a3d3d8b60..8361953b9 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/BaseStateFragment.java @@ -13,6 +13,8 @@ import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.fragment.app.Fragment; +import com.evernote.android.state.State; + import org.schabi.newpipe.BaseFragment; import org.schabi.newpipe.R; import org.schabi.newpipe.error.ErrorInfo; @@ -22,8 +24,6 @@ import org.schabi.newpipe.util.InfoCache; import java.util.concurrent.atomic.AtomicBoolean; -import icepick.State; - public abstract class BaseStateFragment extends BaseFragment implements ViewContract { @State protected AtomicBoolean wasLoading = new AtomicBoolean(); @@ -134,6 +134,7 @@ public abstract class BaseStateFragment extends BaseFragment implements ViewC hideErrorPanel(); } + @Override public void showEmptyState() { isLoading.set(false); if (emptyStateView != null) { diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java index 581e54156..52fb3f29e 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/DescriptionFragment.java @@ -11,6 +11,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.StringRes; +import com.evernote.android.state.State; + import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.stream.Description; @@ -19,8 +21,6 @@ import org.schabi.newpipe.util.Localization; import java.util.List; -import icepick.State; - public class DescriptionFragment extends BaseDescriptionFragment { @State @@ -31,7 +31,7 @@ public class DescriptionFragment extends BaseDescriptionFragment { } public DescriptionFragment() { - // keep empty constructor for IcePick when resuming fragment from memory + // keep empty constructor for State when resuming fragment from memory } diff --git a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java index 11a315d69..33f489d9d 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/detail/VideoDetailFragment.java @@ -56,6 +56,7 @@ import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.preference.PreferenceManager; +import com.evernote.android.state.State; import com.google.android.exoplayer2.PlaybackException; import com.google.android.exoplayer2.PlaybackParameters; import com.google.android.material.appbar.AppBarLayout; @@ -128,7 +129,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import coil.util.CoilUtils; -import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.disposables.Disposable; diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java index dd5eb6c8a..61a361f23 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/BaseListInfoFragment.java @@ -9,6 +9,8 @@ import android.view.View; import androidx.annotation.NonNull; +import com.evernote.android.state.State; + import org.schabi.newpipe.R; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.UserAction; @@ -24,7 +26,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Queue; -import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Single; import io.reactivex.rxjava3.disposables.Disposable; @@ -143,7 +144,7 @@ public abstract class BaseListInfoFragment { + .subscribe((@NonNull final L result) -> { isLoading.set(false); currentInfo = result; currentNextPage = result.getNextPage(); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java index 0dc2fb65a..b7f4a9d3d 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelAboutFragment.java @@ -10,6 +10,8 @@ import android.widget.LinearLayout; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.evernote.android.state.State; + import org.schabi.newpipe.R; import org.schabi.newpipe.extractor.StreamingService; import org.schabi.newpipe.extractor.channel.ChannelInfo; @@ -20,8 +22,6 @@ import org.schabi.newpipe.util.Localization; import java.util.List; -import icepick.State; - public class ChannelAboutFragment extends BaseDescriptionFragment { @State protected ChannelInfo channelInfo; @@ -31,7 +31,7 @@ public class ChannelAboutFragment extends BaseDescriptionFragment { } public ChannelAboutFragment() { - // keep empty constructor for IcePick when resuming fragment from memory + // keep empty constructor for State when resuming fragment from memory } @Override diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java index 3890e4865..56d8a9315 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelFragment.java @@ -25,6 +25,7 @@ import androidx.core.graphics.ColorUtils; import androidx.core.view.MenuProvider; import androidx.preference.PreferenceManager; +import com.evernote.android.state.State; import com.google.android.material.snackbar.Snackbar; import com.google.android.material.tabs.TabLayout; import com.jakewharton.rxbinding4.view.RxView; @@ -60,7 +61,6 @@ import java.util.Queue; import java.util.concurrent.TimeUnit; import coil.util.CoilUtils; -import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.disposables.CompositeDisposable; @@ -249,7 +249,7 @@ public class ChannelFragment extends BaseStateFragment //////////////////////////////////////////////////////////////////////////*/ private void monitorSubscription(final ChannelInfo info) { - final Consumer onError = (Throwable throwable) -> { + final Consumer onError = (final Throwable throwable) -> { animate(binding.channelSubscribeButton, false, 100); showSnackBarError(new ErrorInfo(throwable, UserAction.SUBSCRIPTION_GET, "Get subscription status", currentInfo)); @@ -284,14 +284,14 @@ public class ChannelFragment extends BaseStateFragment } private Function mapOnSubscribe(final SubscriptionEntity subscription) { - return (@NonNull Object o) -> { + return (@NonNull final Object o) -> { subscriptionManager.insertSubscription(subscription); return o; }; } private Function mapOnUnsubscribe(final SubscriptionEntity subscription) { - return (@NonNull Object o) -> { + return (@NonNull final Object o) -> { subscriptionManager.deleteSubscription(subscription); return o; }; @@ -318,7 +318,7 @@ public class ChannelFragment extends BaseStateFragment } private Disposable monitorSubscribeButton(final Function action) { - final Consumer onNext = (@NonNull Object o) -> { + final Consumer onNext = (@NonNull final Object o) -> { if (DEBUG) { Log.d(TAG, "Changed subscription status to this channel!"); } @@ -338,7 +338,7 @@ public class ChannelFragment extends BaseStateFragment } private Consumer> getSubscribeUpdateMonitor(final ChannelInfo info) { - return (List subscriptionEntities) -> { + return (final List subscriptionEntities) -> { if (DEBUG) { Log.d(TAG, "subscriptionManager.subscriptionTable.doOnNext() called with: " + "subscriptionEntities = [" + subscriptionEntities + "]"); diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelTabFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelTabFragment.java index 95ac42eed..5d398821a 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelTabFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/channel/ChannelTabFragment.java @@ -9,6 +9,8 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.evernote.android.state.State; + import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.PlaylistControlBinding; import org.schabi.newpipe.error.UserAction; @@ -32,13 +34,12 @@ import java.util.List; import java.util.function.Supplier; import java.util.stream.Collectors; -import icepick.State; import io.reactivex.rxjava3.core.Single; public class ChannelTabFragment extends BaseListInfoFragment implements PlaylistControlViewHolder { - // states must be protected and not private for IcePick being able to access them + // states must be protected and not private for State being able to access them @State protected ListLinkHandler tabHandler; @State @@ -156,6 +157,7 @@ public class ChannelTabFragment extends BaseListInfoFragment streamItems = infoListAdapter.getItemsList().stream() .filter(StreamInfoItem.class::isInstance) diff --git a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java index 4eb73520f..a585a5b39 100644 --- a/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java +++ b/app/src/main/java/org/schabi/newpipe/fragments/list/comments/CommentRepliesFragment.java @@ -12,6 +12,8 @@ import androidx.annotation.Nullable; import androidx.constraintlayout.widget.ConstraintLayout; import androidx.core.text.HtmlCompat; +import com.evernote.android.state.State; + import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.CommentRepliesHeaderBinding; import org.schabi.newpipe.error.UserAction; @@ -30,7 +32,6 @@ import org.schabi.newpipe.util.text.TextLinkifier; import java.util.Queue; import java.util.function.Supplier; -import icepick.State; import io.reactivex.rxjava3.core.Single; import io.reactivex.rxjava3.disposables.CompositeDisposable; 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 b90dccb17..6823e13d3 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 @@ -11,6 +11,8 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.ActionBar; +import com.evernote.android.state.State; + import org.schabi.newpipe.R; import org.schabi.newpipe.error.ErrorInfo; import org.schabi.newpipe.error.UserAction; @@ -29,7 +31,6 @@ import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.KioskTranslator; import org.schabi.newpipe.util.Localization; -import icepick.State; import io.reactivex.rxjava3.core.Single; /** 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 eef3455ae..18c60400b 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 @@ -40,6 +40,8 @@ import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; +import com.evernote.android.state.State; + import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.FragmentSearchBinding; import org.schabi.newpipe.error.ErrorInfo; @@ -77,7 +79,6 @@ import java.util.Queue; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Observable; import io.reactivex.rxjava3.core.Single; @@ -550,7 +551,7 @@ public class SearchFragment extends BaseListFragment { + searchEditText.setOnFocusChangeListener((final View v, final boolean hasFocus) -> { if (DEBUG) { Log.d(TAG, "onFocusChange() called with: " + "v = [" + v + "], hasFocus = [" + hasFocus + "]"); @@ -611,7 +612,7 @@ public class SearchFragment extends BaseListFragment { + (final TextView v, final int actionId, final KeyEvent event) -> { if (DEBUG) { Log.d(TAG, "onEditorAction() called with: v = [" + v + "], " + "actionId = [" + actionId + "], event = [" + event + "]"); 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 a366723e0..a5e1594d1 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 @@ -19,6 +19,8 @@ import androidx.fragment.app.FragmentManager; import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; +import com.evernote.android.state.State; + import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import org.schabi.newpipe.NewPipeDatabase; @@ -36,16 +38,15 @@ import org.schabi.newpipe.local.holder.LocalBookmarkPlaylistItemHolder; import org.schabi.newpipe.local.holder.RemoteBookmarkPlaylistItemHolder; import org.schabi.newpipe.local.playlist.LocalPlaylistManager; import org.schabi.newpipe.local.playlist.RemotePlaylistManager; -import org.schabi.newpipe.util.debounce.DebounceSavable; -import org.schabi.newpipe.util.debounce.DebounceSaver; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.OnClickGesture; +import org.schabi.newpipe.util.debounce.DebounceSavable; +import org.schabi.newpipe.util.debounce.DebounceSaver; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; -import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.disposables.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 b99291309..a4e53aab1 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 @@ -44,11 +44,11 @@ import androidx.lifecycle.ViewModelProvider import androidx.preference.PreferenceManager import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView +import com.evernote.android.state.State import com.xwray.groupie.GroupieAdapter import com.xwray.groupie.Item import com.xwray.groupie.OnItemClickListener import com.xwray.groupie.OnItemLongClickListener -import icepick.State import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers import io.reactivex.rxjava3.core.Single import io.reactivex.rxjava3.disposables.CompositeDisposable 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 1fea7e155..fac358075 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 @@ -15,6 +15,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.viewbinding.ViewBinding; +import com.evernote.android.state.State; import com.google.android.material.snackbar.Snackbar; import org.reactivestreams.Subscriber; @@ -45,7 +46,6 @@ import java.util.Comparator; import java.util.List; import java.util.Objects; -import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.disposables.CompositeDisposable; import io.reactivex.rxjava3.disposables.Disposable; @@ -368,6 +368,7 @@ public class StatisticsPlaylistFragment } } + @Override public PlayQueue getPlayQueue() { return getPlayQueue(0); } 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 d5ae431fa..c87d9cccc 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 @@ -26,6 +26,8 @@ import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.RecyclerView; import androidx.viewbinding.ViewBinding; +import com.evernote.android.state.State; + import org.reactivestreams.Subscriber; import org.reactivestreams.Subscription; import org.schabi.newpipe.NewPipeDatabase; @@ -49,12 +51,12 @@ import org.schabi.newpipe.local.BaseLocalListFragment; import org.schabi.newpipe.local.history.HistoryRecordManager; import org.schabi.newpipe.player.playqueue.PlayQueue; import org.schabi.newpipe.player.playqueue.SinglePlayQueue; -import org.schabi.newpipe.util.debounce.DebounceSavable; -import org.schabi.newpipe.util.debounce.DebounceSaver; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.OnClickGesture; import org.schabi.newpipe.util.PlayButtonHelper; +import org.schabi.newpipe.util.debounce.DebounceSavable; +import org.schabi.newpipe.util.debounce.DebounceSaver; import org.schabi.newpipe.util.external_communication.ShareUtils; import java.util.ArrayList; @@ -63,7 +65,6 @@ import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; -import icepick.State; import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; import io.reactivex.rxjava3.core.Single; import io.reactivex.rxjava3.disposables.CompositeDisposable; @@ -843,6 +844,7 @@ public class LocalPlaylistFragment extends BaseLocalListFragment) { diff --git a/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java b/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java index dfb49a25b..7e74c3848 100644 --- a/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java +++ b/app/src/main/java/org/schabi/newpipe/player/helper/PlaybackParameterDialog.java @@ -24,6 +24,9 @@ import androidx.core.math.MathUtils; import androidx.fragment.app.DialogFragment; import androidx.preference.PreferenceManager; +import com.evernote.android.state.State; +import com.livefront.bridge.Bridge; + import org.schabi.newpipe.R; import org.schabi.newpipe.databinding.DialogPlaybackParameterBinding; import org.schabi.newpipe.player.ui.VideoPlayerUi; @@ -37,9 +40,6 @@ import java.util.function.DoubleConsumer; import java.util.function.DoubleFunction; import java.util.function.DoubleSupplier; -import icepick.Icepick; -import icepick.State; - public class PlaybackParameterDialog extends DialogFragment { private static final String TAG = "PlaybackParameterDialog"; @@ -135,7 +135,7 @@ public class PlaybackParameterDialog extends DialogFragment { @Override public void onSaveInstanceState(@NonNull final Bundle outState) { super.onSaveInstanceState(outState); - Icepick.saveInstanceState(this, outState); + Bridge.saveInstanceState(this, outState); } /*////////////////////////////////////////////////////////////////////////// @@ -146,7 +146,7 @@ public class PlaybackParameterDialog extends DialogFragment { @Override public Dialog onCreateDialog(@Nullable final Bundle savedInstanceState) { assureCorrectAppLanguage(getContext()); - Icepick.restoreInstanceState(this, savedInstanceState); + Bridge.restoreInstanceState(this, savedInstanceState); binding = DialogPlaybackParameterBinding.inflate(getLayoutInflater()); initUI(); diff --git a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java index 529e53442..0d57ce174 100644 --- a/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java +++ b/app/src/main/java/org/schabi/newpipe/settings/SettingsActivity.java @@ -21,7 +21,9 @@ import androidx.fragment.app.FragmentManager; import androidx.preference.Preference; import androidx.preference.PreferenceFragmentCompat; +import com.evernote.android.state.State; import com.jakewharton.rxbinding4.widget.RxTextView; +import com.livefront.bridge.Bridge; import org.schabi.newpipe.MainActivity; import org.schabi.newpipe.R; @@ -41,9 +43,6 @@ import org.schabi.newpipe.views.FocusOverlayView; import java.util.concurrent.TimeUnit; -import icepick.Icepick; -import icepick.State; - /* * Created by Christian Schabesberger on 31.08.15. * @@ -93,7 +92,7 @@ public class SettingsActivity extends AppCompatActivity implements assureCorrectAppLanguage(this); super.onCreate(savedInstanceBundle); - Icepick.restoreInstanceState(this, savedInstanceBundle); + Bridge.restoreInstanceState(this, savedInstanceBundle); final boolean restored = savedInstanceBundle != null; final SettingsLayoutBinding settingsLayoutBinding = @@ -125,7 +124,7 @@ public class SettingsActivity extends AppCompatActivity implements @Override protected void onSaveInstanceState(@NonNull final Bundle outState) { super.onSaveInstanceState(outState); - Icepick.saveInstanceState(this, outState); + Bridge.saveInstanceState(this, outState); } @Override diff --git a/app/src/main/java/org/schabi/newpipe/util/BridgeStateSaverInitializer.java b/app/src/main/java/org/schabi/newpipe/util/BridgeStateSaverInitializer.java new file mode 100644 index 000000000..aeda4717c --- /dev/null +++ b/app/src/main/java/org/schabi/newpipe/util/BridgeStateSaverInitializer.java @@ -0,0 +1,61 @@ +package org.schabi.newpipe.util; + +import android.content.Context; +import android.os.Bundle; +import android.os.Parcelable; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.evernote.android.state.StateSaver; +import com.livefront.bridge.Bridge; +import com.livefront.bridge.SavedStateHandler; +import com.livefront.bridge.ViewSavedStateHandler; + +/** + * Configures Bridge's state saver. + */ +public final class BridgeStateSaverInitializer { + + public static void init(final Context context) { + Bridge.initialize( + context, + new SavedStateHandler() { + @Override + public void saveInstanceState( + @NonNull final Object target, + @NonNull final Bundle state) { + StateSaver.saveInstanceState(target, state); + } + + @Override + public void restoreInstanceState( + @NonNull final Object target, + @Nullable final Bundle state) { + StateSaver.restoreInstanceState(target, state); + } + }, + new ViewSavedStateHandler() { + @NonNull + @Override + public Parcelable saveInstanceState( + @NonNull final T target, + @Nullable final Parcelable parentState) { + return StateSaver.saveInstanceState(target, parentState); + } + + @Nullable + @Override + public Parcelable restoreInstanceState( + @NonNull final T target, + @Nullable final Parcelable state) { + return StateSaver.restoreInstanceState(target, state); + } + } + ); + } + + private BridgeStateSaverInitializer() { + } +} diff --git a/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java b/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java index f79e1e3a3..91b5ebd07 100644 --- a/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java +++ b/app/src/main/java/org/schabi/newpipe/views/CollapsibleView.java @@ -19,6 +19,9 @@ package org.schabi.newpipe.views; +import static org.schabi.newpipe.MainActivity.DEBUG; +import static java.lang.annotation.RetentionPolicy.SOURCE; + import android.animation.ValueAnimator; import android.content.Context; import android.os.Parcelable; @@ -29,18 +32,15 @@ import android.widget.LinearLayout; import androidx.annotation.IntDef; import androidx.annotation.Nullable; +import com.evernote.android.state.State; +import com.livefront.bridge.Bridge; + import org.schabi.newpipe.ktx.ViewUtils; import java.lang.annotation.Retention; import java.util.ArrayList; import java.util.List; -import icepick.Icepick; -import icepick.State; - -import static java.lang.annotation.RetentionPolicy.SOURCE; -import static org.schabi.newpipe.MainActivity.DEBUG; - /** * A view that can be fully collapsed and expanded. */ @@ -207,12 +207,12 @@ public class CollapsibleView extends LinearLayout { @Nullable @Override public Parcelable onSaveInstanceState() { - return Icepick.saveInstanceState(this, super.onSaveInstanceState()); + return Bridge.saveInstanceState(this, super.onSaveInstanceState()); } @Override public void onRestoreInstanceState(final Parcelable state) { - super.onRestoreInstanceState(Icepick.restoreInstanceState(this, state)); + super.onRestoreInstanceState(Bridge.restoreInstanceState(this, state)); ready(); }