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