diff --git a/frontend/src/app/pages/altitude/chat/chat.component.html b/frontend/src/app/pages/altitude/chat/chat.component.html index 8170bb8..0e9e0f1 100644 --- a/frontend/src/app/pages/altitude/chat/chat.component.html +++ b/frontend/src/app/pages/altitude/chat/chat.component.html @@ -6,6 +6,20 @@ + @if (showFullscreenPrompt()) { +
+
+

Enter fullscreen?

+

Would you like to view chat in fullscreen mode?

+ +
+ + +
+
+
+ } +
diff --git a/frontend/src/app/pages/altitude/chat/chat.component.scss b/frontend/src/app/pages/altitude/chat/chat.component.scss index 7f357e8..6d18af0 100644 --- a/frontend/src/app/pages/altitude/chat/chat.component.scss +++ b/frontend/src/app/pages/altitude/chat/chat.component.scss @@ -1,3 +1,53 @@ +.fullscreen-prompt-backdrop { + position: fixed; + inset: 0; + z-index: 10000; + display: flex; + align-items: center; + justify-content: center; + padding: 20px; + background: rgb(0 0 0 / 70%); +} + +.fullscreen-prompt { + width: min(420px, 100%); + padding: 24px; + border-radius: 14px; + background: #1f1f1f; + color: #ffffff; + box-shadow: 0 20px 60px rgb(0 0 0 / 45%); + text-align: center; + + h2 { + margin: 0 0 10px; + } + + p { + margin: 0 0 22px; + color: rgb(255 255 255 / 75%); + } +} + +.fullscreen-prompt-actions { + display: flex; + justify-content: center; + gap: 12px; + + button { + cursor: pointer; + border: 0; + border-radius: 8px; + padding: 10px 16px; + background: #4f8cff; + color: #ffffff; + font-weight: 700; + + &.secondary { + background: rgb(255 255 255 / 14%); + } + } +} + .page-layout { display: flex; flex-direction: row; diff --git a/frontend/src/app/pages/altitude/chat/chat.component.ts b/frontend/src/app/pages/altitude/chat/chat.component.ts index 15cf10b..e351228 100644 --- a/frontend/src/app/pages/altitude/chat/chat.component.ts +++ b/frontend/src/app/pages/altitude/chat/chat.component.ts @@ -1,4 +1,4 @@ -import {Component, inject, OnDestroy, OnInit} from '@angular/core'; +import {AfterViewInit, Component, inject, OnDestroy, OnInit, signal} from '@angular/core'; import {Subscription} from 'rxjs'; import {ChatService} from '@pages/altitude/chat/service/chat.service'; import {HeaderComponent} from '@header/header.component'; @@ -21,12 +21,13 @@ import {ChatInfoComponent} from '@pages/altitude/chat/components/chat-info/chat- styleUrl: './chat.component.scss', providers: [MiniMessageInteractionService] }) -export class ChatComponent implements OnInit, OnDestroy { +export class ChatComponent implements OnInit, AfterViewInit, OnDestroy { private sub?: Subscription; private readonly chatService: ChatService = inject(ChatService) protected readonly messages = this.chatService.messages; protected readonly servers = this.chatService.servers; protected readonly selectedServer = this.chatService.selectedServer; + protected readonly showFullscreenPrompt = signal(true); constructor(private interaction: MiniMessageInteractionService) { interaction.clicks$.subscribe(({action, value}) => { @@ -40,12 +41,39 @@ export class ChatComponent implements OnInit, OnDestroy { this.chatService.selectServer(server); } + protected enterFullscreen(): void { + this.showFullscreenPrompt.set(false); + + if (!document.fullscreenElement) { + document.documentElement.requestFullscreen().catch(() => { + // Ignore fullscreen request failures. + }); + } + } + + protected skipFullscreen(): void { + this.showFullscreenPrompt.set(false); + } + + ngOnInit(): void { this.chatService.connect(); } + ngAfterViewInit(): void { + document.documentElement.requestFullscreen().catch(() => { + console.error('Failed to enter fullscreen'); + }); + } + ngOnDestroy(): void { this.sub?.unsubscribe(); - this.chatService.disconnect(); // triggers onCompletion server-side, cleans up the emitter + this.chatService.disconnect(); + + if (document.fullscreenElement) { + document.exitFullscreen().catch(() => { + console.error('Failed to exit fullscreen'); + }); + } } }