mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-13 08:38:43 +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('/');
|
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) {
|
export function getResourcePath(workspace: Workspace, path: string, joined: boolean, mod: string) {
|
||||||
const base = workspace.type === 'group'
|
const base = workspace.type === 'group'
|
||||||
? `/~landscape${workspace.group}`
|
? `/~landscape${workspace.group}`
|
||||||
|
@ -2,6 +2,14 @@ import f from 'lodash/fp';
|
|||||||
import { RemoteContentPolicy, LeapCategories, leapCategories } from "~/types/local-update";
|
import { RemoteContentPolicy, LeapCategories, leapCategories } from "~/types/local-update";
|
||||||
import { BaseState, createState } from '~/logic/state/base';
|
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> {
|
export interface SettingsState extends BaseState<SettingsState> {
|
||||||
display: {
|
display: {
|
||||||
@ -17,13 +25,7 @@ export interface SettingsState extends BaseState<SettingsState> {
|
|||||||
hideGroups: boolean;
|
hideGroups: boolean;
|
||||||
hideUtilities: boolean;
|
hideUtilities: boolean;
|
||||||
};
|
};
|
||||||
keyboard: {
|
keyboard: ShortcutMapping;
|
||||||
cycleForward: string;
|
|
||||||
cycleBack: string;
|
|
||||||
navForward: string;
|
|
||||||
navBack: string;
|
|
||||||
hideSidebar: string;
|
|
||||||
}
|
|
||||||
remoteContentPolicy: RemoteContentPolicy;
|
remoteContentPolicy: RemoteContentPolicy;
|
||||||
leap: {
|
leap: {
|
||||||
categories: LeapCategories[];
|
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 { PropFunc } from '~/types';
|
||||||
import DebugPane from './components/lib/Debug';
|
import DebugPane from './components/lib/Debug';
|
||||||
import useHarkState from '~/logic/state/hark';
|
import useHarkState from '~/logic/state/hark';
|
||||||
|
import ShortcutSettings from './components/lib/ShortcutSettings';
|
||||||
|
|
||||||
export const Skeleton = (props: { children: ReactNode }) => (
|
export const Skeleton = (props: { children: ReactNode }) => (
|
||||||
<Box height='100%' width='100%' px={[0, 3]} pb={[0, 3]} borderRadius={1}>
|
<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='Upload' text='Remote Storage' hash='s3' />
|
||||||
<SidebarItem icon='LeapArrow' text='Leap' hash='leap' />
|
<SidebarItem icon='LeapArrow' text='Leap' hash='leap' />
|
||||||
<SidebarItem icon='Node' text='CalmEngine' hash='calm' />
|
<SidebarItem icon='Node' text='CalmEngine' hash='calm' />
|
||||||
|
<SidebarItem icon='Keyboard' text='Shortcuts' hash='shortcuts' />
|
||||||
<SidebarItem
|
<SidebarItem
|
||||||
icon='Locked'
|
icon='Locked'
|
||||||
text='Devices + Security'
|
text='Devices + Security'
|
||||||
@ -131,6 +133,7 @@ export default function SettingsScreen(props: any) {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{hash === 'display' && <DisplayForm api={props.api} />}
|
{hash === 'display' && <DisplayForm api={props.api} />}
|
||||||
|
{hash === 'shortcuts' && <ShortcutSettings api={props.api} />}
|
||||||
{hash === 's3' && <S3Form api={props.api} />}
|
{hash === 's3' && <S3Form api={props.api} />}
|
||||||
{hash === 'leap' && <LeapSettings api={props.api} />}
|
{hash === 'leap' && <LeapSettings api={props.api} />}
|
||||||
{hash === 'calm' && <CalmPrefs api={props.api} />}
|
{hash === 'calm' && <CalmPrefs api={props.api} />}
|
||||||
|
Loading…
Reference in New Issue
Block a user