Files
Toju/toju-app/src/app/features/room/chat-room/chat-room.component.html

226 lines
8.5 KiB
HTML

<div class="flex h-full flex-col bg-background">
@if (currentRoom()) {
@if (isMobile()) {
<!-- Mobile: Swiper-driven page stack (channels -> main -> members) -->
<swiper-container
#swiperEl
class="block min-h-0 w-full flex-1"
slides-per-view="1"
space-between="0"
initial-slide="0"
threshold="10"
resistance-ratio="0"
>
<swiper-slide class="block h-full w-full">
<div class="flex h-full w-full min-h-0 overflow-hidden">
<app-servers-rail class="block h-full shrink-0" />
<div class="flex min-h-0 flex-1 overflow-hidden border-l border-border bg-card">
<app-rooms-side-panel
panelMode="channels"
(textChannelSelected)="setMobilePage('main')"
class="block h-full w-full"
/>
</div>
</div>
</swiper-slide>
<swiper-slide class="block h-full w-full">
<div class="flex h-full w-full min-h-0 flex-col overflow-hidden bg-background">
<div class="flex shrink-0 items-center gap-2 border-b border-border bg-card px-3 py-2">
<button
type="button"
(click)="setMobilePage('channels')"
class="grid h-11 w-11 place-items-center rounded-lg text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground"
aria-label="Back to channels"
>
<ng-icon
name="lucideChevronLeft"
class="h-5 w-5"
/>
</button>
<div class="min-w-0 flex-1">
@if (activeChannel(); as channel) {
<p class="flex min-w-0 items-center gap-1 truncate text-sm font-semibold text-foreground">
@if (channel.type === 'text') {
<ng-icon
name="lucideHash"
class="h-4 w-4 shrink-0 text-muted-foreground"
/>
}
<span class="truncate">{{ channel.name }}</span>
</p>
} @else {
<p class="truncate text-sm font-semibold text-foreground">{{ currentRoom()?.name }}</p>
}
</div>
@if (activeCall()) {
<button
type="button"
(click)="openActiveCall()"
class="grid h-11 w-11 place-items-center rounded-lg text-emerald-600 transition-colors hover:bg-emerald-500/10 hover:text-emerald-500"
aria-label="Return to call"
title="Return to call"
>
<ng-icon
name="lucidePhoneCall"
class="h-5 w-5"
/>
</button>
}
<button
type="button"
(click)="setMobilePage('members')"
class="grid h-11 w-11 place-items-center rounded-lg text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground"
aria-label="Show members"
>
<ng-icon
name="lucideUsers"
class="h-5 w-5"
/>
</button>
</div>
<main class="relative min-h-0 min-w-0 flex-1 overflow-hidden bg-background">
@if (!isVoiceWorkspaceExpanded()) {
@if (hasTextChannels()) {
<div class="h-full overflow-hidden">
<app-chat-messages />
</div>
} @else {
<div class="flex h-full items-center justify-center px-6">
<div class="max-w-md text-center text-muted-foreground">
<ng-icon
name="lucideHash"
class="mx-auto mb-4 h-16 w-16 opacity-30"
/>
<h2 class="mb-2 text-xl font-medium text-foreground">No text channels</h2>
<p class="text-sm">There are no existing text channels currently.</p>
</div>
</div>
}
}
<app-voice-workspace />
</main>
</div>
</swiper-slide>
<swiper-slide class="block h-full w-full">
<div class="flex h-full w-full min-h-0 flex-col overflow-hidden bg-card">
<div class="flex shrink-0 items-center gap-2 border-b border-border px-3 py-2">
<button
type="button"
(click)="setMobilePage('main')"
class="grid h-11 w-11 place-items-center rounded-lg text-muted-foreground transition-colors hover:bg-secondary hover:text-foreground"
aria-label="Back to chat"
>
<ng-icon
name="lucideChevronLeft"
class="h-5 w-5"
/>
</button>
<p class="truncate text-sm font-semibold text-foreground">Members</p>
</div>
<app-rooms-side-panel
panelMode="users"
[showVoiceControls]="false"
class="block h-full w-full"
/>
</div>
</swiper-slide>
</swiper-container>
} @else {
<!-- Desktop: theme-driven 3-pane grid layout -->
<div
class="grid min-h-0 flex-1 overflow-hidden"
[ngStyle]="roomLayoutStyles()"
>
<aside
appThemeNode="chatRoomChannelsPanel"
class="flex min-h-0 overflow-hidden border-r border-border bg-card"
[ngStyle]="channelsPanelLayoutStyles()"
>
<app-rooms-side-panel
panelMode="channels"
class="block h-full w-full"
/>
</aside>
<main
appThemeNode="chatRoomMainPanel"
class="relative min-h-0 min-w-0 overflow-hidden bg-background"
[ngStyle]="mainPanelLayoutStyles()"
>
@if (!isVoiceWorkspaceExpanded()) {
@if (hasTextChannels()) {
<div class="h-full overflow-hidden">
<app-chat-messages />
</div>
} @else {
<div
appThemeNode="chatRoomEmptyState"
class="flex h-full items-center justify-center px-6"
>
<div class="max-w-md text-center text-muted-foreground">
<div
data-theme-slot="icon"
class="theme-icon-slot mx-auto mb-4 h-14 w-14 items-center justify-center rounded-3xl border border-border/70 bg-secondary/70 bg-center bg-cover bg-no-repeat text-sm font-semibold uppercase tracking-[0.18em] text-foreground"
></div>
<ng-icon
name="lucideHash"
class="mx-auto mb-4 h-16 w-16 opacity-30"
/>
<h2
data-theme-slot="text"
class="mb-2 text-xl font-medium text-foreground"
>
No text channels
</h2>
<p class="text-sm">There are no existing text channels currently.</p>
</div>
</div>
}
}
<app-voice-workspace />
</main>
<aside
appThemeNode="chatRoomMembersPanel"
class="flex min-h-0 overflow-hidden border-l border-border bg-card"
[ngStyle]="membersPanelLayoutStyles()"
>
<app-rooms-side-panel
panelMode="users"
[showVoiceControls]="false"
class="block h-full w-full"
/>
</aside>
</div>
}
} @else {
<div
appThemeNode="chatRoomEmptyState"
class="flex flex-1 items-center justify-center bg-background px-6"
>
<div class="text-center text-muted-foreground">
<div
data-theme-slot="icon"
class="theme-icon-slot mx-auto mb-4 h-14 w-14 items-center justify-center rounded-3xl border border-border/70 bg-secondary/70 bg-center bg-cover bg-no-repeat text-sm font-semibold uppercase tracking-[0.18em] text-foreground"
></div>
<ng-icon
name="lucideHash"
class="mx-auto mb-4 h-16 w-16 opacity-30"
/>
<h2
data-theme-slot="text"
class="mb-2 text-xl font-medium"
>
No room selected
</h2>
<p class="text-sm">Select or create a room to start chatting</p>
</div>
</div>
}
</div>