desktop: components/apps/settings — settings panel with display/audio/network/about sections
This commit is contained in:
parent
0048eabb60
commit
6beb93b16f
@ -0,0 +1,62 @@
|
|||||||
|
<div class="settings">
|
||||||
|
<!-- Sidebar -->
|
||||||
|
<div class="settings-sidebar">
|
||||||
|
<div class="settings-title">Settings</div>
|
||||||
|
@for (section of sections; track section.id) {
|
||||||
|
<button
|
||||||
|
class="settings-nav-item"
|
||||||
|
[class.active]="activeSection() === section.id"
|
||||||
|
(click)="activeSection.set(section.id)"
|
||||||
|
>
|
||||||
|
<span class="nav-icon">{{ section.icon }}</span>
|
||||||
|
<span class="nav-label">{{ section.title }}</span>
|
||||||
|
</button>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Content -->
|
||||||
|
<div class="settings-content">
|
||||||
|
@switch (activeSection()) {
|
||||||
|
@case ('display') {
|
||||||
|
<div class="settings-section">
|
||||||
|
<h3>Display Settings</h3>
|
||||||
|
<div class="setting-row">
|
||||||
|
<label>Frame Buffer Size</label>
|
||||||
|
<input type="number" [ngModel]="frameBufferSize()" min="10" max="300" />
|
||||||
|
</div>
|
||||||
|
<div class="setting-desc">Number of frames to buffer for late-joining viewers (default: 60).</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@case ('audio') {
|
||||||
|
<div class="settings-section">
|
||||||
|
<h3>Audio Settings</h3>
|
||||||
|
<div class="setting-desc">Audio settings will be available once the VM agent is connected.</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@case ('network') {
|
||||||
|
<div class="settings-section">
|
||||||
|
<h3>Network Settings</h3>
|
||||||
|
<div class="setting-row">
|
||||||
|
<label>Server URL</label>
|
||||||
|
<input type="text" [ngModel]="serverUrl()" />
|
||||||
|
</div>
|
||||||
|
<div class="setting-row">
|
||||||
|
<label>Idle Timeout (sec)</label>
|
||||||
|
<input type="number" [ngModel]="idleTimeout()" min="30" max="3600" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
@case ('about') {
|
||||||
|
<div class="settings-section">
|
||||||
|
<h3>About Butterfly</h3>
|
||||||
|
<div class="about-info">
|
||||||
|
<div class="about-row"><span>Version</span><span>0.1.0</span></div>
|
||||||
|
<div class="about-row"><span>Backend</span><span>Rust / Actix-Web 4</span></div>
|
||||||
|
<div class="about-row"><span>Frontend</span><span>Angular 21</span></div>
|
||||||
|
<div class="about-row"><span>Protocol</span><span>WebSocket + REST</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
127
desktop/src/app/components/apps/settings/settings.component.scss
Normal file
127
desktop/src/app/components/apps/settings/settings.component.scss
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
background: #1e1e1e;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-sidebar {
|
||||||
|
width: 200px;
|
||||||
|
background: #252526;
|
||||||
|
border-right: 1px solid #404040;
|
||||||
|
padding: 12px 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-title {
|
||||||
|
padding: 0 16px 12px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-nav-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border: none;
|
||||||
|
background: transparent;
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 13px;
|
||||||
|
cursor: pointer;
|
||||||
|
text-align: left;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: rgba(255, 255, 255, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: rgba(0, 120, 212, 0.15);
|
||||||
|
color: #fff;
|
||||||
|
border-left: 2px solid #0078d4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-icon {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-content {
|
||||||
|
flex: 1;
|
||||||
|
padding: 24px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-section {
|
||||||
|
max-width: 500px;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0 0 16px;
|
||||||
|
color: #e0e0e0;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
label {
|
||||||
|
color: #ccc;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 120px;
|
||||||
|
height: 30px;
|
||||||
|
padding: 0 8px;
|
||||||
|
border: 1px solid #555;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: #383838;
|
||||||
|
color: #e0e0e0;
|
||||||
|
font-size: 13px;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: #0078d4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-desc {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #888;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-info {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 8px 0;
|
||||||
|
border-bottom: 1px solid #333;
|
||||||
|
font-size: 13px;
|
||||||
|
|
||||||
|
span:first-child {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
span:last-child {
|
||||||
|
color: #e0e0e0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,31 @@
|
|||||||
|
import { Component, signal } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
interface SettingSection {
|
||||||
|
id: string;
|
||||||
|
title: string;
|
||||||
|
icon: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-settings',
|
||||||
|
standalone: true,
|
||||||
|
imports: [CommonModule],
|
||||||
|
templateUrl: './settings.component.html',
|
||||||
|
styleUrl: './settings.component.scss',
|
||||||
|
})
|
||||||
|
export class SettingsComponent {
|
||||||
|
readonly activeSection = signal('display');
|
||||||
|
|
||||||
|
sections: SettingSection[] = [
|
||||||
|
{ id: 'display', title: 'Display', icon: '🖥️' },
|
||||||
|
{ id: 'audio', title: 'Audio', icon: '🔊' },
|
||||||
|
{ id: 'network', title: 'Network', icon: '🌐' },
|
||||||
|
{ id: 'about', title: 'About', icon: 'ℹ️' },
|
||||||
|
];
|
||||||
|
|
||||||
|
readonly serverUrl = signal(window.location.origin);
|
||||||
|
readonly maxSessions = signal('100');
|
||||||
|
readonly frameBufferSize = signal('60');
|
||||||
|
readonly idleTimeout = signal('300');
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user