mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-04-25 01:58:39 +02:00
Show full paths in command palette switcher
https://feedback.yaak.app/p/command-palette-search-should-include-parent-folder-names
This commit is contained in:
@@ -30,7 +30,10 @@ import { deleteModelWithConfirm } from '../lib/deleteModelWithConfirm';
|
|||||||
import { showDialog } from '../lib/dialog';
|
import { showDialog } from '../lib/dialog';
|
||||||
import { editEnvironment } from '../lib/editEnvironment';
|
import { editEnvironment } from '../lib/editEnvironment';
|
||||||
import { renameModelWithPrompt } from '../lib/renameModelWithPrompt';
|
import { renameModelWithPrompt } from '../lib/renameModelWithPrompt';
|
||||||
import { resolvedModelNameWithFolders } from '../lib/resolvedModelName';
|
import {
|
||||||
|
resolvedModelNameWithFolders,
|
||||||
|
resolvedModelNameWithFoldersArray,
|
||||||
|
} from '../lib/resolvedModelName';
|
||||||
import { router } from '../lib/router';
|
import { router } from '../lib/router';
|
||||||
import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams';
|
import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams';
|
||||||
import { CookieDialog } from './CookieDialog';
|
import { CookieDialog } from './CookieDialog';
|
||||||
@@ -40,7 +43,6 @@ import { HotKey } from './core/HotKey';
|
|||||||
import { HttpMethodTag } from './core/HttpMethodTag';
|
import { HttpMethodTag } from './core/HttpMethodTag';
|
||||||
import { Icon } from './core/Icon';
|
import { Icon } from './core/Icon';
|
||||||
import { PlainInput } from './core/PlainInput';
|
import { PlainInput } from './core/PlainInput';
|
||||||
import { HStack } from './core/Stacks';
|
|
||||||
|
|
||||||
interface CommandPaletteGroup {
|
interface CommandPaletteGroup {
|
||||||
key: string;
|
key: string;
|
||||||
@@ -275,10 +277,17 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
|
|||||||
key: `switch-request-${r.id}`,
|
key: `switch-request-${r.id}`,
|
||||||
searchText: resolvedModelNameWithFolders(r),
|
searchText: resolvedModelNameWithFolders(r),
|
||||||
label: (
|
label: (
|
||||||
<HStack space={2}>
|
<div className="flex items-center gap-x-0.5">
|
||||||
<HttpMethodTag short className="text-xs" request={r} />
|
<HttpMethodTag short className="text-xs mr-2" request={r} />
|
||||||
<div className="truncate">{resolvedModelNameWithFolders(r)}</div>
|
{resolvedModelNameWithFoldersArray(r).map((name, i, all) => (
|
||||||
</HStack>
|
<>
|
||||||
|
{i !== 0 && (
|
||||||
|
<Icon icon="chevron_right" className="opacity-80"/>
|
||||||
|
)}
|
||||||
|
<div className={classNames(i < all.length - 1 && 'truncate')}>{name}</div>
|
||||||
|
</>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
),
|
),
|
||||||
onSelect: async () => {
|
onSelect: async () => {
|
||||||
await router.navigate({
|
await router.navigate({
|
||||||
@@ -400,7 +409,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-[400px] grid grid-rows-[auto_minmax(0,1fr)] overflow-hidden py-2">
|
<div className="h-full w-[min(700px,80vw)] grid grid-rows-[auto_minmax(0,1fr)] overflow-hidden py-2">
|
||||||
<div className="px-2 w-full">
|
<div className="px-2 w-full">
|
||||||
<PlainInput
|
<PlainInput
|
||||||
autoFocus
|
autoFocus
|
||||||
|
|||||||
@@ -52,7 +52,13 @@ export function Overlay({
|
|||||||
{open && (
|
{open && (
|
||||||
<FocusTrap
|
<FocusTrap
|
||||||
focusTrapOptions={{
|
focusTrapOptions={{
|
||||||
allowOutsideClick: true, // So we can still click toasts and things
|
// Allow outside click so we can click things like toasts
|
||||||
|
allowOutsideClick: true,
|
||||||
|
delayInitialFocus: true,
|
||||||
|
checkCanFocusTrap: async () => {
|
||||||
|
// Not sure why delayInitialFocus: true doesn't help, but having this no-op promise
|
||||||
|
// seems to be required to make things work.
|
||||||
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<m.div
|
<m.div
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
} from 'react';
|
} from 'react';
|
||||||
import { useRandomKey } from '../../hooks/useRandomKey';
|
import { useRandomKey } from '../../hooks/useRandomKey';
|
||||||
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
|
import { useStateWithDeps } from '../../hooks/useStateWithDeps';
|
||||||
|
import { generateId } from '../../lib/generateId';
|
||||||
import { IconButton } from './IconButton';
|
import { IconButton } from './IconButton';
|
||||||
import type { InputProps } from './Input';
|
import type { InputProps } from './Input';
|
||||||
import { Label } from './Label';
|
import { Label } from './Label';
|
||||||
@@ -99,7 +100,7 @@ export const PlainInput = forwardRef<{ focus: () => void }, PlainInputProps>(fun
|
|||||||
}
|
}
|
||||||
}, [regenerateFocusedUpdateKey, defaultValue]);
|
}, [regenerateFocusedUpdateKey, defaultValue]);
|
||||||
|
|
||||||
const id = `input-${name}`;
|
const id = useRef(`input-${generateId()}`);
|
||||||
const commonClassName = classNames(
|
const commonClassName = classNames(
|
||||||
className,
|
className,
|
||||||
'!bg-transparent min-w-0 w-full focus:outline-none placeholder:text-placeholder',
|
'!bg-transparent min-w-0 w-full focus:outline-none placeholder:text-placeholder',
|
||||||
@@ -134,7 +135,7 @@ export const PlainInput = forwardRef<{ focus: () => void }, PlainInputProps>(fun
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Label
|
<Label
|
||||||
htmlFor={id}
|
htmlFor={id.current}
|
||||||
className={labelClassName}
|
className={labelClassName}
|
||||||
visuallyHidden={hideLabel}
|
visuallyHidden={hideLabel}
|
||||||
required={required}
|
required={required}
|
||||||
@@ -177,10 +178,11 @@ export const PlainInput = forwardRef<{ focus: () => void }, PlainInputProps>(fun
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id={id}
|
id={id.current}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
key={forceUpdateKey}
|
key={forceUpdateKey}
|
||||||
type={type === 'password' && !obscured ? 'text' : type}
|
type={type === 'password' && !obscured ? 'text' : type}
|
||||||
|
name={name}
|
||||||
defaultValue={defaultValue ?? undefined}
|
defaultValue={defaultValue ?? undefined}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCapitalize="off"
|
autoCapitalize="off"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { AnyModel} from '@yaakapp-internal/models';
|
import type { AnyModel } from '@yaakapp-internal/models';
|
||||||
import { foldersAtom } from '@yaakapp-internal/models';
|
import { foldersAtom } from '@yaakapp-internal/models';
|
||||||
import { jotaiStore } from './jotai';
|
import { jotaiStore } from './jotai';
|
||||||
|
|
||||||
@@ -39,7 +39,11 @@ export function resolvedModelName(r: AnyModel | null): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function resolvedModelNameWithFolders(model: AnyModel | null): string {
|
export function resolvedModelNameWithFolders(model: AnyModel | null): string {
|
||||||
if (model == null) return '';
|
return resolvedModelNameWithFoldersArray(model).join(' / ');
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolvedModelNameWithFoldersArray(model: AnyModel | null): string[] {
|
||||||
|
if (model == null) return [];
|
||||||
const folders = jotaiStore.get(foldersAtom) ?? [];
|
const folders = jotaiStore.get(foldersAtom) ?? [];
|
||||||
|
|
||||||
const getParents = (m: AnyModel, names: string[]) => {
|
const getParents = (m: AnyModel, names: string[]) => {
|
||||||
@@ -47,11 +51,11 @@ export function resolvedModelNameWithFolders(model: AnyModel | null): string {
|
|||||||
if ('folderId' in m) {
|
if ('folderId' in m) {
|
||||||
const parent = folders.find((f) => f.id === m.folderId);
|
const parent = folders.find((f) => f.id === m.folderId);
|
||||||
if (parent) {
|
if (parent) {
|
||||||
names = [resolvedModelName(parent), ...names];
|
names = [...resolvedModelNameWithFoldersArray(parent), ...names];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
};
|
};
|
||||||
|
|
||||||
return getParents(model, []).join(' / ');
|
return getParents(model, []);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user