mirror of
https://github.com/discourse/discourse.git
synced 2025-04-27 22:54:41 +08:00
UX: implements swipe on row channel
This commit is contained in:
parent
19567daeb9
commit
63bdd93622
@ -0,0 +1,204 @@
|
|||||||
|
import { inject as service } from "@ember/service";
|
||||||
|
import Component from "@glimmer/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { LinkTo } from "@ember/routing";
|
||||||
|
import concatClass from "discourse/helpers/concat-class";
|
||||||
|
import eq from "truth-helpers/helpers/eq";
|
||||||
|
import and from "truth-helpers/helpers/and";
|
||||||
|
import ChatChannelTitle from "discourse/plugins/chat/discourse/components/chat-channel-title";
|
||||||
|
import ChatChannelMetadata from "discourse/plugins/chat/discourse/components/chat-channel-metadata";
|
||||||
|
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||||
|
import ToggleChannelMembershipButton from "discourse/plugins/chat/discourse/components/toggle-channel-membership-button";
|
||||||
|
import willDestroy from "@ember/render-modifiers/modifiers/will-destroy";
|
||||||
|
import { hash } from "@ember/helper";
|
||||||
|
import I18n from "I18n";
|
||||||
|
import { modifier } from "ember-modifier";
|
||||||
|
import { bind } from "discourse-common/utils/decorators";
|
||||||
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import discourseLater from "discourse-common/lib/later";
|
||||||
|
import { cancel } from "@ember/runloop";
|
||||||
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
|
||||||
|
export default class ChatChannelRow extends Component {
|
||||||
|
<template>
|
||||||
|
<LinkTo
|
||||||
|
@route="chat.channel"
|
||||||
|
@models={{@channel.routeModels}}
|
||||||
|
class={{concatClass
|
||||||
|
"chat-channel-row"
|
||||||
|
(if @channel.focused "focused")
|
||||||
|
(if @channel.currentUserMembership.muted "muted")
|
||||||
|
(if @options.leaveButton "can-leave")
|
||||||
|
(if (eq this.chat.activeChannel.id @channel.id) "active")
|
||||||
|
(if this.channelHasUnread "has-unread")
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
data-chat-channel-id={{@channel.id}}
|
||||||
|
{{didInsert this.startTrackingStatus}}
|
||||||
|
{{willDestroy this.stopTrackingStatus}}
|
||||||
|
{{this.handleSwipe}}
|
||||||
|
{{(if this.scheduleRowRemoval (modifier this.rowRemoval))}}
|
||||||
|
>
|
||||||
|
<ChatChannelTitle @channel={{@channel}} />
|
||||||
|
<ChatChannelMetadata @channel={{@channel}} @unreadIndicator={{true}} />
|
||||||
|
|
||||||
|
{{#if
|
||||||
|
(and @options.leaveButton @channel.isFollowing this.site.desktopView)
|
||||||
|
}}
|
||||||
|
<ToggleChannelMembershipButton
|
||||||
|
@channel={{@channel}}
|
||||||
|
@options={{hash
|
||||||
|
leaveClass="btn-flat chat-channel-leave-btn"
|
||||||
|
labelType="none"
|
||||||
|
leaveIcon="times"
|
||||||
|
leaveTitle=(if
|
||||||
|
@channel.isDirectMessageChannel
|
||||||
|
this.leaveDirectMessageLabel
|
||||||
|
this.leaveChanelLabel
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div
|
||||||
|
class={{concatClass
|
||||||
|
"chat-channel-row__action-btn"
|
||||||
|
(if this.canCancelAction "-cancel" "-remove")
|
||||||
|
}}
|
||||||
|
{{this.removeButton}}
|
||||||
|
>
|
||||||
|
{{#if this.canCancelAction}}
|
||||||
|
{{this.cancelActionLabel}}
|
||||||
|
{{else}}
|
||||||
|
{{this.removeActionLabel}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
</LinkTo>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
@service router;
|
||||||
|
@service chat;
|
||||||
|
@service currentUser;
|
||||||
|
@service site;
|
||||||
|
@service api;
|
||||||
|
|
||||||
|
@tracked scheduleRowRemoval = false;
|
||||||
|
@tracked reachedThreshold = false;
|
||||||
|
@tracked canCancelAction = false;
|
||||||
|
|
||||||
|
removeButton = modifier((element) => {
|
||||||
|
this.removeButton = element;
|
||||||
|
this.removeButton.style.left = window.innerWidth + "px";
|
||||||
|
});
|
||||||
|
|
||||||
|
rowRemoval = modifier((element) => {
|
||||||
|
element.classList.add("-fade-out");
|
||||||
|
|
||||||
|
const handler = discourseLater(
|
||||||
|
() => this.chat.unfollowChannel(this.args.channel).catch(popupAjaxError),
|
||||||
|
250
|
||||||
|
);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancel(handler);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
handleSwipe = modifier((element) => {
|
||||||
|
this.element = element;
|
||||||
|
|
||||||
|
element.addEventListener("touchstart", this.onSwipeStart);
|
||||||
|
element.addEventListener("touchmove", this.onSwipeMove);
|
||||||
|
element.addEventListener("touchend", this.onSwipeEnd);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
element.removeEventListener("touchstart", this.onSwipeStart);
|
||||||
|
element.removeEventListener("touchmove", this.onSwipeMove);
|
||||||
|
element.removeEventListener("touchend", this.onSwipeEnd);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
@bind
|
||||||
|
onSwipeStart(event) {
|
||||||
|
if (!this.removeButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reachedThreshold = false;
|
||||||
|
this.canCancelAction = false;
|
||||||
|
this.initialX = event.changedTouches[0].screenX;
|
||||||
|
}
|
||||||
|
|
||||||
|
@bind
|
||||||
|
onSwipeMove(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const diff = this.initialX - event.changedTouches[0].screenX;
|
||||||
|
|
||||||
|
if (diff < 10) {
|
||||||
|
this.canCancelAction = false;
|
||||||
|
this.reachedThreshold = false;
|
||||||
|
this.element.style.left = "0px";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diff >= window.innerWidth / 3) {
|
||||||
|
this.canCancelAction = false;
|
||||||
|
this.reachedThreshold = true;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (this.reachedThreshold) {
|
||||||
|
this.canCancelAction = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.removeButton.style.width = diff + "px";
|
||||||
|
this.element.style.left =
|
||||||
|
-(this.initialX - event.changedTouches[0].screenX) + "px";
|
||||||
|
}
|
||||||
|
|
||||||
|
@bind
|
||||||
|
onSwipeEnd() {
|
||||||
|
const diff = this.initialX - event.changedTouches[0].screenX;
|
||||||
|
|
||||||
|
if (diff >= window.innerWidth / 3) {
|
||||||
|
this.scheduleRowRemoval = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.element.style.left = "0px";
|
||||||
|
}
|
||||||
|
|
||||||
|
get cancelActionLabel() {
|
||||||
|
return "Cancel";
|
||||||
|
}
|
||||||
|
|
||||||
|
get removeActionLabel() {
|
||||||
|
return "Remove";
|
||||||
|
}
|
||||||
|
|
||||||
|
get leaveDirectMessageLabel() {
|
||||||
|
return I18n.t("chat.direct_messages.leave");
|
||||||
|
}
|
||||||
|
|
||||||
|
get leaveChanelLabel() {
|
||||||
|
return I18n.t("chat.channel_settings.leave_channel");
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
startTrackingStatus() {
|
||||||
|
this.#firstDirectMessageUser?.trackStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
@action
|
||||||
|
stopTrackingStatus() {
|
||||||
|
this.#firstDirectMessageUser?.stopTrackingStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
get channelHasUnread() {
|
||||||
|
return this.args.channel.tracking.unreadCount > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get #firstDirectMessageUser() {
|
||||||
|
return this.args.channel?.chatable?.users?.firstObject;
|
||||||
|
}
|
||||||
|
}
|
@ -1,35 +0,0 @@
|
|||||||
<LinkTo
|
|
||||||
@route="chat.channel"
|
|
||||||
@models={{@channel.routeModels}}
|
|
||||||
class={{concat-class
|
|
||||||
"chat-channel-row"
|
|
||||||
(if @channel.focused "focused")
|
|
||||||
(if @channel.currentUserMembership.muted "muted")
|
|
||||||
(if @options.leaveButton "can-leave")
|
|
||||||
(if (eq this.chat.activeChannel.id @channel.id) "active")
|
|
||||||
(if this.channelHasUnread "has-unread")
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
data-chat-channel-id={{@channel.id}}
|
|
||||||
{{did-insert this.startTrackingStatus}}
|
|
||||||
{{will-destroy this.stopTrackingStatus}}
|
|
||||||
>
|
|
||||||
<ChatChannelTitle @channel={{@channel}} />
|
|
||||||
<ChatChannelMetadata @channel={{@channel}} @unreadIndicator={{true}} />
|
|
||||||
|
|
||||||
{{#if (and @options.leaveButton @channel.isFollowing this.site.desktopView)}}
|
|
||||||
<ToggleChannelMembershipButton
|
|
||||||
@channel={{@channel}}
|
|
||||||
@options={{hash
|
|
||||||
leaveClass="btn-flat chat-channel-leave-btn"
|
|
||||||
labelType="none"
|
|
||||||
leaveIcon="times"
|
|
||||||
leaveTitle=(if
|
|
||||||
@channel.isDirectMessageChannel
|
|
||||||
(i18n "chat.direct_messages.leave")
|
|
||||||
(i18n "chat.channel_settings.leave_channel")
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{{/if}}
|
|
||||||
</LinkTo>
|
|
@ -1,28 +0,0 @@
|
|||||||
import { inject as service } from "@ember/service";
|
|
||||||
import Component from "@glimmer/component";
|
|
||||||
import { action } from "@ember/object";
|
|
||||||
|
|
||||||
export default class ChatChannelRow extends Component {
|
|
||||||
@service router;
|
|
||||||
@service chat;
|
|
||||||
@service currentUser;
|
|
||||||
@service site;
|
|
||||||
|
|
||||||
@action
|
|
||||||
startTrackingStatus() {
|
|
||||||
this.#firstDirectMessageUser?.trackStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@action
|
|
||||||
stopTrackingStatus() {
|
|
||||||
this.#firstDirectMessageUser?.stopTrackingStatus();
|
|
||||||
}
|
|
||||||
|
|
||||||
get channelHasUnread() {
|
|
||||||
return this.args.channel.tracking.unreadCount > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
get #firstDirectMessageUser() {
|
|
||||||
return this.args.channel?.chatable?.users?.firstObject;
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,6 +12,26 @@ import discourseDebounce from "discourse-common/lib/debounce";
|
|||||||
import { bind } from "discourse-common/utils/decorators";
|
import { bind } from "discourse-common/utils/decorators";
|
||||||
import { updateUserStatusOnMention } from "discourse/lib/update-user-status-on-mention";
|
import { updateUserStatusOnMention } from "discourse/lib/update-user-status-on-mention";
|
||||||
import { tracked } from "@glimmer/tracking";
|
import { tracked } from "@glimmer/tracking";
|
||||||
|
import ChatMessageSeparatorDate from "discourse/plugins/chat/discourse/components/chat-message-separator-date";
|
||||||
|
import ChatMessageSeparatorNew from "discourse/plugins/chat/discourse/components/chat-message-separator-new";
|
||||||
|
import concatClass from "discourse/helpers/concat-class";
|
||||||
|
import DButton from "discourse/components/d-button";
|
||||||
|
import ChatMessageInReplyToIndicator from "discourse/plugins/chat/discourse/components/chat-message-in-reply-to-indicator";
|
||||||
|
import ChatMessageLeftGutter from "discourse/plugins/chat/discourse/components/chat/message/left-gutter";
|
||||||
|
import ChatMessageAvatar from "discourse/plugins/chat/discourse/components/chat/message/avatar";
|
||||||
|
import ChatMessageError from "discourse/plugins/chat/discourse/components/chat/message/error";
|
||||||
|
import ChatMessageInfo from "discourse/plugins/chat/discourse/components/chat/message/info";
|
||||||
|
import ChatMessageText from "discourse/plugins/chat/discourse/components/chat-message-text";
|
||||||
|
import ChatMessageReaction from "discourse/plugins/chat/discourse/components/chat-message-reaction";
|
||||||
|
import ChatMessageThreadIndicator from "discourse/plugins/chat/discourse/components/chat-message-thread-indicator";
|
||||||
|
import eq from "truth-helpers/helpers/eq";
|
||||||
|
import not from "truth-helpers/helpers/not";
|
||||||
|
import { on } from "@ember/modifier";
|
||||||
|
import { Input } from "@ember/component";
|
||||||
|
import didInsert from "@ember/render-modifiers/modifiers/did-insert";
|
||||||
|
import didUpdate from "@ember/render-modifiers/modifiers/did-update";
|
||||||
|
import willDestroy from "@ember/render-modifiers/modifiers/will-destroy";
|
||||||
|
import ChatOnLongPress from "discourse/plugins/chat/discourse/modifiers/chat/on-long-press";
|
||||||
|
|
||||||
let _chatMessageDecorators = [];
|
let _chatMessageDecorators = [];
|
||||||
let _tippyInstances = [];
|
let _tippyInstances = [];
|
||||||
@ -28,6 +48,139 @@ export const MENTION_KEYWORDS = ["here", "all"];
|
|||||||
export const MESSAGE_CONTEXT_THREAD = "thread";
|
export const MESSAGE_CONTEXT_THREAD = "thread";
|
||||||
|
|
||||||
export default class ChatMessage extends Component {
|
export default class ChatMessage extends Component {
|
||||||
|
<template>
|
||||||
|
{{! template-lint-disable no-invalid-interactive }}
|
||||||
|
|
||||||
|
{{#if this.shouldRender}}
|
||||||
|
{{#if (eq @context "channel")}}
|
||||||
|
<ChatMessageSeparatorDate
|
||||||
|
@fetchMessagesByDate={{@fetchMessagesByDate}}
|
||||||
|
@message={{@message}}
|
||||||
|
/>
|
||||||
|
<ChatMessageSeparatorNew @message={{@message}} />
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div
|
||||||
|
class={{concatClass
|
||||||
|
"chat-message-container"
|
||||||
|
(if this.pane.selectingMessages "-selectable")
|
||||||
|
(if @message.highlighted "-highlighted")
|
||||||
|
(if (eq @message.user.id this.currentUser.id) "is-by-current-user")
|
||||||
|
(if @message.staged "-staged" "-persisted")
|
||||||
|
(if this.hasActiveState "-active")
|
||||||
|
(if @message.bookmark "-bookmarked")
|
||||||
|
(if @message.deletedAt "-deleted")
|
||||||
|
(if @message.selected "-selected")
|
||||||
|
(if @message.error "-errored")
|
||||||
|
(if this.showThreadIndicator "has-thread-indicator")
|
||||||
|
(if this.hideUserInfo "-user-info-hidden")
|
||||||
|
(if this.hasReply "has-reply")
|
||||||
|
}}
|
||||||
|
data-id={{@message.id}}
|
||||||
|
data-thread-id={{@message.thread.id}}
|
||||||
|
{{didInsert this.didInsertMessage}}
|
||||||
|
{{didUpdate this.didUpdateMessageId @message.id}}
|
||||||
|
{{didUpdate this.didUpdateMessageVersion @message.version}}
|
||||||
|
{{willDestroy this.willDestroyMessage}}
|
||||||
|
{{on "mouseenter" this.onMouseEnter passive=true}}
|
||||||
|
{{on "mouseleave" this.onMouseLeave passive=true}}
|
||||||
|
{{on "mousemove" this.onMouseMove passive=true}}
|
||||||
|
{{ChatOnLongPress
|
||||||
|
this.onLongPressStart
|
||||||
|
this.onLongPressEnd
|
||||||
|
this.onLongPressCancel
|
||||||
|
}}
|
||||||
|
...attributes
|
||||||
|
>
|
||||||
|
{{#if this.show}}
|
||||||
|
{{#if this.pane.selectingMessages}}
|
||||||
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
class="chat-message-selector"
|
||||||
|
@checked={{@message.selected}}
|
||||||
|
{{on "click" this.toggleChecked}}
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if this.deletedAndCollapsed}}
|
||||||
|
<div class="chat-message-text -deleted">
|
||||||
|
<DButton
|
||||||
|
@action={{this.expand}}
|
||||||
|
@translatedLabel={{this.deletedMessageLabel}}
|
||||||
|
class="btn-flat chat-message-expand"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{else if this.hiddenAndCollapsed}}
|
||||||
|
<div class="chat-message-text -hidden">
|
||||||
|
<DButton
|
||||||
|
@action={{this.expand}}
|
||||||
|
@label="chat.hidden"
|
||||||
|
class="btn-flat chat-message-expand"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="chat-message">
|
||||||
|
{{#unless this.hideReplyToInfo}}
|
||||||
|
<ChatMessageInReplyToIndicator @message={{@message}} />
|
||||||
|
{{/unless}}
|
||||||
|
|
||||||
|
{{#if this.hideUserInfo}}
|
||||||
|
<ChatMessageLeftGutter @message={{@message}} />
|
||||||
|
{{else}}
|
||||||
|
<ChatMessageAvatar @message={{@message}} />
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
<div class="chat-message-content">
|
||||||
|
<ChatMessageInfo
|
||||||
|
@message={{@message}}
|
||||||
|
@show={{not this.hideUserInfo}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ChatMessageText
|
||||||
|
@cooked={{@message.cooked}}
|
||||||
|
@uploads={{@message.uploads}}
|
||||||
|
@edited={{@message.edited}}
|
||||||
|
>
|
||||||
|
{{#if @message.reactions.length}}
|
||||||
|
<div class="chat-message-reaction-list">
|
||||||
|
{{#each @message.reactions as |reaction|}}
|
||||||
|
<ChatMessageReaction
|
||||||
|
@reaction={{reaction}}
|
||||||
|
@onReaction={{this.messageInteractor.react}}
|
||||||
|
@message={{@message}}
|
||||||
|
@showTooltip={{true}}
|
||||||
|
/>
|
||||||
|
{{/each}}
|
||||||
|
|
||||||
|
{{#if this.shouldRenderOpenEmojiPickerButton}}
|
||||||
|
<DButton
|
||||||
|
@action={{this.messageInteractor.openEmojiPicker}}
|
||||||
|
@icon="discourse-emojis"
|
||||||
|
@title="chat.react"
|
||||||
|
@forwardEvent={{true}}
|
||||||
|
class="chat-message-react-btn"
|
||||||
|
/>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</ChatMessageText>
|
||||||
|
|
||||||
|
<ChatMessageError
|
||||||
|
@message={{@message}}
|
||||||
|
@onRetry={{@resendStagedMessage}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{#if this.showThreadIndicator}}
|
||||||
|
<ChatMessageThreadIndicator @message={{@message}} />
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
</template>
|
||||||
|
|
||||||
@service site;
|
@service site;
|
||||||
@service dialog;
|
@service dialog;
|
||||||
@service currentUser;
|
@service currentUser;
|
@ -1,130 +0,0 @@
|
|||||||
{{! template-lint-disable no-invalid-interactive }}
|
|
||||||
|
|
||||||
{{#if this.shouldRender}}
|
|
||||||
{{#if (eq @context "channel")}}
|
|
||||||
<ChatMessageSeparatorDate
|
|
||||||
@fetchMessagesByDate={{@fetchMessagesByDate}}
|
|
||||||
@message={{@message}}
|
|
||||||
/>
|
|
||||||
<ChatMessageSeparatorNew @message={{@message}} />
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div
|
|
||||||
class={{concat-class
|
|
||||||
"chat-message-container"
|
|
||||||
(if this.pane.selectingMessages "-selectable")
|
|
||||||
(if @message.highlighted "-highlighted")
|
|
||||||
(if (eq @message.user.id this.currentUser.id) "is-by-current-user")
|
|
||||||
(if @message.staged "-staged" "-persisted")
|
|
||||||
(if this.hasActiveState "-active")
|
|
||||||
(if @message.bookmark "-bookmarked")
|
|
||||||
(if @message.deletedAt "-deleted")
|
|
||||||
(if @message.selected "-selected")
|
|
||||||
(if @message.error "-errored")
|
|
||||||
(if this.showThreadIndicator "has-thread-indicator")
|
|
||||||
(if this.hideUserInfo "-user-info-hidden")
|
|
||||||
(if this.hasReply "has-reply")
|
|
||||||
}}
|
|
||||||
data-id={{@message.id}}
|
|
||||||
data-thread-id={{@message.thread.id}}
|
|
||||||
{{did-insert this.didInsertMessage}}
|
|
||||||
{{did-update this.didUpdateMessageId @message.id}}
|
|
||||||
{{did-update this.didUpdateMessageVersion @message.version}}
|
|
||||||
{{will-destroy this.willDestroyMessage}}
|
|
||||||
{{on "mouseenter" this.onMouseEnter passive=true}}
|
|
||||||
{{on "mouseleave" this.onMouseLeave passive=true}}
|
|
||||||
{{on "mousemove" this.onMouseMove passive=true}}
|
|
||||||
{{chat/on-long-press
|
|
||||||
this.onLongPressStart
|
|
||||||
this.onLongPressEnd
|
|
||||||
this.onLongPressCancel
|
|
||||||
}}
|
|
||||||
...attributes
|
|
||||||
>
|
|
||||||
{{#if this.show}}
|
|
||||||
{{#if this.pane.selectingMessages}}
|
|
||||||
<Input
|
|
||||||
@type="checkbox"
|
|
||||||
class="chat-message-selector"
|
|
||||||
@checked={{@message.selected}}
|
|
||||||
{{on "click" this.toggleChecked}}
|
|
||||||
/>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if this.deletedAndCollapsed}}
|
|
||||||
<div class="chat-message-text -deleted">
|
|
||||||
<DButton
|
|
||||||
@action={{this.expand}}
|
|
||||||
@translatedLabel={{this.deletedMessageLabel}}
|
|
||||||
class="btn-flat chat-message-expand"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{{else if this.hiddenAndCollapsed}}
|
|
||||||
<div class="chat-message-text -hidden">
|
|
||||||
<DButton
|
|
||||||
@action={{this.expand}}
|
|
||||||
@label="chat.hidden"
|
|
||||||
class="btn-flat chat-message-expand"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{{else}}
|
|
||||||
<div class="chat-message">
|
|
||||||
{{#unless this.hideReplyToInfo}}
|
|
||||||
<ChatMessageInReplyToIndicator @message={{@message}} />
|
|
||||||
{{/unless}}
|
|
||||||
|
|
||||||
{{#if this.hideUserInfo}}
|
|
||||||
<Chat::Message::LeftGutter @message={{@message}} />
|
|
||||||
{{else}}
|
|
||||||
<Chat::Message::Avatar @message={{@message}} />
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div class="chat-message-content">
|
|
||||||
<Chat::Message::Info
|
|
||||||
@message={{@message}}
|
|
||||||
@show={{not this.hideUserInfo}}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<ChatMessageText
|
|
||||||
@cooked={{@message.cooked}}
|
|
||||||
@uploads={{@message.uploads}}
|
|
||||||
@edited={{@message.edited}}
|
|
||||||
>
|
|
||||||
{{#if @message.reactions.length}}
|
|
||||||
<div class="chat-message-reaction-list">
|
|
||||||
{{#each @message.reactions as |reaction|}}
|
|
||||||
<ChatMessageReaction
|
|
||||||
@reaction={{reaction}}
|
|
||||||
@onReaction={{this.messageInteractor.react}}
|
|
||||||
@message={{@message}}
|
|
||||||
@showTooltip={{true}}
|
|
||||||
/>
|
|
||||||
{{/each}}
|
|
||||||
|
|
||||||
{{#if this.shouldRenderOpenEmojiPickerButton}}
|
|
||||||
<DButton
|
|
||||||
@action={{this.messageInteractor.openEmojiPicker}}
|
|
||||||
@icon="discourse-emojis"
|
|
||||||
@title="chat.react"
|
|
||||||
@forwardEvent={{true}}
|
|
||||||
class="chat-message-react-btn"
|
|
||||||
/>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</ChatMessageText>
|
|
||||||
|
|
||||||
<Chat::Message::Error
|
|
||||||
@message={{@message}}
|
|
||||||
@onRetry={{@resendStagedMessage}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#if this.showThreadIndicator}}
|
|
||||||
<ChatMessageThreadIndicator @message={{@message}} />
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
@ -97,6 +97,34 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: var(--primary-high);
|
color: var(--primary-high);
|
||||||
|
transition: height 0.25s ease-out, opacity 0.25s ease-out;
|
||||||
|
transform-origin: top center;
|
||||||
|
opacity: 1;
|
||||||
|
will-change: height, opacity, left;
|
||||||
|
|
||||||
|
&__action-btn {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
position: absolute;
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
padding-inline: 0.5rem;
|
||||||
|
color: var(--primary);
|
||||||
|
|
||||||
|
&.-cancel {
|
||||||
|
background: var(--tertiary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-remove {
|
||||||
|
background: var(--danger);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.-fade-out {
|
||||||
|
opacity: 0;
|
||||||
|
height: 0 !important;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
@media (hover: none) {
|
@media (hover: none) {
|
||||||
&:hover,
|
&:hover,
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
.channels-list-container {
|
.channels-list-container {
|
||||||
background: var(--secondary);
|
background: var(--secondary);
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-channel-row {
|
.chat-channel-row {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user