1- package org .schabi .newpipe .settings ;
1+ package org .schabi .newpipe .settings .migration ;
2+
3+ import static org .schabi .newpipe .MainActivity .DEBUG ;
4+ import static org .schabi .newpipe .extractor .ServiceList .SoundCloud ;
5+ import static org .schabi .newpipe .extractor .ServiceList .YouTube ;
26
37import android .content .Context ;
48import android .content .SharedPreferences ;
59import android .util .Log ;
610
711import androidx .annotation .NonNull ;
8- import androidx .appcompat .app .AlertDialog ;
912import androidx .core .util .Consumer ;
1013import androidx .preference .PreferenceManager ;
1114
2528import java .util .Set ;
2629import java .util .stream .Collectors ;
2730
28- import static org .schabi .newpipe .MainActivity .DEBUG ;
29- import static org .schabi .newpipe .extractor .ServiceList .SoundCloud ;
30-
3131/**
32- * In order to add a migration, follow these steps, given P is the previous version:<br>
33- * - in the class body add a new {@code MIGRATION_P_P+1 = new Migration(P, P+1) { ... }} and put in
34- * the {@code migrate()} method the code that need to be run when migrating from P to P+1<br>
35- * - add {@code MIGRATION_P_P+1} at the end of {@link SettingMigrations#SETTING_MIGRATIONS}<br>
36- * - increment {@link SettingMigrations#VERSION}'s value by 1 (so it should become P+1)
32+ * This class contains the code to migrate the settings from one version to another.
33+ * Migrations are run automatically when the app is started and the settings version changed.
34+ * <br>
35+ * In order to add a migration, follow these steps, given {@code P} is the previous version:
36+ * <ul>
37+ * <li>in the class body add a new {@code MIGRATION_P_P+1 = new Migration(P, P+1) { ... }} and put
38+ * in the {@code migrate()} method the code that need to be run
39+ * when migrating from {@code P} to {@code P+1}</li>
40+ * <li>add {@code MIGRATION_P_P+1} at the end of {@link SettingMigrations#SETTING_MIGRATIONS}</li>
41+ * <li>increment {@link SettingMigrations#VERSION}'s value by 1
42+ * (so it becomes {@code P+1})</li>
43+ * </ul>
44+ * Migrations can register UI actions using {@link MigrationManager#addMigrationInfo(Consumer)}
45+ * that will be performed after the UI is initialized to inform the user about changes
46+ * that were applied by migrations.
3747 */
3848public final class SettingMigrations {
3949
4050 private static final String TAG = SettingMigrations .class .toString ();
4151 private static SharedPreferences sp ;
4252
43- /**
44- * List of UI actions that are performed after the UI is initialized (e.g. showing alert
45- * dialogs) to inform the user about changes that were applied by migrations.
46- */
47- private static final List <Consumer <Context >> MIGRATION_INFO = new ArrayList <>();
48-
4953 private static final Migration MIGRATION_0_1 = new Migration (0 , 1 ) {
5054 @ Override
5155 public void migrate (@ NonNull final Context context ) {
@@ -169,16 +173,63 @@ protected void migrate(@NonNull final Context context) {
169173 && kioskTab .getKioskServiceId () == SoundCloud .getServiceId ()
170174 && kioskTab .getKioskId ().equals ("Top 50" )))
171175 .collect (Collectors .toUnmodifiableList ());
172- if (tabs .size () != cleanedTabs .size ()) {
176+ if (tabs .size () != cleanedTabs .size () || DEBUG ) { // TODO: remove debug condition
173177 tabsManager .saveTabs (cleanedTabs );
174178 // create an AlertDialog to inform the user about the change
175- MIGRATION_INFO .add ((Context uiContext ) -> new AlertDialog .Builder (uiContext )
176- .setTitle (R .string .migration_info_6_7_title )
177- .setMessage (R .string .migration_info_6_7_message )
178- .setPositiveButton (R .string .ok , null )
179- .setCancelable (false )
180- .create ()
181- .show ());
179+ MigrationManager .addMigrationInfo (uiContext ->
180+ MigrationManager .createMigrationInfoDialog (
181+ uiContext ,
182+ uiContext .getString (R .string .migration_info_6_7_title ),
183+ uiContext .getString (R .string .migration_info_6_7_message ))
184+ .show ());
185+ }
186+ }
187+ };
188+
189+ private static final Migration MIGRATION_7_8 = new Migration (7 , 8 ) {
190+ @ Override
191+ protected void migrate (@ NonNull final Context context ) {
192+ // YouTube remove the combined Trending kiosk, see
193+ // https://github.com/TeamNewPipe/NewPipe/discussions/12445 for more information.
194+ // If the user has a dedicated YouTube/Trending kiosk tab,
195+ // it is removed and replaced with the new live kiosk tab.
196+ // The default trending kiosk tab is not touched
197+ // because it uses the default kiosk provided by the extractor
198+ // and is thus updated automatically.
199+ final TabsManager tabsManager = TabsManager .getManager (context );
200+ final List <Tab > tabs = tabsManager .getTabs ();
201+ final boolean hadYtTrendingTab = tabs .stream ()
202+ .anyMatch (tab -> !(tab instanceof Tab .KioskTab kioskTab
203+ && kioskTab .getKioskServiceId () == YouTube .getServiceId ()
204+ && kioskTab .getKioskId ().equals ("Trending" )));
205+ if (hadYtTrendingTab ) {
206+ final List <Tab > cleanedTabs = new ArrayList <>();
207+ for (final Tab tab : tabs ) {
208+ if (tab instanceof Tab .KioskTab kioskTab
209+ && kioskTab .getKioskServiceId () == YouTube .getServiceId ()
210+ && kioskTab .getKioskId ().equals ("Trending" )) {
211+ // replace the YouTube Trending tab with the new live kiosk tab
212+ // TODO: use the correct kiosk ID for the live kiosk tab
213+ cleanedTabs .add (new Tab .KioskTab (YouTube .getServiceId (), "Live" ));
214+ } else {
215+ cleanedTabs .add (tab );
216+ }
217+ }
218+ tabsManager .saveTabs (cleanedTabs );
219+ }
220+
221+ final boolean hasDefaultTrendingTab = tabs .stream ()
222+ .anyMatch (tab -> tab instanceof Tab .DefaultKioskTab );
223+
224+ // TODO: remove debugging code
225+ if (hadYtTrendingTab || hasDefaultTrendingTab || newVersion == VERSION ) {
226+ // User is informed about the change
227+ MigrationManager .addMigrationInfo (uiContext ->
228+ MigrationManager .createMigrationInfoDialog (
229+ uiContext ,
230+ uiContext .getString (R .string .migration_info_7_8_title ),
231+ uiContext .getString (R .string .migration_info_7_8_message ))
232+ .show ());
182233 }
183234 }
184235 };
@@ -196,26 +247,28 @@ protected void migrate(@NonNull final Context context) {
196247 MIGRATION_3_4 ,
197248 MIGRATION_4_5 ,
198249 MIGRATION_5_6 ,
199- MIGRATION_6_7
250+ MIGRATION_6_7 ,
251+ MIGRATION_7_8 ,
200252 };
201253
202254 /**
203255 * Version number for preferences. Must be incremented every time a migration is necessary.
204256 */
205- private static final int VERSION = 7 ;
257+ private static final int VERSION = 8 ;
206258
207259
208- public static void runMigrationsIfNeeded (@ NonNull final Context context ) {
260+ static void runMigrationsIfNeeded (@ NonNull final Context context ) {
209261 // setup migrations and check if there is something to do
210262 sp = PreferenceManager .getDefaultSharedPreferences (context );
211263 final String lastPrefVersionKey = context .getString (R .string .last_used_preferences_version );
212- final int lastPrefVersion = sp .getInt (lastPrefVersionKey , 0 );
264+ //final int lastPrefVersion = sp.getInt(lastPrefVersionKey, 0);
265+ final int lastPrefVersion = 6 ; // TODO: remove this line after testing
213266
214267 // no migration to run, already up to date
215268 if (App .getApp ().isFirstRun ()) {
216269 sp .edit ().putInt (lastPrefVersionKey , VERSION ).apply ();
217270 return ;
218- } else if (lastPrefVersion == VERSION ) {
271+ } else if (lastPrefVersion == VERSION && ! DEBUG ) { // TODO: remove DEBUG check
219272 return ;
220273 }
221274
@@ -249,21 +302,6 @@ public static void runMigrationsIfNeeded(@NonNull final Context context) {
249302 sp .edit ().putInt (lastPrefVersionKey , currentVersion ).apply ();
250303 }
251304
252- /**
253- * Perform UI actions informing about migrations that took place if they are present.
254- * @param context Context that can be used to show dialogs/snackbars/toasts
255- */
256- public static void showUserInfoIfPresent (@ NonNull final Context context ) {
257- for (final Consumer <Context > consumer : MIGRATION_INFO ) {
258- try {
259- consumer .accept (context );
260- } catch (final Exception e ) {
261- ErrorUtil .showUiErrorSnackbar (context , "Showing migration info to the user" , e );
262- }
263- }
264- MIGRATION_INFO .clear ();
265- }
266-
267305 private SettingMigrations () { }
268306
269307 abstract static class Migration {
@@ -282,7 +320,7 @@ protected Migration(final int oldVersion, final int newVersion) {
282320 * the current settings version.
283321 */
284322 private boolean shouldMigrate (final int currentVersion ) {
285- return oldVersion >= currentVersion ;
323+ return oldVersion >= currentVersion || newVersion == VERSION ;
286324 }
287325
288326 protected abstract void migrate (@ NonNull Context context );
0 commit comments