Fix lint, make design more consistent, add license texts,
All checks were successful
Queue Release Build / prepare (push) Successful in 11s
Deploy Web Apps / deploy (push) Successful in 14m0s
Queue Release Build / build-linux (push) Successful in 35m41s
Queue Release Build / build-windows (push) Successful in 28m53s
Queue Release Build / finalize (push) Successful in 2m6s

This commit is contained in:
2026-04-02 04:08:53 +02:00
parent 37cac95b38
commit ae0ee8fac7
45 changed files with 988 additions and 572 deletions

View File

@@ -17,6 +17,8 @@ import {
} from '@angular/router';
import { CommonModule } from '@angular/common';
import { Store } from '@ngrx/store';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucideX } from '@ng-icons/lucide';
import {
DatabaseService,
@@ -51,6 +53,7 @@ import {
selector: 'app-root',
imports: [
CommonModule,
NgIcon,
RouterOutlet,
ServersRailComponent,
TitleBarComponent,
@@ -61,6 +64,11 @@ import {
ThemeNodeDirective,
ThemePickerOverlayComponent
],
viewProviders: [
provideIcons({
lucideX
})
],
templateUrl: './app.html',
styleUrl: './app.scss'
})
@@ -72,20 +80,17 @@ export class App implements OnInit, OnDestroy {
currentRoom = this.store.selectSignal(selectCurrentRoom);
desktopUpdates = inject(DesktopAppUpdateService);
desktopUpdateState = this.desktopUpdates.state;
private databaseService = inject(DatabaseService);
private router = inject(Router);
private servers = inject(ServerDirectoryFacade);
private notifications = inject(NotificationsFacade);
private settingsModal = inject(SettingsModalService);
private timeSync = inject(TimeSyncService);
private theme = inject(ThemeService);
private voiceSession = inject(VoiceSessionFacade);
private externalLinks = inject(ExternalLinkService);
private electronBridge = inject(ElectronBridgeService);
private deepLinkCleanup: (() => void) | null = null;
private themeStudioControlsDragOffset: { x: number; y: number } | null = null;
private themeStudioControlsBounds: { width: number; height: number } | null = null;
readonly databaseService = inject(DatabaseService);
readonly router = inject(Router);
readonly servers = inject(ServerDirectoryFacade);
readonly notifications = inject(NotificationsFacade);
readonly settingsModal = inject(SettingsModalService);
readonly timeSync = inject(TimeSyncService);
readonly theme = inject(ThemeService);
readonly voiceSession = inject(VoiceSessionFacade);
readonly externalLinks = inject(ExternalLinkService);
readonly electronBridge = inject(ElectronBridgeService);
readonly dismissedDesktopUpdateNoticeKey = signal<string | null>(null);
readonly themeStudioFullscreenComponent = signal<Type<unknown> | null>(null);
readonly themeStudioControlsPosition = signal<{ x: number; y: number } | null>(null);
readonly isDraggingThemeStudioControls = signal(false);
@@ -102,6 +107,17 @@ export class App implements OnInit, OnDestroy {
return this.settingsModal.activePage() === 'theme'
&& this.settingsModal.themeStudioMinimized();
});
readonly desktopUpdateNoticeKey = computed(() => {
const updateState = this.desktopUpdateState();
return updateState.targetVersion?.trim()
|| updateState.latestVersion?.trim()
|| `restart:${updateState.currentVersion}`;
});
readonly showDesktopUpdateNotice = computed(() => {
return this.desktopUpdateState().restartRequired
&& this.dismissedDesktopUpdateNoticeKey() !== this.desktopUpdateNoticeKey();
});
readonly appWorkspaceShellStyles = computed(() => {
const workspaceStyles = this.appWorkspaceLayoutStyles();
@@ -131,6 +147,10 @@ export class App implements OnInit, OnDestroy {
};
});
private deepLinkCleanup: (() => void) | null = null;
private themeStudioControlsDragOffset: { x: number; y: number } | null = null;
private themeStudioControlsBounds: { width: number; height: number } | null = null;
constructor() {
effect(() => {
if (!this.isThemeStudioFullscreen() || this.themeStudioFullscreenComponent()) {
@@ -259,6 +279,14 @@ export class App implements OnInit, OnDestroy {
this.settingsModal.open('updates');
}
dismissDesktopUpdateNotice(): void {
if (!this.desktopUpdateState().restartRequired) {
return;
}
this.dismissedDesktopUpdateNoticeKey.set(this.desktopUpdateNoticeKey());
}
startThemeStudioControlsDrag(event: PointerEvent, controlsElement: HTMLElement): void {
if (event.button !== 0) {
return;
@@ -309,15 +337,15 @@ export class App implements OnInit, OnDestroy {
await this.desktopUpdates.restartToApplyUpdate();
}
private clampThemeStudioControlsPosition(x: number, y: number, width: number, height: number): { x: number; y: number } {
private clampThemeStudioControlsPosition(left: number, top: number, width: number, height: number): { x: number; y: number } {
const minX = App.THEME_STUDIO_CONTROLS_MARGIN;
const minY = App.TITLE_BAR_HEIGHT + App.THEME_STUDIO_CONTROLS_MARGIN;
const maxX = Math.max(minX, window.innerWidth - width - App.THEME_STUDIO_CONTROLS_MARGIN);
const maxY = Math.max(minY, window.innerHeight - height - App.THEME_STUDIO_CONTROLS_MARGIN);
return {
x: Math.min(Math.max(minX, x), maxX),
y: Math.min(Math.max(minY, y), maxY)
x: Math.min(Math.max(minX, left), maxX),
y: Math.min(Math.max(minY, top), maxY)
};
}