Skip to content

Commit a46fbfd

Browse files
committed
frontend/aria/hotkey: improve dialog …
1 parent db006b2 commit a46fbfd

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1450
-857
lines changed

src/packages/frontend/account/account-page.tsx

Lines changed: 55 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ and configuration.
1212

1313
// cSpell:ignore payg
1414

15-
import type {
16-
PreferencesSubTabKey,
17-
PreferencesSubTabType,
18-
} from "@cocalc/util/types/settings";
15+
import type { PreferencesSubTabKey } from "@cocalc/util/types/settings";
1916

2017
import { Button, Flex, Menu, Space } from "antd";
2118
import { useEffect, useState } from "react";
@@ -50,42 +47,25 @@ import {
5047
KUCALC_ON_PREMISES,
5148
} from "@cocalc/util/db-schema/site-defaults";
5249
import { COLORS } from "@cocalc/util/theme";
53-
import { VALID_PREFERENCES_SUB_TYPES } from "@cocalc/util/types/settings";
5450
import { AccountPreferencesAI } from "./account-preferences-ai";
55-
import {
56-
AccountPreferencesAppearance,
57-
APPEARANCE_ICON_NAME,
58-
} from "./account-preferences-appearance";
59-
import {
60-
AccountPreferencesCommunication,
61-
COMMUNICATION_ICON_NAME,
62-
} from "./account-preferences-communication";
63-
import {
64-
AccountPreferencesEditor,
65-
EDITOR_ICON_NAME,
66-
} from "./account-preferences-editor";
67-
import {
68-
AccountPreferencesKeyboard,
69-
KEYBOARD_ICON_NAME,
70-
} from "./account-preferences-keyboard";
71-
import {
72-
AccountPreferencesOther,
73-
OTHER_ICON_NAME,
74-
} from "./account-preferences-other";
51+
import { AccountPreferencesAppearance } from "./account-preferences-appearance";
52+
import { AccountPreferencesCommunication } from "./account-preferences-communication";
53+
import { PREFERENCES_SUB_TABS } from "./account-preferences-config";
54+
import { AccountPreferencesEditor } from "./account-preferences-editor";
55+
import { AccountPreferencesKeyboard } from "./account-preferences-keyboard";
56+
import { AccountPreferencesOther } from "./account-preferences-other";
7557
import {
7658
ACCOUNT_PREFERENCES_ICON_NAME,
7759
ACCOUNT_PROFILE_ICON_NAME,
7860
AccountPreferencesProfile,
7961
} from "./account-preferences-profile";
80-
import {
81-
AccountPreferencesSecurity,
82-
KEYS_ICON_NAME,
83-
} from "./account-preferences-security";
62+
import { AccountPreferencesSecurity } from "./account-preferences-security";
8463
import { I18NSelector } from "./i18n-selector";
8564
import { LicensesPage } from "./licenses/licenses-page";
8665
import { PublicPaths } from "./public-paths/public-paths";
8766
import { SettingsOverview } from "./settings-index";
8867
import { UpgradesPage } from "./upgrades/upgrades-page";
68+
import { switchAccountPage } from "./util";
8969

9070
export const ACCOUNT_SETTINGS_ICON_NAME: IconName = "settings";
9171

@@ -99,17 +79,6 @@ type MenuKey =
9979
| PreferencesSubTabKey
10080
| string;
10181

102-
// Utility function to safely create preferences sub-tab key
103-
function createPreferencesSubTabKey(
104-
subTab: string,
105-
): PreferencesSubTabKey | null {
106-
if (VALID_PREFERENCES_SUB_TYPES.includes(subTab as PreferencesSubTabType)) {
107-
const validSubTab = subTab as PreferencesSubTabType;
108-
return `preferences-${validSubTab}`;
109-
}
110-
return null;
111-
}
112-
11382
// give up on trying to load account info and redirect to landing page.
11483
// Do NOT make too short, since loading account info might takes ~10 seconds, e,g., due
11584
// to slow network or some backend failure that times and retires involving
@@ -138,49 +107,35 @@ export const AccountPage: React.FC = () => {
138107
const get_api_key = useTypedRedux("page", "get_api_key");
139108

140109
function handle_select(key: MenuKey): void {
141-
switch (key) {
142-
case "settings":
143-
// Handle settings overview page
144-
redux.getActions("account").setState({
145-
active_page: "index",
146-
active_sub_tab: undefined,
147-
});
148-
redux.getActions("account").push_state(`/settings/index`);
149-
return;
150-
case "billing":
110+
switchAccountPage(key, redux.getActions("account"), {
111+
onBilling: () => {
151112
redux.getActions("billing").update_customer();
152-
break;
153-
case "support":
154-
break;
155-
case "signout":
156-
return;
157-
case "profile":
158-
// Handle profile as standalone page
159-
redux.getActions("account").setState({
160-
active_page: "profile",
161-
active_sub_tab: undefined,
162-
});
163-
redux.getActions("account").push_state(`/profile`);
164-
return;
165-
}
113+
},
114+
onSignout: () => {
115+
// Signout does not navigate
116+
},
117+
});
118+
}
166119

167-
// Handle sub-tabs under preferences
168-
if (typeof key === "string" && key.startsWith("preferences-")) {
169-
const subTab = key.replace("preferences-", "");
170-
const subTabKey = createPreferencesSubTabKey(subTab);
171-
if (subTabKey) {
172-
redux.getActions("account").setState({
173-
active_sub_tab: subTabKey,
174-
active_page: "preferences",
175-
});
176-
// Update URL to settings/preferences/[sub-tab]
177-
redux.getActions("account").push_state(`/preferences/${subTab}`);
178-
}
179-
return;
120+
function getPreferencesComponent(tabId: string): React.ReactNode {
121+
switch (tabId) {
122+
case "preferences-appearance":
123+
return <AccountPreferencesAppearance />;
124+
case "preferences-editor":
125+
return <AccountPreferencesEditor />;
126+
case "preferences-keyboard":
127+
return <AccountPreferencesKeyboard />;
128+
case "preferences-ai":
129+
return <AccountPreferencesAI />;
130+
case "preferences-communication":
131+
return <AccountPreferencesCommunication />;
132+
case "preferences-keys":
133+
return <AccountPreferencesSecurity />;
134+
case "preferences-other":
135+
return <AccountPreferencesOther />;
136+
default:
137+
return null;
180138
}
181-
182-
redux.getActions("account").set_active_tab(key);
183-
redux.getActions("account").push_state(`/${key}`);
184139
}
185140

186141
function getTabs(): any[] {
@@ -215,97 +170,25 @@ export const AccountPage: React.FC = () => {
215170
{intl.formatMessage(labels.preferences)}
216171
</span>
217172
),
218-
children: [
219-
{
220-
key: "preferences-appearance",
221-
label: (
173+
children: PREFERENCES_SUB_TABS.map((tab) => {
174+
const tabLabel = intl.formatMessage(tab.label);
175+
return {
176+
key: tab.id,
177+
label: tab.useAIAvatar ? (
222178
<span>
223-
<Icon name={APPEARANCE_ICON_NAME} />{" "}
224-
{intl.formatMessage(labels.appearance)}
179+
<AIAvatar size={16} style={{ top: "-5px" }} /> {tabLabel}
225180
</span>
226-
),
227-
children: active_page === "preferences" &&
228-
active_sub_tab === "preferences-appearance" && (
229-
<AccountPreferencesAppearance />
230-
),
231-
},
232-
{
233-
key: "preferences-editor",
234-
label: (
235-
<span>
236-
<Icon name={EDITOR_ICON_NAME} />{" "}
237-
{intl.formatMessage(labels.editor)}
238-
</span>
239-
),
240-
children: active_page === "preferences" &&
241-
active_sub_tab === "preferences-editor" && (
242-
<AccountPreferencesEditor />
243-
),
244-
},
245-
{
246-
key: "preferences-keyboard",
247-
label: (
248-
<span>
249-
<Icon name={KEYBOARD_ICON_NAME} />{" "}
250-
{intl.formatMessage(labels.keyboard)}
251-
</span>
252-
),
253-
children: active_page === "preferences" &&
254-
active_sub_tab === "preferences-keyboard" && (
255-
<AccountPreferencesKeyboard />
256-
),
257-
},
258-
{
259-
key: "preferences-ai",
260-
label: (
261-
<span>
262-
<AIAvatar size={16} style={{ top: "-5px" }} />{" "}
263-
{intl.formatMessage(labels.ai)}
264-
</span>
265-
),
266-
children: active_page === "preferences" &&
267-
active_sub_tab === "preferences-ai" && <AccountPreferencesAI />,
268-
},
269-
{
270-
key: "preferences-communication",
271-
label: (
272-
<span>
273-
<Icon name={COMMUNICATION_ICON_NAME} />{" "}
274-
{intl.formatMessage(labels.communication)}
275-
</span>
276-
),
277-
children: active_page === "preferences" &&
278-
active_sub_tab === "preferences-communication" && (
279-
<AccountPreferencesCommunication />
280-
),
281-
},
282-
{
283-
key: "preferences-keys",
284-
label: (
285-
<span>
286-
<Icon name={KEYS_ICON_NAME} />{" "}
287-
{intl.formatMessage(labels.ssh_and_api_keys)}
288-
</span>
289-
),
290-
children: active_page === "preferences" &&
291-
active_sub_tab === "preferences-keys" && (
292-
<AccountPreferencesSecurity />
293-
),
294-
},
295-
{
296-
key: "preferences-other",
297-
label: (
181+
) : (
298182
<span>
299-
<Icon name={OTHER_ICON_NAME} />{" "}
300-
{intl.formatMessage(labels.other)}
183+
<Icon name={tab.icon as IconName} /> {tabLabel}
301184
</span>
302185
),
303-
children: active_page === "preferences" &&
304-
active_sub_tab === "preferences-other" && (
305-
<AccountPreferencesOther />
306-
),
307-
},
308-
],
186+
children:
187+
active_page === "preferences" && active_sub_tab === tab.id
188+
? getPreferencesComponent(tab.id)
189+
: null,
190+
};
191+
}),
309192
},
310193
];
311194
// adds a few conditional tabs
@@ -621,8 +504,12 @@ export const AccountPage: React.FC = () => {
621504
role="region"
622505
aria-label={
623506
active_page === "preferences" && active_sub_tab
624-
? `${titles[active_sub_tab]?.props?.children?.[1] || active_sub_tab} settings`
625-
: `${titles[active_page]?.props?.children?.[1] || active_page} settings`
507+
? `${
508+
titles[active_sub_tab]?.props?.children?.[1] || active_sub_tab
509+
} settings`
510+
: `${
511+
titles[active_page]?.props?.children?.[1] || active_page
512+
} settings`
626513
}
627514
style={{
628515
overflow: "auto",

src/packages/frontend/account/account-preferences-appearance.tsx

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ import {
2828
} from "./dark-mode";
2929
import { EditorSettingsColorScheme } from "./editor-settings/color-schemes";
3030
import { HotkeyDelayTest } from "./hotkey-delay-test";
31-
import { HotkeySelector } from "./hotkey-selector";
31+
import {
32+
DEFAULT_HOTKEY,
33+
DEFAULT_HOTKEY_DELAY_MS,
34+
HotkeySelector,
35+
} from "./hotkey-selector";
3236
import { I18NSelector, I18N_MESSAGE, I18N_TITLE } from "./i18n-selector";
3337
import { OtherSettings } from "./other-settings";
3438
import { TerminalSettings } from "./terminal-settings";
@@ -213,6 +217,9 @@ export function AccountPreferencesAppearance() {
213217
}
214218

215219
function renderUserInterfacePanel(): ReactElement {
220+
const quick_nav_hotkey =
221+
other_settings.get("quick_nav_hotkey") ?? DEFAULT_HOTKEY;
222+
216223
return (
217224
<Panel
218225
size="small"
@@ -251,17 +258,16 @@ export function AccountPreferencesAppearance() {
251258
}
252259
>
253260
<HotkeySelector
254-
value={other_settings.get("quick_nav_hotkey") ?? "shift+shift"}
261+
value={quick_nav_hotkey}
255262
onChange={(value) => on_change("quick_nav_hotkey", value)}
256263
style={{ width: 200 }}
257264
/>
258265
</LabeledRow>
259-
{(other_settings.get("quick_nav_hotkey") ?? "shift+shift") ===
260-
"shift+shift" && (
266+
{quick_nav_hotkey === "shift+shift" && (
261267
<LabeledRow
262268
label={
263269
<>
264-
<Icon name="clock" /> Hotkey Delay (milliseconds)
270+
<Icon name="clock" /> Hotkey Delay
265271
</>
266272
}
267273
>
@@ -277,7 +283,10 @@ export function AccountPreferencesAppearance() {
277283
min={100}
278284
max={800}
279285
step={100}
280-
value={other_settings.get("quick_nav_hotkey_delay") ?? 300}
286+
value={
287+
other_settings.get("quick_nav_hotkey_delay") ??
288+
DEFAULT_HOTKEY_DELAY_MS
289+
}
281290
onChange={(value) =>
282291
on_change("quick_nav_hotkey_delay", value)
283292
}
@@ -297,7 +306,9 @@ export function AccountPreferencesAppearance() {
297306
marginLeft: 12,
298307
}}
299308
>
300-
{other_settings.get("quick_nav_hotkey_delay") ?? 300}ms
309+
{other_settings.get("quick_nav_hotkey_delay") ??
310+
DEFAULT_HOTKEY_DELAY_MS}
311+
ms
301312
</span>
302313
</div>
303314
<div
@@ -309,7 +320,10 @@ export function AccountPreferencesAppearance() {
309320
}}
310321
>
311322
<HotkeyDelayTest
312-
delayMs={other_settings.get("quick_nav_hotkey_delay") ?? 300}
323+
delayMs={
324+
other_settings.get("quick_nav_hotkey_delay") ??
325+
DEFAULT_HOTKEY_DELAY_MS
326+
}
313327
/>
314328
</div>
315329
</div>

0 commit comments

Comments
 (0)