fix ssh, undeprecate wifi

This commit is contained in:
Matt Hill
2026-02-10 13:41:54 -07:00
parent b6262c8e13
commit fe28a812a4
11 changed files with 151 additions and 95 deletions

View File

@@ -5,7 +5,7 @@ export default {
2: 'Aktualisieren',
4: 'System',
5: 'Allgemein',
6: 'E-Mail',
6: 'SMTP',
7: 'Sicherung erstellen',
8: 'Sicherung wiederherstellen',
9: 'Zum Login gehen',
@@ -385,8 +385,8 @@ export default {
405: 'Verbunden',
406: 'Vergessen',
407: 'WiFi-Zugangsdaten',
408: 'Veraltet',
409: 'Die WLAN-Unterstützung wird in StartOS v0.4.1 entfernt. Wenn Sie keinen Zugriff auf Ethernet haben, können Sie einen WLAN-Extender verwenden, um sich mit dem lokalen Netzwerk zu verbinden und dann Ihren Server über Ethernet an den Extender anschließen. Bitte wenden Sie sich bei Fragen an den Start9-Support.',
408: 'Mit verstecktem Netzwerk verbinden',
409: 'Verbinden mit',
410: 'Bekannte Netzwerke',
411: 'Weitere Netzwerke',
412: 'WiFi ist deaktiviert',

View File

@@ -4,7 +4,7 @@ export const ENGLISH: Record<string, number> = {
'Update': 2, // verb
'System': 4, // as in, system preferences
'General': 5, // as in, general settings
'Email': 6,
'SMTP': 6,
'Create Backup': 7, // create a backup
'Restore Backup': 8, // restore from backup
'Go to login': 9,
@@ -384,8 +384,8 @@ export const ENGLISH: Record<string, number> = {
'Connected': 405,
'Forget': 406, // as in, delete or remove
'WiFi Credentials': 407,
'Deprecated': 408,
'WiFi support will be removed in StartOS v0.4.1. If you do not have access to Ethernet, you can use a WiFi extender to connect to the local network, then connect your server to the extender via Ethernet. Please contact Start9 support with any questions or concerns.': 409,
'Connect to hidden network': 408,
'Connect to': 409, // followed by a network name, e.g. "Connect to MyWiFi?"
'Known Networks': 410,
'Other Networks': 411,
'WiFi is disabled': 412,

View File

@@ -5,7 +5,7 @@ export default {
2: 'Actualizar',
4: 'Sistema',
5: 'General',
6: 'Correo electrónico',
6: 'SMTP',
7: 'Crear copia de seguridad',
8: 'Restaurar copia de seguridad',
9: 'Ir a inicio de sesión',
@@ -385,8 +385,8 @@ export default {
405: 'Conectado',
406: 'Olvidar',
407: 'Credenciales WiFi',
408: 'Obsoleto',
409: 'El soporte para WiFi será eliminado en StartOS v0.4.1. Si no tienes acceso a Ethernet, puedes usar un extensor WiFi para conectarte a la red local y luego conectar tu servidor al extensor por Ethernet. Por favor, contacta al soporte de Start9 si tienes dudas o inquietudes.',
408: 'Conectar a red oculta',
409: 'Conectar a',
410: 'Redes conocidas',
411: 'Otras redes',
412: 'WiFi está deshabilitado',

View File

@@ -5,7 +5,7 @@ export default {
2: 'Mettre à jour',
4: 'Système',
5: 'Général',
6: 'Email',
6: 'SMTP',
7: 'Créer une sauvegarde',
8: 'Restaurer une sauvegarde',
9: 'Se connecter',
@@ -385,8 +385,8 @@ export default {
405: 'Connecté',
406: 'Oublier',
407: 'Identifiants WiFi',
408: 'Obsolète',
409: 'Le support WiFi sera supprimé dans StartOS v0.4.1. Si vous navez pas accès à internet via Ethernet, vous pouvez utiliser un répéteur WiFi pour vous connecter au réseau local, puis brancher votre serveur sur le répéteur en Ethernet. Contactez le support Start9 pour toute question.',
408: 'Se connecter à un réseau masqué',
409: 'Se connecter à',
410: 'Réseaux connus',
411: 'Autres réseaux',
412: 'Le WiFi est désactivé',

View File

@@ -5,7 +5,7 @@ export default {
2: 'Aktualizuj',
4: 'Ustawienia',
5: 'Ogólne',
6: 'E-mail',
6: 'SMTP',
7: 'Utwórz kopię zapasową',
8: 'Przywróć z kopii zapasowej',
9: 'Przejdź do logowania',
@@ -385,8 +385,8 @@ export default {
405: 'Połączono',
406: 'Zapomnij',
407: 'Dane logowania WiFi',
408: 'Przestarzałe',
409: 'Obsługa WiFi zostanie usunięta w StartOS v0.4.1. Jeśli nie masz dostępu do sieci Ethernet, możesz użyć wzmacniacza WiFi do połączenia z siecią lokalną, a następnie podłączyć serwer do wzmacniacza przez Ethernet. W razie pytań lub wątpliwości skontaktuj się z pomocą techniczną Start9.',
408: 'Połącz z ukrytą siecią',
409: 'Połącz z',
410: 'Znane sieci',
411: 'Inne sieci',
412: 'WiFi jest wyłączone',

View File

@@ -28,7 +28,7 @@ import { configBuilderToSpec } from 'src/app/utils/configBuilderToSpec'
<a routerLink=".." tuiIconButton iconStart="@tui.arrow-left">
{{ 'Back' | i18n }}
</a>
{{ 'Email' | i18n }}
{{ 'SMTP' | i18n }}
</ng-container>
@if (form$ | async; as form) {
<form [formGroup]="form">

View File

@@ -160,7 +160,11 @@ export default class SystemSSHComponent {
const loader = this.loader.open('Deleting').subscribe()
try {
await this.api.deleteSshKey({ fingerprint: '' })
await Promise.all(
fingerprints.map(fingerprint =>
this.api.deleteSshKey({ fingerprint }),
),
)
this.local$.next(
all.filter(s => !fingerprints.includes(s.fingerprint)),
)

View File

@@ -5,8 +5,23 @@ import {
inject,
Input,
} from '@angular/core'
import { ErrorService, i18nPipe, LoadingService } from '@start9labs/shared'
import { TuiButton, TuiIcon, TuiTitle } from '@taiga-ui/core'
import { NgTemplateOutlet } from '@angular/common'
import {
DialogService,
ErrorService,
i18nPipe,
LoadingService,
} from '@start9labs/shared'
import { filter } from 'rxjs'
import { IST } from '@start9labs/start-sdk'
import {
TuiButton,
TuiDataList,
TuiDropdown,
TuiIcon,
TuiTextfield,
TuiTitle,
} from '@taiga-ui/core'
import { TuiBadge, TuiFade } from '@taiga-ui/kit'
import { TuiCell } from '@taiga-ui/layout'
import {
@@ -22,38 +37,7 @@ import { wifiSpec } from './wifi.const'
@Component({
selector: '[wifi]',
template: `
@for (network of wifi; track $index) {
@if (network.ssid) {
<button
tuiCell
[disabled]="network.connected"
(click)="prompt(network)"
>
<div tuiTitle>
<strong tuiFade>
{{ network.ssid }}
@if (network.connected) {
<tui-badge appearance="positive">
{{ 'Connected' | i18n }}
</tui-badge>
}
</strong>
</div>
@if (network.connected !== undefined) {
<button
tuiIconButton
size="s"
appearance="icon"
iconStart="@tui.trash-2"
(click.stop)="forget(network)"
>
{{ 'Forget' | i18n }}
</button>
} @else {
<tui-icon
[icon]="network.security.length ? '@tui.lock' : '@tui.lock-open'"
/>
}
<ng-template #row let-network>
@if (getSignal(network.strength); as signal) {
<tui-icon
background="@tui.wifi"
@@ -64,7 +48,66 @@ import { wifiSpec } from './wifi.const'
} @else {
<tui-icon icon="@tui.wifi-off" />
}
<tui-icon
[icon]="network.security.length ? '@tui.lock' : '@tui.lock-open'"
/>
<div tuiTitle>
<strong tuiFade>
{{ network.ssid }}
</strong>
</div>
@if (network.connected) {
<tui-badge appearance="positive">
{{ 'Connected' | i18n }}
</tui-badge>
}
@if (network.connected === false) {
<button
tuiIconButton
tuiDropdown
size="s"
appearance="flat-grayscale"
iconStart="@tui.ellipsis-vertical"
[(tuiDropdownOpen)]="open"
>
{{ 'More' | i18n }}
<tui-data-list *tuiTextfieldDropdown>
<button
tuiOption
new
iconStart="@tui.wifi"
(click)="prompt(network)"
>
{{ 'Connect' | i18n }}
</button>
<button
tuiOption
new
iconStart="@tui.trash"
class="g-negative"
(click)="forget(network)"
>
{{ 'Forget' | i18n }}
</button>
</tui-data-list>
</button>
}
</ng-template>
@for (network of wifi; track $index) {
@if (network.ssid) {
@if (network.connected === undefined) {
<button tuiCell (click)="prompt(network)">
<ng-container
*ngTemplateOutlet="row; context: { $implicit: network }"
/>
</button>
} @else {
<div tuiCell>
<ng-container
*ngTemplateOutlet="row; context: { $implicit: network }"
/>
</div>
}
}
}
`,
@@ -75,8 +118,6 @@ import { wifiSpec } from './wifi.const'
}
[tuiCell] {
padding-inline: 1rem !important;
&:disabled > * {
opacity: 1;
}
@@ -88,11 +129,24 @@ import { wifiSpec } from './wifi.const'
}
`,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [TuiCell, TuiTitle, TuiBadge, TuiButton, TuiIcon, TuiFade, i18nPipe],
imports: [
NgTemplateOutlet,
TuiCell,
TuiTitle,
TuiBadge,
TuiButton,
TuiIcon,
TuiFade,
TuiDropdown,
TuiDataList,
TuiTextfield,
i18nPipe,
],
})
export class WifiTableComponent {
private readonly loader = inject(LoadingService)
private readonly errorService = inject(ErrorService)
private readonly dialogs = inject(DialogService)
private readonly api = inject(ApiService)
private readonly formDialog = inject(FormDialogService)
private readonly component = inject(SystemWifiComponent)
@@ -102,6 +156,8 @@ export class WifiTableComponent {
@Input()
wifi: readonly Wifi[] = []
open = false
getSignal(signal: number) {
if (signal < 5) {
return null
@@ -141,17 +197,30 @@ export class WifiTableComponent {
async prompt(network: Wifi): Promise<void> {
if (!network.security.length) {
await this.component.saveAndConnect(network.ssid)
this.dialogs
.openConfirm({
label: `${this.i18n.transform('Connect to')} ${network.ssid}?`,
size: 's',
})
.pipe(filter(Boolean))
.subscribe(() => this.component.saveAndConnect(network.ssid))
} else {
const ssid = wifiSpec.spec['ssid'] as IST.ValueSpecText
const spec: IST.InputSpec = {
...wifiSpec.spec,
ssid: { ...ssid, disabled: 'ssid', default: network.ssid },
}
this.formDialog.open<FormContext<WiFiForm>>(FormComponent, {
label: 'Password needed',
data: {
spec: wifiSpec.spec,
spec,
value: { ssid: network.ssid, password: '' },
buttons: [
{
text: this.i18n.transform('Connect')!,
handler: async ({ ssid, password }) =>
this.component.saveAndConnect(ssid, password),
handler: async ({ password }) =>
this.component.saveAndConnect(network.ssid, password),
},
],
},

View File

@@ -8,6 +8,7 @@ import { toSignal } from '@angular/core/rxjs-interop'
import { FormsModule } from '@angular/forms'
import { RouterLink } from '@angular/router'
import {
DocsLinkDirective,
ErrorService,
i18nKey,
i18nPipe,
@@ -19,11 +20,9 @@ import {
TuiAppearance,
TuiButton,
TuiLoader,
TuiNotification,
TuiTitle,
} from '@taiga-ui/core'
import { TuiSwitch } from '@taiga-ui/kit'
import { TuiCardLarge, TuiHeader } from '@taiga-ui/layout'
import { TuiCardLarge } from '@taiga-ui/layout'
import { PatchDB } from 'patch-db-client'
import { catchError, defer, map, merge, Observable, of, Subject } from 'rxjs'
import {
@@ -47,23 +46,20 @@ import { wifiSpec } from './wifi.const'
</a>
WiFi
</ng-container>
<header tuiHeader>
<tui-notification appearance="negative">
<div tuiTitle>
{{ 'Deprecated' | i18n }}
<div tuiSubtitle>
{{
'WiFi support will be removed in StartOS v0.4.1. If you do not have access to Ethernet, you can use a WiFi extender to connect to the local network, then connect your server to the extender via Ethernet. Please contact Start9 support with any questions or concerns.'
| i18n
}}
</div>
</div>
</tui-notification>
</header>
@if (status()?.interface) {
<section class="g-card">
<header>
Wi-Fi
<a
tuiIconButton
size="xs"
docsLink
path="/user-manual/wifi.html"
appearance="icon"
iconStart="@tui.external-link"
>
{{ 'Documentation' | i18n }}
</a>
<input
type="checkbox"
tuiSwitch
@@ -92,8 +88,8 @@ import { wifiSpec } from './wifi.const'
></div>
}
<p>
<button tuiButton (click)="other(data)">
{{ 'Add' | i18n }}
<button tuiButton (click)="other(data)" appearance="flat">
+ {{ 'Connect to hidden network' | i18n }}
</button>
</p>
} @else {
@@ -128,10 +124,8 @@ import { wifiSpec } from './wifi.const'
TitleDirective,
RouterLink,
PlaceholderComponent,
TuiHeader,
TuiTitle,
TuiNotification,
i18nPipe,
DocsLinkDirective,
],
})
export default class SystemWifiComponent {

View File

@@ -1,4 +1,3 @@
import { AsyncPipe } from '@angular/common'
import { ChangeDetectionStrategy, Component, inject } from '@angular/core'
import { toSignal } from '@angular/core/rxjs-interop'
import { RouterModule } from '@angular/router'
@@ -6,12 +5,9 @@ import { i18nPipe } from '@start9labs/shared'
import { TuiIcon, TuiTitle } from '@taiga-ui/core'
import { TuiBadgeNotification } from '@taiga-ui/kit'
import { TuiCell } from '@taiga-ui/layout'
import { PatchDB } from 'patch-db-client'
import { BadgeService } from 'src/app/services/badge.service'
import { DataModel } from 'src/app/services/patch-db/data-model'
import { TitleDirective } from 'src/app/services/title.service'
import { SYSTEM_MENU } from './system.const'
import { map } from 'rxjs'
@Component({
template: `
@@ -26,9 +22,6 @@ import { map } from 'rxjs'
tuiCell="s"
routerLinkActive="active"
[routerLink]="page.link"
[style.display]="
!(wifiEnabled$ | async) && page.item === 'WiFi' ? 'none' : null
"
>
<tui-icon [icon]="page.icon" />
<span tuiTitle>
@@ -116,13 +109,9 @@ import { map } from 'rxjs'
TitleDirective,
TuiBadgeNotification,
i18nPipe,
AsyncPipe,
],
})
export class SystemComponent {
readonly menu = SYSTEM_MENU
readonly badge = toSignal(inject(BadgeService).getCount('system'))
readonly wifiEnabled$ = inject<PatchDB<DataModel>>(PatchDB)
.watch$('serverInfo', 'network', 'wifi')
.pipe(map(wifi => !!wifi.interface && wifi.enabled))
}

View File

@@ -28,7 +28,7 @@ export const SYSTEM_MENU = [
},
{
icon: '@tui.mail',
item: 'Email',
item: 'SMTP',
link: 'email',
},
{