100 lines
3.5 KiB
HTML
100 lines
3.5 KiB
HTML
<section class="chat-layout relative h-full bg-background">
|
|
<header class="flex h-14 shrink-0 items-center gap-3 border-b border-border px-4">
|
|
<app-user-avatar
|
|
[name]="peerName()"
|
|
[avatarUrl]="peerUser()?.avatarUrl"
|
|
[status]="peerUser()?.status"
|
|
[showStatusBadge]="true"
|
|
size="md"
|
|
/>
|
|
<div class="min-w-0">
|
|
<h1 class="truncate text-base font-semibold text-foreground">{{ peerName() }}</h1>
|
|
<p class="text-xs text-muted-foreground">Direct Message</p>
|
|
</div>
|
|
</header>
|
|
|
|
@if (conversation()) {
|
|
<div class="absolute inset-x-0 bottom-0 top-14">
|
|
<app-chat-message-list
|
|
[allMessages]="chatMessages()"
|
|
[channelMessages]="chatMessages()"
|
|
[loading]="false"
|
|
[syncing]="false"
|
|
[currentUserId]="currentUserId()"
|
|
[isAdmin]="false"
|
|
[bottomPadding]="composerBottomPadding()"
|
|
[conversationKey]="conversationKey()"
|
|
[userLookupOverrides]="participantUsers()"
|
|
(replyRequested)="setReplyTo($event)"
|
|
(deleteRequested)="handleDeleteRequested($event)"
|
|
(editSaved)="handleEditSaved($event)"
|
|
(reactionAdded)="handleReactionAdded($event)"
|
|
(reactionToggled)="handleReactionToggled($event)"
|
|
(downloadRequested)="downloadAttachment($event)"
|
|
(imageOpened)="openLightbox($event)"
|
|
(imageContextMenuRequested)="openImageContextMenu($event)"
|
|
(embedRemoved)="handleEmbedRemoved($event)"
|
|
/>
|
|
|
|
@for (messageStatus of messageStatuses(); track messageStatus.id) {
|
|
<span
|
|
data-testid="message-status"
|
|
class="sr-only"
|
|
>{{ messageStatus.status }}</span
|
|
>
|
|
}
|
|
</div>
|
|
|
|
<div class="chat-bottom-bar absolute bottom-0 left-0 right-2 z-10 bg-background/85 backdrop-blur-md">
|
|
<app-chat-message-composer
|
|
[replyTo]="replyTo()"
|
|
[showKlipyGifPicker]="showGifPicker()"
|
|
[klipyEnabled]="klipyEnabled()"
|
|
[klipySignalSource]="null"
|
|
[textareaTestId]="'dm-input'"
|
|
(messageSubmitted)="handleMessageSubmitted($event)"
|
|
(replyCleared)="clearReply()"
|
|
(heightChanged)="composerBottomPadding.set($event + 20)"
|
|
(klipyGifPickerToggleRequested)="toggleGifPicker()"
|
|
/>
|
|
</div>
|
|
|
|
@if (showGifPicker()) {
|
|
<div
|
|
class="fixed inset-0 z-[89]"
|
|
tabindex="0"
|
|
role="button"
|
|
aria-label="Close GIF picker"
|
|
(click)="closeGifPicker()"
|
|
(keydown.enter)="closeGifPicker()"
|
|
(keydown.space)="closeGifPicker()"
|
|
></div>
|
|
|
|
<div class="pointer-events-none fixed inset-0 z-[90]">
|
|
<div
|
|
class="pointer-events-auto absolute w-[calc(100vw-2rem)] max-w-5xl sm:w-[34rem] md:w-[42rem] xl:w-[52rem]"
|
|
[style.bottom.px]="composerBottomPadding() + 8"
|
|
[style.right.px]="gifPickerAnchorRight()"
|
|
>
|
|
<app-klipy-gif-picker
|
|
(gifSelected)="handleGifSelected($event)"
|
|
(closed)="closeGifPicker()"
|
|
/>
|
|
</div>
|
|
</div>
|
|
}
|
|
|
|
<app-chat-message-overlays
|
|
[lightboxAttachment]="lightboxAttachment()"
|
|
[imageContextMenu]="imageContextMenu()"
|
|
(lightboxClosed)="closeLightbox()"
|
|
(contextMenuClosed)="closeImageContextMenu()"
|
|
(downloadRequested)="downloadAttachment($event)"
|
|
(copyRequested)="copyImageToClipboard($event)"
|
|
(imageContextMenuRequested)="openImageContextMenu($event)"
|
|
/>
|
|
} @else {
|
|
<div class="flex flex-1 items-center justify-center px-6 text-sm text-muted-foreground">Select a direct message from the rail.</div>
|
|
}
|
|
</section>
|