Skip to content

Commit

Permalink
[web] Add keymap switcher
Browse files Browse the repository at this point in the history
  • Loading branch information
joseivanlopez authored and lslezak committed Dec 6, 2023
1 parent 3a1f1fe commit 6e46d40
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 2 deletions.
3 changes: 2 additions & 1 deletion web/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -117,6 +117,7 @@ function App() {
<div className="full-width highlighted">
<div className="flex-stack">
<InstallerLocaleSwitcher />
<InstallerKeymapSwitcher />
</div>
</div>
</Sidebar>
Expand Down
55 changes: 55 additions & 0 deletions web/src/components/l10n/InstallerKeymapSwitcher.jsx
Original file line number Diff line number Diff line change
@@ -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) => <FormSelectOption key={index} value={keymap.id} label={keymap.name} />);

return (
<>
<h3>
<Icon name="keyboard" size="24" />{_("Keyboard")}
</h3>
<FormSelect
id="keyboard"
aria-label={_("keyboard")}
value={keymap}
onChange={onChange}
>
{options}
</FormSelect>
</>
);
}
1 change: 1 addition & 0 deletions web/src/components/l10n/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
27 changes: 26 additions & 1 deletion web/src/context/installerL10n.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
* find current contact information at www.suse.com.
*/

// cspell:ignore localectl
// @ts-check

import React, { useCallback, useEffect, useState } from "react";
Expand Down Expand Up @@ -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
Expand All @@ -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();

Expand Down Expand Up @@ -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]);
Expand All @@ -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 (
<L10nContext.Provider value={{ language, changeLanguage }}>{children}</L10nContext.Provider>
<L10nContext.Provider value={value}>{children}</L10nContext.Provider>
);
}

Expand Down

0 comments on commit 6e46d40

Please sign in to comment.