FEATURE: Allow overriding text size from a different device (#6955)

FEATURE: Allow overriding text size from a different device (#6955)

This brings the feature in line with the theme selection system

diff --git a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6 b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
index 86e8f0e..a418cea 100644
--- a/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
+++ b/app/assets/javascripts/discourse/controllers/preferences/interface.js.es6
@@ -126,13 +126,8 @@ export default Ember.Controller.extend(PreferencesTabController, {
               this.get("model.user_option.theme_key_seq")
             );
           }
-          if (
-            makeTextSizeDefault ||
-            this.get("model.user_option.text_size") === $.cookie("text_size")
-          ) {
-            $.removeCookie("text_size");
-          } else {
-            $.cookie("text_size", this.get("textSize"));
+          if (!makeTextSizeDefault) {
+            this.get("model").updateTextSizeCookie(this.get("textSize"));
           }
 
           this.homeChanged();
diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6
index 70b6dbc..1de31d7 100644
--- a/app/assets/javascripts/discourse/models/user.js.es6
+++ b/app/assets/javascripts/discourse/models/user.js.es6
@@ -705,6 +705,25 @@ const User = RestModel.extend({
     });
 
     return _.uniq(titles).sort();
+  },
+
+  @computed("user_option.text_size_seq", "user_option.text_size")
+  currentTextSize(serverSeq, serverSize) {
+    if ($.cookie("text_size")) {
+      const [cookieSize, cookieSeq] = $.cookie("text_size").split("|");
+      if (cookieSeq >= serverSeq) {
+        return cookieSize;
+      }
+    }
+    return serverSize;
+  },
+
+  updateTextSizeCookie(newSize) {
+    const seq = this.get("user_option.text_size_seq");
+    $.cookie("text_size", `${newSize}|${seq}`, {
+      path: "/",
+      expires: 9999
+    });
   }
 });
 
diff --git a/app/assets/javascripts/discourse/routes/preferences-interface.js.es6 b/app/assets/javascripts/discourse/routes/preferences-interface.js.es6
index 283195b..ddd1fe4 100644
--- a/app/assets/javascripts/discourse/routes/preferences-interface.js.es6
+++ b/app/assets/javascripts/discourse/routes/preferences-interface.js.es6
@@ -4,10 +4,9 @@ export default RestrictedUserRoute.extend({
   showFooter: true,
 
   setupController(controller, user) {
-    const textSize = $.cookie("text_size") || user.get("user_option.text_size");
     controller.setProperties({
       model: user,
-      textSize
+      textSize: user.get("currentTextSize")
     });
   }
 });
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 2d89139..8ca6e21 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -133,7 +133,13 @@ module ApplicationHelper
   end
 
   def text_size_class
-    cookie_size = cookies[:text_size] if UserOption.text_sizes.keys.include?(cookies[:text_size]&.to_sym)
+    requested_cookie_size, cookie_seq = cookies[:text_size]&.split("|")
+    server_seq = current_user&.user_option&.text_size_seq
+    if cookie_seq && server_seq && cookie_seq.to_i >= server_seq &&
+              UserOption.text_sizes.keys.include?(requested_cookie_size&.to_sym)
+      cookie_size = requested_cookie_size
+    end
+
     size = cookie_size || current_user&.user_option&.text_size || SiteSetting.default_text_size
     "text-size-#{size}"
   end
diff --git a/app/serializers/user_option_serializer.rb b/app/serializers/user_option_serializer.rb
index 0a0e704..d7797c3 100644
--- a/app/serializers/user_option_serializer.rb
+++ b/app/serializers/user_option_serializer.rb
@@ -24,7 +24,8 @@ class UserOptionSerializer < ApplicationSerializer
              :allow_private_messages,
              :homepage_id,
              :hide_profile_and_presence,
-             :text_size
+             :text_size,
+             :text_size_seq
 
   def auto_track_topics_after_msecs
     object.auto_track_topics_after_msecs || SiteSetting.default_other_auto_track_topics_after_msecs
diff --git a/app/services/user_updater.rb b/app/services/user_updater.rb
index 3828b1d..52df88f 100644
--- a/app/services/user_updater.rb
+++ b/app/services/user_updater.rb
@@ -96,6 +96,10 @@ class UserUpdater
       end
     end
 
+    if attributes.key?(:text_size)
+      user.user_option.text_size_seq += 1 if user.user_option.text_size.to_s != attributes[:text_size]
+    end
+
     OPTION_ATTR.each do |attribute|
       if attributes.key?(attribute)
         save_options = true
diff --git a/db/migrate/20190125153345_add_text_size_seq_to_user_option.rb b/db/migrate/20190125153345_add_text_size_seq_to_user_option.rb
new file mode 100644
index 0000000..b1d0a4c
--- /dev/null
+++ b/db/migrate/20190125153345_add_text_size_seq_to_user_option.rb
@@ -0,0 +1,5 @@
+class AddTextSizeSeqToUserOption < ActiveRecord::Migration[5.2]
+  def change
+    add_column :user_options, :text_size_seq, :integer, null: false, default: 0
+  end
+end
diff --git a/spec/helpers/application_helper_spec.rb b/spec/helpers/application_helper_spec.rb
index 62939db..5186ddd 100644
--- a/spec/helpers/application_helper_spec.rb
+++ b/spec/helpers/application_helper_spec.rb
@@ -178,9 +178,18 @@ describe ApplicationHelper do
           expect(helper.html_classes.split(" ")).to include('text-size-larger')
         end
 
+        it 'ignores cookies with lower sequence' do
+          user.user_option.update!(text_size_seq: 2)
+
+          helper.request.cookies["text_size"] = "normal|1"
+          expect(helper.html_classes.split(" ")).to include('text-size-larger')
+        end
+
         it 'prioritises the cookie specified text size' do
-          helper.request.cookies["text_size"] = "normal"
-          expect(helper.html_classes.split(" ")).to include('text-size-normal')
+          user.user_option.update!(text_size_seq: 2)
+
+          helper.request.cookies["text_size"] = "largest|4"
+          expect(helper.html_classes.split(" ")).to include('text-size-largest')
         end
 
         it 'includes the user specified text size' do
diff --git a/test/javascripts/acceptance/preferences-test.js.es6 b/test/javascripts/acceptance/preferences-test.js.es6
index 7727082..319e0b4 100644
--- a/test/javascripts/acceptance/preferences-test.js.es6
+++ b/test/javascripts/acceptance/preferences-test.js.es6
@@ -135,17 +135,13 @@ QUnit.test("font size change", async assert => {
 
   await savePreferences();
 
-  assert.equal($.cookie("text_size"), "larger", "cookie is set");
+  assert.equal($.cookie("text_size"), "larger|1", "cookie is set");
   await click(".text-size input[type=checkbox]");
   await expandSelectKit(".text-size .combobox");
   await selectKitSelectRowByValue("largest", ".text-size .combobox");
 
   await savePreferences();
-  assert.equal(
-    $.cookie("text_size"),
-    null,
-    "cookie is unset when matches user preference"
-  );
+  assert.equal($.cookie("text_size"), "larger|1", "cookie remains the same");
 
   $.removeCookie("text_size");
 });
diff --git a/test/javascripts/fixtures/user_fixtures.js.es6 b/test/javascripts/fixtures/user_fixtures.js.es6
index b639c5c..0ac8d77 100644
--- a/test/javascripts/fixtures/user_fixtures.js.es6
+++ b/test/javascripts/fixtures/user_fixtures.js.es6
@@ -106,7 +106,9 @@ export default {
       }
     ],
     user: {
-      user_option: {},
+      user_option: {
+        text_size_seq: 1
+      },
       id: 19,
       username: "eviltrout",
       uploaded_avatar_id: null,

GitHub sha: aca0b32f