1
0

mobile.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // TODO: This file was created by bulk-decaffeinate.
  2. // Sanity-check the conversion and remove this comment.
  3. /*
  4. * decaffeinate suggestions:
  5. * DS002: Fix invalid constructor
  6. * DS102: Remove unnecessary code created because of implicit returns
  7. * DS206: Consider reworking classes to avoid initClass
  8. * DS207: Consider shorter variations of null checks
  9. * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
  10. */
  11. app.views.Mobile = class Mobile extends app.View {
  12. static initClass() {
  13. this.className = "_mobile";
  14. this.elements = {
  15. body: "body",
  16. content: "._container",
  17. sidebar: "._sidebar",
  18. docPicker: "._settings ._sidebar",
  19. };
  20. this.shortcuts = { escape: "onEscape" };
  21. this.routes = { after: "afterRoute" };
  22. }
  23. static detect() {
  24. if (Cookies.get("override-mobile-detect") != null) {
  25. return JSON.parse(Cookies.get("override-mobile-detect"));
  26. }
  27. try {
  28. return (
  29. window.matchMedia("(max-width: 480px)").matches ||
  30. window.matchMedia("(max-width: 767px)").matches ||
  31. window.matchMedia("(max-height: 767px) and (max-width: 1024px)")
  32. .matches ||
  33. // Need to sniff the user agent because some Android and Windows Phone devices don't take
  34. // resolution (dpi) into account when reporting device width/height.
  35. (navigator.userAgent.indexOf("Android") !== -1 &&
  36. navigator.userAgent.indexOf("Mobile") !== -1) ||
  37. navigator.userAgent.indexOf("IEMobile") !== -1
  38. );
  39. } catch (error) {
  40. return false;
  41. }
  42. }
  43. static detectAndroidWebview() {
  44. try {
  45. return /(Android).*( Version\/.\.. ).*(Chrome)/.test(navigator.userAgent);
  46. } catch (error) {
  47. return false;
  48. }
  49. }
  50. constructor() {
  51. this.showSidebar = this.showSidebar.bind(this);
  52. this.hideSidebar = this.hideSidebar.bind(this);
  53. this.onClickBack = this.onClickBack.bind(this);
  54. this.onClickForward = this.onClickForward.bind(this);
  55. this.onClickToggleSidebar = this.onClickToggleSidebar.bind(this);
  56. this.onClickDocPickerTab = this.onClickDocPickerTab.bind(this);
  57. this.onClickSettingsTab = this.onClickSettingsTab.bind(this);
  58. this.onTapSearch = this.onTapSearch.bind(this);
  59. this.onEscape = this.onEscape.bind(this);
  60. this.afterRoute = this.afterRoute.bind(this);
  61. this.el = document.documentElement;
  62. super(...arguments);
  63. }
  64. init() {
  65. $.on($("._search"), "touchend", this.onTapSearch);
  66. this.toggleSidebar = $("button[data-toggle-sidebar]");
  67. this.toggleSidebar.removeAttribute("hidden");
  68. $.on(this.toggleSidebar, "click", this.onClickToggleSidebar);
  69. this.back = $("button[data-back]");
  70. this.back.removeAttribute("hidden");
  71. $.on(this.back, "click", this.onClickBack);
  72. this.forward = $("button[data-forward]");
  73. this.forward.removeAttribute("hidden");
  74. $.on(this.forward, "click", this.onClickForward);
  75. this.docPickerTab = $('button[data-tab="doc-picker"]');
  76. this.docPickerTab.removeAttribute("hidden");
  77. $.on(this.docPickerTab, "click", this.onClickDocPickerTab);
  78. this.settingsTab = $('button[data-tab="settings"]');
  79. this.settingsTab.removeAttribute("hidden");
  80. $.on(this.settingsTab, "click", this.onClickSettingsTab);
  81. app.document.sidebar.search.on("searching", this.showSidebar);
  82. this.activate();
  83. }
  84. showSidebar() {
  85. let selection;
  86. if (this.isSidebarShown()) {
  87. window.scrollTo(0, 0);
  88. return;
  89. }
  90. this.contentTop = window.scrollY;
  91. this.content.style.display = "none";
  92. this.sidebar.style.display = "block";
  93. if ((selection = this.findByClass(app.views.ListSelect.activeClass))) {
  94. const scrollContainer =
  95. window.scrollY === this.body.scrollTop
  96. ? this.body
  97. : document.documentElement;
  98. $.scrollTo(selection, scrollContainer, "center");
  99. } else {
  100. window.scrollTo(
  101. 0,
  102. (this.findByClass(app.views.ListFold.activeClass) && this.sidebarTop) ||
  103. 0,
  104. );
  105. }
  106. }
  107. hideSidebar() {
  108. if (!this.isSidebarShown()) {
  109. return;
  110. }
  111. this.sidebarTop = window.scrollY;
  112. this.sidebar.style.display = "none";
  113. this.content.style.display = "block";
  114. window.scrollTo(0, this.contentTop || 0);
  115. }
  116. isSidebarShown() {
  117. return this.sidebar.style.display !== "none";
  118. }
  119. onClickBack() {
  120. return history.back();
  121. }
  122. onClickForward() {
  123. return history.forward();
  124. }
  125. onClickToggleSidebar() {
  126. if (this.isSidebarShown()) {
  127. this.hideSidebar();
  128. } else {
  129. this.showSidebar();
  130. }
  131. }
  132. onClickDocPickerTab(event) {
  133. $.stopEvent(event);
  134. this.showDocPicker();
  135. }
  136. onClickSettingsTab(event) {
  137. $.stopEvent(event);
  138. this.showSettings();
  139. }
  140. showDocPicker() {
  141. window.scrollTo(0, 0);
  142. this.docPickerTab.classList.add("active");
  143. this.settingsTab.classList.remove("active");
  144. this.docPicker.style.display = "block";
  145. this.content.style.display = "none";
  146. }
  147. showSettings() {
  148. window.scrollTo(0, 0);
  149. this.docPickerTab.classList.remove("active");
  150. this.settingsTab.classList.add("active");
  151. this.docPicker.style.display = "none";
  152. this.content.style.display = "block";
  153. }
  154. onTapSearch() {
  155. return window.scrollTo(0, 0);
  156. }
  157. onEscape() {
  158. return this.hideSidebar();
  159. }
  160. afterRoute(route) {
  161. this.hideSidebar();
  162. if (route === "settings") {
  163. this.showDocPicker();
  164. } else {
  165. this.content.style.display = "block";
  166. }
  167. if (page.canGoBack()) {
  168. this.back.removeAttribute("disabled");
  169. } else {
  170. this.back.setAttribute("disabled", "disabled");
  171. }
  172. if (page.canGoForward()) {
  173. this.forward.removeAttribute("disabled");
  174. } else {
  175. this.forward.setAttribute("disabled", "disabled");
  176. }
  177. }
  178. };
  179. app.views.Mobile.initClass();