ankidroid / ankidroid/Anki-Android
Add support for profiles
- 主要言語
- Kotlin
- スター
- 11.8k
- フォーク
- 2.9k
- 平均マージ
- 2日 3時間
- マージ済み PR(30日)
- 171
説明
> [!NOTE]
> Users can use **parallel builds** to simulate this feature: https://github.com/ankidroid/Anki-Android/wiki/FAQ#how-to-use-different-anki-profiles
----
This issue can be resolved when AnkiDroid users can have multiple profiles on the same device with the same app.
This is a duplicate of #2545. This 10 year old issue is FAR too long. A lot of its comment are not relevant anymore. As I don't want to delete them, I'll just copy here what is still relevant in 2025. It then will be easier for any interested contributor to read it, and for people to exchange idea about what the feature will looks like without having to read the full history.
https://github.com/user-attachments/assets/f485cdcb-27c6-4248-9f33-039fca7a3b0f shows how the feature works on AnkiMobile. We don't and can't use the exact same UI because we use material and not UIKit, but we certainly should have at least those features. Adding, deleting, renaming the profile. A very quick access to profile switching for users that share often. Switch with a shortcut for people on chromebook (probably reusing the shortcut of anki desktop)
I'll start with Draft of David's thought
>
>
> Anki's screen
>
> 
>
>
>
> **Functionality**
> * A profile does not require an AnkiWeb account
> * A profile can be opened
> * Each profile contains a separate `Collection`, set of `SharedPreferences` and **WebView Cookies**
> * A user will be able to add a named profile.
> * Preferences may be copied from another profile
> * A user will be able to rename an existing profile
> * A user will be able to delete a profile
> * We will not implement 'Downgrade & Quit/Open Backup' here. The Deck Picker contains 'Open Backup' already, and this screen will not be used by the majority of users.
> * Widgets are ignored for now
> * A user may select the app shortcuts they want to appear
> * Profile names may contain special characters.
> * When creating a folder, these characters are removed
> * If the user is in a private folder, the folders under `/files` are the profile
> * If the user is in a public folder, use `AnkiDroid Profiles` by default
> * But allow a user to change the location on a per-folder basis
>
> **Defaults**
> * The default Profile name is AnkiDroid
> * We have a 'default' profile, which will launch on open
> * The default is the last-opened profile
> * The 'open profile' may be shown on launch instead
>
> **Unknown**
> * How do we handle 'Manage Data'
> * How do we handle the API
>
> **Constraints**
> * The standard onboarding process should not be affected, neither will the default user experience. Profiles are an extra
> * We should not modify the navigation drawer, as this is soon to be removed
>
> **TODO:**
>
> * What happens when a profile is deleted?
> * Offer to permanently delete linked collection folder + backups?
> * [Security] if AnkiDroid is acting as a file manager, ensure you can't use this to delete an arbitrary folder
> * Can two profiles have the same name?
> * Technically, yes, but block it
> * AnkiDroid needs to know the current profile and load this efficiently (blocker on hot startup path)
> * Should the current profile name be visible, are there latency concerns if it's on the hot path?
> * What can go wrong? How to recover?
Brayan's answer
> > How do we handle WebView cookies
> Specifically: Shared Decks -> AnkiWeb login
>
> Share it, I guess
>
> > How do we handle app shortcuts
>
> Maybe add the profile name to each one? (I have no idea if that is possible) -> Add (David), Study (Arthur)
>
> > Profile names may contain special characters. Should the name map to a folder name?
>
> Mimic Anki desktop behavior or allow any characters in the profile name but strip the unallowed in the folder name
>
> > Our current folder is AnkiDroid
>
> For app private builds, doesn't seem to be a problem
>
> For full builds, ideally the profile should be in `AnkiDroid/profile name` but `AnkiDroid/` already has the collection. The easiest solution I see is keeping the old `AnkiDro id/` folder and if the user tries to create a new profile, default it to a new directory called `AnkiDroid profiles` or some better name (ideally one that doesn't need to be localized). For new installs, we can default to this new folder
David:
> I specifically chose `AnkiDroid` so we're not writing to the root of `com.ichi2.anki/files` in the private directory (so `AnkiDroid` can be the default profile)
>
> For the public directory, `AnkiDroid Profiles` seems ideal
>
> >> How do we handle app shortcuts
> > Maybe add the profile name to each one? (I have no idea if that is possible) -> Add (David), Study (Arthur)
>
> I believe this is workable. Our shortcuts are dynamic.
> * + We want a per-profile setting to determine which icons (if any) appear
>
> ----
>
> * Widgets: probably 'unsupported' for now and have them tied to the current profile
> * API: probably the same
>
> ----
>
> I think we want to isolate the WebView cookies if at all possible
Brayan answer:
> > Widgets: probably 'unsupported' for now and have them tied to the current profile
>
> For the add note widget, I don't suggest any work because it should deprecated when minSdk reaches Nougat and everyone can use shortcuts.
>
> For the reviews shortcut, it needs a redesign so it can have some configurable aspect to distinct it from other instances of it (a color, icon, emoji, text, whatever).
>
> edit: when I say redesign, I mean a whole redesign in appearance, size, etc. It doesn't need to be similar to the current one
>
> > I think we want to isolate the WebView cookies if at all possible
>
> Now that I thought a little bit more, I agree
> API 28+: [`WebView.setDataDirectorySuffix`](https://developer.android.com/reference/android/webkit/WebView#setDataDirectorySuffix(java.lang.String))
> **Pseudocode**
>
> A profile will be of the format:
>
> ```kotlin
> data class ProfileData(val identifier: String, var name: String) {
> val webViewDataDirectory get() = identifier
> fun preferences(context: Context) = context.getSharedPreferences(
> name = identifier,
> mode = getDefaultSharedPreferencesMode(),
> )
> fun rename(name: String) = TODO()
> fun select() = TODO()
> fun delete() = TODO("do we also delete data?")
> companion object {
> fun listAll(): List { }
> }
> }
> ```
>
> `identifier` must NOT contain path separators (`setDataDirectorySuffix`)
> Proposal: current unix timestamp in ms
>
> ----
>
> A file containing `List` should exist, for use on the Profile Management screen
>
> * It would be inefficient to store the `name` inside `ProfileData.preferences()`
> * O(n)
> * A large amount of XML needs to be read for one field
> * If an issue occurs with a profile, the name is lost
> * But it would be very unusual to have more than 50 profiles, even as a developer
> * architecture is a better argument than speed
>
> Realistic options for storage of the ProfileCollection:
>
> 1. in the current `SharedPreferences` using `StringSet` + concatenated string
> * As we've done previously
> * Fast
> 2. In a new `SharedPreferences`
> * slightly faster than the above
> 3. Jetpack Data Store
> * Strongly Typed
> * Async
> * Slower
>
> ----
# Arthur's Note:
We need for each preferences to decide whether they are shared or whether they are profile specific.
Since we already have a welcome screen that invite people to sync with ankiweb, I think we should reuse it. If the user decide to use an ankiweb account, we could suggest the email as the profile name.
I think the default user name should be "user 1" as in AnkiMobile, and not "ankidroid". It's a strange user name; I'm not ankidroid.
I don't think the folder and the profile name should be related. We had a lot of issue with file system, renaming folder is something that could go wrong and be a huge issue, and it present almost no user interest. If we want that advanced users that look at the file structure get information about which profile is being used, I guess it'd be better to have something such as a file named ProfileName.txt (using the profile name as the file name, stripped of any forbidden characater) that contains the profile name.
## Split shared collection
Since we may have user that have shared the same device for a lot of time, I think we should also allow to copy the collection. This way, if I have a deck named "Arthur's deck" and my sister have a deck named "Sister's deck" we each end up with both deck in our collection. I then can delete "sister's deck" and she can delete "Arthur's deck".
Admittedly, this is already something a user could do by exporting the collection and importing them again, or both syncing with the same ankiweb account; but it may be too complex for some users (and sync may be expensive and slow). It seems better to offer it as a native feature.
This feature would only exists on ankidroid, because it's the only place where we have a need for this feature.
コントリビューションガイド
評価
この issue はまだ評価されていません。