feat: Response mobile layout support v1
All checks were successful
Queue Release Build / prepare (push) Successful in 1m6s
Deploy Web Apps / deploy (push) Successful in 7m35s
Queue Release Build / build-windows (push) Successful in 29m57s
Queue Release Build / build-linux (push) Successful in 46m28s
Queue Release Build / finalize (push) Successful in 49s

This commit is contained in:
2026-05-18 02:25:16 +02:00
parent ecb1a4b3a0
commit dea114aed0
45 changed files with 2369 additions and 377 deletions

View File

@@ -18,6 +18,7 @@ import {
} from 'rxjs';
import { NgIcon, provideIcons } from '@ng-icons/core';
import {
lucideArrowLeft,
lucideExternalLink,
lucideFileText,
lucideSearch,
@@ -34,14 +35,15 @@ import {
selectSearchResults,
selectIsSearching,
selectRoomsError,
selectSavedRooms
selectSavedRooms,
selectCurrentRoom
} from '../../../../store/rooms/rooms.selectors';
import {
Room,
User,
type PluginRequirementSummary
} from '../../../../shared-kernel';
import { ExternalLinkService } from '../../../../core/platform';
import { ExternalLinkService, ViewportService } from '../../../../core/platform';
import { SettingsModalService } from '../../../../core/services/settings-modal.service';
import { DatabaseService } from '../../../../infrastructure/persistence';
import { type ServerInfo } from '../../domain/models/server-directory.model';
@@ -83,6 +85,7 @@ interface JoinPluginConsentDialog {
],
viewProviders: [
provideIcons({
lucideArrowLeft,
lucideExternalLink,
lucideFileText,
lucideSearch,
@@ -110,14 +113,22 @@ export class ServerSearchComponent implements OnInit {
private webrtc = inject(RealtimeSessionFacade);
private pluginRequirements = inject(PluginRequirementService);
private pluginStore = inject(PluginStoreService);
private viewport = inject(ViewportService);
private searchSubject = new Subject<string>();
private banLookupRequestVersion = 0;
/** True on mobile breakpoints. Drives the tabbed mobile layout. */
readonly isMobile = this.viewport.isMobile;
/** Active mobile tab. Ignored on desktop where both panes are visible side-by-side. */
readonly mobileTab = signal<'people' | 'servers'>('servers');
searchQuery = '';
searchResults = this.store.selectSignal(selectSearchResults);
isSearching = this.store.selectSignal(selectIsSearching);
error = this.store.selectSignal(selectRoomsError);
savedRooms = this.store.selectSignal(selectSavedRooms);
currentRoom = this.store.selectSignal(selectCurrentRoom);
currentUser = this.store.selectSignal(selectCurrentUser);
activeEndpoints = this.serverDirectory.activeServers;
bannedServerLookup = signal<Record<string, boolean>>({});
@@ -235,6 +246,24 @@ export class ServerSearchComponent implements OnInit {
this.settingsModal.open('network');
}
/**
* Navigate back from the Search page to the chat-room view (server rail + current server).
* Prefers the current room; falls back to the first saved room. No-op when the user has not
* joined any servers.
*/
goBack(): void {
const target = this.currentRoom() ?? this.savedRooms()[0] ?? null;
if (target) {
this.store.dispatch(RoomsActions.viewServer({ room: target }));
}
}
/** True when the back button has a destination (user is in or has joined at least one server). */
canGoBack(): boolean {
return !!this.currentRoom() || this.savedRooms().length > 0;
}
/** Join a previously saved room by converting it to a ServerInfo payload. */
joinSavedRoom(room: Room): void {
this.openJoinedRoom(room);