about summary refs log tree commit diff
path: root/src/state/models/ui/preferences.ts
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2023-08-23 15:40:15 -0500
committerGitHub <noreply@github.com>2023-08-23 13:40:15 -0700
commitb6317d4ce7a6c27787b625fdde6e387e4368d5d6 (patch)
tree0aa2b6aa2a63897081d4623986e86ae595e291b0 /src/state/models/ui/preferences.ts
parentacad8cb4555760ca858830a4b916d2bf80c1b7b4 (diff)
downloadvoidsky-b6317d4ce7a6c27787b625fdde6e387e4368d5d6.tar.zst
Improve handling of unselecting languanges in composer language menu (#1093)
* allow toggling off/on multiple from main composer lang menu

* fix dropdown styles for long labels

* udpate model to use new string field

* update language UI

* save langs to history on submit

* remove edit

* clean up use new fields

* default to deviceLocales

* fix default valu

* feedback

* use radio icon
Diffstat (limited to 'src/state/models/ui/preferences.ts')
-rw-r--r--src/state/models/ui/preferences.ts75
1 files changed, 61 insertions, 14 deletions
diff --git a/src/state/models/ui/preferences.ts b/src/state/models/ui/preferences.ts
index 23668a3dc..e9ffe28c2 100644
--- a/src/state/models/ui/preferences.ts
+++ b/src/state/models/ui/preferences.ts
@@ -33,6 +33,9 @@ const LABEL_GROUPS = [
   'impersonation',
 ]
 const VISIBILITY_VALUES = ['show', 'warn', 'hide']
+const DEFAULT_LANG_CODES = (deviceLocales || [])
+  .concat(['en', 'ja', 'pt', 'de'])
+  .slice(0, 6)
 
 export class LabelPreferencesModel {
   nsfw: LabelPreference = 'hide'
@@ -51,7 +54,8 @@ export class LabelPreferencesModel {
 export class PreferencesModel {
   adultContentEnabled = !isIOS
   contentLanguages: string[] = deviceLocales || []
-  postLanguages: string[] = deviceLocales || []
+  postLanguage: string = deviceLocales[0] || 'en'
+  postLanguageHistory: string[] = DEFAULT_LANG_CODES
   contentLabels = new LabelPreferencesModel()
   savedFeeds: string[] = []
   pinnedFeeds: string[] = []
@@ -71,7 +75,8 @@ export class PreferencesModel {
   serialize() {
     return {
       contentLanguages: this.contentLanguages,
-      postLanguages: this.postLanguages,
+      postLanguage: this.postLanguage,
+      postLanguageHistory: this.postLanguageHistory,
       contentLabels: this.contentLabels,
       savedFeeds: this.savedFeeds,
       pinnedFeeds: this.pinnedFeeds,
@@ -101,16 +106,23 @@ export class PreferencesModel {
         // default to the device languages
         this.contentLanguages = deviceLocales
       }
-      // check if post languages in preferences exist, otherwise default to device languages
+      if (hasProp(v, 'postLanguage') && typeof v.postLanguage === 'string') {
+        this.postLanguage = v.postLanguage
+      } else {
+        // default to the device languages
+        this.postLanguage = deviceLocales[0] || 'en'
+      }
       if (
-        hasProp(v, 'postLanguages') &&
-        Array.isArray(v.postLanguages) &&
-        typeof v.postLanguages.every(item => typeof item === 'string')
+        hasProp(v, 'postLanguageHistory') &&
+        Array.isArray(v.postLanguageHistory) &&
+        typeof v.postLanguageHistory.every(item => typeof item === 'string')
       ) {
-        this.postLanguages = v.postLanguages
+        this.postLanguageHistory = v.postLanguageHistory
+          .concat(DEFAULT_LANG_CODES)
+          .slice(0, 6)
       } else {
-        // default to the device languages
-        this.postLanguages = deviceLocales
+        // default to a starter set
+        this.postLanguageHistory = DEFAULT_LANG_CODES
       }
       // check if content labels in preferences exist, then hydrate
       if (hasProp(v, 'contentLabels') && typeof v.contentLabels === 'object') {
@@ -279,7 +291,8 @@ export class PreferencesModel {
       runInAction(() => {
         this.contentLabels = new LabelPreferencesModel()
         this.contentLanguages = deviceLocales
-        this.postLanguages = deviceLocales
+        this.postLanguage = deviceLocales ? deviceLocales.join(',') : 'en'
+        this.postLanguageHistory = DEFAULT_LANG_CODES
         this.savedFeeds = []
         this.pinnedFeeds = []
       })
@@ -305,20 +318,54 @@ export class PreferencesModel {
     }
   }
 
+  /**
+   * A getter that splits `this.postLanguage` into an array of strings.
+   *
+   * This was previously the main field on this model, but now we're
+   * concatenating lang codes to make multi-selection a little better.
+   */
+  get postLanguages() {
+    // filter out empty strings if exist
+    return this.postLanguage.split(',').filter(Boolean)
+  }
+
   hasPostLanguage(code2: string) {
     return this.postLanguages.includes(code2)
   }
 
   togglePostLanguage(code2: string) {
     if (this.hasPostLanguage(code2)) {
-      this.postLanguages = this.postLanguages.filter(lang => lang !== code2)
+      this.postLanguage = this.postLanguages
+        .filter(lang => lang !== code2)
+        .join(',')
     } else {
-      this.postLanguages = this.postLanguages.concat([code2])
+      // sort alphabetically for deterministic comparison in context menu
+      this.postLanguage = this.postLanguages
+        .concat([code2])
+        .sort((a, b) => a.localeCompare(b))
+        .join(',')
     }
   }
 
-  setPostLanguage(code2: string) {
-    this.postLanguages = [code2]
+  setPostLanguage(commaSeparatedLangCodes: string) {
+    this.postLanguage = commaSeparatedLangCodes
+  }
+
+  /**
+   * Saves whatever language codes are currently selected into a history array,
+   * which is then used to populate the language selector menu.
+   */
+  savePostLanguageToHistory() {
+    // filter out duplicate `this.postLanguage` if exists, and prepend
+    // value to start of array
+    this.postLanguageHistory = [this.postLanguage]
+      .concat(
+        this.postLanguageHistory.filter(
+          commaSeparatedLangCodes =>
+            commaSeparatedLangCodes !== this.postLanguage,
+        ),
+      )
+      .slice(0, 6)
   }
 
   getReadablePostLanguages() {