nodebb-theme-harmony 2.0.0-pre.9 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/.eslintrc +3 -3
  2. package/README.md +22 -19
  3. package/lib/controllers.js +29 -29
  4. package/library.js +184 -190
  5. package/package.json +48 -48
  6. package/plugin.json +24 -25
  7. package/public/.eslintrc +3 -3
  8. package/public/admin.js +15 -15
  9. package/public/harmony.js +287 -287
  10. package/public/settings.js +31 -31
  11. package/renovate.json +6 -6
  12. package/scss/account.scss +27 -27
  13. package/scss/category.scss +3 -3
  14. package/scss/chats.scss +11 -11
  15. package/scss/common.scss +122 -128
  16. package/scss/fonts.scss +19 -19
  17. package/scss/groups.scss +22 -22
  18. package/scss/harmony.scss +24 -25
  19. package/scss/header.scss +15 -15
  20. package/scss/mixins.scss +183 -176
  21. package/scss/modals.scss +6 -6
  22. package/scss/modules/breadcrumbs.scss +15 -15
  23. package/scss/modules/cover.scss +102 -104
  24. package/scss/modules/filters.scss +7 -7
  25. package/scss/modules/nprogress.scss +80 -80
  26. package/scss/modules/paginator.scss +23 -23
  27. package/scss/modules/tags.scss +5 -5
  28. package/scss/modules/topic-navigator.scss +52 -52
  29. package/scss/modules/topics-list.scss +40 -40
  30. package/scss/modules/user-menu.scss +10 -10
  31. package/scss/overrides.scss +65 -61
  32. package/scss/sidebar.scss +188 -189
  33. package/scss/skins.scss +58 -49
  34. package/scss/status.scss +24 -24
  35. package/scss/topic.scss +130 -138
  36. package/templates/account/blocks.tpl +51 -40
  37. package/templates/account/categories.tpl +63 -63
  38. package/templates/account/consent.tpl +73 -73
  39. package/templates/account/edit/password.tpl +34 -34
  40. package/templates/account/edit/username.tpl +29 -30
  41. package/templates/account/edit.tpl +137 -122
  42. package/templates/account/followers.tpl +14 -14
  43. package/templates/account/following.tpl +15 -15
  44. package/templates/account/groups.tpl +15 -15
  45. package/templates/account/info.tpl +270 -201
  46. package/templates/account/posts.tpl +35 -35
  47. package/templates/account/profile.tpl +92 -95
  48. package/templates/account/read.tpl +1 -0
  49. package/templates/account/sessions.tpl +8 -8
  50. package/templates/account/settings.tpl +236 -236
  51. package/templates/account/shares.tpl +20 -0
  52. package/templates/account/tags.tpl +12 -12
  53. package/templates/account/theme.tpl +63 -63
  54. package/templates/account/topics.tpl +44 -43
  55. package/templates/account/uploads.tpl +37 -37
  56. package/templates/admin/plugins/harmony.tpl +57 -56
  57. package/templates/categories.tpl +29 -29
  58. package/templates/category.tpl +72 -72
  59. package/templates/footer.tpl +17 -17
  60. package/templates/groups/details.tpl +86 -86
  61. package/templates/groups/list.tpl +58 -56
  62. package/templates/groups/members.tpl +9 -9
  63. package/templates/header.tpl +45 -45
  64. package/templates/notifications.tpl +32 -32
  65. package/templates/partials/account/admin-menu.tpl +36 -36
  66. package/templates/partials/account/category-item.tpl +22 -22
  67. package/templates/partials/account/footer.tpl +2 -2
  68. package/templates/partials/account/header.tpl +98 -98
  69. package/templates/partials/account/session-list.tpl +18 -18
  70. package/templates/partials/account/sidebar-left.tpl +116 -102
  71. package/templates/partials/breadcrumbs-json-ld.tpl +16 -26
  72. package/templates/partials/breadcrumbs.tpl +12 -12
  73. package/templates/partials/buttons/newTopic.tpl +22 -22
  74. package/templates/partials/categories/item.tpl +56 -56
  75. package/templates/partials/categories/lastpost.tpl +24 -24
  76. package/templates/partials/categories/link.tpl +4 -4
  77. package/templates/partials/category/subcategory.tpl +18 -18
  78. package/templates/partials/category/tags.tpl +3 -3
  79. package/templates/partials/cookie-consent.tpl +6 -6
  80. package/templates/partials/groups/admin.tpl +95 -95
  81. package/templates/partials/groups/invited.tpl +32 -32
  82. package/templates/partials/groups/list.tpl +15 -15
  83. package/templates/partials/groups/memberlist.tpl +46 -46
  84. package/templates/partials/groups/pending.tpl +29 -29
  85. package/templates/partials/groups/sidebar-left.tpl +27 -27
  86. package/templates/partials/header/brand.tpl +27 -25
  87. package/templates/partials/mobile-footer.tpl +95 -98
  88. package/templates/partials/notifications_list.tpl +44 -44
  89. package/templates/partials/paginator.tpl +46 -46
  90. package/templates/partials/post_bar.tpl +27 -29
  91. package/templates/partials/posts_list.tpl +7 -7
  92. package/templates/partials/posts_list_item.tpl +19 -19
  93. package/templates/partials/quick-search-results.tpl +46 -46
  94. package/templates/partials/search-filters.tpl +183 -183
  95. package/templates/partials/search-results.tpl +54 -54
  96. package/templates/partials/sidebar/chats.tpl +45 -45
  97. package/templates/partials/sidebar/drafts.tpl +63 -63
  98. package/templates/partials/sidebar/logged-in-menu.tpl +22 -22
  99. package/templates/partials/sidebar/logged-out-menu.tpl +44 -44
  100. package/templates/partials/sidebar/notifications.tpl +49 -49
  101. package/templates/partials/sidebar/search-mobile.tpl +28 -28
  102. package/templates/partials/sidebar/search.tpl +30 -30
  103. package/templates/partials/sidebar/user-menu.tpl +103 -103
  104. package/templates/partials/sidebar-left.tpl +39 -42
  105. package/templates/partials/sidebar-right.tpl +16 -16
  106. package/templates/partials/skin-switcher.tpl +50 -50
  107. package/templates/partials/tags_list.tpl +7 -5
  108. package/templates/partials/toast.tpl +19 -19
  109. package/templates/partials/topic/event.tpl +12 -12
  110. package/templates/partials/topic/navigation-post.tpl +9 -9
  111. package/templates/partials/topic/navigator-mobile.tpl +61 -61
  112. package/templates/partials/topic/navigator.tpl +26 -26
  113. package/templates/partials/topic/necro-post.tpl +5 -5
  114. package/templates/partials/topic/post-menu-list.tpl +156 -140
  115. package/templates/partials/topic/post-menu.tpl +4 -30
  116. package/templates/partials/topic/post-placeholder.tpl +14 -14
  117. package/templates/partials/topic/post.tpl +146 -139
  118. package/templates/partials/topic/quickreply.tpl +28 -28
  119. package/templates/partials/topic/reply-button.tpl +26 -24
  120. package/templates/partials/topic/selection-tooltip.tpl +2 -2
  121. package/templates/partials/topic/sort.tpl +27 -27
  122. package/templates/partials/topic/stats.tpl +14 -14
  123. package/templates/partials/topic/thumbs.tpl +4 -4
  124. package/templates/partials/topic/tools.tpl +8 -12
  125. package/templates/partials/topic/topic-menu-list.tpl +73 -73
  126. package/templates/partials/topic/watch.tpl +59 -59
  127. package/templates/partials/topic-filters.tpl +15 -15
  128. package/templates/partials/topic-list-bar.tpl +54 -54
  129. package/templates/partials/topic-terms.tpl +15 -15
  130. package/templates/partials/topics_list.tpl +131 -123
  131. package/templates/partials/users/item.tpl +39 -37
  132. package/templates/partials/users_list.tpl +4 -4
  133. package/templates/partials/users_list_menu.tpl +14 -14
  134. package/templates/popular.tpl +34 -34
  135. package/templates/post-queue.tpl +211 -207
  136. package/templates/recent.tpl +42 -35
  137. package/templates/search.tpl +46 -46
  138. package/templates/tag.tpl +34 -34
  139. package/templates/tags.tpl +49 -49
  140. package/templates/top.tpl +34 -34
  141. package/templates/topic.tpl +123 -130
  142. package/templates/unread.tpl +31 -31
  143. package/templates/users.tpl +39 -39
  144. package/templates/world.tpl +66 -35
  145. package/theme.json +6 -6
  146. package/package-lock.json +0 -2368
  147. package/scss/modules/bottom-sheet.scss +0 -52
  148. package/templates/flags/detail.tpl +0 -179
  149. package/templates/flags/list.tpl +0 -6
  150. package/templates/login.tpl +0 -102
  151. package/templates/partials/category/filter-dropdown-content.tpl +0 -41
  152. package/templates/partials/category/selector-dropdown-content.tpl +0 -39
  153. package/templates/partials/category/sort.tpl +0 -39
  154. package/templates/partials/category/tools.tpl +0 -89
  155. package/templates/partials/category/watch.tpl +0 -67
  156. package/templates/partials/flags/bulk-actions.tpl +0 -9
  157. package/templates/partials/flags/filters.tpl +0 -189
  158. package/templates/partials/flags/results.tpl +0 -38
  159. package/templates/partials/groups/filter-dropdown-content.tpl +0 -25
  160. package/templates/partials/tags/filter-dropdown-content.tpl +0 -38
  161. package/templates/partials/tags/watch.tpl +0 -42
  162. package/templates/partials/users/filter-dropdown-content.tpl +0 -23
  163. package/templates/register.tpl +0 -104
package/public/admin.js CHANGED
@@ -1,15 +1,15 @@
1
- 'use strict';
2
-
3
- define('admin/plugins/harmony', ['settings'], function (Settings) {
4
- var ACP = {};
5
-
6
- ACP.init = function () {
7
- Settings.load('harmony', $('.harmony-settings'));
8
-
9
- $('#save').on('click', function () {
10
- Settings.save('harmony', $('.harmony-settings'));
11
- });
12
- };
13
-
14
- return ACP;
15
- });
1
+ 'use strict';
2
+
3
+ define('admin/plugins/harmony', ['settings'], function (Settings) {
4
+ var ACP = {};
5
+
6
+ ACP.init = function () {
7
+ Settings.load('harmony', $('.harmony-settings'));
8
+
9
+ $('#save').on('click', function () {
10
+ Settings.save('harmony', $('.harmony-settings'));
11
+ });
12
+ };
13
+
14
+ return ACP;
15
+ });
package/public/harmony.js CHANGED
@@ -1,287 +1,287 @@
1
- 'use strict';
2
-
3
- $(document).ready(function () {
4
- setupSkinSwitcher();
5
- setupNProgress();
6
- setupMobileMenu();
7
- setupSearch();
8
- setupDrafts();
9
- handleMobileNavigator();
10
- setupNavTooltips();
11
- fixPlaceholders();
12
- fixSidebarOverflow();
13
-
14
- function setupSkinSwitcher() {
15
- $('[component="skinSwitcher"]').on('click', '.dropdown-item', function () {
16
- const skin = $(this).attr('data-value');
17
- $('[component="skinSwitcher"] .dropdown-item .fa-check').addClass('invisible');
18
- $(this).find('.fa-check').removeClass('invisible');
19
- require(['forum/account/settings', 'hooks'], function (accountSettings, hooks) {
20
- hooks.one('action:skin.change', function () {
21
- $('[component="skinSwitcher"] [component="skinSwitcher/icon"]').removeClass('fa-fade');
22
- });
23
- $('[component="skinSwitcher"] [component="skinSwitcher/icon"]').addClass('fa-fade');
24
- accountSettings.changeSkin(skin);
25
- });
26
- });
27
- }
28
-
29
- require(['hooks'], function (hooks) {
30
- $(window).on('action:composer.resize action:sidebar.toggle', function () {
31
- const isRtl = $('html').attr('data-dir') === 'rtl';
32
- const css = {
33
- width: $('#panel').width(),
34
- };
35
- const sidebarEl = $('.sidebar-left');
36
- css[isRtl ? 'right' : 'left'] = sidebarEl.is(':visible') ? sidebarEl.outerWidth(true) : 0;
37
- $('[component="composer"]').css(css);
38
- });
39
-
40
- hooks.on('filter:chat.openChat', function (hookData) {
41
- // disables chat modals & goes straight to chat page based on user setting
42
- hookData.modal = config.theme.chatModals && !utils.isMobile();
43
- return hookData;
44
- });
45
- });
46
-
47
- function setupMobileMenu() {
48
- require(['hooks', 'api', 'navigator'], function (hooks, api, navigator) {
49
- $('[component="sidebar/toggle"]').on('click', async function () {
50
- const sidebarEl = $('.sidebar');
51
- sidebarEl.toggleClass('open');
52
- if (app.user.uid) {
53
- await api.put(`/users/${app.user.uid}/settings`, {
54
- settings: {
55
- openSidebars: sidebarEl.hasClass('open') ? 'on' : 'off',
56
- },
57
- });
58
- }
59
- $(window).trigger('action:sidebar.toggle');
60
- if (ajaxify.data.template.topic) {
61
- hooks.fire('action:navigator.update', { newIndex: navigator.getIndex() });
62
- }
63
- });
64
-
65
- const bottomBar = $('[component="bottombar"]');
66
- const $body = $('body');
67
- const $window = $(window);
68
- $body.on('shown.bs.dropdown hidden.bs.dropdown', '.sticky-tools', function () {
69
- bottomBar.toggleClass('hidden', $(this).find('.dropdown-menu.show').length);
70
- });
71
- function isSearchVisible() {
72
- return !!$('[component="bottombar"] [component="sidebar/search"] .search-dropdown.show').length;
73
- }
74
-
75
- let lastScrollTop = 0;
76
- let newPostsLoaded = false;
77
-
78
- function onWindowScroll() {
79
- const st = $window.scrollTop();
80
- if (newPostsLoaded) {
81
- newPostsLoaded = false;
82
- lastScrollTop = st;
83
- return;
84
- }
85
- if (st !== lastScrollTop && !navigator.scrollActive && !isSearchVisible()) {
86
- const diff = Math.abs(st - lastScrollTop);
87
- const scrolledDown = st > lastScrollTop;
88
- const scrolledUp = st < lastScrollTop;
89
- if (diff > 5) {
90
- bottomBar.css({
91
- bottom: !scrolledUp && scrolledDown ?
92
- -bottomBar.find('.bottombar-nav').outerHeight(true) :
93
- 0,
94
- });
95
- }
96
- }
97
- lastScrollTop = st;
98
- }
99
-
100
- const delayedScroll = utils.throttle(onWindowScroll, 250);
101
- function enableAutohide() {
102
- $window.off('scroll', delayedScroll);
103
- if (config.theme.autohideBottombar) {
104
- lastScrollTop = $window.scrollTop();
105
- $window.on('scroll', delayedScroll);
106
- }
107
- }
108
-
109
- hooks.on('action:posts.loading', function () {
110
- $window.off('scroll', delayedScroll);
111
- });
112
- hooks.on('action:posts.loaded', function () {
113
- newPostsLoaded = true;
114
- setTimeout(enableAutohide, 250);
115
- });
116
- hooks.on('action:ajaxify.end', function () {
117
- $window.off('scroll', delayedScroll);
118
- bottomBar.css({ bottom: 0 });
119
- setTimeout(enableAutohide, 250);
120
- });
121
- });
122
- }
123
-
124
- function setupSearch() {
125
- $('[component="sidebar/search"]').on('shown.bs.dropdown', function () {
126
- $(this).find('[component="search/fields"] input[name="query"]').trigger('focus');
127
- });
128
- }
129
-
130
- function setupDrafts() {
131
- require(['composer/drafts', 'bootbox'], function (drafts, bootbox) {
132
- const draftsEl = $('[component="sidebar/drafts"]');
133
-
134
- function updateBadgeCount() {
135
- const count = drafts.getAvailableCount();
136
- if (count > 0) {
137
- draftsEl.removeClass('hidden');
138
- }
139
- $('[component="drafts/count"]').toggleClass('hidden', count <= 0).text(count);
140
- }
141
-
142
- async function renderDraftList() {
143
- const draftListEl = $('[component="drafts/list"]');
144
- const draftItems = drafts.listAvailable();
145
- if (!draftItems.length) {
146
- draftListEl.find('.no-drafts').removeClass('hidden');
147
- draftListEl.find('.placeholder-wave').addClass('hidden');
148
- draftListEl.find('.draft-item-container').html('');
149
- return;
150
- }
151
- draftItems.reverse().forEach((draft) => {
152
- if (draft) {
153
- if (draft.title) {
154
- draft.title = utils.escapeHTML(String(draft.title));
155
- }
156
- draft.text = utils.escapeHTML(
157
- draft.text
158
- ).replace(/(?:\r\n|\r|\n)/g, '<br>');
159
- }
160
- });
161
-
162
- const html = await app.parseAndTranslate('partials/sidebar/drafts', 'drafts', { drafts: draftItems });
163
- draftListEl.find('.no-drafts').addClass('hidden');
164
- draftListEl.find('.placeholder-wave').addClass('hidden');
165
- draftListEl.find('.draft-item-container').html(html).find('.timeago').timeago();
166
- }
167
-
168
-
169
- draftsEl.on('shown.bs.dropdown', renderDraftList);
170
-
171
- draftsEl.on('click', '[component="drafts/open"]', function () {
172
- drafts.open($(this).attr('data-save-id'));
173
- });
174
-
175
- draftsEl.on('click', '[component="drafts/delete"]', function () {
176
- const save_id = $(this).attr('data-save-id');
177
- bootbox.confirm('[[modules:composer.discard-draft-confirm]]', function (ok) {
178
- if (ok) {
179
- drafts.removeDraft(save_id);
180
- renderDraftList();
181
- }
182
- });
183
- return false;
184
- });
185
-
186
- $(window).on('action:composer.drafts.save', updateBadgeCount);
187
- $(window).on('action:composer.drafts.remove', updateBadgeCount);
188
- updateBadgeCount();
189
- });
190
- }
191
-
192
- function setupNProgress() {
193
- require(['nprogress'], function (NProgress) {
194
- window.nprogress = NProgress;
195
- if (NProgress) {
196
- $(window).on('action:ajaxify.start', function () {
197
- NProgress.set(0.7);
198
- });
199
-
200
- $(window).on('action:ajaxify.end', function () {
201
- NProgress.done(true);
202
- });
203
- }
204
- });
205
- }
206
-
207
- function handleMobileNavigator() {
208
- const paginationBlockEl = $('.pagination-block');
209
- require(['hooks'], function (hooks) {
210
- hooks.on('action:ajaxify.end', function () {
211
- paginationBlockEl.find('.dropdown-menu.show').removeClass('show');
212
- });
213
- hooks.on('filter:navigator.scroll', function (hookData) {
214
- paginationBlockEl.find('.dropdown-menu.show').removeClass('show');
215
- return hookData;
216
- });
217
- });
218
- }
219
-
220
- function setupNavTooltips() {
221
- // remove title from user icon in sidebar to prevent double tooltip
222
- $('.sidebar [component="header/avatar"] .avatar').removeAttr('title');
223
- const tooltipEls = $('.sidebar [title]');
224
- const lefttooltipEls = $('.sidebar-left [title]');
225
- const rightooltipEls = $('.sidebar-right [title]');
226
- const isRtl = $('html').attr('data-dir') === 'rtl';
227
- lefttooltipEls.tooltip({
228
- trigger: 'manual',
229
- animation: false,
230
- placement: isRtl ? 'left' : 'right',
231
- });
232
- rightooltipEls.tooltip({
233
- trigger: 'manual',
234
- animation: false,
235
- placement: isRtl ? 'right' : 'left',
236
- });
237
-
238
- tooltipEls.on('mouseenter', function (ev) {
239
- const target = $(ev.target);
240
- const isDropdown = target.hasClass('dropdown-menu') || !!target.parents('.dropdown-menu').length;
241
- if (!$('.sidebar').hasClass('open') && !isDropdown) {
242
- $(this).tooltip('show');
243
- }
244
- });
245
- tooltipEls.on('click mouseleave', function () {
246
- $(this).tooltip('hide');
247
- });
248
- }
249
-
250
- function fixPlaceholders() {
251
- if (!config.loggedIn) {
252
- return;
253
- }
254
- ['notifications', 'chat'].forEach((type) => {
255
- const countEl = document.querySelector(`[component="${type}/count"]`);
256
- if (!countEl) {
257
- return;
258
- }
259
- const count = parseInt(countEl.innerText, 10);
260
- if (count > 1) {
261
- const listEls = document.querySelectorAll(`[component="${type}/list"]`);
262
- listEls.forEach((listEl) => {
263
- const placeholder = listEl.querySelector('*');
264
- if (placeholder) {
265
- for (let x = 0; x < count - 1; x++) {
266
- const cloneEl = placeholder.cloneNode(true);
267
- listEl.insertBefore(cloneEl, placeholder);
268
- }
269
- }
270
- });
271
- }
272
- });
273
- }
274
-
275
- function fixSidebarOverflow() {
276
- // overflow-y-auto needs to be removed on main-nav when dropdowns are opened
277
- const mainNavEl = $('#main-nav');
278
- function toggleOverflow() {
279
- mainNavEl.toggleClass(
280
- 'overflow-y-auto',
281
- !mainNavEl.find('.dropdown-menu.show').length
282
- );
283
- }
284
- mainNavEl.on('shown.bs.dropdown', toggleOverflow)
285
- .on('hidden.bs.dropdown', toggleOverflow);
286
- }
287
- });
1
+ 'use strict';
2
+
3
+ $(document).ready(function () {
4
+ setupSkinSwitcher();
5
+ setupNProgress();
6
+ setupMobileMenu();
7
+ setupSearch();
8
+ setupDrafts();
9
+ handleMobileNavigator();
10
+ setupNavTooltips();
11
+ fixPlaceholders();
12
+ fixSidebarOverflow();
13
+
14
+ function setupSkinSwitcher() {
15
+ $('[component="skinSwitcher"]').on('click', '.dropdown-item', function () {
16
+ const skin = $(this).attr('data-value');
17
+ $('[component="skinSwitcher"] .dropdown-item .fa-check').addClass('invisible');
18
+ $(this).find('.fa-check').removeClass('invisible');
19
+ require(['forum/account/settings', 'hooks'], function (accountSettings, hooks) {
20
+ hooks.one('action:skin.change', function () {
21
+ $('[component="skinSwitcher"] [component="skinSwitcher/icon"]').removeClass('fa-fade');
22
+ });
23
+ $('[component="skinSwitcher"] [component="skinSwitcher/icon"]').addClass('fa-fade');
24
+ accountSettings.changeSkin(skin);
25
+ });
26
+ });
27
+ }
28
+
29
+ require(['hooks'], function (hooks) {
30
+ $(window).on('action:composer.resize action:sidebar.toggle', function () {
31
+ const isRtl = $('html').attr('data-dir') === 'rtl';
32
+ const css = {
33
+ width: $('#panel').width(),
34
+ };
35
+ const sidebarEl = $('.sidebar-left');
36
+ css[isRtl ? 'right' : 'left'] = sidebarEl.is(':visible') ? sidebarEl.outerWidth(true) : 0;
37
+ $('[component="composer"]').css(css);
38
+ });
39
+
40
+ hooks.on('filter:chat.openChat', function (hookData) {
41
+ // disables chat modals & goes straight to chat page based on user setting
42
+ hookData.modal = config.theme.chatModals && !utils.isMobile();
43
+ return hookData;
44
+ });
45
+ });
46
+
47
+ function setupMobileMenu() {
48
+ require(['hooks', 'api', 'navigator'], function (hooks, api, navigator) {
49
+ $('[component="sidebar/toggle"]').on('click', async function () {
50
+ const sidebarEl = $('.sidebar');
51
+ sidebarEl.toggleClass('open');
52
+ if (app.user.uid) {
53
+ await api.put(`/users/${app.user.uid}/settings`, {
54
+ settings: {
55
+ openSidebars: sidebarEl.hasClass('open') ? 'on' : 'off',
56
+ },
57
+ });
58
+ }
59
+ $(window).trigger('action:sidebar.toggle');
60
+ if (ajaxify.data.template.topic) {
61
+ hooks.fire('action:navigator.update', { newIndex: navigator.getIndex() });
62
+ }
63
+ });
64
+
65
+ const bottomBar = $('[component="bottombar"]');
66
+ const $body = $('body');
67
+ const $window = $(window);
68
+ $body.on('shown.bs.dropdown hidden.bs.dropdown', '.sticky-tools', function () {
69
+ bottomBar.toggleClass('hidden', $(this).find('.dropdown-menu.show').length);
70
+ });
71
+ function isSearchVisible() {
72
+ return !!$('[component="bottombar"] [component="sidebar/search"] .search-dropdown.show').length;
73
+ }
74
+
75
+ let lastScrollTop = $window.scrollTop();
76
+ let newPostsLoaded = false;
77
+
78
+ function onWindowScroll() {
79
+ const st = $window.scrollTop();
80
+ if (newPostsLoaded) {
81
+ newPostsLoaded = false;
82
+ lastScrollTop = st;
83
+ return;
84
+ }
85
+ if (st !== lastScrollTop && !navigator.scrollActive && !isSearchVisible()) {
86
+ const diff = Math.abs(st - lastScrollTop);
87
+ const scrolledDown = st > lastScrollTop;
88
+ const scrolledUp = st < lastScrollTop;
89
+ if (diff > 10) {
90
+ bottomBar.css({
91
+ bottom: !scrolledUp && scrolledDown ?
92
+ -bottomBar.find('.bottombar-nav').outerHeight(true) :
93
+ 0,
94
+ });
95
+ }
96
+ }
97
+ lastScrollTop = st;
98
+ }
99
+
100
+ const delayedScroll = utils.throttle(onWindowScroll, 250);
101
+ function enableAutohide() {
102
+ $window.off('scroll', delayedScroll);
103
+ if (config.theme.autohideBottombar) {
104
+ lastScrollTop = $window.scrollTop();
105
+ $window.on('scroll', delayedScroll);
106
+ }
107
+ }
108
+
109
+ hooks.on('action:posts.loading', function () {
110
+ $window.off('scroll', delayedScroll);
111
+ });
112
+ hooks.on('action:posts.loaded', function () {
113
+ newPostsLoaded = true;
114
+ setTimeout(enableAutohide, 250);
115
+ });
116
+ hooks.on('action:ajaxify.end', function () {
117
+ $window.off('scroll', delayedScroll);
118
+ if (config.theme.autohideBottombar) {
119
+ bottomBar.css({ bottom: 0 });
120
+ setTimeout(enableAutohide, 250);
121
+ }
122
+ });
123
+ });
124
+ }
125
+
126
+ function setupSearch() {
127
+ $('[component="sidebar/search"]').on('shown.bs.dropdown', function () {
128
+ $(this).find('[component="search/fields"] input[name="query"]').trigger('focus');
129
+ });
130
+ }
131
+
132
+ function setupDrafts() {
133
+ require(['composer/drafts', 'bootbox'], function (drafts, bootbox) {
134
+ const draftsEl = $('[component="sidebar/drafts"]');
135
+
136
+ function updateBadgeCount() {
137
+ const count = drafts.getAvailableCount();
138
+ if (count > 0) {
139
+ draftsEl.removeClass('hidden');
140
+ }
141
+ $('[component="drafts/count"]').toggleClass('hidden', count <= 0).text(count);
142
+ }
143
+
144
+ async function renderDraftList() {
145
+ const draftListEl = $('[component="drafts/list"]');
146
+ const draftItems = drafts.listAvailable();
147
+ if (!draftItems.length) {
148
+ draftListEl.find('.no-drafts').removeClass('hidden');
149
+ draftListEl.find('.placeholder-wave').addClass('hidden');
150
+ draftListEl.find('.draft-item-container').html('');
151
+ return;
152
+ }
153
+ draftItems.reverse().forEach((draft) => {
154
+ if (draft) {
155
+ if (draft.title) {
156
+ draft.title = utils.escapeHTML(String(draft.title));
157
+ }
158
+ draft.text = utils.escapeHTML(
159
+ draft.text
160
+ ).replace(/(?:\r\n|\r|\n)/g, '<br>');
161
+ }
162
+ });
163
+
164
+ const html = await app.parseAndTranslate('partials/sidebar/drafts', 'drafts', { drafts: draftItems });
165
+ draftListEl.find('.no-drafts').addClass('hidden');
166
+ draftListEl.find('.placeholder-wave').addClass('hidden');
167
+ draftListEl.find('.draft-item-container').html(html).find('.timeago').timeago();
168
+ }
169
+
170
+
171
+ draftsEl.on('shown.bs.dropdown', renderDraftList);
172
+
173
+ draftsEl.on('click', '[component="drafts/open"]', function () {
174
+ drafts.open($(this).attr('data-save-id'));
175
+ });
176
+
177
+ draftsEl.on('click', '[component="drafts/delete"]', function () {
178
+ const save_id = $(this).attr('data-save-id');
179
+ bootbox.confirm('[[modules:composer.discard-draft-confirm]]', function (ok) {
180
+ if (ok) {
181
+ drafts.removeDraft(save_id);
182
+ renderDraftList();
183
+ }
184
+ });
185
+ return false;
186
+ });
187
+
188
+ $(window).on('action:composer.drafts.save', updateBadgeCount);
189
+ $(window).on('action:composer.drafts.remove', updateBadgeCount);
190
+ updateBadgeCount();
191
+ });
192
+ }
193
+
194
+ function setupNProgress() {
195
+ require(['nprogress'], function (NProgress) {
196
+ window.nprogress = NProgress;
197
+ if (NProgress) {
198
+ $(window).on('action:ajaxify.start', function () {
199
+ NProgress.set(0.7);
200
+ });
201
+
202
+ $(window).on('action:ajaxify.end', function () {
203
+ NProgress.done(true);
204
+ });
205
+ }
206
+ });
207
+ }
208
+
209
+ function handleMobileNavigator() {
210
+ const paginationBlockEl = $('.pagination-block');
211
+ require(['hooks'], function (hooks) {
212
+ hooks.on('action:ajaxify.end', function () {
213
+ paginationBlockEl.find('.dropdown-menu.show').removeClass('show');
214
+ });
215
+ hooks.on('filter:navigator.scroll', function (hookData) {
216
+ paginationBlockEl.find('.dropdown-menu.show').removeClass('show');
217
+ return hookData;
218
+ });
219
+ });
220
+ }
221
+
222
+ function setupNavTooltips() {
223
+ // remove title from user icon in sidebar to prevent double tooltip
224
+ $('.sidebar [component="header/avatar"] .avatar').removeAttr('title');
225
+ const tooltipEls = $('.sidebar [title]');
226
+ const lefttooltipEls = $('.sidebar-left [title]');
227
+ const rightooltipEls = $('.sidebar-right [title]');
228
+ const isRtl = $('html').attr('data-dir') === 'rtl';
229
+ lefttooltipEls.tooltip({
230
+ trigger: 'manual',
231
+ animation: false,
232
+ placement: isRtl ? 'left' : 'right',
233
+ });
234
+ rightooltipEls.tooltip({
235
+ trigger: 'manual',
236
+ animation: false,
237
+ placement: isRtl ? 'right' : 'left',
238
+ });
239
+
240
+ tooltipEls.on('mouseenter', function (ev) {
241
+ const target = $(ev.target);
242
+ const isDropdown = target.hasClass('dropdown-menu') || !!target.parents('.dropdown-menu').length;
243
+ if (!$('.sidebar').hasClass('open') && !isDropdown) {
244
+ $(this).tooltip('show');
245
+ }
246
+ });
247
+ tooltipEls.on('click mouseleave', function () {
248
+ $(this).tooltip('hide');
249
+ });
250
+ }
251
+
252
+ function fixPlaceholders() {
253
+ if (!config.loggedIn) {
254
+ return;
255
+ }
256
+ ['notifications', 'chat'].forEach((type) => {
257
+ const countEl = $(`nav.sidebar [component="${type}/count"]`).first();
258
+ if (!countEl.length) {
259
+ return;
260
+ }
261
+ const count = parseInt(countEl.text(), 10);
262
+ if (count > 1) {
263
+ const listEls = $(`.dropdown-menu [component="${type}/list"]`);
264
+ listEls.each((index, el) => {
265
+ const placeholder = $(el).children().first();
266
+ for (let x = 0; x < count - 1; x++) {
267
+ const cloneEl = placeholder.clone(true);
268
+ cloneEl.insertAfter(placeholder);
269
+ }
270
+ });
271
+ }
272
+ });
273
+ }
274
+
275
+ function fixSidebarOverflow() {
276
+ // overflow-y-auto needs to be removed on main-nav when dropdowns are opened
277
+ const mainNavEl = $('#main-nav');
278
+ function toggleOverflow() {
279
+ mainNavEl.toggleClass(
280
+ 'overflow-y-auto',
281
+ !mainNavEl.find('.dropdown-menu.show').length
282
+ );
283
+ }
284
+ mainNavEl.on('shown.bs.dropdown', toggleOverflow)
285
+ .on('hidden.bs.dropdown', toggleOverflow);
286
+ }
287
+ });