mirror of
https://github.com/Start9Labs/start-os.git
synced 2026-03-26 10:21:52 +00:00
keyboard keymap also
This commit is contained in:
@@ -82,7 +82,7 @@ export default class KeyboardPage {
|
||||
this.stateService.language as LanguageCode,
|
||||
)
|
||||
selected =
|
||||
this.keyboards.find(k => k.code === this.stateService.keyboard) ||
|
||||
this.keyboards.find(k => k.layout === this.stateService.keyboard) ||
|
||||
this.keyboards[0]!
|
||||
|
||||
readonly saving = signal(false)
|
||||
@@ -95,13 +95,14 @@ export default class KeyboardPage {
|
||||
try {
|
||||
// Send keyboard to backend
|
||||
await this.api.setKeyboard({
|
||||
layout: this.selected.code,
|
||||
layout: this.selected.layout,
|
||||
keymap: this.selected.keymap,
|
||||
model: null,
|
||||
variant: null,
|
||||
options: [],
|
||||
})
|
||||
|
||||
this.stateService.keyboard = this.selected.code
|
||||
this.stateService.keyboard = this.selected.layout
|
||||
await this.navigateToNextStep()
|
||||
} finally {
|
||||
this.saving.set(false)
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
import { LanguageCode } from './languages'
|
||||
|
||||
/**
|
||||
* Keyboard layout codes
|
||||
* Keyboard layout codes (X11/Wayland)
|
||||
*/
|
||||
export type KeyboardCode = 'us' | 'gb' | 'es' | 'latam' | 'de' | 'fr' | 'pl'
|
||||
export type KeyboardLayout = 'us' | 'gb' | 'es' | 'latam' | 'de' | 'fr' | 'pl'
|
||||
|
||||
/**
|
||||
* Keyboard keymap codes (console/TTY)
|
||||
*/
|
||||
export type KeyboardKeymap = 'us' | 'uk' | 'es' | 'la' | 'de' | 'fr' | 'pl'
|
||||
|
||||
/**
|
||||
* Keyboard layout display names
|
||||
@@ -18,10 +23,11 @@ export type KeyboardName =
|
||||
| 'Polish'
|
||||
|
||||
/**
|
||||
* Keyboard layout definition
|
||||
* Keyboard definition with layout and keymap
|
||||
*/
|
||||
export interface Keyboard {
|
||||
code: KeyboardCode
|
||||
layout: KeyboardLayout
|
||||
keymap: KeyboardKeymap
|
||||
name: KeyboardName
|
||||
}
|
||||
|
||||
@@ -29,7 +35,8 @@ export interface Keyboard {
|
||||
* Full keyboard configuration for backend API
|
||||
*/
|
||||
export interface FullKeyboard {
|
||||
layout: string
|
||||
layout: KeyboardLayout
|
||||
keymap: KeyboardKeymap
|
||||
model: string | null
|
||||
variant: string | null
|
||||
options: string[]
|
||||
@@ -40,29 +47,29 @@ export interface FullKeyboard {
|
||||
*/
|
||||
export const KEYBOARDS_BY_LANGUAGE: Record<LanguageCode, Keyboard[]> = {
|
||||
en: [
|
||||
{ code: 'us', name: 'US English' },
|
||||
{ code: 'gb', name: 'UK English' },
|
||||
{ layout: 'us', keymap: 'us', name: 'US English' },
|
||||
{ layout: 'gb', keymap: 'uk', name: 'UK English' },
|
||||
],
|
||||
es: [
|
||||
{ code: 'es', name: 'Spanish' },
|
||||
{ code: 'latam', name: 'Latin American' },
|
||||
{ layout: 'es', keymap: 'es', name: 'Spanish' },
|
||||
{ layout: 'latam', keymap: 'la', name: 'Latin American' },
|
||||
],
|
||||
de: [{ code: 'de', name: 'German' }],
|
||||
fr: [{ code: 'fr', name: 'French' }],
|
||||
pl: [{ code: 'pl', name: 'Polish' }],
|
||||
de: [{ layout: 'de', keymap: 'de', name: 'German' }],
|
||||
fr: [{ layout: 'fr', keymap: 'fr', name: 'French' }],
|
||||
pl: [{ layout: 'pl', keymap: 'pl', name: 'Polish' }],
|
||||
}
|
||||
|
||||
/**
|
||||
* All available keyboard layouts
|
||||
*/
|
||||
export const ALL_KEYBOARDS: Keyboard[] = [
|
||||
{ code: 'us', name: 'US English' },
|
||||
{ code: 'gb', name: 'UK English' },
|
||||
{ code: 'es', name: 'Spanish' },
|
||||
{ code: 'latam', name: 'Latin American' },
|
||||
{ code: 'de', name: 'German' },
|
||||
{ code: 'fr', name: 'French' },
|
||||
{ code: 'pl', name: 'Polish' },
|
||||
{ layout: 'us', keymap: 'us', name: 'US English' },
|
||||
{ layout: 'gb', keymap: 'uk', name: 'UK English' },
|
||||
{ layout: 'es', keymap: 'es', name: 'Spanish' },
|
||||
{ layout: 'latam', keymap: 'la', name: 'Latin American' },
|
||||
{ layout: 'de', keymap: 'de', name: 'German' },
|
||||
{ layout: 'fr', keymap: 'fr', name: 'French' },
|
||||
{ layout: 'pl', keymap: 'pl', name: 'Polish' },
|
||||
]
|
||||
|
||||
/**
|
||||
@@ -71,20 +78,20 @@ export const ALL_KEYBOARDS: Keyboard[] = [
|
||||
*/
|
||||
export function getAllKeyboardsSorted(languageCode: LanguageCode): Keyboard[] {
|
||||
const languageKeyboards = KEYBOARDS_BY_LANGUAGE[languageCode]
|
||||
const languageKeyboardCodes = new Set(languageKeyboards.map(kb => kb.code))
|
||||
const languageLayouts = new Set(languageKeyboards.map(kb => kb.layout))
|
||||
const otherKeyboards = ALL_KEYBOARDS.filter(
|
||||
kb => !languageKeyboardCodes.has(kb.code),
|
||||
kb => !languageLayouts.has(kb.layout),
|
||||
).sort((a, b) => a.name.localeCompare(b.name))
|
||||
return [...languageKeyboards, ...otherKeyboards]
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the display name for a keyboard code.
|
||||
* Get the display name for a keyboard layout.
|
||||
*/
|
||||
export function getKeyboardName(
|
||||
code: KeyboardCode | string,
|
||||
layout: KeyboardLayout | string,
|
||||
): KeyboardName | string {
|
||||
const keyboard = ALL_KEYBOARDS.find(kb => kb.code === code)
|
||||
const keyboard = ALL_KEYBOARDS.find(kb => kb.layout === layout)
|
||||
if (keyboard) return keyboard.name
|
||||
return code // fallback to the code itself if not found
|
||||
return layout // fallback to the layout itself if not found
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
i18nPipe,
|
||||
i18nService,
|
||||
Keyboard,
|
||||
KeyboardCode,
|
||||
KeyboardLayout,
|
||||
Language,
|
||||
LANGUAGES,
|
||||
LANGUAGE_TO_CODE,
|
||||
@@ -317,29 +317,30 @@ export default class SystemGeneralComponent {
|
||||
if (!server) return
|
||||
|
||||
const keyboards = getAllKeyboardsSorted(LANGUAGE_TO_CODE[server.language])
|
||||
const currentKeyboard = (server.keyboard?.layout as KeyboardCode) || null
|
||||
const currentLayout = (server.keyboard?.layout as KeyboardLayout) || null
|
||||
|
||||
this.dialog
|
||||
.openComponent<KeyboardCode | null>(
|
||||
.openComponent<Keyboard | null>(
|
||||
new PolymorpheusComponent(KeyboardSelectComponent, this.injector),
|
||||
{
|
||||
label: 'Select Keyboard Layout',
|
||||
size: 's',
|
||||
data: { keyboards, currentKeyboard },
|
||||
data: { keyboards, currentLayout },
|
||||
},
|
||||
)
|
||||
.pipe(filter((code): code is KeyboardCode => code !== null))
|
||||
.subscribe(keyboardCode => {
|
||||
this.saveKeyboard(keyboardCode)
|
||||
.pipe(filter((keyboard): keyboard is Keyboard => keyboard !== null))
|
||||
.subscribe(keyboard => {
|
||||
this.saveKeyboard(keyboard)
|
||||
})
|
||||
}
|
||||
|
||||
private async saveKeyboard(keyboardCode: KeyboardCode) {
|
||||
private async saveKeyboard(keyboard: Keyboard) {
|
||||
const loader = this.loader.open('Saving').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.setKeyboard({
|
||||
layout: keyboardCode,
|
||||
layout: keyboard.layout,
|
||||
keymap: keyboard.keymap,
|
||||
model: null,
|
||||
variant: null,
|
||||
options: [],
|
||||
@@ -457,17 +458,17 @@ export default class SystemGeneralComponent {
|
||||
|
||||
private promptKeyboardSelection(keyboards: Keyboard[]) {
|
||||
this.dialog
|
||||
.openComponent<KeyboardCode | null>(
|
||||
.openComponent<Keyboard | null>(
|
||||
new PolymorpheusComponent(KeyboardSelectComponent, this.injector),
|
||||
{
|
||||
label: 'Select Keyboard Layout',
|
||||
size: 's',
|
||||
data: { keyboards, currentKeyboard: null },
|
||||
data: { keyboards, currentLayout: null },
|
||||
},
|
||||
)
|
||||
.pipe(filter((code): code is KeyboardCode => code !== null))
|
||||
.subscribe(keyboardCode => {
|
||||
this.enableKioskWithKeyboard(keyboardCode)
|
||||
.pipe(filter((keyboard): keyboard is Keyboard => keyboard !== null))
|
||||
.subscribe(keyboard => {
|
||||
this.enableKioskWithKeyboard(keyboard)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -484,12 +485,13 @@ export default class SystemGeneralComponent {
|
||||
}
|
||||
}
|
||||
|
||||
private async enableKioskWithKeyboard(keyboardCode: KeyboardCode) {
|
||||
private async enableKioskWithKeyboard(keyboard: Keyboard) {
|
||||
const loader = this.loader.open('Enabling').subscribe()
|
||||
|
||||
try {
|
||||
await this.api.setKeyboard({
|
||||
layout: keyboardCode,
|
||||
layout: keyboard.layout,
|
||||
keymap: keyboard.keymap,
|
||||
model: null,
|
||||
variant: null,
|
||||
options: [],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Component, inject } from '@angular/core'
|
||||
import { FormsModule } from '@angular/forms'
|
||||
import { i18nPipe, Keyboard, KeyboardCode } from '@start9labs/shared'
|
||||
import { i18nPipe, Keyboard, KeyboardLayout } from '@start9labs/shared'
|
||||
import { TUI_IS_MOBILE } from '@taiga-ui/cdk'
|
||||
import { TuiButton, TuiDialogContext, TuiTextfield } from '@taiga-ui/core'
|
||||
import { TuiChevron, TuiDataListWrapper, TuiSelect } from '@taiga-ui/kit'
|
||||
@@ -29,7 +29,7 @@ import { injectContext } from '@taiga-ui/polymorpheus'
|
||||
</button>
|
||||
<button
|
||||
tuiButton
|
||||
[disabled]="!selected || selected.code === initialCode"
|
||||
[disabled]="!selected || selected.layout === initialLayout"
|
||||
(click)="confirm()"
|
||||
>
|
||||
{{ 'Confirm' | i18n }}
|
||||
@@ -61,16 +61,16 @@ export class KeyboardSelectComponent {
|
||||
private readonly context =
|
||||
injectContext<
|
||||
TuiDialogContext<
|
||||
KeyboardCode | null,
|
||||
{ keyboards: Keyboard[]; currentKeyboard: KeyboardCode | null }
|
||||
Keyboard | null,
|
||||
{ keyboards: Keyboard[]; currentLayout: KeyboardLayout | null }
|
||||
>
|
||||
>()
|
||||
|
||||
protected readonly mobile = inject(TUI_IS_MOBILE)
|
||||
readonly keyboards = this.context.data.keyboards
|
||||
readonly initialCode = this.context.data.currentKeyboard
|
||||
readonly initialLayout = this.context.data.currentLayout
|
||||
selected =
|
||||
this.keyboards.find(kb => kb.code === this.initialCode) ||
|
||||
this.keyboards.find(kb => kb.layout === this.initialLayout) ||
|
||||
this.keyboards[0]!
|
||||
|
||||
readonly stringify = (kb: Keyboard) => kb.name
|
||||
@@ -80,6 +80,6 @@ export class KeyboardSelectComponent {
|
||||
}
|
||||
|
||||
confirm() {
|
||||
this.context.completeWith(this.selected.code)
|
||||
this.context.completeWith(this.selected)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,12 +460,7 @@ export class MockApiService extends ApiService {
|
||||
{
|
||||
op: PatchOp.REPLACE,
|
||||
path: '/serverInfo/keyboard',
|
||||
value: {
|
||||
layout: params.layout,
|
||||
model: params.model,
|
||||
variant: params.variant,
|
||||
options: params.options,
|
||||
},
|
||||
value: params,
|
||||
},
|
||||
]
|
||||
this.mockRevision(patch)
|
||||
|
||||
@@ -222,6 +222,7 @@ export const mockPatchData: DataModel = {
|
||||
language: 'en_US',
|
||||
keyboard: {
|
||||
layout: 'us',
|
||||
keymap: 'us',
|
||||
model: null,
|
||||
variant: null,
|
||||
options: [],
|
||||
|
||||
Reference in New Issue
Block a user