mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-23 20:54:50 +03:00
cmdk hotkeys work if input if focsed
This commit is contained in:
parent
70d61314a6
commit
0d21f17509
@ -61,7 +61,7 @@
|
|||||||
action.href.startsWith('http') || action.href.startsWith('mailto')
|
action.href.startsWith('http') || action.href.startsWith('mailto')
|
||||||
? open(action.href)
|
? open(action.href)
|
||||||
: goto(action.href);
|
: goto(action.href);
|
||||||
modal?.hide();
|
modal?.close();
|
||||||
} else if (Action.isGroup(action)) {
|
} else if (Action.isGroup(action)) {
|
||||||
selectedGroup.set(action);
|
selectedGroup.set(action);
|
||||||
}
|
}
|
||||||
@ -115,11 +115,9 @@
|
|||||||
if (command.hotkey) {
|
if (command.hotkey) {
|
||||||
unregisterCommandHotkeys.push(
|
unregisterCommandHotkeys.push(
|
||||||
tinykeys(window, {
|
tinykeys(window, {
|
||||||
[command.hotkey]: (event: KeyboardEvent) => {
|
[command.hotkey]: () => {
|
||||||
const target = event.target as HTMLElement;
|
if (!modal?.isOpen()) return;
|
||||||
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') return;
|
trigger(command.action);
|
||||||
// only trigger if the modal is visible
|
|
||||||
modal?.isOpen() && trigger(command.action);
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
@ -5,182 +5,184 @@ import type { SvelteComponent } from 'svelte';
|
|||||||
import { format, startOfISOWeek, startOfMonth, subDays, subMonths, subWeeks } from 'date-fns';
|
import { format, startOfISOWeek, startOfMonth, subDays, subMonths, subWeeks } from 'date-fns';
|
||||||
|
|
||||||
type ActionLink = {
|
type ActionLink = {
|
||||||
href: string;
|
href: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
interface Newable<ReturnType> {
|
interface Newable<ReturnType> {
|
||||||
new (...args: any[]): ReturnType;
|
new(...args: any[]): ReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Action = ActionLink | Group;
|
export type Action = ActionLink | Group;
|
||||||
|
|
||||||
export namespace Action {
|
export namespace Action {
|
||||||
export const isLink = (action: Action): action is ActionLink => 'href' in action;
|
export const isLink = (action: Action): action is ActionLink => 'href' in action;
|
||||||
export const isGroup = (action: Action): action is Group => 'commands' in action;
|
export const isGroup = (action: Action): action is Group => 'commands' in action;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type Command = {
|
export type Command = {
|
||||||
title: string;
|
title: string;
|
||||||
hotkey?: string;
|
hotkey?: string;
|
||||||
action: Action;
|
action: Action;
|
||||||
icon?: Newable<SvelteComponent>;
|
icon?: Newable<SvelteComponent>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Group = {
|
export type Group = {
|
||||||
title: string;
|
title: string;
|
||||||
description?: string;
|
description?: string;
|
||||||
commands: Command[];
|
commands: Command[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const goToProjectGroup = ({ projects, input }: { projects: Project[]; input: string }): Group => ({
|
const goToProjectGroup = ({ projects, input }: { projects: Project[]; input: string }): Group => ({
|
||||||
title: 'Go to project',
|
title: 'Go to project',
|
||||||
commands: projects
|
commands: projects
|
||||||
.map((project) => ({
|
.filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
|
||||||
title: project.title,
|
.map((project, i) => ({
|
||||||
action: {
|
title: project.title,
|
||||||
href: `/projects/${project.id}/`
|
hotkey: `${i + 1}`,
|
||||||
},
|
action: {
|
||||||
icon: IconProject
|
href: `/projects/${project.id}/`
|
||||||
}))
|
},
|
||||||
.filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
|
icon: IconProject
|
||||||
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
const actionsGroup = ({ project, input }: { project: Project; input: string }): Group => ({
|
const actionsGroup = ({ project, input }: { project: Project; input: string }): Group => ({
|
||||||
title: 'Actions',
|
title: 'Actions',
|
||||||
commands: [
|
commands: [
|
||||||
{
|
{
|
||||||
title: 'Commit',
|
title: 'Commit',
|
||||||
hotkey: 'Shift+C',
|
hotkey: 'Shift+C',
|
||||||
action: {
|
action: {
|
||||||
href: `/projects/${project.id}/commit/`
|
href: `/projects/${project.id}/commit/`
|
||||||
},
|
},
|
||||||
icon: GitCommitIcon
|
icon: GitCommitIcon
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Terminal',
|
title: 'Terminal',
|
||||||
hotkey: 'Shift+T',
|
hotkey: 'Shift+T',
|
||||||
action: {
|
action: {
|
||||||
href: `/projects/${project?.id}/terminal/`
|
href: `/projects/${project?.id}/terminal/`
|
||||||
},
|
},
|
||||||
icon: IconTerminal
|
icon: IconTerminal
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Replay History',
|
title: 'Replay History',
|
||||||
action: {
|
hotkey: 'Shift+R',
|
||||||
title: 'Replay working history',
|
action: {
|
||||||
commands: [
|
title: 'Replay working history',
|
||||||
{
|
commands: [
|
||||||
title: 'Eralier today',
|
{
|
||||||
icon: RewindIcon,
|
title: 'Eralier today',
|
||||||
hotkey: '1',
|
icon: RewindIcon,
|
||||||
action: {
|
hotkey: '1',
|
||||||
href: `/projects/${project.id}/player/${format(new Date(), 'yyyy-MM-dd')}/`
|
action: {
|
||||||
}
|
href: `/projects/${project.id}/player/${format(new Date(), 'yyyy-MM-dd')}/`
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
title: 'Yesterday',
|
{
|
||||||
icon: RewindIcon,
|
title: 'Yesterday',
|
||||||
hotkey: '2',
|
icon: RewindIcon,
|
||||||
action: {
|
hotkey: '2',
|
||||||
href: `/projects/${project.id}/player/${format(
|
action: {
|
||||||
subDays(new Date(), 1),
|
href: `/projects/${project.id}/player/${format(
|
||||||
'yyyy-MM-dd'
|
subDays(new Date(), 1),
|
||||||
)}/`
|
'yyyy-MM-dd'
|
||||||
}
|
)}/`
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
title: 'The day before yesterday',
|
{
|
||||||
icon: RewindIcon,
|
title: 'The day before yesterday',
|
||||||
hotkey: '3',
|
icon: RewindIcon,
|
||||||
action: {
|
hotkey: '3',
|
||||||
href: `/projects/${project.id}/player/${format(
|
action: {
|
||||||
subDays(new Date(), 2),
|
href: `/projects/${project.id}/player/${format(
|
||||||
'yyyy-MM-dd'
|
subDays(new Date(), 2),
|
||||||
)}/`
|
'yyyy-MM-dd'
|
||||||
}
|
)}/`
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
title: 'The beginning of last week',
|
{
|
||||||
icon: RewindIcon,
|
title: 'The beginning of last week',
|
||||||
hotkey: '4',
|
icon: RewindIcon,
|
||||||
action: {
|
hotkey: '4',
|
||||||
href: `/projects/${project.id}/player/${format(
|
action: {
|
||||||
startOfISOWeek(subWeeks(new Date(), 1)),
|
href: `/projects/${project.id}/player/${format(
|
||||||
'yyyy-MM-dd'
|
startOfISOWeek(subWeeks(new Date(), 1)),
|
||||||
)}/`
|
'yyyy-MM-dd'
|
||||||
}
|
)}/`
|
||||||
},
|
}
|
||||||
{
|
},
|
||||||
title: 'The beginning of last month',
|
{
|
||||||
icon: RewindIcon,
|
title: 'The beginning of last month',
|
||||||
hotkey: '5',
|
icon: RewindIcon,
|
||||||
action: {
|
hotkey: '5',
|
||||||
href: `/projects/${project.id}/player/${format(
|
action: {
|
||||||
startOfMonth(subMonths(new Date(), 1)),
|
href: `/projects/${project.id}/player/${format(
|
||||||
'yyyy-MM-dd'
|
startOfMonth(subMonths(new Date(), 1)),
|
||||||
)}/`
|
'yyyy-MM-dd'
|
||||||
}
|
)}/`
|
||||||
}
|
}
|
||||||
]
|
}
|
||||||
},
|
]
|
||||||
icon: RewindIcon
|
},
|
||||||
}
|
icon: RewindIcon
|
||||||
].filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
|
}
|
||||||
|
].filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
|
||||||
});
|
});
|
||||||
|
|
||||||
const fileGroup = ({
|
const fileGroup = ({
|
||||||
project,
|
project,
|
||||||
input
|
input
|
||||||
}: {
|
}: {
|
||||||
project: Project;
|
project: Project;
|
||||||
input: string;
|
input: string;
|
||||||
}): Group | Promise<Group> =>
|
}): Group | Promise<Group> =>
|
||||||
input.length === 0
|
input.length === 0
|
||||||
? {
|
? {
|
||||||
title: 'Files',
|
title: 'Files',
|
||||||
description: 'type part of a file name',
|
description: 'type part of a file name',
|
||||||
commands: []
|
commands: []
|
||||||
}
|
}
|
||||||
: matchFiles({ projectId: project.id, matchPattern: input }).then((files) => ({
|
: matchFiles({ projectId: project.id, matchPattern: input }).then((files) => ({
|
||||||
title: 'Files',
|
title: 'Files',
|
||||||
description: files.length === 0 ? `no files containing '${input}'` : '',
|
description: files.length === 0 ? `no files containing '${input}'` : '',
|
||||||
commands: files.map((file) => ({
|
commands: files.map((file) => ({
|
||||||
title: file,
|
title: file,
|
||||||
action: {
|
action: {
|
||||||
href: '/'
|
href: '/'
|
||||||
},
|
},
|
||||||
icon: IconFile
|
icon: IconFile
|
||||||
}))
|
}))
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const supportGroup = ({ input }: { input: string }): Group => ({
|
const supportGroup = ({ input }: { input: string }): Group => ({
|
||||||
title: 'Help & Support',
|
title: 'Help & Support',
|
||||||
commands: [
|
commands: [
|
||||||
{
|
{
|
||||||
title: 'Documentation',
|
title: 'Documentation',
|
||||||
action: {
|
action: {
|
||||||
href: `https://docs.gitbutler.com`
|
href: `https://docs.gitbutler.com`
|
||||||
},
|
},
|
||||||
icon: FileIcon
|
icon: FileIcon
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'Discord',
|
title: 'Discord',
|
||||||
action: {
|
action: {
|
||||||
href: `https://discord.gg/MmFkmaJ42D`
|
href: `https://discord.gg/MmFkmaJ42D`
|
||||||
},
|
},
|
||||||
icon: GitCommitIcon
|
icon: GitCommitIcon
|
||||||
}
|
}
|
||||||
].filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
|
].filter(({ title }) => input.length === 0 || title.toLowerCase().includes(input.toLowerCase()))
|
||||||
});
|
});
|
||||||
|
|
||||||
export default (params: { projects: Project[]; project?: Project; input: string }) => {
|
export default (params: { projects: Project[]; project?: Project; input: string }) => {
|
||||||
const { projects, input, project } = params;
|
const { projects, input, project } = params;
|
||||||
const groups = [];
|
const groups = [];
|
||||||
|
|
||||||
!project && groups.push(goToProjectGroup({ projects, input }));
|
!project && groups.push(goToProjectGroup({ projects, input }));
|
||||||
project && groups.push(actionsGroup({ project, input }));
|
project && groups.push(actionsGroup({ project, input }));
|
||||||
project && groups.push(fileGroup({ project, input }));
|
project && groups.push(fileGroup({ project, input }));
|
||||||
groups.push(supportGroup({ input }));
|
groups.push(supportGroup({ input }));
|
||||||
|
|
||||||
return groups;
|
return groups;
|
||||||
};
|
};
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
};
|
};
|
||||||
export const isOpen = () => open;
|
export const isOpen = () => open;
|
||||||
|
|
||||||
const close = () => {
|
export const close = () => {
|
||||||
open = false;
|
open = false;
|
||||||
dialog.close();
|
dialog.close();
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user