Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 64 additions & 38 deletions src/components/QuickSwitcherDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
Menu,
MenuItem,
Spinner,
Tooltip,
} from "@blueprintjs/core";
import React, {
useCallback,
Expand All @@ -22,6 +23,8 @@ import type {
} from "~/types/quickSwitcher";
import {
filterBookmarks,
getBookmarkRowPresentation,
getBookmarkTargetLabel,
getBookmarkTargetType,
getBookmarkTargetUid,
} from "~/utils/quickSwitcher";
Expand Down Expand Up @@ -151,18 +154,6 @@ const getModeFromTabId = ({
tabId: string | number;
}): QuickSwitcherDialogMode => (tabId === "manage" ? "manage" : "open");

const getBookmarkDisplayTitle = ({
bookmark,
}: {
bookmark: QuickSwitcherBookmark;
}): string => bookmark.alias || bookmark.title;

const getBookmarkSubtitle = ({
bookmark,
}: {
bookmark: QuickSwitcherBookmark;
}): string | undefined => (bookmark.alias ? bookmark.title : undefined);

const renderFooterActionContent = ({
label,
hotkeys = [],
Expand Down Expand Up @@ -804,11 +795,9 @@ const QuickSwitcherDialog = ({

const renderRowContent = ({
breadcrumbs = [],
subtitle,
title,
}: {
breadcrumbs?: string[];
subtitle?: string;
title: string;
}): React.ReactElement => (
<div
Expand All @@ -826,14 +815,46 @@ const QuickSwitcherDialog = ({
}
>
<span>{title}</span>
{subtitle ? (
<div className="bp3-text-muted truncate text-xs">{subtitle}</div>
) : null}
</div>
</div>
</div>
);

const renderOriginalTitleButton = ({
bookmark,
}: {
bookmark: QuickSwitcherBookmark;
}): React.ReactElement | null => {
const { originalTitle } = getBookmarkRowPresentation({ bookmark });
if (!originalTitle) {
return null;
}

const targetLabel = getBookmarkTargetLabel({ bookmark }).toLowerCase();
return (
<Tooltip
content={
<div className="max-w-sm">
<div className="mb-1 font-semibold">Original {targetLabel}</div>
<div className="break-words">{originalTitle}</div>
</div>
}
hoverOpenDelay={250}
>
<Button
aria-label={`Show original ${targetLabel}: ${originalTitle}`}
icon="eye-open"
minimal
onClick={(event): void => {
event.preventDefault();
event.stopPropagation();
}}
small
/>
</Tooltip>
);
};

const renderAliasEditor = ({
bookmark,
}: {
Expand Down Expand Up @@ -884,25 +905,29 @@ const QuickSwitcherDialog = ({

return (
<Menu className="rm-find-or-create-modal-body__list">
{visibleBookmarks.map((bookmark, index) => (
<MenuItem
aria-selected={selectedIndex === index}
key={bookmark.id}
onClick={(event): void => onBookmarkRowClick({ bookmark, event })}
onMouseEnter={(): void => setSelectedIndex(index)}
multiline
style={
selectedIndex === index
? SELECTED_MENU_ITEM_STYLE
: MENU_ITEM_STYLE
}
text={renderRowContent({
breadcrumbs: getBookmarkBreadcrumbs({ bookmark }),
subtitle: getBookmarkSubtitle({ bookmark }),
title: getBookmarkDisplayTitle({ bookmark }),
})}
/>
))}
{visibleBookmarks.map((bookmark, index) => {
const isSelected = selectedIndex === index;
const { title } = getBookmarkRowPresentation({ bookmark });
return (
<MenuItem
aria-selected={isSelected}
key={bookmark.id}
labelElement={
isSelected ? renderOriginalTitleButton({ bookmark }) : null
}
onClick={(event): void =>
onBookmarkRowClick({ bookmark, event })
}
onMouseEnter={(): void => setSelectedIndex(index)}
multiline
style={isSelected ? SELECTED_MENU_ITEM_STYLE : MENU_ITEM_STYLE}
text={renderRowContent({
breadcrumbs: getBookmarkBreadcrumbs({ bookmark }),
title,
})}
/>
);
})}
</Menu>
);
};
Expand Down Expand Up @@ -964,6 +989,7 @@ const QuickSwitcherDialog = ({
<Menu className="rm-find-or-create-modal-body__list">
{bookmarks.map((bookmark) => {
const isEditingAlias = editingAliasBookmarkId === bookmark.id;
const { title } = getBookmarkRowPresentation({ bookmark });
return (
<MenuItem
key={bookmark.id}
Expand Down Expand Up @@ -996,6 +1022,7 @@ const QuickSwitcherDialog = ({
</div>
) : (
<div className="flex items-center gap-1">
{renderOriginalTitleButton({ bookmark })}
<Button
aria-label={`Edit alias for ${bookmark.title}`}
icon="edit"
Expand Down Expand Up @@ -1034,8 +1061,7 @@ const QuickSwitcherDialog = ({
? renderAliasEditor({ bookmark })
: renderRowContent({
breadcrumbs: getBookmarkBreadcrumbs({ bookmark }),
subtitle: getBookmarkSubtitle({ bookmark }),
title: getBookmarkDisplayTitle({ bookmark }),
title,
})
}
style={MENU_ITEM_STYLE}
Expand Down
9 changes: 9 additions & 0 deletions src/utils/quickSwitcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,15 @@ export const getBookmarkTargetLabel = ({
}): string =>
getBookmarkTargetType({ bookmark }) === "block" ? "Block" : "Page";

export const getBookmarkRowPresentation = ({
bookmark,
}: {
bookmark: QuickSwitcherBookmark;
}): { originalTitle?: string; title: string } => ({
title: bookmark.alias || bookmark.title,
...(bookmark.alias ? { originalTitle: bookmark.title } : {}),
});

export const deriveBlockTitle = ({
text,
maxWords = 8,
Expand Down
25 changes: 25 additions & 0 deletions tests/quickSwitcher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
deriveBlockTitle,
extractBlockRefUid,
filterBookmarks,
getBookmarkRowPresentation,
getCommandPaletteCommandLabel,
normalizeCommandPaletteSettings,
parsePageUidFromUrl,
Expand Down Expand Up @@ -59,6 +60,30 @@ test("filters bookmarks by title or url", () => {
expect(filterBookmarks({ bookmarks, query: "graph/page" })).toHaveLength(2);
});

test("hides original titles only when a bookmark has an alias", () => {
const baseBookmark: QuickSwitcherBookmark = {
id: "block-1",
title: "Meeting Notes {{Today:SmartBlock:DevMeetingToday}}",
url: "https://roamresearch.com/#/app/graph/page/block-1",
targetType: "block",
pageUid: null,
blockUid: "block-1",
breadcrumbs: ["Sync", "Dev team"],
};

expect(getBookmarkRowPresentation({ bookmark: baseBookmark })).toEqual({
title: "Meeting Notes {{Today:SmartBlock:DevMeetingToday}}",
});
expect(
getBookmarkRowPresentation({
bookmark: { ...baseBookmark, alias: "Dev Team" },
}),
).toEqual({
title: "Dev Team",
originalTitle: "Meeting Notes {{Today:SmartBlock:DevMeetingToday}}",
});
});

test("parses and sanitizes stored bookmarks", () => {
const parsed = parseStoredBookmarks({
value: [
Expand Down
Loading