From 6e46d407bfd0da1554edfa4929a1a0457298313b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Iv=C3=A1n=20L=C3=B3pez=20Gonz=C3=A1lez?= Date: Tue, 5 Dec 2023 16:30:30 +0000 Subject: [PATCH] [web] Add keymap switcher --- web/src/App.jsx | 3 +- .../l10n/InstallerKeymapSwitcher.jsx | 55 +++++++++++++++++++ web/src/components/l10n/index.js | 1 + web/src/context/installerL10n.jsx | 27 ++++++++- 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 web/src/components/l10n/InstallerKeymapSwitcher.jsx diff --git a/web/src/App.jsx b/web/src/App.jsx index afe3502838..c7c9681209 100644 --- a/web/src/App.jsx +++ b/web/src/App.jsx @@ -39,7 +39,7 @@ import { ShowTerminalButton, Sidebar } from "~/components/core"; -import { InstallerLocaleSwitcher } from "./components/l10n"; +import { InstallerKeymapSwitcher, InstallerLocaleSwitcher } from "./components/l10n"; import { Layout, Loading, Title } from "./components/layout"; import { useInstallerL10n } from "./context/installerL10n"; @@ -117,6 +117,7 @@ function App() {
+
diff --git a/web/src/components/l10n/InstallerKeymapSwitcher.jsx b/web/src/components/l10n/InstallerKeymapSwitcher.jsx new file mode 100644 index 0000000000..990cdc898f --- /dev/null +++ b/web/src/components/l10n/InstallerKeymapSwitcher.jsx @@ -0,0 +1,55 @@ +/* + * Copyright (c) [2023] SUSE LLC + * + * All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, contact SUSE LLC. + * + * To contact SUSE LLC about this file by physical or electronic mail, you may + * find current contact information at www.suse.com. + */ + +import React from "react"; +import { Icon } from "../layout"; +import { FormSelect, FormSelectOption } from "@patternfly/react-core"; +import { _ } from "~/i18n"; +import { useInstallerL10n } from "~/context/installerL10n"; +import { useL10n } from "~/context/l10n"; + +const sort = (keymaps) => keymaps.sort((k1, k2) => k1.name > k2.name ? 1 : -1); + +export default function InstallerKeymapSwitcher() { + const { keymap, changeKeymap } = useInstallerL10n(); + const { keymaps } = useL10n(); + + const onChange = (_, id) => changeKeymap(id); + + const options = sort(keymaps) + .map((keymap, index) => ); + + return ( + <> +

+ {_("Keyboard")} +

+ + {options} + + + ); +} diff --git a/web/src/components/l10n/index.js b/web/src/components/l10n/index.js index 1a9f090279..f5f2eb3840 100644 --- a/web/src/components/l10n/index.js +++ b/web/src/components/l10n/index.js @@ -19,6 +19,7 @@ * find current contact information at www.suse.com. */ +export { default as InstallerKeymapSwitcher } from "./InstallerKeymapSwitcher"; export { default as InstallerLocaleSwitcher } from "./InstallerLocaleSwitcher"; export { default as KeymapSelector } from "./KeymapSelector"; export { default as L10nPage } from "./L10nPage"; diff --git a/web/src/context/installerL10n.jsx b/web/src/context/installerL10n.jsx index 482843a274..491765d239 100644 --- a/web/src/context/installerL10n.jsx +++ b/web/src/context/installerL10n.jsx @@ -19,6 +19,7 @@ * find current contact information at www.suse.com. */ +// cspell:ignore localectl // @ts-check import React, { useCallback, useEffect, useState } from "react"; @@ -178,6 +179,18 @@ function reload(newLanguage) { } } +/** + * Extracts keymap from localectl output. + * + * @param {string} output + * @returns {string|undefined} + */ +function keymapFromLocalectl(output) { + const matcher = /X11 Layout: (.*)\n/; + + return matcher.exec(output)?.at(1); +} + /** * This provider sets the installer locale. By default, it uses the URL "lang" query parameter or * the preferred locale from the browser and synchronizes the UI and the backend locales. To @@ -196,6 +209,7 @@ function reload(newLanguage) { function InstallerL10nProvider({ children }) { const client = useInstallerClient(); const [language, setLanguage] = useState(undefined); + const [keymap, setKeymap] = useState(undefined); const [backendPending, setBackendPending] = useState(false); const { cancellablePromise } = useCancellablePromise(); @@ -240,6 +254,11 @@ function InstallerL10nProvider({ children }) { } }, [storeInstallerLanguage, setLanguage]); + const changeKeymap = useCallback(async (id) => { + setKeymap(id); + await cockpit.spawn(["localectl", "set-x11-keymap", id]); + }, [setKeymap]); + useEffect(() => { if (!language) changeLanguage(); }, [changeLanguage, language]); @@ -251,8 +270,14 @@ function InstallerL10nProvider({ children }) { setBackendPending(false); }, [client, language, backendPending, storeInstallerLanguage]); + useEffect(() => { + cockpit.spawn(["localectl", "status"]).then(output => setKeymap(keymapFromLocalectl(output))); + }, [setKeymap]); + + const value = { language, changeLanguage, keymap, changeKeymap }; + return ( - {children} + {children} ); }