97 lines
2.9 KiB
TypeScript
97 lines
2.9 KiB
TypeScript
import { useMemo } from "react";
|
|
import { Text, View } from "react-native";
|
|
import { StyleSheet } from "react-native-unistyles";
|
|
import { getIsDesktop } from "@/constants/layout";
|
|
import { AdaptiveModalSheet } from "@/components/adaptive-modal-sheet";
|
|
import { Shortcut } from "@/components/ui/shortcut";
|
|
import { useKeyboardShortcutsStore } from "@/stores/keyboard-shortcuts-store";
|
|
import { getShortcutOs } from "@/utils/shortcut-platform";
|
|
import { buildKeyboardShortcutHelpSections } from "@/keyboard/keyboard-shortcuts";
|
|
|
|
export function KeyboardShortcutsDialog() {
|
|
const open = useKeyboardShortcutsStore((s) => s.shortcutsDialogOpen);
|
|
const setOpen = useKeyboardShortcutsStore((s) => s.setShortcutsDialogOpen);
|
|
|
|
const isMac = getShortcutOs() === "mac";
|
|
const isDesktopApp = getIsDesktop();
|
|
const sections = useMemo(
|
|
() => buildKeyboardShortcutHelpSections({ isMac, isDesktop: isDesktopApp }),
|
|
[isDesktopApp, isMac]
|
|
);
|
|
|
|
return (
|
|
<AdaptiveModalSheet
|
|
title="Keyboard shortcuts"
|
|
visible={open}
|
|
onClose={() => setOpen(false)}
|
|
testID="keyboard-shortcuts-dialog"
|
|
snapPoints={["70%", "92%"]}
|
|
>
|
|
<View testID="keyboard-shortcuts-dialog-content" style={styles.content}>
|
|
{sections.map((section) => (
|
|
<View key={section.title} style={styles.section}>
|
|
<Text style={styles.sectionTitle}>{section.title}</Text>
|
|
<View style={styles.rows}>
|
|
{section.rows.map((row) => (
|
|
<View key={row.id} style={styles.row}>
|
|
<View style={styles.rowText}>
|
|
<Text style={styles.rowLabel}>{row.label}</Text>
|
|
{row.note ? <Text style={styles.rowNote}>{row.note}</Text> : null}
|
|
</View>
|
|
<Shortcut keys={row.keys} style={styles.rowShortcut} />
|
|
</View>
|
|
))}
|
|
</View>
|
|
</View>
|
|
))}
|
|
</View>
|
|
</AdaptiveModalSheet>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create((theme) => ({
|
|
content: {
|
|
gap: theme.spacing[4],
|
|
},
|
|
section: {
|
|
gap: theme.spacing[2],
|
|
},
|
|
sectionTitle: {
|
|
fontSize: theme.fontSize.xs,
|
|
fontWeight: theme.fontWeight.medium,
|
|
color: theme.colors.foregroundMuted,
|
|
},
|
|
rows: {
|
|
borderWidth: theme.borderWidth[1],
|
|
borderColor: theme.colors.surface2,
|
|
borderRadius: theme.borderRadius.lg,
|
|
overflow: "hidden",
|
|
},
|
|
row: {
|
|
flexDirection: "row",
|
|
alignItems: "center",
|
|
justifyContent: "space-between",
|
|
gap: theme.spacing[3],
|
|
paddingHorizontal: theme.spacing[4],
|
|
paddingVertical: theme.spacing[3],
|
|
borderBottomWidth: theme.borderWidth[1],
|
|
borderBottomColor: theme.colors.surface2,
|
|
},
|
|
rowText: {
|
|
flex: 1,
|
|
minWidth: 0,
|
|
},
|
|
rowLabel: {
|
|
fontSize: theme.fontSize.sm,
|
|
color: theme.colors.foreground,
|
|
},
|
|
rowNote: {
|
|
marginTop: 2,
|
|
fontSize: theme.fontSize.xs,
|
|
color: theme.colors.foregroundMuted,
|
|
},
|
|
rowShortcut: {
|
|
alignSelf: "flex-start",
|
|
},
|
|
}));
|