diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-metadata.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-metadata.js new file mode 100644 index 00000000000..34796d5657c --- /dev/null +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-metadata.js @@ -0,0 +1,16 @@ +import Component from "@glimmer/component"; + +export default class ChatChannelMetadata extends Component { + unreadIndicator = false; + + get lastMessageFormatedDate() { + return moment(this.args.channel.last_message_sent_at).calendar(null, { + sameDay: "LT", + nextDay: "[Tomorrow]", + nextWeek: "dddd", + lastDay: "[Yesterday]", + lastWeek: "dddd", + sameElse: "l", + }); + } +} diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-row.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-row.js index ae3b281645c..a54012c85b3 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-row.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-row.js @@ -47,6 +47,7 @@ export default Component.extend({ @discourseComputed("active", "channel.{id,muted}", "channel.focused") rowClassNames(active, channel, focused) { const classes = ["chat-channel-row", `chat-channel-${channel.id}`]; + if (active) { classes.push("active"); } @@ -56,6 +57,16 @@ export default Component.extend({ if (channel.current_user_membership.muted) { classes.push("muted"); } + if (this.options?.leaveButton) { + classes.push("can-leave"); + } + + const channelUnreadCount = + this.currentUser.chat_channel_tracking_state?.[channel.id]?.unread_count; + if (channelUnreadCount > 0) { + classes.push("has-unread"); + } + return classes.join(" "); }, diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.js b/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.js index fc261ddcfac..6bb9dba438a 100644 --- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.js +++ b/plugins/chat/assets/javascripts/discourse/components/chat-channel-title.js @@ -6,7 +6,6 @@ import { gt, reads } from "@ember/object/computed"; export default class ChatChannelTitle extends Component { tagName = ""; channel = null; - unreadIndicator = false; @reads("channel.chatable.users.[]") users; @gt("users.length", 1) multiDm; @@ -20,4 +19,15 @@ export default class ChatChannelTitle extends Component { get channelColorStyle() { return htmlSafe(`color: #${this.channel.chatable.color}`); } + + @computed( + "channel.chatable.users.length", + "channel.chatable.users.@each.status" + ) + get showUserStatus() { + return !!( + this.channel.chatable.users.length === 1 && + this.channel.chatable.users[0].status + ); + } } diff --git a/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-metadata.hbs b/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-metadata.hbs new file mode 100644 index 00000000000..f15678cde7e --- /dev/null +++ b/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-metadata.hbs @@ -0,0 +1,9 @@ +
+
+ {{this.lastMessageFormatedDate}} +
+ + {{#if @unreadIndicator}} + + {{/if}} +
diff --git a/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-row.hbs b/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-row.hbs index a94cd95ada2..4c75b80da70 100644 --- a/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-row.hbs +++ b/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-row.hbs @@ -1,9 +1,6 @@ - - - {{#if this.showUserStatus}} - - {{/if}} + + {{#if (and this.options.leaveButton this.channel.isFollowing (not this.site.mobileView))}} {{else}} - + {{/if}} diff --git a/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-title.hbs b/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-title.hbs index 8dd95e60723..b9adac8d235 100644 --- a/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-title.hbs +++ b/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-title.hbs @@ -8,20 +8,32 @@ {{else}} {{#if this.channel.isDirectMessageChannel}}
- {{#if this.multiDm}} - - {{this.channel.chatable.users.length}} - - {{this.usernames}} - {{else}} - - - {{#let this.channel.chatable.users.firstObject as |user|}} - {{user.username}} - - {{/let}} - - {{/if}} + +
+ {{#if this.multiDm}} + + {{this.channel.chatable.users.length}} + + {{else}} + + {{/if}} +
+ + {{#if (has-block)}} {{yield}} @@ -47,8 +59,4 @@ {{/if}}
{{/if}} - - {{#if this.unreadIndicator}} - - {{/if}} {{/if}} diff --git a/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-unread-indicator.hbs b/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-unread-indicator.hbs index dc93697fff0..4a53e0296a9 100644 --- a/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-unread-indicator.hbs +++ b/plugins/chat/assets/javascripts/discourse/templates/components/chat-channel-unread-indicator.hbs @@ -1,3 +1,5 @@ {{#if this.hasUnread}} - +
+
{{this.unreadCount}}
+
{{/if}} diff --git a/plugins/chat/assets/stylesheets/common/chat-channel-title.scss b/plugins/chat/assets/stylesheets/common/chat-channel-title.scss index 4eac8df3c18..d5bbb14222e 100644 --- a/plugins/chat/assets/stylesheets/common/chat-channel-title.scss +++ b/plugins/chat/assets/stylesheets/common/chat-channel-title.scss @@ -6,6 +6,7 @@ .chat-channel-title { display: flex; align-items: center; + @include ellipsis; .category-chat-private .d-icon { background-color: var(--secondary); @@ -19,6 +20,10 @@ top: -4px; } + .user-status-message { + display: none; // we only show when in channels list + } + .chat-name, .category-chat-name, &__usernames, @@ -71,10 +76,6 @@ font-size: var(--font-down-1); align-items: center; padding: 0.25rem 0.5rem; - - & + .chat-channel-title__name { - margin-left: 0.5rem; - } } .chat-channel-title__category-badge { @@ -82,10 +83,6 @@ display: flex; font-size: var(--font-up-1); position: relative; - - + .chat-channel-title__name { - margin-left: 0.5rem; - } } .chat-channel-title .chat-user-avatar { @@ -120,6 +117,7 @@ @include ellipsis; font-size: var(--font-0); color: var(--primary); + margin-left: 0.5rem; } .channel-info { @@ -127,3 +125,7 @@ max-width: 100%; } } + +.has-unread .chat-channel-title__name { + font-weight: bold; +} diff --git a/plugins/chat/assets/stylesheets/common/chat-drawer.scss b/plugins/chat/assets/stylesheets/common/chat-drawer.scss index 5587c49955a..5e6dcf786f7 100644 --- a/plugins/chat/assets/stylesheets/common/chat-drawer.scss +++ b/plugins/chat/assets/stylesheets/common/chat-drawer.scss @@ -38,22 +38,13 @@ body.composer-open .chat-drawer-outlet-container { .channels-list { .chat-channel-row { - padding: 0 0 0 0.5rem; - margin: 0 0.5rem 0.125rem 0.5rem; - border-radius: 0.25em; - } + height: 3.6em; + padding: 0 0.5rem; + margin: 0 0 0 0.5rem; - .chat-channel-unread-indicator { - left: 3px; - min-width: 8px; - width: 8px; - height: 8px; - border-radius: 7px; - top: calc(50% - 5px); - } - - .chat-channel-title { - padding: 0.5rem; + &:not(:last-of-type) { + border-bottom: 1px solid var(--primary-low); + } } } } @@ -114,7 +105,7 @@ body.composer-open .chat-drawer-outlet-container { flex-direction: column; width: 100%; font-weight: 700; - padding: 0 0.5rem; + padding: 0 0.5rem 0 1rem; cursor: pointer; .chat-channel-title { @@ -222,6 +213,7 @@ body.composer-open .chat-drawer-outlet-container { padding-bottom: 0.25em; .channels-list .chat-channel-divider { - padding: 0.25rem 0.5rem 0.25rem 1rem; + padding: 1.5rem 0.5rem 1rem 1rem; + color: var(--quaternary); } } diff --git a/plugins/chat/assets/stylesheets/common/chat-index.scss b/plugins/chat/assets/stylesheets/common/chat-index.scss new file mode 100644 index 00000000000..f4a05ec290c --- /dev/null +++ b/plugins/chat/assets/stylesheets/common/chat-index.scss @@ -0,0 +1,13 @@ +.channels-list { + .chat-channel-divider { + padding: 2.5rem 1.5rem 0.5rem 1.5rem; + + &:first-of-type { + padding-top: 1rem; + } + } + + .chat-channel-title { + padding-right: 0.5em; + } +} diff --git a/plugins/chat/assets/stylesheets/common/common.scss b/plugins/chat/assets/stylesheets/common/common.scss index 1610f814474..8f266e29cc1 100644 --- a/plugins/chat/assets/stylesheets/common/common.scss +++ b/plugins/chat/assets/stylesheets/common/common.scss @@ -4,6 +4,7 @@ $float-height: 530px; --message-left-width: 42px; --full-page-border-radius: 12px; --full-page-sidebar-width: 275px; + --channel-list-avatar-size: 30px; --chat-header-offset: 65px; } @@ -77,10 +78,11 @@ $float-height: 530px; height: 14px; border-radius: 100%; box-sizing: content-box; - border: 2px solid var(--secondary); -webkit-touch-callout: none; background: var(--tertiary-med-or-tertiary); + color: var(--secondary); font-size: var(--font-down-2); + text-align: center; &.urgent { background: var(--success); @@ -137,26 +139,26 @@ $float-height: 530px; } .chat-channel-unread-indicator { - flex-shrink: 0; - width: 10px; - height: 10px; - border-radius: 10px; - border: 0; - right: 7px; - top: calc(50% - 5px); - - &.urgent .number-wrap { - display: none; - } + font-size: var(--font-down-1); } .open-browse-page-btn, .open-draft-channel-page-btn, .chat-channel-leave-btn { + position: relative; + padding: 0; background: transparent; color: var(--primary-medium); font-size: var(--font-0-rem); - padding: 0.5rem; + + &:after { + content: ""; + position: absolute; + top: -50%; + left: -50%; + width: 200%; + height: 200%; + } &:hover { background: transparent; @@ -209,10 +211,6 @@ $float-height: 530px; background: none; } } - - .chat-channel-title { - padding: 0.5rem; - } } .chat-messages-container { @@ -431,18 +429,61 @@ $float-height: 530px; align-items: center; box-sizing: border-box; display: flex; + justify-content: space-between; position: relative; cursor: pointer; color: var(--primary-high); transition: opacity 50ms ease-in; opacity: 1; - .chat-user-avatar { - pointer-events: none; + .chat-channel-title { + &__user-info { + @include ellipsis; + } + + &__usernames { + display: flex; + align-items: center; + justify-content: start; + } + + .user-status-message { + display: inline-block; + color: var(--primary-medium); + font-size: var(--font-down-2); + margin-right: 0.5rem; + } } - .chat-channel-unread-indicator { - margin-left: 0.5rem; + .chat-channel-metadata { + display: flex; + align-items: flex-end; + flex-direction: column; + + &__date { + color: var(--primary-high); + font-size: var(--font-down-2); + } + + .chat-channel-unread-indicator { + display: flex; + align-items: center; + justify-content: center; + margin-top: 0.25rem; + width: auto; + min-width: 14px; + padding: 2px; + font-size: var(--font-down-3); + border-radius: 1em; + + .number { + line-height: 1rem; + } + } + } + + .chat-user-avatar { + pointer-events: none; } &.unfollowing { @@ -450,18 +491,22 @@ $float-height: 530px; } .toggle-channel-membership-button.-leave { - visibility: hidden; + display: none; margin-left: auto; } - &:hover { + &.can-leave:hover { .toggle-channel-membership-button.-leave { - visibility: visible; + display: block; > * { pointer-events: auto; } } + + .chat-channel-metadata { + display: none; + } } .discourse-no-touch &:hover, @@ -492,6 +537,10 @@ $float-height: 530px; } } + &:visited { + color: var(--primary-high); + } + &.muted { opacity: 0.65; } @@ -508,13 +557,6 @@ $float-height: 530px; } } - .chat-channel-row-unread-count { - display: inline-block; - margin-left: 5px; - font-size: var(--font-down-1); - color: var(--primary-high); - } - .emoji { margin-left: 0.3em; } @@ -972,3 +1014,22 @@ html.has-full-page-chat { [data-popper-reference-hidden] { visibility: hidden; } + +.channels-list { + .chat-user-avatar { + img { + width: calc(var(--channel-list-avatar-size) - 2px); + height: calc(var(--channel-list-avatar-size) - 2px); + } + } + + .chat-channel-title { + &__users-count { + width: var(--channel-list-avatar-size); + height: var(--channel-list-avatar-size); + padding: 0; + font-size: var(--font-up-1); + justify-content: center; + } + } +} diff --git a/plugins/chat/assets/stylesheets/desktop/desktop.scss b/plugins/chat/assets/stylesheets/desktop/desktop.scss index 2be4ff3ee48..3b55a455020 100644 --- a/plugins/chat/assets/stylesheets/desktop/desktop.scss +++ b/plugins/chat/assets/stylesheets/desktop/desktop.scss @@ -77,7 +77,25 @@ background: var(--primary-very-low); .chat-channel-divider { - padding: 0.5rem 0.5rem 0 1rem; + padding: 2rem 0.5rem 0.5rem 1rem; + + &:first-of-type { + padding-top: 1.5rem; + } + } + + .chat-channel-row { + height: 2.5em; + padding-right: 0.5rem; + + .chat-channel-metadata { + &__date { + display: none; + } + .chat-channel-unread-indicator { + margin-top: 0; + } + } } .loading-container { diff --git a/plugins/chat/assets/stylesheets/mobile/chat-index.scss b/plugins/chat/assets/stylesheets/mobile/chat-index.scss index 2a037ac1715..68365943e03 100644 --- a/plugins/chat/assets/stylesheets/mobile/chat-index.scss +++ b/plugins/chat/assets/stylesheets/mobile/chat-index.scss @@ -6,12 +6,6 @@ padding-bottom: 6rem; box-sizing: border-box; - .direct-message-channels { - .chat-channel-title { - padding: 0.6rem 0; //minor adjustment for visual consistency with channels which dont have avatars - } - } - @media (hover: none) { .chat-channel-row:hover { background: transparent; @@ -23,20 +17,26 @@ } .chat-channel-row { + height: 4em; margin: 0 1.5rem; padding: 0; border-radius: 0; border-bottom: 1px solid var(--primary-low); + + .chat-channel-metadata { + &__date { + font-size: var(--font-down-2); + } + } } .chat-channel-divider { background-color: var(--secondary); - padding: 2.5rem 1.5rem 0.5rem 1.5rem; + padding: 2.5rem 1.5rem 0.75rem 1.5rem; font-size: var(--font-up-1); &:first-of-type { padding-top: 1rem; - padding-bottom: 0; //visual compensation } .channel-title { @@ -54,35 +54,24 @@ } .chat-user-avatar { - img { - width: calc(var(--chat-mobile-avatar-size) - 2px); - height: calc(var(--chat-mobile-avatar-size) - 2px); - } - + .chat-channel-title__usernames { margin-left: 1rem; } } .chat-channel-title { - padding: 1rem 0; width: 100%; overflow: hidden; &__users-count { - width: var(--chat-mobile-avatar-size); - height: var(--chat-mobile-avatar-size); - padding: 0; font-size: var(--font-up-2); - font-weight: normal; - justify-content: center; - & + .chat-channel-title__name { margin-left: 1rem; } } &__name { + margin-left: 0.75em; font-size: var(--font-up-1); } diff --git a/plugins/chat/assets/stylesheets/mobile/mobile.scss b/plugins/chat/assets/stylesheets/mobile/mobile.scss index a01476f5202..a54cdf5fcf0 100644 --- a/plugins/chat/assets/stylesheets/mobile/mobile.scss +++ b/plugins/chat/assets/stylesheets/mobile/mobile.scss @@ -1,5 +1,5 @@ :root { - --chat-mobile-avatar-size: 38px; + --channel-list-avatar-size: 38px; } .chat-message { @@ -73,16 +73,17 @@ body.has-full-page-chat { } } -.channels-list .chat-channel-row { - .category-chat-private .d-icon { - background-color: var(--secondary); - } +.channels-list { + .chat-channel-row { + .category-chat-private .d-icon { + background-color: var(--secondary); + } - .chat-channel-unread-indicator { - width: 6px; - height: 6px; - left: 5px; - top: calc(50% - 3px); + .chat-channel-metadata { + .chat-channel-unread-indicator { + font-size: var(--font-down-2); + } + } } } diff --git a/plugins/chat/config/locales/client.en.yml b/plugins/chat/config/locales/client.en.yml index 0bfd12f57c0..4a5f3b61d4a 100644 --- a/plugins/chat/config/locales/client.en.yml +++ b/plugins/chat/config/locales/client.en.yml @@ -49,7 +49,7 @@ en: leave_channel: "Leave channel" join: "Join" leave: "Leave" - save_label: + save_label: mute_channel: "Mute channel preference saved" desktop_notification: "Desktop notification preference saved" mobile_notification: "Mobile push notification preference saved" diff --git a/plugins/chat/plugin.rb b/plugins/chat/plugin.rb index 10416b4a3c1..7ae448ac5a3 100644 --- a/plugins/chat/plugin.rb +++ b/plugins/chat/plugin.rb @@ -17,6 +17,7 @@ register_asset "stylesheets/common/dc-filter-input.scss" register_asset "stylesheets/common/common.scss" register_asset "stylesheets/common/chat-browse.scss" register_asset "stylesheets/common/chat-drawer.scss" +register_asset "stylesheets/common/chat-index.scss" register_asset "stylesheets/mobile/chat-index.scss", :mobile register_asset "stylesheets/common/chat-channel-preview-card.scss" register_asset "stylesheets/common/chat-channel-info.scss" diff --git a/plugins/chat/test/javascripts/components/chat-channel-metadata-test.js b/plugins/chat/test/javascripts/components/chat-channel-metadata-test.js new file mode 100644 index 00000000000..8605b4fb534 --- /dev/null +++ b/plugins/chat/test/javascripts/components/chat-channel-metadata-test.js @@ -0,0 +1,42 @@ +import { setupRenderingTest } from "discourse/tests/helpers/component-test"; +import { exists } from "discourse/tests/helpers/qunit-helpers"; +import hbs from "htmlbars-inline-precompile"; +import fabricators from "../helpers/fabricators"; +import { module, test } from "qunit"; +import { render } from "@ember/test-helpers"; + +module("Discourse Chat | Component | chat-channel-metadata", function (hooks) { + setupRenderingTest(hooks); + + test("displays last message sent at", async function (assert) { + const lastMessageSentAt = moment(); + this.channel = fabricators.directMessageChatChannel({ + last_message_sent_at: lastMessageSentAt, + }); + await render(hbs``); + + assert + .dom(".chat-channel-metadata__date") + .hasText(lastMessageSentAt.format("LT")); + }); + + test("unreadIndicator", async function (assert) { + this.channel = fabricators.directMessageChatChannel(); + this.currentUser.set("chat_channel_tracking_state", { + [this.channel.id]: { unread_count: 1 }, + }); + this.unreadIndicator = true; + await render( + hbs`` + ); + + assert.ok(exists(".chat-channel-unread-indicator")); + + this.unreadIndicator = false; + await render( + hbs`` + ); + + assert.notOk(exists(".chat-channel-unread-indicator")); + }); +}); diff --git a/plugins/chat/test/javascripts/components/chat-channel-title-test.js b/plugins/chat/test/javascripts/components/chat-channel-title-test.js index 29f5526c769..35773810692 100644 --- a/plugins/chat/test/javascripts/components/chat-channel-title-test.js +++ b/plugins/chat/test/javascripts/components/chat-channel-title-test.js @@ -142,32 +142,4 @@ module("Discourse Chat | Component | chat-channel-title", function (hooks) { ); }, }); - - componentTest("unreadIndicator", { - template: hbs`{{chat-channel-title channel=channel unreadIndicator=unreadIndicator}}`, - - beforeEach() { - const channel = fabricators.chatChannel({ - chatable_type: CHATABLE_TYPES.directMessageChannel, - }); - - const state = {}; - state[channel.id] = { - unread_count: 1, - }; - this.currentUser.set("chat_channel_tracking_state", state); - - this.set("channel", channel); - }, - - async test(assert) { - this.set("unreadIndicator", true); - - assert.ok(exists(".chat-channel-unread-indicator")); - - this.set("unreadIndicator", false); - - assert.notOk(exists(".chat-channel-unread-indicator")); - }, - }); });