nodebb-theme-harmony 1.0.0-beta.2 → 1.0.0-beta.20

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 (59) hide show
  1. package/package.json +1 -1
  2. package/public/harmony.js +21 -21
  3. package/scss/chats.scss +7 -2
  4. package/scss/common.scss +16 -4
  5. package/scss/modules/composer.scss +0 -4
  6. package/scss/modules/cover.scss +1 -11
  7. package/scss/overrides.scss +2 -0
  8. package/scss/sidebar.scss +27 -2
  9. package/scss/topic.scss +22 -12
  10. package/templates/account/categories.tpl +0 -1
  11. package/templates/account/consent.tpl +62 -0
  12. package/templates/account/edit.tpl +1 -1
  13. package/templates/account/info.tpl +1 -18
  14. package/templates/account/sessions.tpl +1 -18
  15. package/templates/categories.tpl +1 -1
  16. package/templates/category.tpl +1 -2
  17. package/templates/chats.tpl +1 -1
  18. package/templates/flags/detail.tpl +0 -1
  19. package/templates/flags/list.tpl +1 -1
  20. package/templates/partials/account/header.tpl +10 -17
  21. package/templates/partials/account/session-list.tpl +18 -0
  22. package/templates/partials/categories/lastpost.tpl +1 -1
  23. package/templates/partials/{category-filter-content.tpl → category/filter-dropdown-content.tpl} +2 -2
  24. package/templates/partials/{category-selector-content.tpl → category/selector-dropdown-content.tpl} +1 -1
  25. package/templates/partials/category/subcategory.tpl +1 -1
  26. package/templates/partials/category/watch.tpl +28 -4
  27. package/templates/partials/chats/message-window.tpl +3 -2
  28. package/templates/partials/chats/message.tpl +1 -1
  29. package/templates/partials/flags/filters.tpl +1 -1
  30. package/templates/partials/groups/admin.tpl +1 -1
  31. package/templates/partials/mobile-footer.tpl +70 -62
  32. package/templates/partials/post_bar.tpl +5 -4
  33. package/templates/partials/posts_list_item.tpl +2 -2
  34. package/templates/partials/quick-search-results.tpl +1 -1
  35. package/templates/partials/sidebar/chats.tpl +5 -2
  36. package/templates/partials/sidebar/drafts.tpl +4 -4
  37. package/templates/partials/sidebar/notifications.tpl +3 -3
  38. package/templates/partials/sidebar/search-mobile.tpl +1 -1
  39. package/templates/partials/sidebar/user-menu.tpl +1 -1
  40. package/templates/partials/sidebar-left.tpl +3 -0
  41. package/templates/partials/topic/event.tpl +1 -1
  42. package/templates/partials/topic/navigation-post.tpl +5 -9
  43. package/templates/partials/topic/navigator-mobile.tpl +43 -0
  44. package/templates/partials/topic/post.tpl +2 -2
  45. package/templates/partials/topic/quickreply.tpl +3 -3
  46. package/templates/partials/topic/watch.tpl +28 -4
  47. package/templates/partials/topic-list-bar.tpl +6 -6
  48. package/templates/partials/topics_list.tpl +4 -4
  49. package/templates/partials/users/filter-dropdown-content.tpl +20 -0
  50. package/templates/popular.tpl +1 -1
  51. package/templates/post-queue.tpl +112 -0
  52. package/templates/recent.tpl +1 -1
  53. package/templates/top.tpl +1 -1
  54. package/templates/topic.tpl +2 -2
  55. package/templates/unread.tpl +1 -1
  56. package/templates/partials/category-filter-right.tpl +0 -5
  57. package/templates/partials/category-filter.tpl +0 -3
  58. package/templates/partials/category-selector-right.tpl +0 -5
  59. package/templates/partials/category-selector.tpl +0 -3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nodebb-theme-harmony",
3
- "version": "1.0.0-beta.2",
3
+ "version": "1.0.0-beta.20",
4
4
  "nbbpm": {
5
5
  "compatibility": "^3.0.0"
6
6
  },
package/public/harmony.js CHANGED
@@ -5,6 +5,7 @@ $(document).ready(function () {
5
5
  setupMobileMenu();
6
6
  setupSearch();
7
7
  setupDrafts();
8
+ handleMobileNavigator();
8
9
 
9
10
  $('[component="skinSwitcher"]').on('click', '.dropdown-item', function () {
10
11
  const skin = $(this).attr('data-value');
@@ -56,32 +57,17 @@ $(document).ready(function () {
56
57
  $('[component="sidebar/search"]').on('shown.bs.dropdown', function () {
57
58
  $(this).find('[component="search/fields"] input[name="query"]').trigger('focus');
58
59
  });
59
-
60
- function resizeResults(hookData) {
61
- if (hookData && hookData.data && !hookData.data.posts.length) {
62
- $('.bottombar .quick-search-results').css({ height: 'initial' });
63
- return;
64
- }
65
- const dropdown = $('.bottombar .search-dropdown');
66
- const padY = dropdown.innerHeight() - dropdown.height();
67
- const input = dropdown.find('.input-container').outerHeight(true);
68
- const showMore = dropdown.find('.show-more-container').outerHeight(true);
69
- const newHeight = Math.max(
70
- 150,
71
- $(window).height() - (input + (showMore || 0) + (padY * 2) + 30)
72
- );
73
- $('.bottombar .quick-search-results').height(newHeight);
74
- }
75
- require(['hooks'], function (hooks) {
76
- $(window).on('resize', resizeResults);
77
- hooks.on('action:search.quick.complete', resizeResults);
78
- });
79
60
  }
80
61
 
81
62
  function setupDrafts() {
82
63
  require(['composer/drafts'], function (drafts) {
64
+ const draftsEl = $('[component="sidebar/drafts"]');
65
+
83
66
  function updateBadgeCount() {
84
67
  const count = drafts.getAvailableCount();
68
+ if (count > 0) {
69
+ draftsEl.removeClass('hidden');
70
+ }
85
71
  $('[component="drafts/count"]').toggleClass('hidden', count <= 0).text(count);
86
72
  }
87
73
 
@@ -105,7 +91,7 @@ $(document).ready(function () {
105
91
  draftListEl.append(html).find('.timeago').timeago();
106
92
  }
107
93
 
108
- const draftsEl = $('[component="sidebar/drafts"]');
94
+
109
95
  draftsEl.on('shown.bs.dropdown', renderDraftList);
110
96
 
111
97
  draftsEl.on('click', '[component="drafts/open"]', function () {
@@ -123,6 +109,7 @@ $(document).ready(function () {
123
109
  updateBadgeCount();
124
110
  });
125
111
  }
112
+
126
113
  function setupNProgress() {
127
114
  require(['nprogress'], function (NProgress) {
128
115
  window.nprogress = NProgress;
@@ -137,4 +124,17 @@ $(document).ready(function () {
137
124
  }
138
125
  });
139
126
  }
127
+
128
+ function handleMobileNavigator() {
129
+ const paginationBlockEl = $('.pagination-block');
130
+ require(['hooks'], function (hooks) {
131
+ hooks.on('action:ajaxify.end', function () {
132
+ paginationBlockEl.find('.dropdown-menu.show').removeClass('show');
133
+ });
134
+ hooks.on('filter:navigator.scroll', function (hookData) {
135
+ paginationBlockEl.find('.dropdown-menu.show').removeClass('show');
136
+ return hookData;
137
+ });
138
+ });
139
+ }
140
140
  });
package/scss/chats.scss CHANGED
@@ -6,8 +6,10 @@
6
6
  body.page-user-chats {
7
7
  overflow: hidden;
8
8
  }
9
-
10
- .expanded-chat, .chat-modal {
9
+ [component="chat/nav-wrapper"] {
10
+ width: 300px;
11
+ }
12
+ .expanded-chat {
11
13
  // no taskbar so hide minimize button
12
14
  [data-action="minimize"] {
13
15
  display: none!important;
@@ -38,6 +40,9 @@ body.page-user-chats {
38
40
 
39
41
  /* Mobile handling of chat page */
40
42
  @include media-breakpoint-down(md) {
43
+ [component="chat/nav-wrapper"] {
44
+ width: 100%;
45
+ }
41
46
  .page-user-chats {
42
47
  .chats-full {
43
48
  padding-bottom: 8rem!important;
package/scss/common.scss CHANGED
@@ -14,8 +14,13 @@ body {
14
14
  .text-sm { font-size: 0.875rem!important; } // 14px
15
15
  .text-xs { font-size: 0.75rem!important; } // 12px
16
16
 
17
- .btn-link:hover {
18
- text-decoration: none;
17
+ .caret {
18
+ &::after {
19
+ border: none;
20
+ font-family: "FontAwesome";
21
+ content: "\f078";
22
+ color: tint-color($primary, 40%);
23
+ }
19
24
  }
20
25
 
21
26
  .sticky-tools {
@@ -35,6 +40,13 @@ body {
35
40
  }
36
41
  }
37
42
 
43
+ .btn-link {
44
+ &:hover, &.active {
45
+ background-color: $btn-ghost-hover-color;
46
+ text-decoration: none;
47
+ }
48
+ }
49
+
38
50
  @mixin btn-ghost-base {
39
51
  display: flex;
40
52
  align-items: center;
@@ -48,10 +60,10 @@ body {
48
60
  text-align: left;
49
61
  --bs-text-opacity: 1;
50
62
  color: inherit !important;
51
- $hover-color: mix($light, $dark, 90);
63
+
52
64
  cursor: pointer;
53
65
  &:hover, &.active {
54
- background-color: $hover-color;
66
+ background-color: $btn-ghost-hover-color;
55
67
  text-decoration: none;
56
68
  }
57
69
  }
@@ -6,10 +6,6 @@ $composer-bg: $body-bg !default;
6
6
  background-color: $bg !important;
7
7
  }
8
8
 
9
- .composer {
10
- z-index: 3 !important;
11
- }
12
-
13
9
  .skin-noskin {
14
10
  // only using colors when there is no bootswatch skin applied
15
11
  $composer-color: $secondary;
@@ -12,12 +12,11 @@
12
12
 
13
13
  &:hover {
14
14
  .controls {
15
- opacity: 0.8;
15
+ opacity: 1;
16
16
  }
17
17
  }
18
18
 
19
19
  .controls {
20
- text-align: center;
21
20
  height: 200px;
22
21
  line-height: 200px;
23
22
  opacity: 0;
@@ -28,15 +27,6 @@
28
27
  > * {
29
28
  pointer-events: all;
30
29
  }
31
-
32
- .fa {
33
- color: white;
34
- background-color: #333;
35
- opacity: 1;
36
- margin: 15px;
37
- padding: 5px;
38
- border-radius: 4px;
39
- }
40
30
  }
41
31
 
42
32
  &.active {
@@ -39,6 +39,8 @@ $text-muted: $gray-600 !default;
39
39
  $border-color: $gray-200 !default;
40
40
  $link-color: shade-color($blue, 20%) !default;
41
41
 
42
+ $btn-ghost-hover-color: mix($light, $dark, 90);
43
+
42
44
  // no caret on dropdown-toggle
43
45
  $enable-caret: false;
44
46
 
package/scss/sidebar.scss CHANGED
@@ -113,7 +113,32 @@
113
113
  font-size: 9px;
114
114
  line-height: 12px;
115
115
  }
116
- .search.bottom-sheet .dropdown-menu {
117
- max-height: 100%;
116
+
117
+ .navigation-dropdown, .user-dropdown {
118
+ > li {
119
+ > a, .dropdown-item {
120
+ padding: 10px 20px!important;
121
+ }
122
+ }
123
+ left: 0!important;
124
+ right: 0!important;
125
+ bottom: $spacer!important;
126
+ box-shadow: none!important;
127
+ max-height: 60vh!important;
128
+ overflow: auto!important;
129
+ }
130
+ .search-dropdown .quick-search-results {
131
+ max-height: 225px!important;
132
+ overflow-y: auto!important;
133
+ }
134
+ .search-dropdown, .chats-dropdown, .notifications-dropdown, .drafts-dropdown {
135
+ left: 0!important;
136
+ right: 0!important;
137
+ bottom: $spacer!important;
138
+ box-shadow: none!important;
139
+ ul {
140
+ max-height: 60vh!important;
141
+ overflow-y: auto!important;
142
+ }
118
143
  }
119
144
  }
package/scss/topic.scss CHANGED
@@ -1,3 +1,5 @@
1
+ .pagination-block { display: none; }
2
+
1
3
  .page-topic {
2
4
  [component="topic/title"] {
3
5
  font-size: 28px;
@@ -14,18 +16,6 @@
14
16
  line-height: 20px;
15
17
  }
16
18
 
17
- .action-bar {
18
- .dropdown-toggle::after {
19
- border: none;
20
- font-family: "FontAwesome";
21
- content: "\f078";
22
- color: tint-color($primary, 40%);
23
-
24
- position: relative;
25
- top: 2px;
26
- }
27
- }
28
-
29
19
  .topic {
30
20
  .posts {
31
21
  max-width: 960px;
@@ -67,6 +57,17 @@
67
57
  [component="post/reply-count"] {
68
58
  font-size: $font-size-base * .75;
69
59
  }
60
+
61
+ [component="post/upvote"], [component="post/downvote"] {
62
+ &.upvoted, &.downvoted {
63
+ background-color: lighten($btn-ghost-hover-color, 5%);
64
+
65
+ &:hover {
66
+ background-color: $btn-ghost-hover-color;
67
+
68
+ }
69
+ }
70
+ }
70
71
  }
71
72
  }
72
73
 
@@ -106,6 +107,15 @@
106
107
  }
107
108
  }
108
109
  }
110
+
111
+ .pagination-block {
112
+ display: block;
113
+ transition: opacity 250ms ease-in;
114
+ opacity: 0;
115
+ &.ready {
116
+ opacity: 1;
117
+ }
118
+ }
109
119
  }
110
120
 
111
121
  @include media-breakpoint-up(sm) {
@@ -11,7 +11,6 @@
11
11
  <div class="btn-group bottom-sheet" component="category/watch/all">
12
12
  <button class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown" type="button">
13
13
  <span>[[user:change_all]]</span>
14
- <span class="caret"></span>
15
14
  </button>
16
15
  <ul class="dropdown-menu">
17
16
  <li><a class="dropdown-item" href="#" component="category/watching" data-state="watching"><i class="fa fa-fw fa-inbox"></i> [[category:watching]]<p class="help-text"><small>[[category:watching.description]]</small></p></a></li>
@@ -12,6 +12,68 @@
12
12
  <hr />
13
13
 
14
14
  <div class="row">
15
+ <div class="col-sm-6">
16
+ <!-- IF gdpr_consent -->
17
+ <div class="alert alert-success">
18
+ <i class="fa fa-check float-end fa-3x"></i>
19
+ [[user:consent.received]]
20
+ </div>
21
+ <!-- ELSE -->
22
+ <div class="alert alert-warning">
23
+ [[user:consent.not_received]]
24
+ <br /><br />
25
+ <div class="text-center">
26
+ <button class="btn btn-warning" data-action="consent">[[user:consent.give]]</button>
27
+ </div>
28
+ </div>
29
+ <!-- END -->
30
+ <div class="card">
31
+ <div class="card-body">
32
+ <p>[[user:consent.email_intro]]</p>
33
+ {{{ if digest.enabled }}}
34
+ <p>[[user:consent.digest_frequency, {digest.frequency}]]</p>
35
+ {{{ else }}}
36
+ <p>[[user:consent.digest_off]]</p>
37
+ {{{ end }}}
38
+
39
+ <div class="d-grid">
40
+ <a class="btn btn-outline-secondary" href="./settings">
41
+ <i class="fa fa-cog"></i>
42
+ [[pages:account/settings]]
43
+ </a>
44
+ </div>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ <div class="col-sm-6">
49
+ <div class="card">
50
+ <div class="card-body">
51
+ <p><strong>[[user:consent.right_of_access]]</strong></p>
52
+ <p>[[user:consent.right_of_access_description]]</p>
53
+ <p><strong>[[user:consent.right_to_rectification]]</strong></p>
54
+ <p>[[user:consent.right_to_rectification_description]]</p>
55
+ <p><strong>[[user:consent.right_to_erasure]]</strong></p>
56
+ <p>[[user:consent.right_to_erasure_description]]</p>
57
+ <p><strong>[[user:consent.right_to_data_portability]]</strong></p>
58
+ <p>[[user:consent.right_to_data_portability_description]]</p>
59
+
60
+ <hr />
61
+
62
+ <div class="btn-group-vertical d-grid">
63
+ <a data-action="export-profile" class="btn btn-outline-secondary">
64
+ <i class="fa fa-download"></i> [[user:consent.export_profile]]
65
+ </a>
66
+ <a data-action="export-posts" class="btn btn-outline-secondary">
67
+ <i class="fa fa-download"></i> [[user:consent.export_posts]]
68
+ </a>
69
+ <a data-action="export-uploads" class="btn btn-outline-secondary">
70
+ <i class="fa fa-download"></i> [[user:consent.export_uploads]]
71
+ </a>
72
+ </div>
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </div>
15
77
  </div>
16
78
  </div>
17
79
  </div>
@@ -74,7 +74,7 @@
74
74
  <div class="text-center">
75
75
  <ul class="list-group mb-3 text-sm text-nowrap">
76
76
  <!-- IF allowProfilePicture -->
77
- <a id="changePictureBtn" href="#" class="list-group-item px-1 text-decoration-none">[[user:change_picture]]</a>
77
+ <a component="profile/change/picture" href="#" class="list-group-item px-1 text-decoration-none">[[user:change_picture]]</a>
78
78
  <!-- ENDIF allowProfilePicture -->
79
79
  <!-- IF !username:disableEdit -->
80
80
  <a href="{config.relative_path}/user/{userslug}/edit/username" class="list-group-item px-1 text-decoration-none">[[user:change_username]]</a>
@@ -8,24 +8,7 @@
8
8
  <div class="mb-3">
9
9
  <h4>[[global:sessions]]</h4>
10
10
  <ul class="list-group" component="user/sessions">
11
- {{{each sessions}}}
12
- <li class="list-group-item" data-uuid="{../uuid}">
13
- <div class="float-end">
14
- <!-- IF isSelfOrAdminOrGlobalModerator -->
15
- <!-- IF !../current -->
16
- <button class="btn btn-sm btn-outline-secondary" type="button" data-action="revokeSession">Revoke Session</button>
17
- <!-- ENDIF !../current -->
18
- <!-- ENDIF isSelfOrAdminOrGlobalModerator -->
19
- {function.userAgentIcons}
20
- <i class="fa fa-circle text-<!-- IF ../current -->success<!-- ELSE -->muted<!-- ENDIF ../current -->"></i>
21
- </div>
22
- {../browser} {../version} on {../platform}<br />
23
- <small class="timeago text-muted" title="{../datetimeISO}"></small>
24
- <ul>
25
- <li><strong>[[global:ip_address]]</strong>: {../ip}</li>
26
- </ul>
27
- </li>
28
- {{{end}}}
11
+ <!-- IMPORT partials/account/session-list.tpl -->
29
12
  </ul>
30
13
  </div>
31
14
  {{{ end }}}
@@ -7,24 +7,7 @@
7
7
  <p class="lead">[[user:sessions.description]]</p>
8
8
  <hr />
9
9
  <ul class="list-group" component="user/sessions">
10
- {{{each sessions}}}
11
- <li class="list-group-item" data-uuid="{../uuid}">
12
- <div class="float-end">
13
- <!-- IF isSelfOrAdminOrGlobalModerator -->
14
- <!-- IF !../current -->
15
- <button class="btn btn-sm btn-outline-secondary" type="button" data-action="revokeSession">Revoke Session</button>
16
- <!-- ENDIF !../current -->
17
- <!-- ENDIF isSelfOrAdminOrGlobalModerator -->
18
- {function.userAgentIcons}
19
- <i class="fa fa-circle text-<!-- IF ../current -->success<!-- ELSE -->muted<!-- ENDIF ../current -->"></i>
20
- </div>
21
- {../browser} {../version} on {../platform}<br />
22
- <small class="timeago text-muted" title="{../datetimeISO}"></small>
23
- <ul>
24
- <li><strong>[[global:ip_address]]</strong>: {../ip}</li>
25
- </ul>
26
- </li>
27
- {{{end}}}
10
+ <!-- IMPORT partials/account/session-list.tpl -->
28
11
  </ul>
29
12
  </div>
30
13
  </div>
@@ -6,7 +6,7 @@
6
6
  <div class="row">
7
7
  <div class="{{{ if widgets.sidebar.length }}}col-lg-9 col-sm-12{{{ else }}}col-lg-12{{{ end }}}">
8
8
  {{{ if pagination.pages.length }}}
9
- <div><!-- IMPORT partials/category-selector.tpl --></div>
9
+ <div><!-- IMPORT partials/category/selector-dropdown-left.tpl --></div>
10
10
  {{{ end }}}
11
11
  <ul class="categories list-unstyled" itemscope itemtype="http://www.schema.org/ItemList">
12
12
  {{{ each categories }}}
@@ -33,8 +33,7 @@
33
33
 
34
34
  {{{ if !topics.length }}}
35
35
  {{{ if privileges.topics:create }}}
36
- <hr class="visible-xs" />
37
- <div class="alert alert-warning" id="category-no-topics">
36
+ <div class="alert alert-info mt-3" id="category-no-topics">
38
37
  [[category:no_topics]]
39
38
  </div>
40
39
  {{{ end }}}
@@ -1,5 +1,5 @@
1
1
  <div class="chats-full d-flex gap-1 vh-100 py-3">
2
- <div class="d-flex flex-column h-100" style="width:300px;" component="chat/nav-wrapper" data-loaded="{{{ if roomId }}}1{{{ else }}}0{{{ end }}}">
2
+ <div class="d-flex flex-column h-100" component="chat/nav-wrapper" data-loaded="{{{ if roomId }}}1{{{ else }}}0{{{ end }}}">
3
3
  <div class="chat-search dropdown mb-2">
4
4
  <label class="text-xs text-muted">[[users:search-user-for-chat]]</label>
5
5
 
@@ -146,7 +146,6 @@
146
146
  <button type="button" class="btn btn-light dropdown-toggle" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
147
147
  <i class="fa fa-street-view"></i>
148
148
  [[flags:flagged-user]]
149
- <span class="caret"></span>
150
149
  </button>
151
150
  <ul class="dropdown-menu">
152
151
  <li><a class="dropdown-item" href="{config.relative_path}/uid/{target.uid}">[[flags:view-profile]]</a></li>
@@ -18,7 +18,7 @@
18
18
 
19
19
  <div class="btn-group float-end" component="flags/bulk-actions">
20
20
  <button type="button" class="btn btn-outline-secondary dropdown-toggle" data-bs-toggle="dropdown" autocomplete="off" aria-haspopup="true" aria-expanded="false" disabled="disabled">
21
- <i class="fa fa-clone"></i> [[flags:bulk-actions]] <span class="caret"></span>
21
+ <i class="fa fa-clone"></i> <span class="fw-semibold">[[flags:bulk-actions]]</span>
22
22
  </button>
23
23
  <ul class="dropdown-menu">
24
24
  <li><a href="#" class="dropdown-item" data-action="bulk-assign">[[flags:assign-to-me]]</a></li>
@@ -8,10 +8,10 @@
8
8
  <div class="container">
9
9
  {{{ if allowCoverPicture }}}
10
10
  {{{ if canEdit }}}
11
- <div class="controls">
12
- <span class="upload"><i class="fa fa-fw fa-2x fa-upload"></i></span>
13
- <span class="resize"><i class="fa fa-fw fa-2x fa-arrows"></i></span>
14
- <span class="remove"><i class="fa fa-fw fa-2x fa-times"></i></span>
11
+ <div class="controls text-center">
12
+ <span class="upload p-2 m-2 rounded-1 text-bg-light opacity-75"><i class="fa fa-fw fa-upload"></i></span>
13
+ <span class="resize p-2 m-2 rounded-1 text-bg-light opacity-75"><i class="fa fa-fw fa-arrows"></i></span>
14
+ <span class="remove p-2 m-2 rounded-1 text-bg-light opacity-75"><i class="fa fa-fw fa-times"></i></span>
15
15
  </div>
16
16
  <div class="save text-bg-primary">[[groups:cover-save]] <i class="fa fa-fw fa-floppy-o"></i></div>
17
17
  <div class="indicator text-bg-primary">[[groups:cover-saving]] <i class="fa fa-fw fa-refresh fa-spin"></i></div>
@@ -21,19 +21,12 @@
21
21
  </div>
22
22
 
23
23
  <div class="d-flex flex-column flex-md-row gap-2 w-100 pb-4 mb-4 mt-2 border-bottom">
24
- <div class="avatar-wrapper border-4 position-relative align-self-start d-none d-md-block" style="margin-top: -75px;">
25
- {{{ if picture }}}
26
- <img src="{picture}" class="avatar avatar-rounded" style="--avatar-size: 142px;" />
27
- {{{ else }}}
28
- <div class="avatar avatar-rounded" style="background-color: {icon:bgColor}; --avatar-size: 142px;" title="{username}">{icon:text}</div>
29
- {{{ end }}}
30
- </div>
31
-
32
- <div class="avatar-wrapper border-4 position-relative align-self-center d-block d-md-none" style="margin-top: -75px;">
33
- {{{ if picture }}}
34
- <img src="{picture}" class="avatar avatar-rounded" style="--avatar-size: 142px;" />
35
- {{{ else }}}
36
- <div class="avatar avatar-rounded" style="background-color: {icon:bgColor}; --avatar-size: 142px;" title="{username}">{icon:text}</div>
24
+ <div {{{ if (allowProfilePicture && isSelfOrAdminOrGlobalModerator)}}}component="profile/change/picture"{{{ end }}} class="avatar-wrapper border-4 position-relative align-self-center align-self-md-start hover-parent" style="margin-top: -75px;">
25
+ {buildAvatar(@value, "142px", true)}
26
+ {{{ if (allowProfilePicture && isSelfOrAdminOrGlobalModerator)}}}
27
+ <div component="profile/change/picture" class="d-none d-md-block pointer p-2 rounded-1 opacity-75 text-bg-light position-absolute top-50 start-50 translate-middle hover-visible">
28
+ <span class="upload"><i class="fa fa-fw fa-upload"></i></span>
29
+ </div>
37
30
  {{{ end }}}
38
31
  </div>
39
32
 
@@ -0,0 +1,18 @@
1
+ {{{ each sessions }}}
2
+ <li class="list-group-item text-break" data-uuid="{./uuid}">
3
+ <div class="float-end">
4
+ {{{ if isSelfOrAdminOrGlobalModerator }}}
5
+ {{{ if !./current }}}
6
+ <button class="btn btn-sm btn-outline-secondary" type="button" data-action="revokeSession">[[user:revoke-session]]</button>
7
+ {{{ end }}}
8
+ {{{ end }}}
9
+ {function.userAgentIcons}
10
+ <i class="fa fa-circle text-{{{ if ./current }}}success{{{ else }}}muted{{{ end }}}"></i>
11
+ </div>
12
+ [[user:browser-version-on-platform, {./browser}, {./version}, {./platform}]]<br />
13
+ <small class="timeago text-muted" title="{../datetimeISO}"></small>
14
+ <ul>
15
+ <li><strong>[[global:ip_address]]</strong>: {../ip}</li>
16
+ </ul>
17
+ </li>
18
+ {{{ end }}}
@@ -4,7 +4,7 @@
4
4
  <div component="category/posts" class="ps-3">
5
5
  <a class="background-link" href="{config.relative_path}/topic/{./topic.slug}{{{ if ./index }}}/{./index}{{{ end }}}"></a>
6
6
  <p class="mb-0">
7
- <a class="text-decoration-none" href="{config.relative_path}/user/{./user.userslug}">{buildAvatar(posts.user, "20px", true)}</a>
7
+ <a class="text-decoration-none" href="{config.relative_path}/user/{./user.userslug}">{buildAvatar(posts.user, "20px", true, "avatar-tooltip")}</a>
8
8
  <a class="permalink text-muted" href="{config.relative_path}/topic/{./topic.slug}{{{ if ./index }}}/{./index}{{{ end }}}">
9
9
  <span class="timeago text-xs" title="{../timestampISO}"></span>
10
10
  </a>
@@ -1,7 +1,7 @@
1
1
  <button type="button" class="btn-ghost-sm d-flex gap-2 align-items-baseline dropdown-toggle" data-bs-toggle="dropdown">
2
2
  {{{ if selectedCategory }}}
3
3
  <span class="category-item">
4
- {buildCategoryIcon(selectedCategory, "20px", "rounded-circle")}
4
+ {buildCategoryIcon(selectedCategory, "18px", "rounded-circle")}
5
5
  <span class="visible-md-inline visible-lg-inline fw-semibold">{selectedCategory.name}</span>
6
6
  </span>
7
7
  {{{ else }}}
@@ -9,7 +9,7 @@
9
9
  <span class="visible-md-inline visible-lg-inline fw-semibold">[[unread:all_categories]]</span>{{{ end }}}
10
10
  </button>
11
11
  <div component="category-selector-search" class="hidden position-absolute">
12
- <input type="text" class="form-control" autocomplete="off">
12
+ <input type="text" class="form-control form-control-sm" autocomplete="off">
13
13
  </div>
14
14
  <ul component="category/list" class="dropdown-menu category-dropdown-menu" role="menu">
15
15
  <li role="presentation" class="category" data-all="all">
@@ -12,7 +12,7 @@
12
12
  </span>
13
13
  </button>
14
14
  <div component="category-selector-search" class="hidden position-absolute">
15
- <input type="text" class="form-control" autocomplete="off">
15
+ <input type="text" class="form-control form-control-sm" autocomplete="off">
16
16
  </div>
17
17
  <ul component="category/list" class="dropdown-menu category-dropdown-menu" role="menu">
18
18
  <li component="category/no-matches" role="presentation" class="category hidden">
@@ -1,7 +1,7 @@
1
1
  {{{ if children.length }}}
2
2
  <div class="subcategory">
3
3
  {{{ if hasMoreSubCategories }}}
4
- <div class="mb-2"><!-- IMPORT partials/category-selector.tpl --></div>
4
+ <div class="mb-2"><!-- IMPORT partials/category/selector-dropdown-left.tpl --></div>
5
5
  {{{ else }}}
6
6
  <h3 class="fs-6 fw-semibold">[[category:subcategories]]</h3>
7
7
  {{{ end }}}
@@ -1,5 +1,5 @@
1
1
  {{{ if config.loggedIn }}}
2
- <div class="btn-group topic-watch-dropdown bottom-sheet" component="topic/watch">
2
+ <div class="btn-group bottom-sheet" component="topic/watch">
3
3
  <button class="btn-ghost-sm d-flex gap-2 align-items-baseline dropdown-toggle" data-bs-toggle="dropdown" type="button">
4
4
  <span component="category/watching/menu" {{{ if !./isWatched }}}class="hidden"{{{ end }}}><i class="fa fa-fw fa-inbox text-primary"></i><span class="visible-md-inline visible-lg-inline fw-semibold"> [[category:watching]]</span></span>
5
5
 
@@ -9,11 +9,35 @@
9
9
  </button>
10
10
 
11
11
  <ul class="dropdown-menu">
12
- <li><a class="dropdown-item" href="#" component="category/watching" data-state="watching"><i component="category/watching/check" class="fa fa-fw {{{ if ./isWatched }}}fa-check{{{ end }}}"></i><i class="fa fa-fw fa-inbox"></i> [[category:watching]]<p class="help-text text-muted"><small>[[category:watching.description]]</small></p></a></li>
12
+ <li>
13
+ <a class="dropdown-item d-flex" href="#" component="category/watching" data-state="watching">
14
+ <span><i component="category/watching/check" class="fa fa-fw {{{ if ./isWatched }}}fa-check{{{ end }}}"></i></span>
15
+ <div class="d-flex flex-column">
16
+ <span><i class="fa fa-fw fa-inbox"></i> [[category:watching]]</span>
17
+ <p class="help-text text-muted"><small>[[category:watching.description]]</small></p>
18
+ </div>
19
+ </a>
20
+ </li>
13
21
 
14
- <li><a class="dropdown-item" href="#" component="category/notwatching" data-state="notwatching"><i component="category/notwatching/check" class="fa fa-fw {{{ if ./isNotWatched }}}fa-check{{{ end }}}"></i><i class="fa fa-fw fa-clock-o"></i> [[category:not-watching]]<p class="help-text text-muted"><small>[[category:not-watching.description]]</small></p></a></li>
22
+ <li>
23
+ <a class="dropdown-item d-flex" href="#" component="category/notwatching" data-state="notwatching">
24
+ <span><i component="category/notwatching/check" class="fa fa-fw {{{ if ./isNotWatched }}}fa-check{{{ end }}}"></i></span>
25
+ <div class="d-flex flex-column">
26
+ <span><i class="fa fa-fw fa-clock-o"></i> [[category:not-watching]]</span>
27
+ <p class="help-text text-muted"><small>[[category:not-watching.description]]</small></p>
28
+ </div>
29
+ </a>
30
+ </li>
15
31
 
16
- <li><a class="dropdown-item" href="#" component="category/ignoring" data-state="ignoring"><i component="category/ignoring/check" class="fa fa-fw {{{ if ./isIgnored }}}fa-check{{{ end }}}"></i><i class="fa fa-fw fa-eye-slash"></i> [[category:ignoring]]<p class="help-text text-muted"><small>[[category:ignoring.description]]</small></p></a></li>
32
+ <li>
33
+ <a class="dropdown-item d-flex" href="#" component="category/ignoring" data-state="ignoring">
34
+ <span><i component="category/ignoring/check" class="fa fa-fw {{{ if ./isIgnored }}}fa-check{{{ end }}}"></i></span>
35
+ <div class="d-flex flex-column">
36
+ <span><i class="fa fa-fw fa-eye-slash"></i> [[category:ignoring]]</span>
37
+ <p class="help-text text-muted"><small>[[category:ignoring.description]]</small></p>
38
+ </div>
39
+ </a>
40
+ </li>
17
41
  </ul>
18
42
  </div>
19
43
  {{{ end }}}