diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9ae3a77c2..54415858e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -47,10 +47,10 @@ jobs: BRANCH: ${{ github.head_ref }} run: git checkout -B "$BRANCH" - - name: set up JDK 17 + - name: set up JDK uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 distribution: "temurin" cache: 'gradle' @@ -88,10 +88,10 @@ jobs: sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm - - name: set up JDK 17 + - name: set up JDK uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 distribution: "temurin" cache: 'gradle' @@ -121,10 +121,10 @@ jobs: with: fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis - - name: Set up JDK 17 + - name: Set up JDK uses: actions/setup-java@v4 with: - java-version: 17 + java-version: 21 distribution: "temurin" cache: 'gradle' diff --git a/app/build.gradle b/app/build.gradle index 081bc2766..d0426d5a2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -92,6 +92,7 @@ android { buildFeatures { viewBinding true + buildConfig true } packagingOptions { @@ -112,7 +113,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' @@ -198,7 +199,8 @@ dependencies { // name and the commit hash with the commit hash of the (pushed) commit you want to test // This works thanks to JitPack: https://jitpack.io/ implementation 'com.github.TeamNewPipe:nanojson:1d9e1aea9049fc9f85e68b43ba39fe7be1c1f751' - implementation 'com.github.TeamNewPipe:NewPipeExtractor:v0.24.2' + // WORKAROUND: v0.24.2 can't be resolved by jitpack -> use git commit hash instead + implementation 'com.github.TeamNewPipe:NewPipeExtractor:176da72cb4c3ec4679211339b0e59f6b01bf2f52' implementation 'com.github.TeamNewPipe:NoNonsense-FilePicker:5.0.0' /** Checkstyle **/ @@ -234,8 +236,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 d92425d20..9bc25d55d 100644 --- a/app/src/main/java/org/schabi/newpipe/App.java +++ b/app/src/main/java/org/schabi/newpipe/App.java @@ -19,11 +19,12 @@ 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.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ServiceHelper; import org.schabi.newpipe.util.StateSaver; +import org.schabi.newpipe.util.image.ImageStrategy; +import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.image.PreferredImageQuality; import java.io.IOException; @@ -101,6 +102,7 @@ public class App extends Application { 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 7f148e9b5..045278da7 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 95b54f65a..1d1e166e7 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; @@ -127,7 +128,6 @@ import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -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 fd382adbf..d67cd11f1 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; @@ -50,16 +51,15 @@ import org.schabi.newpipe.util.ExtractorHelper; import org.schabi.newpipe.util.Localization; import org.schabi.newpipe.util.NavigationHelper; import org.schabi.newpipe.util.StateSaver; -import org.schabi.newpipe.util.image.ImageStrategy; -import org.schabi.newpipe.util.image.PicassoHelper; import org.schabi.newpipe.util.ThemeHelper; import org.schabi.newpipe.util.external_communication.ShareUtils; +import org.schabi.newpipe.util.image.ImageStrategy; +import org.schabi.newpipe.util.image.PicassoHelper; import java.util.List; import java.util.Queue; import java.util.concurrent.TimeUnit; -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 304eaf55a..0514eefde 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 e8c5b1e34..61eb4c8d2 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(); } diff --git a/app/src/main/res/layout-land/list_stream_card_item.xml b/app/src/main/res/layout-land/list_stream_card_item.xml deleted file mode 120000 index 70228ee1d..000000000 --- a/app/src/main/res/layout-land/list_stream_card_item.xml +++ /dev/null @@ -1 +0,0 @@ -../layout/list_stream_item.xml \ No newline at end of file diff --git a/app/src/main/res/layout-land/list_stream_card_item.xml b/app/src/main/res/layout-land/list_stream_card_item.xml new file mode 100644 index 000000000..793942568 --- /dev/null +++ b/app/src/main/res/layout-land/list_stream_card_item.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + diff --git a/build.gradle b/build.gradle index 6d19a6f8a..d93abc4c0 100644 --- a/build.gradle +++ b/build.gradle @@ -1,13 +1,13 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.9.10' + ext.kotlin_version = '1.9.25' repositories { google() mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.2.0' + classpath 'com.android.tools.build:gradle:8.7.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle.properties b/gradle.properties index 0ca913222..ed32303da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,3 @@ -android.defaults.buildfeatures.buildconfig=true android.enableJetifier=false android.nonFinalResIds=false android.nonTransitiveRClass=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d022615ff..4ea536e77 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=38f66cd6eef217b4c35855bb11ea4e9fbc53594ccccb5fb82dfd317ef8c2c5a3 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +distributionSha256Sum=d725d707bfabd4dfdc958c624003b3c80accc03f7037b5122c4b1d0ef15cecab +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists