nodebb-theme-harmony 1.0.65 → 1.1.0

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.
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "nodebb-theme-harmony",
3
- "version": "1.0.65",
3
+ "version": "1.1.0",
4
4
  "nbbpm": {
5
- "compatibility": "^3.0.0"
5
+ "compatibility": "^3.3.0"
6
6
  },
7
7
  "description": "Harmony theme for NodeBB",
8
8
  "main": "library.js",
package/public/harmony.js CHANGED
@@ -116,13 +116,9 @@ $(document).ready(function () {
116
116
  });
117
117
  hooks.on('action:ajaxify.end', function () {
118
118
  $window.off('scroll', delayedScroll);
119
- $body.removeClass('chat-loaded');
120
119
  bottomBar.css({ bottom: 0 });
121
120
  setTimeout(enableAutohide, 250);
122
121
  });
123
- hooks.on('action:chat.loaded', function () {
124
- $body.toggleClass('chat-loaded', !!(ajaxify.data.template.chats && ajaxify.data.roomId));
125
- });
126
122
  });
127
123
  }
128
124
 
package/scss/chats.scss CHANGED
@@ -42,14 +42,12 @@ body.page-user-chats {
42
42
 
43
43
  [component="chat/nav-wrapper"] {
44
44
  width: 300px;
45
+ [component="chat/public/room"].unread {
46
+ font-weight: $font-weight-bold;
47
+ }
45
48
  }
46
49
 
47
50
  .expanded-chat {
48
- // no taskbar so hide minimize button
49
- [data-action="minimize"] {
50
- display: none!important;
51
- }
52
-
53
51
  .chat-content {
54
52
  @include fix-lists;
55
53
 
@@ -114,4 +112,7 @@ body.page-user-chats {
114
112
  right: 2rem;
115
113
  width: auto!important;
116
114
  height: auto!important;
115
+ [component="chat/user/list/btn"] {
116
+ display: none!important;
117
+ }
117
118
  }
@@ -2,7 +2,7 @@
2
2
  <div class="modal-dialog">
3
3
  <div class="modal-content">
4
4
  <div class="modal-header d-flex gap-4 justify-content-between">
5
- <div class="fs-6 flex-grow-1" component="chat/room/name">{./chatWithMessage}</div>
5
+ <div class="fs-6 flex-grow-1" component="chat/room/name">{{{ if ./roomName }}}# {roomName}{{{ else }}}{./chatWithMessage}{{{ end}}}</div>
6
6
  <div class="d-flex gap-1 align-items-center">
7
7
  <button type="button" class="btn-ghost-sm d-none d-md-flex" data-action="maximize">
8
8
  <i class="fa fa-fw fa-expand text-muted"></i>
@@ -1,28 +1,52 @@
1
1
  <div class="chats-full d-flex gap-1 h-100 mt-3 mt-md-0 py-md-3">
2
- <div class="flex-shrink-0 d-flex flex-column h-100" component="chat/nav-wrapper" data-loaded="{{{ if roomId }}}1{{{ else }}}0{{{ end }}}">
3
- <div class="chat-search dropdown mb-2">
4
- <div class="input-group">
5
- <input class="form-control form-control-sm" type="text" component="chat/search" data-bs-toggle="dropdown" placeholder="[[users:search-user-for-chat]]"/>
6
- <ul component="chat/search/list" class="dropdown-menu p-1">
7
- <li component="chat/search/start-typing"><a href="#" class="dropdown-item rounded-1">[[admin/menu:search.start-typing]]</a></li>
8
- <li component="chat/search/no-users" class="hidden"><a href="#" class="dropdown-item rounded-1">[[users:no-users-found]]</a></li>
9
- {{{ each searchUsers }}}
10
- <li component="chat/search/user" data-uid="{./uid}"><a href="#" class="dropdown-item rounded-1">{buildAvatar(@value, "24px", true)} {./username}<a></a></li>
11
- {{{ end }}}
12
- </ul>
13
- <button class="btn btn-primary btn-sm" type="button">
14
- <i class="fa fa-search"></i>
15
- </button>
2
+ <div component="chat/nav-wrapper" class="flex-shrink-0 d-flex flex-column h-100 gap-1" data-loaded="{{{ if roomId }}}1{{{ else }}}0{{{ end }}}">
3
+
4
+ <div>
5
+ <button component="chat/create" class="btn btn-primary btn-sm w-100">[[modules:chat.create-room]]</button>
6
+ </div>
7
+
8
+ {{{ if publicRooms.length }}}
9
+ <hr class="my-1">
10
+
11
+ <div class="d-flex flex-column gap-1">
12
+ <div class="d-flex gap-1 align-items-center justify-content-between justify-content-lg-start">
13
+ <button class="btn-ghost-sm p-1 order-1 order-lg-0" data-bs-toggle="collapse" data-bs-target="#public-rooms"
14
+ onclick="$(this).find('i').toggleClass('fa-rotate-180');"><i class="fa fa-fw fa-chevron-up" style="transition: 0.25s ease;"></i></button>
15
+ <label class="text-sm text-muted lh-1">[[modules:chat.public-rooms, {publicRooms.length}]]</label>
16
+ </div>
17
+ <div id="public-rooms" component="chat/public" class="collapse show">
18
+ {{{ each publicRooms }}}
19
+ <div component="chat/public/room" class="btn-ghost-sm ff-sans justify-content-between hover-parent {{{ if ./unread}}}unread{{{ end }}}" data-roomid="{./roomId}">
20
+ <div># {./roomName}</div>
21
+ <div class="d-flex gap-1">
22
+ <div component="chat/public/room/unread/count" data-count="{./unreadCount}" class="badge border text-primary {{{ if !./unreadCount }}}hidden{{{ end }}}">{./unreadCountText}</div>
23
+ <div component="chat/public/room/sort/handle" class="text-muted {{{ if isAdmin }}}hover-d-block{{{ else }}}d-none{{{ end }}}" style="cursor:grab;"><i class="fa fa-bars"></i></div>
24
+ </div>
25
+ </div>
26
+ {{{ end }}}
16
27
  </div>
17
28
  </div>
29
+ {{{ end }}}
30
+
18
31
  <hr class="my-1">
19
- <div component="chat/recent" class="chats-list overflow-auto mb-0 pe-1" data-nextstart="{nextStart}">
20
- {{{each rooms}}}
21
- <!-- IMPORT partials/chats/recent_room.tpl -->
22
- {{{end}}}
32
+
33
+ <div class="d-flex flex-column gap-1 overflow-auto">
34
+ {{{ if publicRooms.length }}}
35
+ <div class="d-flex gap-1 align-items-center justify-content-between justify-content-lg-start">
36
+ <button class="btn-ghost-sm p-1 order-1 order-lg-0" data-bs-toggle="collapse" data-bs-target="#private-rooms"
37
+ onclick="$(this).find('i').toggleClass('fa-rotate-180')"><i class="fa fa-fw fa-chevron-up" style="transition: 0.25s ease;"></i></button>
38
+ <label class="text-sm text-muted lh-1">[[modules:chat.private-rooms, {privateRoomCount}]]</label>
39
+ </div>
40
+ {{{ end }}}
41
+
42
+ <div id="private-rooms" component="chat/recent" class="chats-list overflow-auto mb-0 pe-1 collapse show" data-nextstart="{nextStart}">
43
+ {{{each rooms}}}
44
+ <!-- IMPORT partials/chats/recent_room.tpl -->
45
+ {{{end}}}
46
+ </div>
23
47
  </div>
24
48
  </div>
25
- <div class="flex-grow-1 ms-md-2 ps-md-2 border-1 border-start-md h-100" component="chat/main-wrapper" style="min-width: 0;">
49
+ <div component="chat/main-wrapper" class="flex-grow-1 ms-md-2 ps-md-2 border-1 border-start-md h-100" style="min-width: 0;">
26
50
  <!-- IMPORT partials/chats/message-window.tpl -->
27
51
  </div>
28
52
  <div class="imagedrop"><div>[[topic:composer.drag_and_drop_images]]</div></div>
@@ -1,26 +1,29 @@
1
- {{{ if !roomId }}}
2
- <div class="text-center p-2">
3
- [[modules:chat.no_active]]
4
- </div>
5
- {{{ end }}}
6
-
7
- {{{ if roomId }}}
8
- <div component="chat/messages" class="expanded-chat d-flex flex-column h-100" data-roomid="{roomId}">
1
+ <div class="d-flex flex-column h-100">
2
+ {{{ if !roomId }}}
3
+ <div class="d-flex flex-column align-items-center gap-3 p-5">
4
+ <i class="fa-solid fa-wind fs-2 text-muted"></i>
5
+ <span class="text-muted text-sm">[[modules:chat.no_active]]</span>
6
+ </div>
7
+ {{{ else }}}
9
8
  <div component="chat/header" class="d-flex align-items-center px-md-3 gap-3">
10
9
  <a href="#" data-action="close" role="button" class="flex-shrink-0 d-flex d-md-none btn btn-outline align-text-top"><i class="fa fa-chevron-left"></i></a>
11
10
  <h5 class="members flex-grow-1 fw-semibold tracking-tight mb-0">
12
- {./chatWithMessage}
11
+ {{{ if ./roomName }}}# {roomName}{{{ else }}}{./chatWithMessage}{{{ end}}}
13
12
  </h5>
14
13
 
15
14
  <!-- IMPORT partials/chats/options.tpl -->
16
15
  </div>
17
16
  <hr class="my-1"/>
18
- <div class="position-relative">
19
- <div component="chat/messages/scroll-up-alert" class="py-1 position-absolute start-50 translate-middle text-sm scroll-up-alert alert alert-info d-none d-md-block text-nowrap" role="button" style="z-index: 500;"><i class="fa fa-fw fa-arrow-down"></i> [[modules:chat.scroll-up-alert]]</div>
17
+ <div class="d-flex flex-grow-1 gap-1 overflow-auto" style="min-width: 0px;">
18
+ <div component="chat/messages" class="expanded-chat d-flex flex-column flex-grow-1" data-roomid="{roomId}" style="min-width: 0px;">
19
+ <!-- IMPORT partials/chats/scroll-up-alert.tpl -->
20
+ <ul class="chat-content p-0 m-0 list-unstyled overflow-auto flex-grow-1">
21
+ <!-- IMPORT partials/chats/messages.tpl -->
22
+ </ul>
23
+ <!-- IMPORT partials/chats/composer.tpl -->
24
+ </div>
25
+
26
+ <!-- IMPORT partials/chats/user-list.tpl -->
20
27
  </div>
21
- <ul class="chat-content p-0 m-0 list-unstyled overflow-auto flex-grow-1">
22
- <!-- IMPORT partials/chats/messages.tpl -->
23
- </ul>
24
- <!-- IMPORT partials/chats/composer.tpl -->
25
- </div>
26
- {{{ end }}}
28
+ {{{ end }}}
29
+ </div>
@@ -1,4 +1,4 @@
1
- <li component="chat/message" class="chat-message mx-2 pe-2 clear{{{ if messages.deleted }}} deleted{{{ end }}} {{{ if messages.newSet }}}border-top pt-3{{{ end }}}" data-index="{messages.index}" data-mid="{messages.messageId}" data-uid="{messages.fromuid}" data-self="{messages.self}" data-break="{messages.newSet}" data-timestamp="{messages.timestamp}">
1
+ <li component="chat/message" class="chat-message mx-2 pe-2 {{{ if messages.deleted }}} deleted{{{ end }}} {{{ if messages.newSet }}}border-top pt-3{{{ end }}}" data-mid="{messages.messageId}" data-uid="{messages.fromuid}" data-self="{messages.self}" data-break="{messages.newSet}" data-timestamp="{messages.timestamp}">
2
2
  <div class="message-header lh-1 d-flex align-items-center gap-2 text-sm {{{ if !messages.newSet }}}hidden{{{ end }}} pb-2">
3
3
  <a href="{config.relative_path}/user/{messages.fromUser.userslug}" class="text-decoration-none">{buildAvatar(messages.fromUser, "18px", true, "not-responsive")}</a>
4
4
  <span class="chat-user fw-semibold"><a href="{config.relative_path}/user/{messages.fromUser.userslug}">{messages.fromUser.displayname}</a></span>
@@ -1,32 +1,51 @@
1
- <div class="dropdown">
2
- <button class="btn-ghost-sm" data-bs-toggle="dropdown" component="chat/controlsToggle">
3
- <i class="fa fa-gear text-muted"></i>
4
- </button>
5
- <ul class="dropdown-menu dropdown-menu-end p-1 text-sm" component="chat/controls">
6
- <li class="dropdown-header">[[modules:chat.options]]</li>
7
- <li>
8
- <a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="members">
9
- <i class="fa fa-fw text-muted fa-cog"></i> [[modules:chat.manage-room]]
10
- </a>
11
- </li>
12
- <li>
13
- <a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="rename">
14
- <i class="fa fa-fw text-muted fa-edit"></i> [[modules:chat.rename-room]]
15
- </a>
16
- </li>
17
- <li>
18
- <a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="leave">
19
- <i class="fa fa-fw text-muted fa-sign-out"></i> [[modules:chat.leave]]
20
- </a>
21
- </li>
22
- {{{ if users.length }}}
23
- <li role="separator" class="dropdown-divider"></li>
24
- <li class="dropdown-header">[[modules:chat.in-room]]</li>
25
- {{{ each users }}}
26
- <li>
27
- <a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="{config.relative_path}/uid/{../uid}">{buildAvatar(users, "24px", true)} {../username}</a>
28
- </li>
29
- {{{ end }}}
30
- {{{ end }}}
31
- </ul>
1
+ <div class="d-flex gap-1 align-items-stretch">
2
+ <div class="dropdown d-flex">
3
+ <button class="btn-ghost-sm" data-bs-toggle="dropdown" component="chat/controlsToggle">
4
+ <i class="fa fa-gear text-muted"></i>
5
+ </button>
6
+ <ul class="dropdown-menu dropdown-menu-end p-1 text-sm" component="chat/controls">
7
+ <li class="dropdown-header">[[modules:chat.options]]</li>
8
+ <li>
9
+ <a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="members">
10
+ <i class="fa fa-fw text-muted fa-cog"></i> [[modules:chat.manage-room]]
11
+ </a>
12
+ </li>
13
+ {{{ if isOwner }}}
14
+ <li>
15
+ <a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="rename">
16
+ <i class="fa fa-fw text-muted fa-edit"></i> [[modules:chat.rename-room]]
17
+ </a>
18
+ </li>
19
+ {{{ end }}}
20
+ <li>
21
+ <a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="leave">
22
+ <i class="fa fa-fw text-muted fa-sign-out"></i> [[modules:chat.leave-room]]
23
+ </a>
24
+ </li>
25
+ {{{ if (public && isAdmin) }}}
26
+ <li>
27
+ <a class="dropdown-item rounded-1 d-flex align-items-center gap-2" href="#" data-action="delete">
28
+ <i class="fa fa-fw text-danger fa-trash"></i> [[modules:chat.delete-room]]
29
+ </a>
30
+ </li>
31
+ {{{ end }}}
32
+ </ul>
33
+ </div>
34
+
35
+ {{{ if users.length }}}
36
+ <div component="chat/user/list/btn" class="btn-ghost-sm d-none d-lg-flex flex-nowrap gap-3" title="[[modules:chat.view-users-list]]" data-bs-toggle="tooltip" data-bs-placement="bottom">
37
+ <div class="d-flex text-nowrap">
38
+ {{{ if ./users.0 }}}
39
+ <span style="width: 18px; z-index: 3;" class="text-decoration-none" href="{config.relative_path}/user/{./users.0.userslug}">{buildAvatar(./users.0, "24px", true)}</span>
40
+ {{{ end }}}
41
+ {{{ if ./users.1 }}}
42
+ <span style="width: 18px; z-index: 2;" class="text-decoration-none" href="{config.relative_path}/user/{./users.1.userslug}">{buildAvatar(./users.1, "24px", true)}</span>
43
+ {{{ end }}}
44
+ {{{ if ./users.2 }}}
45
+ <span style="width: 18px; z-index: 1;" class="text-decoration-none" href="{config.relative_path}/user/{./users.2.userslug}">{buildAvatar(./users.2, "24px", true)}</span>
46
+ {{{ end }}}
47
+ </div>
48
+ {./userCount}
49
+ </div>
50
+ {{{ end }}}
32
51
  </div>
@@ -20,13 +20,18 @@
20
20
  </div>
21
21
 
22
22
  <div class="d-flex flex-grow-1 flex-column w-100">
23
- <div class="room-name fw-semibold text-xs">
23
+ <div component="chat/room/title" class="room-name fw-semibold text-xs">
24
+ {{{ if ./roomName}}}
25
+ {./roomName}
26
+ {{{ else }}}
24
27
  {{{ if !./lastUser.uid }}}
25
- <span>[[modules:chat.no-users-in-room]]</span>
28
+ [[modules:chat.no-users-in-room]]
26
29
  {{{ else }}}
27
- {{{ if ./roomName }}}{./roomName}{{{ else }}}{./usernames}{{{ end }}}
28
- {{{ end }}}
30
+ {./usernames}
31
+ {{{ end }}}
32
+ {{{ end }}}
29
33
  </div>
34
+
30
35
  {{{ if ./teaser }}}
31
36
  <div class="teaser-content text-sm line-clamp-3 text-break">
32
37
  <span href="#" class="text-decoration-none">{buildAvatar(./teaser.user, "14px", true)}</span>
@@ -0,0 +1,3 @@
1
+ <div class="position-relative">
2
+ <div component="chat/messages/scroll-up-alert" class="py-1 position-absolute start-50 translate-middle-x text-sm scroll-up-alert alert alert-info d-none d-md-block text-nowrap" role="button" style="z-index: 500;"><i class="fa fa-fw fa-arrow-down"></i> [[modules:chat.scroll-up-alert]]</div>
3
+ </div>
@@ -1,4 +1,4 @@
1
- <li component="chat/system-message" class="system-message text-muted small py-2 gap-3 d-flex align-items-center justify-content-center" data-index="{messages.index}" data-mid="{messages.messageId}" data-uid="{messages.fromuid}" data-self="{messages.self}" data-break="0" data-timestamp="{messages.timestamp}">
1
+ <li component="chat/system-message" class="system-message text-muted small py-2 gap-3 d-flex align-items-center justify-content-center" data-mid="{messages.messageId}" data-uid="{messages.fromuid}" data-self="{messages.self}" data-break="0" data-timestamp="{messages.timestamp}">
2
2
  <hr class="d-inline-block my-1" style="width: 10%;"/>
3
3
  [[modules:chat.system.{messages.content}, {messages.fromUser.username}]]
4
4
  <hr class="d-inline-block my-1" style="width: 10%;"/>
@@ -0,0 +1,11 @@
1
+ <div component="chat/user/list" class="border-start hidden d-flex flex-column gap-1 p-1 overflow-auto" style="min-width:240px; width: 240px;">
2
+ {{{ each users }}}
3
+ <a data-index="{./index}" class="btn-ghost-sm d-flex justify-content-start align-items-center gap-2" href="{config.relative_path}/uid/{./uid}">
4
+ <div>{buildAvatar(users, "24px", true)}</div>
5
+ <div class="d-flex gap-1 flex-grow-1 text-nowrap text-truncate">
6
+ <span class="text-truncate">{./username}</span>
7
+ {{{ if ./isOwner }}}<span><i class="fa fa-star text-warning" data-bs-toggle="tooltip" title="[[modules:chat.owner]]"></i></span>{{{ end }}}
8
+ </div>
9
+ </a>
10
+ {{{ end }}}
11
+ </div>
@@ -14,8 +14,8 @@
14
14
  </div>
15
15
  </div>
16
16
 
17
- <div style="max-height: 500px; overflow: auto;">
18
- <table component="groups/members" class="table table-hover" data-nextstart="{group.membersNextStart}">
17
+ <div component="groups/members" data-nextstart="{group.membersNextStart}" class="mb-5" style="max-height: 500px; overflow: auto;">
18
+ <table class="table table-hover">
19
19
  <tbody>
20
20
  {{{each group.members}}}
21
21
  <tr class="w-100" data-uid="{group.members.uid}" data-isowner="{{{ if group.members.isOwner }}}1{{{ else }}}0{{{ end }}}">