aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/web/components/dashboard/BulkBookmarksAction.tsx51
-rw-r--r--apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx25
-rw-r--r--apps/workers/crawlerWorker.ts8
-rw-r--r--packages/shared/queues.ts3
-rw-r--r--packages/trpc/routers/bookmarks.ts8
5 files changed, 89 insertions, 6 deletions
diff --git a/apps/web/components/dashboard/BulkBookmarksAction.tsx b/apps/web/components/dashboard/BulkBookmarksAction.tsx
index 0867fdd2..39e13940 100644
--- a/apps/web/components/dashboard/BulkBookmarksAction.tsx
+++ b/apps/web/components/dashboard/BulkBookmarksAction.tsx
@@ -8,10 +8,21 @@ import {
import ActionConfirmingDialog from "@/components/ui/action-confirming-dialog";
import { useToast } from "@/components/ui/use-toast";
import useBulkActionsStore from "@/lib/bulkActions";
-import { CheckCheck, Hash, Link, List, Pencil, Trash2, X } from "lucide-react";
+import {
+ CheckCheck,
+ FileDown,
+ Hash,
+ Link,
+ List,
+ Pencil,
+ RotateCw,
+ Trash2,
+ X,
+} from "lucide-react";
import {
useDeleteBookmark,
+ useRecrawlBookmark,
useUpdateBookmark,
} from "@hoarder/shared-react/hooks/bookmarks";
import { BookmarkTypes } from "@hoarder/shared/types/bookmarks";
@@ -63,11 +74,35 @@ export default function BulkBookmarksAction() {
onError,
});
+ const recrawlBookmarkMutator = useRecrawlBookmark({
+ onSuccess: () => {
+ setIsBulkEditEnabled(false);
+ },
+ onError,
+ });
+
interface UpdateBookmarkProps {
favourited?: boolean;
archived?: boolean;
}
+ const recrawlBookmarks = async (archiveFullPage: boolean) => {
+ const links = selectedBookmarks.filter(
+ (item) => item.content.type === BookmarkTypes.LINK,
+ );
+ await Promise.all(
+ links.map((item) =>
+ recrawlBookmarkMutator.mutateAsync({
+ bookmarkId: item.id,
+ archiveFullPage,
+ }),
+ ),
+ );
+ toast({
+ description: `${links.length} bookmarks will be ${archiveFullPage ? "re-crawled and archived!" : "refreshed!"}`,
+ });
+ };
+
function isClipboardAvailable() {
if (typeof window === "undefined") {
return false;
@@ -173,6 +208,20 @@ export default function BulkBookmarksAction() {
hidden: !isBulkEditEnabled,
},
{
+ name: "Download Full Page Archive",
+ icon: <FileDown size={18} />,
+ action: () => recrawlBookmarks(true),
+ isPending: recrawlBookmarkMutator.isPending,
+ hidden: !isBulkEditEnabled,
+ },
+ {
+ name: "Refresh",
+ icon: <RotateCw size={18} />,
+ action: () => recrawlBookmarks(false),
+ isPending: recrawlBookmarkMutator.isPending,
+ hidden: !isBulkEditEnabled,
+ },
+ {
name: "Delete",
icon: <Trash2 size={18} color="red" />,
action: () => setIsDeleteDialogOpen(true),
diff --git a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
index 4007090e..c09d2e50 100644
--- a/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
+++ b/apps/web/components/dashboard/bookmarks/BookmarkOptions.tsx
@@ -11,6 +11,7 @@ import {
import { useToast } from "@/components/ui/use-toast";
import { useClientConfig } from "@/lib/clientConfig";
import {
+ FileDown,
Link,
List,
ListX,
@@ -88,6 +89,15 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
onError,
});
+ const fullPageArchiveBookmarkMutator = useRecrawlBookmark({
+ onSuccess: () => {
+ toast({
+ description: "Full Page Archive creation has been triggered",
+ });
+ },
+ onError,
+ });
+
const removeFromListMutator = useRemoveBookmarkFromList({
onSuccess: () => {
toast({
@@ -152,6 +162,21 @@ export default function BookmarkOptions({ bookmark }: { bookmark: ZBookmark }) {
/>
<span>{bookmark.archived ? "Un-archive" : "Archive"}</span>
</DropdownMenuItem>
+
+ {bookmark.content.type === BookmarkTypes.LINK && (
+ <DropdownMenuItem
+ onClick={() => {
+ fullPageArchiveBookmarkMutator.mutate({
+ bookmarkId: bookmark.id,
+ archiveFullPage: true,
+ });
+ }}
+ >
+ <FileDown className="mr-2 size-4" />
+ <span>Download Full Page Archive</span>
+ </DropdownMenuItem>
+ )}
+
{bookmark.content.type === BookmarkTypes.LINK && (
<DropdownMenuItem
onClick={() => {
diff --git a/apps/workers/crawlerWorker.ts b/apps/workers/crawlerWorker.ts
index 49e9495d..246e9050 100644
--- a/apps/workers/crawlerWorker.ts
+++ b/apps/workers/crawlerWorker.ts
@@ -214,7 +214,7 @@ async function getBookmarkDetails(bookmarkId: string) {
});
if (!bookmark || !bookmark.link) {
- throw new Error("The bookmark either doesn't exist or not a link");
+ throw new Error("The bookmark either doesn't exist or is not a link");
}
return {
url: bookmark.link.url,
@@ -519,6 +519,7 @@ async function crawlAndParseUrl(
oldScreenshotAssetId: string | undefined,
oldImageAssetId: string | undefined,
oldFullPageArchiveAssetId: string | undefined,
+ archiveFullPage: boolean,
) {
const {
htmlContent,
@@ -578,7 +579,7 @@ async function crawlAndParseUrl(
]);
return async () => {
- if (serverConfig.crawler.fullPageArchive) {
+ if (serverConfig.crawler.fullPageArchive || archiveFullPage) {
const fullPageArchiveAssetId = await archiveWebpage(
htmlContent,
browserUrl,
@@ -615,7 +616,7 @@ async function runCrawler(job: DequeuedJob<ZCrawlLinkRequest>) {
return;
}
- const { bookmarkId } = request.data;
+ const { bookmarkId, archiveFullPage } = request.data;
const {
url,
userId,
@@ -654,6 +655,7 @@ async function runCrawler(job: DequeuedJob<ZCrawlLinkRequest>) {
oldScreenshotAssetId,
oldImageAssetId,
oldFullPageArchiveAssetId,
+ archiveFullPage,
);
}
diff --git a/packages/shared/queues.ts b/packages/shared/queues.ts
index 756f095d..cadeefd0 100644
--- a/packages/shared/queues.ts
+++ b/packages/shared/queues.ts
@@ -17,8 +17,9 @@ export function runQueueDBMigrations() {
export const zCrawlLinkRequestSchema = z.object({
bookmarkId: z.string(),
runInference: z.boolean().optional(),
+ archiveFullPage: z.boolean().optional().default(false),
});
-export type ZCrawlLinkRequest = z.infer<typeof zCrawlLinkRequestSchema>;
+export type ZCrawlLinkRequest = z.input<typeof zCrawlLinkRequestSchema>;
export const LinkCrawlerQueue = new SqliteQueue<ZCrawlLinkRequest>(
"link_crawler_queue",
diff --git a/packages/trpc/routers/bookmarks.ts b/packages/trpc/routers/bookmarks.ts
index 9990c6ed..9b23c88e 100644
--- a/packages/trpc/routers/bookmarks.ts
+++ b/packages/trpc/routers/bookmarks.ts
@@ -426,11 +426,17 @@ export const bookmarksAppRouter = router({
}
}),
recrawlBookmark: authedProcedure
- .input(z.object({ bookmarkId: z.string() }))
+ .input(
+ z.object({
+ bookmarkId: z.string(),
+ archiveFullPage: z.boolean().optional().default(false),
+ }),
+ )
.use(ensureBookmarkOwnership)
.mutation(async ({ input }) => {
await LinkCrawlerQueue.enqueue({
bookmarkId: input.bookmarkId,
+ archiveFullPage: input.archiveFullPage,
});
}),
getBookmark: authedProcedure