implement bookmark link copy

This commit is contained in:
2025-05-21 13:47:33 +01:00
parent cfcd510193
commit 2d03f1f31b
3 changed files with 51 additions and 16 deletions

View File

@@ -26,6 +26,7 @@ function ActionBar({
function BookmarkListActionBar({ className }: { className?: string }) { function BookmarkListActionBar({ className }: { className?: string }) {
const setActiveDialog = useBookmarkPageStore((state) => state.setActiveDialog) const setActiveDialog = useBookmarkPageStore((state) => state.setActiveDialog)
const statusMessage = useBookmarkPageStore((state) => state.statusMessage)
useMnemonics( useMnemonics(
{ {
@@ -40,13 +41,19 @@ function BookmarkListActionBar({ className }: { className?: string }) {
return ( return (
<ActionBar className={className}> <ActionBar className={className}>
<Button onClick={addBookmark}> {statusMessage ? (
<span className="underline">A</span>DD <p>{statusMessage}</p>
</Button> ) : (
<Button> <>
<span className="underline">S</span>EARCH <Button onClick={addBookmark}>
</Button> <span className="underline">A</span>DD
<LogOutButton /> </Button>
<Button>
<span className="underline">S</span>EARCH
</Button>
<LogOutButton />
</>
)}
</ActionBar> </ActionBar>
) )
} }

View File

@@ -15,6 +15,7 @@ enum BookmarkListItemAction {
Open = "Open", Open = "Open",
Edit = "Edit", Edit = "Edit",
Delete = "Delete", Delete = "Delete",
CopyLink = "CopyLink",
} }
type SelectionChangeCallback = (bookmark: Bookmark) => void type SelectionChangeCallback = (bookmark: Bookmark) => void
@@ -178,12 +179,24 @@ const _BookmarkList = memo(({ className }: { className?: string }) => {
d: deleteItem, d: deleteItem,
Enter: openItem, Enter: openItem,
c: (event) => {
if (event.ctrlKey || event.metaKey) {
event.preventDefault()
copyBookmarkLink()
}
},
}, },
{ {
ignore: useCallback(() => useBookmarkPageStore.getState().activeDialog !== ActiveDialog.None, []), ignore: useCallback(() => useBookmarkPageStore.getState().activeDialog !== ActiveDialog.None, []),
}, },
) )
async function copyBookmarkLink() {
const { bookmarks, selectedIndex, onItemAction } = store.getState()
onItemAction(bookmarks[selectedIndex], BookmarkListItemAction.CopyLink)
}
function openItem() { function openItem() {
const { bookmarks, selectedIndex, onItemAction } = store.getState() const { bookmarks, selectedIndex, onItemAction } = store.getState()
expandItem() expandItem()
@@ -261,6 +274,10 @@ const BookmarkListItem = memo(
onItemAction(bookmark, BookmarkListItemAction.Delete) onItemAction(bookmark, BookmarkListItemAction.Delete)
} }
function copyItemLink() {
onItemAction(bookmark, BookmarkListItemAction.CopyLink)
}
return ( return (
<li <li
className={clsx("group flex flex-row justify-start py-2", { className={clsx("group flex flex-row justify-start py-2", {
@@ -296,7 +313,7 @@ const BookmarkListItem = memo(
<BookmarkTagList bookmark={bookmark} /> <BookmarkTagList bookmark={bookmark} />
<div className="flex flex-col space-y-1 md:flex-row md:space-y-0 md:space-x-2 items-end justify-between pt-2"> <div className="flex flex-col space-y-1 md:flex-row md:space-y-0 md:space-x-2 items-end justify-between pt-2">
<div className="flex space-x-2"> <div className="flex space-x-2">
<Button variant="light" className="text-sm"> <Button variant="light" className="text-sm" onClick={copyItemLink}>
<span>COPY LINK</span> <span>COPY LINK</span>
</Button> </Button>
<Button variant="light" className="text-sm"> <Button variant="light" className="text-sm">

View File

@@ -14,29 +14,27 @@ enum ActiveDialog {
DeleteBookmark = "DeleteBookmark", DeleteBookmark = "DeleteBookmark",
} }
const STATUS_MESSAGE_DURATION_MS = 2000
interface BookmarkPageState { interface BookmarkPageState {
bookmarkToBeDeleted: Bookmark | null bookmarkToBeDeleted: Bookmark | null
layoutMode: LayoutMode layoutMode: LayoutMode
activeDialog: ActiveDialog activeDialog: ActiveDialog
statusMessage: string
handleBookmarkListItemAction: (bookmark: Bookmark, action: BookmarkListItemAction) => void handleBookmarkListItemAction: (bookmark: Bookmark, action: BookmarkListItemAction) => void
setActiveDialog: (dialog: ActiveDialog) => void setActiveDialog: (dialog: ActiveDialog) => void
setLayoutMode: (mode: LayoutMode) => void setLayoutMode: (mode: LayoutMode) => void
showStatus: (message: string) => void
} }
const useBookmarkPageStore = create<BookmarkPageState>()((set, get) => ({ const useBookmarkPageStore = create<BookmarkPageState>()((set, get) => ({
bookmarkCount: 0,
bookmarks: [],
selectedBookmarkId: "",
selectedBookmarkIndex: 0,
isBookmarkItemExpanded: false,
isBookmarkPreviewOpened: false,
bookmarkToBeDeleted: null, bookmarkToBeDeleted: null,
layoutMode: LayoutMode.Popup, layoutMode: LayoutMode.Popup,
activeDialog: ActiveDialog.None, activeDialog: ActiveDialog.None,
actionBarHeight: 0, statusMessage: "",
handleBookmarkListItemAction(bookmark: Bookmark, action: BookmarkListItemAction) { async handleBookmarkListItemAction(bookmark: Bookmark, action: BookmarkListItemAction) {
switch (action) { switch (action) {
case BookmarkListItemAction.Open: case BookmarkListItemAction.Open:
router.navigate({ to: `/bookmarks/${bookmark.id}` }) router.navigate({ to: `/bookmarks/${bookmark.id}` })
@@ -45,6 +43,12 @@ const useBookmarkPageStore = create<BookmarkPageState>()((set, get) => ({
case BookmarkListItemAction.Delete: case BookmarkListItemAction.Delete:
set({ bookmarkToBeDeleted: bookmark, activeDialog: ActiveDialog.DeleteBookmark }) set({ bookmarkToBeDeleted: bookmark, activeDialog: ActiveDialog.DeleteBookmark })
break break
case BookmarkListItemAction.CopyLink:
await navigator.clipboard.writeText(bookmark.url)
get().showStatus("Link copied to clipboard!")
break
default: default:
break break
} }
@@ -57,6 +61,13 @@ const useBookmarkPageStore = create<BookmarkPageState>()((set, get) => ({
setLayoutMode(mode: LayoutMode) { setLayoutMode(mode: LayoutMode) {
set({ layoutMode: mode }) set({ layoutMode: mode })
}, },
showStatus(message: string) {
set({ statusMessage: message })
setTimeout(() => {
set({ statusMessage: "" })
}, STATUS_MESSAGE_DURATION_MS)
},
})) }))
export { LayoutMode, ActiveDialog, useBookmarkPageStore } export { LayoutMode, ActiveDialog, useBookmarkPageStore }