Skip to content

[Multiple-Profile]feat: define trigger app restart guard#20652

Merged
mikehardy merged 1 commit intoankidroid:mainfrom
criticalAY:mp/tirgger-restart
Apr 19, 2026
Merged

[Multiple-Profile]feat: define trigger app restart guard#20652
mikehardy merged 1 commit intoankidroid:mainfrom
criticalAY:mp/tirgger-restart

Conversation

@criticalAY
Copy link
Copy Markdown
Contributor

@criticalAY criticalAY commented Apr 4, 2026

Note

Assisted-by: Gemini Pro - unit tests (it was fairly simple so let Gemini Handle)

  • All unit test are written by Gemini Pro but I have verified each one of them

Purpose / Description

Handle restart app logic i.e. complete the TODO that was left beind, put a guard rail to avoid accidental profile switches

Fixes

Approach

NA

How Has This Been Tested?

Unit test

Learning (optional, can help others)

NA

Checklist

Please, go through these checks before submitting the PR.

  • You have a descriptive commit message with a short title (first line, max 50 chars).
  • You have commented your code, particularly in hard-to-understand areas
  • You have performed a self-review of your own code
  • UI changes: include screenshots of all affected screens (in particular showing any new or changed strings)
  • UI Changes: You have tested your change using the Google Accessibility Scanner

@criticalAY criticalAY changed the title feat: define trigger app restart logic [Multiple-Profile]feat: define trigger app restart logic Apr 4, 2026
Comment thread AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileManager.kt Outdated
@david-allison david-allison added the Needs Author Reply Waiting for a reply from the original author label Apr 4, 2026
@criticalAY criticalAY force-pushed the mp/tirgger-restart branch 2 times, most recently from ffb8d50 to 727f17d Compare April 4, 2026 22:57
@criticalAY criticalAY requested a review from david-allison April 4, 2026 22:58
@criticalAY criticalAY removed the Needs Author Reply Waiting for a reply from the original author label Apr 4, 2026
@criticalAY criticalAY changed the title [Multiple-Profile]feat: define trigger app restart logic [Multiple-Profile]feat: define trigger app restart guard Apr 4, 2026
@criticalAY criticalAY force-pushed the mp/tirgger-restart branch from 727f17d to b391840 Compare April 5, 2026 18:04
Copy link
Copy Markdown
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about (untested; needs unit tests fixing):

Index: AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileManager.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileManager.kt b/AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileManager.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileManager.kt	(revision b3918400cb409c6746548d879f47e6529873fb94)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileManager.kt	(date 1775413679178)
@@ -154,13 +154,10 @@
     /**
      * Persists [newProfileId] as the active profile.
      *
-     * **Do not call directly.** Use [ProfileSwitchGuard] to ensure
-     * backup/sync safety checks are run before switching.
-     * Direct calls bypass all safety guards and may corrupt data.
-     *
      * @param newProfileId The [ProfileId] to activate on next launch.
      */
     @VisibleForTesting
+    context(_: ProfileSwitchContext)
     fun switchActiveProfile(newProfileId: ProfileId) {
         Timber.i("Switching profile to ID: $newProfileId")
         profileRegistry.setLastActiveProfileId(newProfileId)
@@ -336,6 +333,17 @@
         fun contains(id: ProfileId): Boolean = globalPrefs.contains(id.value)
     }
 
+    /**
+     * A context representing that it is safe to switch profiles
+     *
+     * - Backups are not occurring
+     * - Sync is completed
+     * - Collection is not open
+     *
+     * @see ProfileSwitchGuard
+     */
+    object ProfileSwitchContext
+
     companion object {
         private const val MAX_ATTEMPTS = 10
         const val PROFILE_REGISTRY_FILENAME = "profiles_prefs"
Index: AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileSwitchGuard.kt
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileSwitchGuard.kt b/AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileSwitchGuard.kt
--- a/AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileSwitchGuard.kt	(revision b3918400cb409c6746548d879f47e6529873fb94)
+++ b/AnkiDroid/src/main/java/com/ichi2/anki/multiprofile/ProfileSwitchGuard.kt	(date 1775413676674)
@@ -17,6 +17,8 @@
 
 package com.ichi2.anki.multiprofile
 
+import com.ichi2.anki.multiprofile.ProfileManager.ProfileSwitchContext
+
 /**
  * Guards profile switching by running a set of safety checks
  * before delegating to [ProfileManager].
@@ -70,7 +72,7 @@
         }
 
         return if (activeBlockedReasons.isEmpty()) {
-            profileManager.switchActiveProfile(newProfileId)
+            with(ProfileSwitchContext) { profileManager.switchActiveProfile(newProfileId) }
             Result.Success
         } else {
             Result.Blocked(activeBlockedReasons)

@david-allison david-allison added the Needs Author Reply Waiting for a reply from the original author label Apr 5, 2026
- unit test for profile guard

Assisted-by: Gemini 3.1 Pro
- Unit test: ProfileSwitchGuardTest
@criticalAY criticalAY force-pushed the mp/tirgger-restart branch from b391840 to 9e3dab7 Compare April 5, 2026 19:18
@criticalAY
Copy link
Copy Markdown
Contributor Author

Surely, thankyou for the patch! (updated test)

@criticalAY criticalAY removed the Needs Author Reply Waiting for a reply from the original author label Apr 5, 2026
Copy link
Copy Markdown
Member

@david-allison david-allison left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feels over-engineered vs closing the collection, but I'll take it on trust.

LGTM

@david-allison david-allison added Needs Second Approval Has one approval, one more approval to merge and removed Needs Review labels Apr 5, 2026
Copy link
Copy Markdown
Member

@mikehardy mikehardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems reasonable enough - this would allow us to expose reasons to the user vs just closing collection, seems that could have UX value

@mikehardy mikehardy added this pull request to the merge queue Apr 19, 2026
@mikehardy mikehardy added Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) and removed Needs Second Approval Has one approval, one more approval to merge labels Apr 19, 2026
Merged via the queue into ankidroid:main with commit 4152002 Apr 19, 2026
15 checks passed
@github-actions github-actions bot added this to the 2.24 release milestone Apr 19, 2026
@github-actions github-actions bot removed the Pending Merge Things with approval that are waiting future merge (e.g. targets a future release, CI wait, etc) label Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants