+
+
+
+
+
+
+
+
+
+ {{#if this.chatStateManager.isDrawerExpanded}}
+
+
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/drawer-routes/threads.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/drawer-routes/threads.gjs
new file mode 100644
index 00000000000..ef12da41282
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/drawer-routes/threads.gjs
@@ -0,0 +1,38 @@
+import Component from "@glimmer/component";
+import { inject as service } from "@ember/service";
+import i18n from "discourse-common/helpers/i18n";
+import I18n from "discourse-i18n";
+import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
+import UserThreads from "discourse/plugins/chat/discourse/components/user-threads";
+
+export default class ChatDrawerRoutesThreads extends Component {
+ @service chat;
+ @service chatStateManager;
+
+ backButtonTitle = I18n.t("chat.return_to_list");
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{#if this.chatStateManager.isDrawerExpanded}}
+
+
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/list/empty-state.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/list/empty-state.gjs
new file mode 100644
index 00000000000..a47a1037e05
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/list/empty-state.gjs
@@ -0,0 +1,9 @@
+import Component from "@glimmer/component";
+
+export default class EmptyState extends Component {
+
+
+ {{yield}}
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/list/index.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/list/index.gjs
new file mode 100644
index 00000000000..20b10d6b825
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/list/index.gjs
@@ -0,0 +1,72 @@
+import Component from "@glimmer/component";
+import { hash } from "@ember/helper";
+import { action } from "@ember/object";
+import { modifier } from "ember-modifier";
+import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
+import isElementInViewport from "discourse/lib/is-element-in-viewport";
+import { INPUT_DELAY } from "discourse-common/config/environment";
+import discourseDebounce from "discourse-common/lib/debounce";
+import EmptyState from "./empty-state";
+import Item from "./item";
+
+export default class List extends Component {
+ loadMore = modifier((element) => {
+ this.intersectionObserver = new IntersectionObserver(this.loadCollection);
+ this.intersectionObserver.observe(element);
+
+ return () => {
+ this.intersectionObserver.disconnect();
+ };
+ });
+
+ fill = modifier((element) => {
+ this.resizeObserver = new ResizeObserver(() => {
+ if (isElementInViewport(element)) {
+ this.loadCollection();
+ }
+ });
+
+ this.resizeObserver.observe(element);
+
+ return () => {
+ this.resizeObserver.disconnect();
+ };
+ });
+
+ get itemComponent() {
+ return this.args.itemComponent ?? Item;
+ }
+
+ get emptyStateComponent() {
+ return EmptyState;
+ }
+
+ @action
+ loadCollection() {
+ discourseDebounce(this, this.debouncedLoadCollection, INPUT_DELAY);
+ }
+
+ async debouncedLoadCollection() {
+ await this.args.collection.load({ limit: 10 });
+ }
+
+
+
+
+ {{#each @collection.items as |item|}}
+ {{yield (hash Item=(component this.itemComponent item=item))}}
+ {{else}}
+ {{#if @collection.fetchedOnce}}
+ {{yield (hash EmptyState=this.emptyStateComponent)}}
+ {{/if}}
+ {{/each}}
+
+
+
+
+
+
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/list/item.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/list/item.gjs
new file mode 100644
index 00000000000..5a7ccc6a8b0
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/list/item.gjs
@@ -0,0 +1,7 @@
+import Component from "@glimmer/component";
+
+export default class Item extends Component {
+
+ {{yield @item}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/actions.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/actions.gjs
new file mode 100644
index 00000000000..4ef52c78330
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/actions.gjs
@@ -0,0 +1,73 @@
+import Component from "@glimmer/component";
+import { hash } from "@ember/helper";
+import CloseDrawerButton from "./close-drawer-button";
+import CloseThreadButton from "./close-thread-button";
+import CloseThreadsButton from "./close-threads-button";
+import FullPageButton from "./full-page-button";
+import NewChannelButton from "./new-channel-button";
+import OpenDrawerButton from "./open-drawer-button";
+import ThreadSettingsButton from "./thread-settings-button";
+import ThreadTrackingDropdown from "./thread-tracking-dropdown";
+import ThreadsListButton from "./threads-list-button";
+import ToggleDrawerButton from "./toggle-drawer-button";
+
+export default class ChatNavbarActions extends Component {
+ get openDrawerButtonComponent() {
+ return OpenDrawerButton;
+ }
+
+ get newChannelButtonComponent() {
+ return NewChannelButton;
+ }
+
+ get threadTrackingDropdownComponent() {
+ return ThreadTrackingDropdown;
+ }
+
+ get closeThreadButtonComponent() {
+ return CloseThreadButton;
+ }
+
+ get closeThreadsButtonComponent() {
+ return CloseThreadsButton;
+ }
+
+ get threadSettingsButtonComponent() {
+ return ThreadSettingsButton;
+ }
+
+ get threadsListButtonComponent() {
+ return ThreadsListButton;
+ }
+
+ get closeDrawerButtonComponent() {
+ return CloseDrawerButton;
+ }
+
+ get toggleDrawerButtonComponent() {
+ return ToggleDrawerButton;
+ }
+
+ get chatNavbarFullPageButtonComponent() {
+ return FullPageButton;
+ }
+
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/back-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/back-button.gjs
new file mode 100644
index 00000000000..e2ca4ac70c2
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/back-button.gjs
@@ -0,0 +1,43 @@
+import Component from "@glimmer/component";
+import { LinkTo } from "@ember/routing";
+import icon from "discourse-common/helpers/d-icon";
+import I18n from "I18n";
+
+export default class ChatNavbarBackButton extends Component {
+ get icon() {
+ return this.args.icon ?? "chevron-left";
+ }
+
+ get title() {
+ return this.args.title ?? I18n.t("chat.browse.back");
+ }
+
+
+ {{#if @routeModels}}
+
+ {{#if (has-block)}}
+ {{yield}}
+ {{else}}
+ {{icon this.icon}}
+ {{/if}}
+
+ {{else}}
+
+ {{#if (has-block)}}
+ {{yield}}
+ {{else}}
+ {{icon this.icon}}
+ {{/if}}
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/channel-title.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/channel-title.gjs
new file mode 100644
index 00000000000..056e21743a1
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/channel-title.gjs
@@ -0,0 +1,17 @@
+import Component from "@glimmer/component";
+import { LinkTo } from "@ember/routing";
+import ChannelTitle from "discourse/plugins/chat/discourse/components/channel-title";
+
+export default class ChatNavbarChannelTitle extends Component {
+
+ {{#if @channel}}
+
+
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-drawer-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-drawer-button.gjs
new file mode 100644
index 00000000000..f8a53fbe1b4
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-drawer-button.gjs
@@ -0,0 +1,24 @@
+import Component from "@glimmer/component";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+import DButton from "discourse/components/d-button";
+
+export default class ChatNavbarCloseDrawerButton extends Component {
+ @service chat;
+ @service chatStateManager;
+
+ @action
+ closeDrawer() {
+ this.chatStateManager.didCloseDrawer();
+ this.chat.activeChannel = null;
+ }
+
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-thread-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-thread-button.gjs
new file mode 100644
index 00000000000..809ea1e78bf
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-thread-button.gjs
@@ -0,0 +1,22 @@
+import Component from "@glimmer/component";
+import { LinkTo } from "@ember/routing";
+import { inject as service } from "@ember/service";
+import icon from "discourse-common/helpers/d-icon";
+import i18n from "discourse-common/helpers/i18n";
+
+export default class ChatNavbarCloseThreadButton extends Component {
+ @service site;
+
+
+ {{#if this.site.desktopView}}
+
+ {{icon "times"}}
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-threads-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-threads-button.gjs
new file mode 100644
index 00000000000..24d2d5462bb
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/close-threads-button.gjs
@@ -0,0 +1,24 @@
+import Component from "@glimmer/component";
+import { LinkTo } from "@ember/routing";
+import { inject as service } from "@ember/service";
+import icon from "discourse-common/helpers/d-icon";
+import I18n from "I18n";
+
+export default class ChatNavbarCloseThreadsButton extends Component {
+ @service site;
+
+ closeButtonTitle = I18n.t("chat.thread.close");
+
+
+ {{#if this.site.desktopView}}
+
+ {{icon "times"}}
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/full-page-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/full-page-button.gjs
new file mode 100644
index 00000000000..c1f1becadb3
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/full-page-button.gjs
@@ -0,0 +1,33 @@
+import Component from "@glimmer/component";
+import { action } from "@ember/object";
+import { next } from "@ember/runloop";
+import { inject as service } from "@ember/service";
+import DButton from "discourse/components/d-button";
+import DiscourseURL from "discourse/lib/url";
+
+export default class ChatNavbarFullPageButton extends Component {
+ @service chat;
+ @service chatStateManager;
+
+ @action
+ async openInFullPage() {
+ this.chatStateManager.storeAppURL();
+ this.chatStateManager.prefersFullPage();
+ this.chat.activeChannel = null;
+
+ await new Promise((resolve) => next(resolve));
+
+ DiscourseURL.routeTo(this.chatStateManager.lastKnownChatURL);
+ }
+
+
+ {{#if this.chatStateManager.isDrawerExpanded}}
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/index.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/index.gjs
new file mode 100644
index 00000000000..bf4e50d59de
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/index.gjs
@@ -0,0 +1,46 @@
+import Component from "@glimmer/component";
+import { hash } from "@ember/helper";
+import { on } from "@ember/modifier";
+import concatClass from "discourse/helpers/concat-class";
+import noop from "discourse/helpers/noop";
+import Actions from "./actions";
+import BackButton from "./back-button";
+import ChannelTitle from "./channel-title";
+import Title from "./title";
+
+export default class ChatNavbar extends Component {
+ get buttonComponent() {
+ return BackButton;
+ }
+
+ get titleComponent() {
+ return Title;
+ }
+
+ get actionsComponent() {
+ return Actions;
+ }
+
+ get channelTitleComponent() {
+ return ChannelTitle;
+ }
+
+
+ {{! template-lint-disable no-invalid-interactive }}
+
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/new-channel-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/new-channel-button.gjs
new file mode 100644
index 00000000000..090cb8fd72f
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/new-channel-button.gjs
@@ -0,0 +1,32 @@
+import Component from "@glimmer/component";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+import DButton from "discourse/components/d-button";
+import concatClass from "discourse/helpers/concat-class";
+import CreateChannelModal from "discourse/plugins/chat/discourse/components/chat/modal/create-channel";
+
+export default class ChatNavbarNewChannelButton extends Component {
+ @service chatStateManager;
+ @service currentUser;
+ @service modal;
+ @service site;
+
+ @action
+ createChannel() {
+ this.modal.show(CreateChannelModal);
+ }
+
+
+ {{#if this.currentUser.staff}}
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/open-drawer-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/open-drawer-button.gjs
new file mode 100644
index 00000000000..442a14cc550
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/open-drawer-button.gjs
@@ -0,0 +1,30 @@
+import Component from "@glimmer/component";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+import DButton from "discourse/components/d-button";
+import DiscourseURL from "discourse/lib/url";
+
+export default class ChatNavbarOpenDrawerButton extends Component {
+ @service chatStateManager;
+ @service site;
+
+ @action
+ async openDrawer() {
+ this.chatStateManager.prefersDrawer();
+
+ DiscourseURL.routeTo(this.chatStateManager.lastKnownAppURL).then(() => {
+ DiscourseURL.routeTo(this.chatStateManager.lastKnownChatURL);
+ });
+ }
+
+
+ {{#if this.site.desktopView}}
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/sub-title.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/sub-title.gjs
new file mode 100644
index 00000000000..6c4020fef12
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/sub-title.gjs
@@ -0,0 +1,18 @@
+import Component from "@glimmer/component";
+import SubTitle from "./sub-title";
+
+export default class ChatNavbarSubTitle extends Component {
+ get subTitleComponent() {
+ return SubTitle;
+ }
+
+
+
+ {{#if (has-block)}}
+ {{yield}}
+ {{else}}
+ {{@title}}
+ {{/if}}
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/thread-settings-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/thread-settings-button.gjs
new file mode 100644
index 00000000000..fdd42f03841
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/thread-settings-button.gjs
@@ -0,0 +1,37 @@
+import Component from "@glimmer/component";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+import DButton from "discourse/components/d-button";
+import ThreadSettingsModal from "discourse/plugins/chat/discourse/components/chat/modal/thread-settings";
+
+export default class ChatNavbarThreadSettingsButton extends Component {
+ @service currentUser;
+ @service modal;
+
+ get canChangeThreadSettings() {
+ if (!this.args.thread) {
+ return false;
+ }
+
+ return (
+ this.currentUser.staff ||
+ this.currentUser.id === this.args.thread.originalMessage.user.id
+ );
+ }
+
+ @action
+ openThreadSettings() {
+ this.modal.show(ThreadSettingsModal, { model: this.args.thread });
+ }
+
+
+ {{#if this.canChangeThreadSettings}}
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/thread-tracking-dropdown.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/thread-tracking-dropdown.gjs
new file mode 100644
index 00000000000..2db8b47d4a9
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/thread-tracking-dropdown.gjs
@@ -0,0 +1,66 @@
+import Component from "@glimmer/component";
+import { tracked } from "@glimmer/tracking";
+import { action } from "@ember/object";
+import { inject as service } from "@ember/service";
+import concatClass from "discourse/helpers/concat-class";
+import { popupAjaxError } from "discourse/lib/ajax-error";
+import { NotificationLevels } from "discourse/lib/notification-levels";
+import ThreadTrackingDropdown from "discourse/plugins/chat/discourse/components/chat-thread-tracking-dropdown";
+import UserChatThreadMembership from "discourse/plugins/chat/discourse/models/user-chat-thread-membership";
+
+export default class ChatNavbarThreadTrackingDropdown extends Component {
+ @service chatApi;
+
+ @tracked persistedNotificationLevel = true;
+
+ get threadNotificationLevel() {
+ return this.membership?.notificationLevel || NotificationLevels.REGULAR;
+ }
+
+ get membership() {
+ return this.args.thread.currentUserMembership;
+ }
+
+ @action
+ async updateThreadNotificationLevel(newNotificationLevel) {
+ this.persistedNotificationLevel = false;
+
+ let currentNotificationLevel;
+
+ if (this.membership) {
+ currentNotificationLevel = this.membership.notificationLevel;
+ this.membership.notificationLevel = newNotificationLevel;
+ } else {
+ this.args.thread.currentUserMembership = UserChatThreadMembership.create({
+ notification_level: newNotificationLevel,
+ last_read_message_id: null,
+ });
+ }
+
+ try {
+ const response =
+ await this.chatApi.updateCurrentUserThreadNotificationsSettings(
+ this.args.thread.channel.id,
+ this.args.thread.id,
+ { notificationLevel: newNotificationLevel }
+ );
+ this.membership.last_read_message_id =
+ response.membership.last_read_message_id;
+ this.persistedNotificationLevel = true;
+ } catch (error) {
+ this.membership.notificationLevel = currentNotificationLevel;
+ popupAjaxError(error);
+ }
+ }
+
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/threads-list-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/threads-list-button.gjs
new file mode 100644
index 00000000000..26bab2c6cef
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/threads-list-button.gjs
@@ -0,0 +1,42 @@
+import Component from "@glimmer/component";
+import { LinkTo } from "@ember/routing";
+import { inject as service } from "@ember/service";
+import concatClass from "discourse/helpers/concat-class";
+import icon from "discourse-common/helpers/d-icon";
+import I18n from "I18n";
+import ThreadHeaderUnreadIndicator from "discourse/plugins/chat/discourse/components/chat/thread/header-unread-indicator";
+
+export default class ChatNavbarThreadsListButton extends Component {
+ @service router;
+
+ threadsListLabel = I18n.t("chat.threads.list");
+
+ get showThreadsListButton() {
+ return (
+ this.args.channel?.threadingEnabled &&
+ this.router.currentRoute.name !== "chat.channel.threads" &&
+ this.router.currentRoute.name !== "chat.channel.thread" &&
+ this.router.currentRoute.name !== "chat.channel.thread.index"
+ );
+ }
+
+
+ {{#if this.showThreadsListButton}}
+
+ {{icon "discourse-threads"}}
+
+
+ {{/if}}
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/navbar/title.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/title.gjs
new file mode 100644
index 00000000000..c28ae553344
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/title.gjs
@@ -0,0 +1,27 @@
+import Component from "@glimmer/component";
+import { hash } from "@ember/helper";
+import icon from "discourse-common/helpers/d-icon";
+import SubTitle from "./sub-title";
+
+export default class ChatNavbarTitle extends Component {
+ get subTitleComponent() {
+ return SubTitle;
+ }
+
+
+
+ {{#if (has-block)}}
+ {{#if @icon}}
+ {{icon @icon}}
+ {{/if}}
+ {{@title}}
+ {{yield (hash SubTitle=this.subTitleComponent)}}
+ {{else}}
+ {{#if @icon}}
+ {{icon @icon}}
+ {{/if}}
+ {{@title}}
+ {{/if}}
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-drawer/header/toggle-expand-button.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/toggle-drawer-button.gjs
similarity index 71%
rename from plugins/chat/assets/javascripts/discourse/components/chat-drawer/header/toggle-expand-button.gjs
rename to plugins/chat/assets/javascripts/discourse/components/chat/navbar/toggle-drawer-button.gjs
index 264a0a02a40..7f535981b8e 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-drawer/header/toggle-expand-button.gjs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/navbar/toggle-drawer-button.gjs
@@ -2,7 +2,8 @@ import Component from "@glimmer/component";
import { inject as service } from "@ember/service";
import DButton from "discourse/components/d-button";
-export default class ChatDrawerHeaderToggleExpandButton extends Component {
+export default class ChatNavbarToggleDrawerButton extends Component {
+ @service chat;
@service chatStateManager;
@@ -12,13 +13,13 @@ export default class ChatDrawerHeaderToggleExpandButton extends Component {
"angle-double-down"
"angle-double-up"
}}
- @action={{@toggleExpand}}
+ @action={{this.chat.toggleDrawer}}
@title={{if
this.chatStateManager.isDrawerExpanded
"chat.collapse"
"chat.expand"
}}
- class="btn-flat btn-link chat-drawer-header__expand-btn"
+ class="btn-flat no-text c-navbar__toggle-drawer-button"
/>
}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/routes/browse.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/routes/browse.gjs
new file mode 100644
index 00000000000..0f967422ad3
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/routes/browse.gjs
@@ -0,0 +1,131 @@
+import { cached, tracked } from "@glimmer/tracking";
+import Component from "@ember/component";
+import { concat, hash } from "@ember/helper";
+import { action, computed } from "@ember/object";
+import didInsert from "@ember/render-modifiers/modifiers/did-insert";
+import { LinkTo } from "@ember/routing";
+import { schedule } from "@ember/runloop";
+import { inject as service } from "@ember/service";
+import DButton from "discourse/components/d-button";
+import { INPUT_DELAY } from "discourse-common/config/environment";
+import i18n from "discourse-common/helpers/i18n";
+import discourseDebounce from "discourse-common/lib/debounce";
+import List from "discourse/plugins/chat/discourse/components/chat/list";
+import ChatModalNewMessage from "discourse/plugins/chat/discourse/components/chat/modal/new-message";
+import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
+import ChatChannelCard from "discourse/plugins/chat/discourse/components/chat-channel-card";
+import DcFilterInput from "discourse/plugins/chat/discourse/components/dc-filter-input";
+
+const TABS = ["all", "open", "closed", "archived"];
+
+export default class ChatRoutesBrowse extends Component {
+ @service chatApi;
+ @service modal;
+
+ @tracked filter = "";
+
+ @cached
+ get channelsCollection() {
+ return this.chatApi.channels({
+ filter: this.filter,
+ status: this.attrs.status,
+ });
+ }
+
+ @computed("siteSettings.chat_allow_archiving_channels")
+ get tabs() {
+ if (this.siteSettings.chat_allow_archiving_channels) {
+ return TABS;
+ } else {
+ return [...TABS].removeObject("archived");
+ }
+ }
+
+ @action
+ showChatNewMessageModal() {
+ this.modal.show(ChatModalNewMessage);
+ }
+
+ @action
+ setFilter(event) {
+ this.filter = event.target.value;
+ discourseDebounce(this.debouncedLoad, INPUT_DELAY);
+ }
+
+ @action
+ debouncedLoad() {
+ this.channelsCollection.load({ limit: 10 });
+ }
+
+ @action
+ focusFilterInput(input) {
+ schedule("afterRender", () => input?.focus());
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{i18n "chat.empty_state.title"}}
+
+
+
{{i18n "chat.empty_state.direct_message"}}
+
+
+
+
+
+
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-members.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info-members.gjs
similarity index 96%
rename from plugins/chat/assets/javascripts/discourse/components/chat-channel-members.gjs
rename to plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info-members.gjs
index 5360174b97e..7ac2da49c9f 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-members.gjs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info-members.gjs
@@ -13,11 +13,11 @@ import icon from "discourse-common/helpers/d-icon";
import discourseDebounce from "discourse-common/lib/debounce";
import I18n from "discourse-i18n";
import MessageCreator from "discourse/plugins/chat/discourse/components/chat/message-creator";
+import { MODES } from "discourse/plugins/chat/discourse/components/chat/message-creator/constants";
import ChatUserInfo from "discourse/plugins/chat/discourse/components/chat-user-info";
import DcFilterInput from "discourse/plugins/chat/discourse/components/dc-filter-input";
-import { MODES } from "./chat/message-creator/constants";
-export default class ChatChannelMembers extends Component {
+export default class ChatRouteChannelInfoMembers extends Component {
@service appEvents;
@service chatApi;
@service modal;
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info-settings.gjs
similarity index 99%
rename from plugins/chat/assets/javascripts/discourse/components/chat-channel-settings.gjs
rename to plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info-settings.gjs
index b571c317a9c..f89260ee34b 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat-channel-settings.gjs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info-settings.gjs
@@ -28,7 +28,7 @@ const NOTIFICATION_LEVELS = [
{ name: I18n.t("chat.notification_levels.always"), value: "always" },
];
-export default class ChatAboutScreen extends Component {
+export default class ChatRouteChannelInfoSettings extends Component {
@service chatApi;
@service chatGuardian;
@service chatChannelsManager;
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info.gjs
new file mode 100644
index 00000000000..d853ae66b50
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-info.gjs
@@ -0,0 +1,91 @@
+import Component from "@glimmer/component";
+import { action } from "@ember/object";
+import { LinkTo } from "@ember/routing";
+import { inject as service } from "@ember/service";
+import I18n from "discourse-i18n";
+import ChatModalEditChannelName from "discourse/plugins/chat/discourse/components/chat/modal/edit-channel-name";
+import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
+import ChatChannelStatus from "discourse/plugins/chat/discourse/components/chat-channel-status";
+
+export default class ChatRoutesChannelInfo extends Component {
+ @service chatChannelInfoRouteOriginManager;
+ @service site;
+ @service modal;
+ @service chatGuardian;
+
+ membersLabel = I18n.t("chat.channel_info.tabs.members");
+ settingsLabel = I18n.t("chat.channel_info.tabs.settings");
+ backToChannelLabel = I18n.t("chat.channel_info.back_to_all_channel");
+ backToAllChannelsLabel = I18n.t("chat.channel_info.back_to_channel");
+
+ get showTabs() {
+ return this.site.desktopView && this.args.channel.isOpen;
+ }
+
+ get canEditChannel() {
+ return (
+ this.chatGuardian.canEditChatChannel() &&
+ (this.args.channel.isCategoryChannel ||
+ (this.args.channel.isDirectMessageChannel &&
+ this.args.channel.chatable.group))
+ );
+ }
+
+ @action
+ editChannelTitle() {
+ return this.modal.show(ChatModalEditChannelName, {
+ model: this.args.channel,
+ });
+ }
+
+
+
+
+ {{#if this.chatChannelInfoRouteOriginManager.isBrowse}}
+
+ {{else}}
+
+ {{/if}}
+
+
+
+
+
+
+ {{#if this.showTabs}}
+
+ {{/if}}
+
+ {{outlet}}
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-thread.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-thread.gjs
new file mode 100644
index 00000000000..1a0c6524a08
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-thread.gjs
@@ -0,0 +1,20 @@
+import Component from "@glimmer/component";
+import { array } from "@ember/helper";
+import ThreadHeader from "discourse/plugins/chat/discourse/components/chat/thread/header";
+import Thread from "discourse/plugins/chat/discourse/components/chat-thread";
+
+export default class ChatRoutesChannelThread extends Component {
+
+
+ {{#each (array @thread) as |thread|}}
+
+
+
+ {{/each}}
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-threads.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-threads.gjs
new file mode 100644
index 00000000000..b4910ff7da7
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel-threads.gjs
@@ -0,0 +1,12 @@
+import Component from "@glimmer/component";
+import ChatThreadListHeader from "discourse/plugins/chat/discourse/components/chat/thread-list/header";
+import ChatThreadList from "discourse/plugins/chat/discourse/components/chat-thread-list";
+
+export default class ChatRoutesChannelThreads extends Component {
+
+
+
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel.gjs
new file mode 100644
index 00000000000..9608079d90a
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/routes/channel.gjs
@@ -0,0 +1,33 @@
+import Component from "@glimmer/component";
+import { inject as service } from "@ember/service";
+import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
+import SidePanel from "discourse/plugins/chat/discourse/components/chat-side-panel";
+import FullPageChat from "discourse/plugins/chat/discourse/components/full-page-chat";
+
+export default class ChatRoutesChannel extends Component {
+ @service site;
+
+
+
+
+ {{#if this.site.mobileView}}
+
+ {{/if}}
+
+
+
+
+
+
+
+
+
+
+
+ {{outlet}}
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/routes/threads.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/routes/threads.gjs
new file mode 100644
index 00000000000..1770de239fa
--- /dev/null
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/routes/threads.gjs
@@ -0,0 +1,24 @@
+import Component from "@glimmer/component";
+import i18n from "discourse-common/helpers/i18n";
+import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
+import UserThreads from "discourse/plugins/chat/discourse/components/user-threads";
+
+export default class ChatRoutesThreads extends Component {
+
+
+
+}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/thread-list/header.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/thread-list/header.gjs
index 424bd098fb1..24c65b4191d 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat/thread-list/header.gjs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/thread-list/header.gjs
@@ -1,70 +1,37 @@
import Component from "@glimmer/component";
-import { LinkTo } from "@ember/routing";
import { inject as service } from "@ember/service";
import replaceEmoji from "discourse/helpers/replace-emoji";
-import icon from "discourse-common/helpers/d-icon";
+import i18n from "discourse-common/helpers/i18n";
import I18n from "discourse-i18n";
+import Navbar from "discourse/plugins/chat/discourse/components/chat/navbar";
export default class ChatThreadListHeader extends Component {
@service router;
@service site;
threadListTitle = I18n.t("chat.threads.list");
- closeButtonTitle = I18n.t("chat.thread.close");
- showCloseButton = !this.site.mobileView;
-
- get showBackButton() {
- return this.args.channel && this.site.mobileView;
- }
-
- get backButton() {
- return {
- route: "chat.channel.index",
- models: this.args.channel.routeModels,
- title: I18n.t("chat.return_to_channel"),
- };
- }
-
+
+
+
+
}
diff --git a/plugins/chat/assets/javascripts/discourse/components/chat/thread-list/item.gjs b/plugins/chat/assets/javascripts/discourse/components/chat/thread-list/item.gjs
index 7229336772f..2a58c5c679a 100644
--- a/plugins/chat/assets/javascripts/discourse/components/chat/thread-list/item.gjs
+++ b/plugins/chat/assets/javascripts/discourse/components/chat/thread-list/item.gjs
@@ -50,7 +50,6 @@ export default class ChatThreadListItem extends Component {