Move preferences in gr-settings-view to model

When preferences are requested with getPreferences response is cached
on first response. If user change something on user settings, it is
changed on server, but cached response is not invalidated. So if user
goest to dashboard and back to user settings, getPreferences fetch
old cache and shows old settings.

Migrating to model fixes this.

Google-Bug-Id: b/244586175
Release-Notes: skip
Change-Id: I1afb1e73c9c9c2efd4cdbd85c906091e1a383e36
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
index 1ad78a6..470d847 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -63,6 +63,7 @@
 import {menuPageStyles} from '../../../styles/gr-menu-page-styles';
 import {formStyles} from '../../../styles/gr-form-styles';
 import {KnownExperimentId} from '../../../services/flags/flags';
+import {subscribe} from '../../lit/subscription-controller';
 
 const GERRIT_DOCS_BASE_URL =
   'https://gerrit-review.googlesource.com/' + 'Documentation';
@@ -191,9 +192,6 @@
   @state() showNumber?: boolean;
 
   // private but used in test
-  @state() themePreference = AppTheme.AUTO;
-
-  // private but used in test
   public _testOnly_loadingPromise?: Promise<void>;
 
   private readonly restApiService = getAppContext().restApiService;
@@ -202,6 +200,29 @@
 
   private readonly flagsService = getAppContext().flagsService;
 
+  constructor() {
+    super();
+    subscribe(
+      this,
+      () => this.userModel.preferences$,
+      prefs => {
+        if (!prefs) {
+          throw new Error('getPreferences returned undefined');
+        }
+        this.prefs = prefs;
+        this.showNumber = !!prefs.legacycid_in_change_table;
+        this.copyPrefs(CopyPrefsDirection.PrefsToLocalPrefs);
+        this.prefsChanged = false;
+        this.localChangeTableColumns =
+          prefs.change_table.length === 0
+            ? Object.values(ColumnNames)
+            : prefs.change_table.map(column =>
+                column === 'Project' ? 'Repo' : column
+              );
+      }
+    );
+  }
+
   override connectedCallback() {
     super.connectedCallback();
     // Polymer 2: anchor tag won't work on shadow DOM
@@ -218,24 +239,6 @@
       this.identities.loadData(),
     ];
 
-    // TODO(dhruvsri): move this to the service
-    promises.push(
-      this.restApiService.getPreferences().then(prefs => {
-        if (!prefs) {
-          throw new Error('getPreferences returned undefined');
-        }
-        this.prefs = prefs;
-        this.showNumber = !!prefs.legacycid_in_change_table;
-        this.copyPrefs(CopyPrefsDirection.PrefsToLocalPrefs);
-        this.localChangeTableColumns =
-          prefs.change_table.length === 0
-            ? Object.values(ColumnNames)
-            : prefs.change_table.map(column =>
-                column === 'Project' ? 'Repo' : column
-              );
-      })
-    );
-
     promises.push(
       this.restApiService.getConfig().then(config => {
         this.serverConfig = config;
@@ -1104,10 +1107,7 @@
 
   // private but used in test
   handleSavePreferences() {
-    return this.userModel.updatePreferences(this.localPrefs).then(() => {
-      this.copyPrefs(CopyPrefsDirection.LocalPrefsToPrefs);
-      this.prefsChanged = false;
-    });
+    return this.userModel.updatePreferences(this.localPrefs);
   }
 
   // private but used in test