Footer navigation for iOS PWAs and DiscourseHub app (#7347)

Footer navigation for iOS PWAs and DiscourseHub app (#7347)

diff --git a/app/assets/javascripts/discourse/components/discourse-topic.js.es6 b/app/assets/javascripts/discourse/components/discourse-topic.js.es6
index 7c6917f..4687203 100644
--- a/app/assets/javascripts/discourse/components/discourse-topic.js.es6
+++ b/app/assets/javascripts/discourse/components/discourse-topic.js.es6
@@ -2,12 +2,11 @@ import DiscourseURL from "discourse/lib/url";
 import AddArchetypeClass from "discourse/mixins/add-archetype-class";
 import ClickTrack from "discourse/lib/click-track";
 import Scrolling from "discourse/mixins/scrolling";
+import MobileScrollDirection from "discourse/mixins/mobile-scroll-direction";
 import { selectedText } from "discourse/lib/utilities";
 import { observes } from "ember-addons/ember-computed-decorators";
 
 const MOBILE_SCROLL_DIRECTION_CHECK_THROTTLE = 300;
-// Small buffer so that very tiny scrolls don't trigger mobile header switch
-const MOBILE_SCROLL_TOLERANCE = 5;
 
 function highlight(postNumber) {
   const $contents = $(`#post_${postNumber} .topic-body`);
@@ -16,222 +15,195 @@ function highlight(postNumber) {
   $contents.on("animationend", () => $contents.removeClass("highlighted"));
 }
 
-export default Ember.Component.extend(AddArchetypeClass, Scrolling, {
-  userFilters: Ember.computed.alias("topic.userFilters"),
-  classNameBindings: [
-    "multiSelect",
-    "topic.archetype",
-    "topic.is_warning",
-    "topic.category.read_restricted:read_restricted",
-    "topic.deleted:deleted-topic",
-    "topic.categoryClass",
-    "topic.tagClasses"
-  ],
-  menuVisible: true,
-  SHORT_POST: 1200,
-
-  postStream: Ember.computed.alias("topic.postStream"),
-  archetype: Ember.computed.alias("topic.archetype"),
-  dockAt: 0,
-
-  _lastShowTopic: null,
-
-  mobileScrollDirection: null,
-  _mobileLastScroll: null,
-
-  @observes("enteredAt")
-  _enteredTopic() {
-    // Ember is supposed to only call observers when values change but something
-    // in our view set up is firing this observer with the same value. This check
-    // prevents scrolled from being called twice.
-    const enteredAt = this.get("enteredAt");
-    if (enteredAt && this.get("lastEnteredAt") !== enteredAt) {
-      this._lastShowTopic = null;
-      Ember.run.schedule("afterRender", () => this.scrolled());
-      this.set("lastEnteredAt", enteredAt);
-    }
-  },
-
-  _highlightPost(postNumber) {
-    Ember.run.scheduleOnce("afterRender", null, highlight, postNumber);
-  },
-
-  _updateTopic(topic) {
-    if (topic === null) {
-      this._lastShowTopic = false;
-      this.appEvents.trigger("header:hide-topic");
-      return;
-    }
+export default Ember.Component.extend(
+  AddArchetypeClass,
+  Scrolling,
+  MobileScrollDirection,
+  {
+    userFilters: Ember.computed.alias("topic.userFilters"),
+    classNameBindings: [
+      "multiSelect",
+      "topic.archetype",
+      "topic.is_warning",
+      "topic.category.read_restricted:read_restricted",
+      "topic.deleted:deleted-topic",
+      "topic.categoryClass",
+      "topic.tagClasses"
+    ],
+    menuVisible: true,
+    SHORT_POST: 1200,
+
+    postStream: Ember.computed.alias("topic.postStream"),
+    archetype: Ember.computed.alias("topic.archetype"),
+    dockAt: 0,
+
+    _lastShowTopic: null,
+
+    mobileScrollDirection: null,
+
+    @observes("enteredAt")
+    _enteredTopic() {
+      // Ember is supposed to only call observers when values change but something
+      // in our view set up is firing this observer with the same value. This check
+      // prevents scrolled from being called twice.
+      const enteredAt = this.get("enteredAt");
+      if (enteredAt && this.get("lastEnteredAt") !== enteredAt) {
+        this._lastShowTopic = null;
+        Ember.run.schedule("afterRender", () => this.scrolled());
+        this.set("lastEnteredAt", enteredAt);
+      }
+    },
 
-    const offset = window.pageYOffset || $("html").scrollTop();
-    this._lastShowTopic = this.showTopicInHeader(topic, offset);
+    _highlightPost(postNumber) {
+      Ember.run.scheduleOnce("afterRender", null, highlight, postNumber);
+    },
 
-    if (this._lastShowTopic) {
-      this.appEvents.trigger("header:show-topic", topic);
-    } else {
-      this.appEvents.trigger("header:hide-topic");
-    }
-  },
-
-  didInsertElement() {
-    this._super(...arguments);
-    this.bindScrolling({ name: "topic-view" });
-
-    $(window).on("resize.discourse-on-scroll", () => this.scrolled());
-
-    this.$().on(
-      "mouseup.discourse-redirect",
-      ".cooked a, a.track-link",
-      function(e) {
-        // bypass if we are selecting stuff
-        const selection = window.getSelection && window.getSelection();
-        if (selection.type === "Range" || selection.rangeCount > 0) {
-          if (selectedText() !== "") {
-            return true;
-          }
-        }
+    _updateTopic(topic) {
+      if (topic === null) {
+        this._lastShowTopic = false;
+        this.appEvents.trigger("header:hide-topic");
+        return;
+      }
 
-        const $target = $(e.target);
-        if (
-          $target.hasClass("mention") ||
-          $target.parents(".expanded-embed").length
-        ) {
-          return false;
-        }
+      const offset = window.pageYOffset || $("html").scrollTop();
+      this._lastShowTopic = this.showTopicInHeader(topic, offset);
 
-        return ClickTrack.trackClick(e);
+      if (this._lastShowTopic) {
+        this.appEvents.trigger("header:show-topic", topic);
+      } else {
+        this.appEvents.trigger("header:hide-topic");
       }
-    );
+    },
+
+    didInsertElement() {
+      this._super(...arguments);
+      this.bindScrolling({ name: "topic-view" });
+
+      $(window).on("resize.discourse-on-scroll", () => this.scrolled());
+
+      this.$().on(
+        "mouseup.discourse-redirect",
+        ".cooked a, a.track-link",
+        function(e) {
+          // bypass if we are selecting stuff
+          const selection = window.getSelection && window.getSelection();
+          if (selection.type === "Range" || selection.rangeCount > 0) {
+            if (selectedText() !== "") {
+              return true;
+            }
+          }
 
-    this.appEvents.on("post:highlight", this, "_highlightPost");
+          const $target = $(e.target);
+          if (
+            $target.hasClass("mention") ||
+            $target.parents(".expanded-embed").length
+          ) {
+            return false;
+          }
 
-    this.appEvents.on("header:update-topic", this, "_updateTopic");
-  },
+          return ClickTrack.trackClick(e);
+        }
+      );
 
-  willDestroyElement() {
-    this._super(...arguments);
-    this.unbindScrolling("topic-view");
-    $(window).unbind("resize.discourse-on-scroll");
+      this.appEvents.on("post:highlight", this, "_highlightPost");
 
-    // Unbind link tracking
-    this.$().off("mouseup.discourse-redirect", ".cooked a, a.track-link");
+      this.appEvents.on("header:update-topic", this, "_updateTopic");
+    },
 
-    this.resetExamineDockCache();
+    willDestroyElement() {
+      this._super(...arguments);
+      this.unbindScrolling("topic-view");
+      $(window).unbind("resize.discourse-on-scroll");
 
-    // this happens after route exit, stuff could have trickled in
-    this.appEvents.trigger("header:hide-topic");
-    this.appEvents.off("post:highlight", this, "_highlightPost");
-    this.appEvents.off("header:update-topic", this, "_updateTopic");
-  },
+      // Unbind link tracking
+      this.$().off("mouseup.discourse-redirect", ".cooked a, a.track-link");
 
-  @observes("Discourse.hasFocus")
-  gotFocus() {
-    if (Discourse.get("hasFocus")) {
-      this.scrolled();
-    }
-  },
-
-  resetExamineDockCache() {
-    this.set("dockAt", 0);
-  },
-
-  showTopicInHeader(topic, offset) {
-    // On mobile, we show the header topic if the user has scrolled past the topic
-    // title and the current scroll direction is down
-    // On desktop the user only needs to scroll past the topic title.
-    return (

[... diff too long, it was truncated ...]

GitHub sha: eae22548

FIX: Prevent input zooming in iOS

This commit has been mentioned on Discourse Meta. There might be relevant details there: