mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-11 04:48:00 +03:00
settings: customize shortcuts
This commit is contained in:
parent
880cde81ca
commit
6d403b67fd
@ -47,6 +47,17 @@ export function parentPath(path: string) {
|
||||
return _.dropRight(path.split('/'), 1).join('/');
|
||||
}
|
||||
|
||||
export const getChord = (e: KeyboardEvent) => {
|
||||
let chord = [e.key];
|
||||
if(e.metaKey) {
|
||||
chord.unshift('meta');
|
||||
}
|
||||
if(e.ctrlKey) {
|
||||
chord.unshift('ctrl');
|
||||
}
|
||||
return chord.join('+');
|
||||
}
|
||||
|
||||
export function getResourcePath(workspace: Workspace, path: string, joined: boolean, mod: string) {
|
||||
const base = workspace.type === 'group'
|
||||
? `/~landscape${workspace.group}`
|
||||
|
@ -2,6 +2,14 @@ import f from 'lodash/fp';
|
||||
import { RemoteContentPolicy, LeapCategories, leapCategories } from "~/types/local-update";
|
||||
import { BaseState, createState } from '~/logic/state/base';
|
||||
|
||||
export interface ShortcutMapping {
|
||||
cycleForward: string;
|
||||
cycleBack: string;
|
||||
navForward: string;
|
||||
navBack: string;
|
||||
hideSidebar: string;
|
||||
}
|
||||
|
||||
|
||||
export interface SettingsState extends BaseState<SettingsState> {
|
||||
display: {
|
||||
@ -17,13 +25,7 @@ export interface SettingsState extends BaseState<SettingsState> {
|
||||
hideGroups: boolean;
|
||||
hideUtilities: boolean;
|
||||
};
|
||||
keyboard: {
|
||||
cycleForward: string;
|
||||
cycleBack: string;
|
||||
navForward: string;
|
||||
navBack: string;
|
||||
hideSidebar: string;
|
||||
}
|
||||
keyboard: ShortcutMapping;
|
||||
remoteContentPolicy: RemoteContentPolicy;
|
||||
leap: {
|
||||
categories: LeapCategories[];
|
||||
|
@ -0,0 +1,117 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import _ from 'lodash';
|
||||
|
||||
import { Box, Col, Text } from '@tlon/indigo-react';
|
||||
import { Formik, Form, useField } from 'formik';
|
||||
|
||||
import GlobalApi from '~/logic/api/global';
|
||||
import { getChord } from '~/logic/lib/util';
|
||||
import useSettingsState, {
|
||||
selectSettingsState,
|
||||
ShortcutMapping,
|
||||
} from '~/logic/state/settings';
|
||||
import { AsyncButton } from '~/views/components/AsyncButton';
|
||||
import { BackButton } from './BackButton';
|
||||
|
||||
interface ShortcutSettingsProps {
|
||||
api: GlobalApi;
|
||||
}
|
||||
|
||||
const settingsSel = selectSettingsState(['keyboard']);
|
||||
|
||||
export function ChordInput(props: { id: string; label: string }) {
|
||||
const { id, label } = props;
|
||||
const [capturing, setCapturing] = useState(false);
|
||||
const [{ value }, , { setValue }] = useField(id);
|
||||
const onCapture = useCallback(() => {
|
||||
setCapturing(true);
|
||||
}, []);
|
||||
useEffect(() => {
|
||||
if (!capturing) {
|
||||
return;
|
||||
}
|
||||
function onKeydown(e: KeyboardEvent) {
|
||||
if (['Control', 'Shift', 'Meta'].includes(e.key)) {
|
||||
return;
|
||||
}
|
||||
const chord = getChord(e);
|
||||
setValue(chord);
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
setCapturing(false);
|
||||
}
|
||||
document.addEventListener('keydown', onKeydown);
|
||||
return () => {
|
||||
document.removeEventListener('keydown', onKeydown);
|
||||
};
|
||||
}, [capturing]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box p="1">
|
||||
<Text>{label}</Text>
|
||||
</Box>
|
||||
<Box
|
||||
border="1"
|
||||
borderColor="lightGray"
|
||||
borderRadius="2"
|
||||
onClick={onCapture}
|
||||
p="1"
|
||||
>
|
||||
<Text>{capturing ? 'Press' : value}</Text>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ShortcutSettings(props: ShortcutSettingsProps) {
|
||||
const { api } = props;
|
||||
|
||||
const { keyboard } = useSettingsState(settingsSel);
|
||||
|
||||
return (
|
||||
<Formik
|
||||
initialValues={keyboard}
|
||||
onSubmit={async (values: ShortcutMapping, actions) => {
|
||||
const promises = _.map(values, (value, key) => {
|
||||
return keyboard[key] !== value
|
||||
? api.settings.putEntry('keyboard', key, value)
|
||||
: Promise.resolve();
|
||||
});
|
||||
await Promise.all(promises);
|
||||
actions.setStatus({ success: null });
|
||||
}}
|
||||
>
|
||||
<Form>
|
||||
<BackButton />
|
||||
<Col p="5" pt="4" gapY="5">
|
||||
<Col gapY="1" mt="0">
|
||||
<Text color="black" fontSize={2} fontWeight="medium">
|
||||
Shortcuts
|
||||
</Text>
|
||||
<Text gray>Customize keyboard shortcuts for landscape</Text>
|
||||
</Col>
|
||||
<Box
|
||||
display="grid"
|
||||
gridTemplateColumns="1fr 100px"
|
||||
gridGap={3}
|
||||
maxWidth="500px"
|
||||
>
|
||||
<ChordInput id="navForward" label="Go forward in history" />
|
||||
<ChordInput id="navBack" label="Go backward in history" />
|
||||
<ChordInput
|
||||
id="cycleForward"
|
||||
label="Cycle forward through channel list"
|
||||
/>
|
||||
<ChordInput
|
||||
id="cycleBack"
|
||||
label="Cycle backward through channel list"
|
||||
/>
|
||||
<ChordInput id="hideSidebar" label="Show/hide group sidebar" />
|
||||
</Box>
|
||||
<AsyncButton primary width="fit-content">Save Changes</AsyncButton>
|
||||
</Col>
|
||||
</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
@ -15,6 +15,7 @@ import { SidebarItem as BaseSidebarItem } from '~/views/landscape/components/Sid
|
||||
import { PropFunc } from '~/types';
|
||||
import DebugPane from './components/lib/Debug';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import ShortcutSettings from './components/lib/ShortcutSettings';
|
||||
|
||||
export const Skeleton = (props: { children: ReactNode }) => (
|
||||
<Box height='100%' width='100%' px={[0, 3]} pb={[0, 3]} borderRadius={1}>
|
||||
@ -115,6 +116,7 @@ export default function SettingsScreen(props: any) {
|
||||
<SidebarItem icon='Upload' text='Remote Storage' hash='s3' />
|
||||
<SidebarItem icon='LeapArrow' text='Leap' hash='leap' />
|
||||
<SidebarItem icon='Node' text='CalmEngine' hash='calm' />
|
||||
<SidebarItem icon='Keyboard' text='Shortcuts' hash='shortcuts' />
|
||||
<SidebarItem
|
||||
icon='Locked'
|
||||
text='Devices + Security'
|
||||
@ -131,6 +133,7 @@ export default function SettingsScreen(props: any) {
|
||||
/>
|
||||
)}
|
||||
{hash === 'display' && <DisplayForm api={props.api} />}
|
||||
{hash === 'shortcuts' && <ShortcutSettings api={props.api} />}
|
||||
{hash === 's3' && <S3Form api={props.api} />}
|
||||
{hash === 'leap' && <LeapSettings api={props.api} />}
|
||||
{hash === 'calm' && <CalmPrefs api={props.api} />}
|
||||
|
Loading…
Reference in New Issue
Block a user