Auto start with system
Some checks failed
Queue Release Build / prepare (push) Has been cancelled
Queue Release Build / build-linux (push) Has been cancelled
Queue Release Build / build-windows (push) Has been cancelled
Queue Release Build / finalize (push) Has been cancelled
Deploy Web Apps / deploy (push) Successful in 6m2s

This commit is contained in:
2026-03-18 23:46:16 +01:00
parent 4faa62864d
commit c862c2fe03
12 changed files with 274 additions and 7 deletions

View File

@@ -1,13 +1,13 @@
import { Injectable, signal } from '@angular/core';
export type SettingsPage = 'network' | 'voice' | 'updates' | 'debugging' | 'server' | 'members' | 'bans' | 'permissions';
export type SettingsPage = 'general' | 'network' | 'voice' | 'updates' | 'debugging' | 'server' | 'members' | 'bans' | 'permissions';
@Injectable({ providedIn: 'root' })
export class SettingsModalService {
readonly isOpen = signal(false);
readonly activePage = signal<SettingsPage>('network');
readonly activePage = signal<SettingsPage>('general');
readonly targetServerId = signal<string | null>(null);
open(page: SettingsPage = 'network', serverId?: string): void {
open(page: SettingsPage = 'general', serverId?: string): void {
this.activePage.set(page);
this.targetServerId.set(serverId ?? null);
this.isOpen.set(true);

View File

@@ -0,0 +1,47 @@
<div class="space-y-6 max-w-xl">
<section>
<div class="flex items-center gap-2 mb-3">
<ng-icon
name="lucidePower"
class="w-5 h-5 text-muted-foreground"
/>
<h4 class="text-sm font-semibold text-foreground">Application</h4>
</div>
<div
class="rounded-lg border border-border bg-secondary/20 p-4 transition-opacity"
[class.opacity-60]="!isElectron"
>
<div class="flex items-center justify-between gap-4">
<div>
<p class="text-sm font-medium text-foreground">Launch on system startup</p>
@if (isElectron) {
<p class="text-xs text-muted-foreground">Automatically start MetoYou when you sign in</p>
} @else {
<p class="text-xs text-muted-foreground">This setting is only available in the desktop app.</p>
}
</div>
<label
class="relative inline-flex items-center"
[class.cursor-pointer]="isElectron && !savingAutoStart()"
[class.cursor-not-allowed]="!isElectron || savingAutoStart()"
>
<input
type="checkbox"
[checked]="autoStart()"
[disabled]="!isElectron || savingAutoStart()"
(change)="onAutoStartChange($event)"
id="general-auto-start-toggle"
aria-label="Toggle launch on startup"
class="sr-only peer"
/>
<div
class="w-10 h-5 bg-secondary rounded-full peer peer-checked:bg-primary peer-disabled:bg-muted/80 peer-disabled:after:bg-muted-foreground/40 peer-checked:after:translate-x-full after:content-[''] after:absolute after:top-0.5 after:left-[2px] after:bg-white after:rounded-full after:h-4 after:w-4 after:transition-all"
></div>
</label>
</div>
</div>
</section>
</div>

View File

@@ -0,0 +1,92 @@
/* eslint-disable @typescript-eslint/member-ordering */
import {
Component,
inject,
signal
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { NgIcon, provideIcons } from '@ng-icons/core';
import { lucidePower } from '@ng-icons/lucide';
import { PlatformService } from '../../../../core/services/platform.service';
interface DesktopSettingsSnapshot {
autoStart: boolean;
}
interface GeneralSettingsElectronApi {
getDesktopSettings?: () => Promise<DesktopSettingsSnapshot>;
setDesktopSettings?: (patch: { autoStart?: boolean }) => Promise<DesktopSettingsSnapshot>;
}
type GeneralSettingsWindow = Window & {
electronAPI?: GeneralSettingsElectronApi;
};
@Component({
selector: 'app-general-settings',
standalone: true,
imports: [CommonModule, NgIcon],
viewProviders: [
provideIcons({
lucidePower
})
],
templateUrl: './general-settings.component.html'
})
export class GeneralSettingsComponent {
private platform = inject(PlatformService);
readonly isElectron = this.platform.isElectron;
autoStart = signal(false);
savingAutoStart = signal(false);
constructor() {
if (this.isElectron) {
void this.loadDesktopSettings();
}
}
async onAutoStartChange(event: Event): Promise<void> {
const input = event.target as HTMLInputElement;
const enabled = !!input.checked;
const api = this.getElectronApi();
if (!this.isElectron || !api?.setDesktopSettings) {
input.checked = this.autoStart();
return;
}
this.savingAutoStart.set(true);
try {
const snapshot = await api.setDesktopSettings({ autoStart: enabled });
this.autoStart.set(snapshot.autoStart);
} catch {
input.checked = this.autoStart();
} finally {
this.savingAutoStart.set(false);
}
}
private async loadDesktopSettings(): Promise<void> {
const api = this.getElectronApi();
if (!api?.getDesktopSettings) {
return;
}
try {
const snapshot = await api.getDesktopSettings();
this.autoStart.set(snapshot.autoStart);
} catch {}
}
private getElectronApi(): GeneralSettingsElectronApi | null {
return typeof window !== 'undefined'
? (window as GeneralSettingsWindow).electronAPI ?? null
: null;
}
}

View File

@@ -116,6 +116,9 @@
<div class="flex items-center justify-between px-6 py-4 border-b border-border flex-shrink-0">
<h3 class="text-lg font-semibold text-foreground">
@switch (activePage()) {
@case ('general') {
General
}
@case ('network') {
Network
}
@@ -157,6 +160,9 @@
<!-- Scrollable Content Area -->
<div class="flex-1 overflow-y-auto p-6">
@switch (activePage()) {
@case ('general') {
<app-general-settings />
}
@case ('network') {
<app-network-settings />
}

View File

@@ -31,6 +31,7 @@ import { Room, UserRole } from '../../../core/models/index';
import { findRoomMember } from '../../../store/rooms/room-members.helpers';
import { WebRTCService } from '../../../core/services/webrtc.service';
import { GeneralSettingsComponent } from './general-settings/general-settings.component';
import { NetworkSettingsComponent } from './network-settings/network-settings.component';
import { VoiceSettingsComponent } from './voice-settings/voice-settings.component';
import { ServerSettingsComponent } from './server-settings/server-settings.component';
@@ -48,6 +49,7 @@ import { THIRD_PARTY_LICENSES, type ThirdPartyLicense } from './third-party-lice
CommonModule,
FormsModule,
NgIcon,
GeneralSettingsComponent,
NetworkSettingsComponent,
VoiceSettingsComponent,
UpdatesSettingsComponent,
@@ -89,6 +91,9 @@ export class SettingsModalComponent {
activePage = this.modal.activePage;
readonly globalPages: { id: SettingsPage; label: string; icon: string }[] = [
{ id: 'general',
label: 'General',
icon: 'lucideSettings' },
{ id: 'network',
label: 'Network',
icon: 'lucideGlobe' },