aboutsummaryrefslogtreecommitdiffstats
path: root/packages/web/app/dashboard
diff options
context:
space:
mode:
authorMohamedBassem <me@mbassem.com>2024-02-22 17:33:12 +0000
committerMohamedBassem <me@mbassem.com>2024-02-22 17:34:37 +0000
commit2ac3c39a9c80305bb959d88561e78f65a1cd1be1 (patch)
treeabdf860a648d691377914702f4d5c804e02fd341 /packages/web/app/dashboard
parent61a1b2f40cf69d8c2055becf9119881cafa9da81 (diff)
downloadkarakeep-2ac3c39a9c80305bb959d88561e78f65a1cd1be1.tar.zst
feature: Adding some loading card while the link is getting crawled
Diffstat (limited to 'packages/web/app/dashboard')
-rw-r--r--packages/web/app/dashboard/bookmarks/components/AddLink.tsx16
-rw-r--r--packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx7
-rw-r--r--packages/web/app/dashboard/bookmarks/components/LinkCard.tsx85
3 files changed, 71 insertions, 37 deletions
diff --git a/packages/web/app/dashboard/bookmarks/components/AddLink.tsx b/packages/web/app/dashboard/bookmarks/components/AddLink.tsx
index 7663543f..242a52a5 100644
--- a/packages/web/app/dashboard/bookmarks/components/AddLink.tsx
+++ b/packages/web/app/dashboard/bookmarks/components/AddLink.tsx
@@ -9,32 +9,24 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { toast } from "@/components/ui/use-toast";
import { api } from "@/lib/trpc";
import { ActionButton } from "@/components/ui/action-button";
-import { useLoadingCard } from "@/lib/hooks/use-loading-card";
const formSchema = z.object({
url: z.string().url({ message: "The link must be a valid URL" }),
});
export default function AddLink() {
- const { setLoading } = useLoadingCard();
+ const form = useForm<z.infer<typeof formSchema>>({
+ resolver: zodResolver(formSchema),
+ });
+
const invalidateBookmarksCache = api.useUtils().bookmarks.invalidate;
const bookmarkLinkMutator = api.bookmarks.bookmarkLink.useMutation({
- onMutate: () => {
- setLoading(true);
- },
onSuccess: () => {
invalidateBookmarksCache();
},
onError: () => {
toast({ description: "Something went wrong", variant: "destructive" });
},
- onSettled: () => {
- setLoading(false);
- },
- });
-
- const form = useForm<z.infer<typeof formSchema>>({
- resolver: zodResolver(formSchema),
});
const onError: SubmitErrorHandler<z.infer<typeof formSchema>> = (errors) => {
diff --git a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx
index c1c8f3e0..dc98472e 100644
--- a/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx
+++ b/packages/web/app/dashboard/bookmarks/components/BookmarksGrid.tsx
@@ -1,7 +1,5 @@
"use client";
-import { useLoadingCard } from "@/lib/hooks/use-loading-card";
-import BookmarkCardSkeleton from "./BookmarkCardSkeleton";
import LinkCard from "./LinkCard";
import { ZBookmark, ZGetBookmarksRequest } from "@/lib/types/api/bookmarks";
import { api } from "@/lib/trpc";
@@ -13,8 +11,6 @@ function renderBookmark(bookmark: ZBookmark) {
}
}
-export const dynamic = "force-dynamic";
-
export default function BookmarksGrid({
query,
bookmarks: initialBookmarks,
@@ -24,12 +20,9 @@ export default function BookmarksGrid({
}) {
const { data } = api.bookmarks.getBookmarks.useQuery(query, {
initialData: { bookmarks: initialBookmarks },
- staleTime: Infinity,
});
- const { loading } = useLoadingCard();
return (
<div className="container grid grid-cols-1 gap-4 sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
- {loading && <BookmarkCardSkeleton />}
{data.bookmarks.map((b) => renderBookmark(b))}
</div>
);
diff --git a/packages/web/app/dashboard/bookmarks/components/LinkCard.tsx b/packages/web/app/dashboard/bookmarks/components/LinkCard.tsx
index 7413c2fe..35696134 100644
--- a/packages/web/app/dashboard/bookmarks/components/LinkCard.tsx
+++ b/packages/web/app/dashboard/bookmarks/components/LinkCard.tsx
@@ -1,3 +1,5 @@
+"use client";
+
import { Badge } from "@/components/ui/badge";
import {
ImageCard,
@@ -10,9 +12,71 @@ import {
import { ZBookmark } from "@/lib/types/api/bookmarks";
import Link from "next/link";
import BookmarkOptions from "./BookmarkOptions";
+import { api } from "@/lib/trpc";
+import { Skeleton } from "@/components/ui/skeleton";
+
+function isStillCrawling(bookmark: ZBookmark) {
+ return (
+ !bookmark.content.crawledAt && Date.now() - bookmark.createdAt < 30 * 1000
+ );
+}
-export default function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
+function TagList(bookmark: ZBookmark, stillCrawling: boolean) {
+ if (stillCrawling) {
+ return (
+ <ImageCardBody className="space-y-2">
+ <Skeleton className="h-4 w-full" />
+ <Skeleton className="h-4 w-full" />
+ <Skeleton className="h-4 w-full" />
+ </ImageCardBody>
+ );
+ }
+ return (
+ <ImageCardBody className="flex h-full flex-wrap space-x-1 overflow-hidden">
+ {bookmark.tags.map((t) => (
+ <Link
+ className="flex h-full flex-col justify-end"
+ key={t.id}
+ href={`/dashboard/tags/${t.name}`}
+ >
+ <Badge
+ variant="default"
+ className="text-nowrap bg-gray-300 text-gray-500 hover:text-white"
+ >
+ #{t.name}
+ </Badge>
+ </Link>
+ ))}
+ </ImageCardBody>
+ );
+}
+
+export default function LinkCard({
+ bookmark: initialData,
+}: {
+ bookmark: ZBookmark;
+}) {
+ const { data: bookmark } = api.bookmarks.getBookmark.useQuery(
+ {
+ id: initialData.id,
+ },
+ {
+ initialData,
+ refetchInterval: (query) => {
+ const data = query.state.data;
+ if (!data) {
+ return false;
+ }
+ // If the link is not crawled and
+ if (isStillCrawling(data)) {
+ return 1000;
+ }
+ return false;
+ },
+ },
+ );
const link = bookmark.content;
+ const isCrawling = isStillCrawling(bookmark);
const parsedUrl = new URL(link.url);
// A dummy white pixel for when there's no image.
@@ -28,7 +92,7 @@ export default function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
}
>
<Link href={link.url}>
- <ImageCardBanner src={image} />
+ <ImageCardBanner src={isCrawling ? "/blur.avif" : image} />
</Link>
<ImageCardContent>
<ImageCardTitle>
@@ -38,22 +102,7 @@ export default function LinkCard({ bookmark }: { bookmark: ZBookmark }) {
</ImageCardTitle>
{/* There's a hack here. Every tag has the full hight of the container itself. That why, when we enable flex-wrap,
the overflowed don't show up. */}
- <ImageCardBody className="flex h-full flex-wrap space-x-1 overflow-hidden">
- {bookmark.tags.map((t) => (
- <Link
- className="flex h-full flex-col justify-end"
- key={t.id}
- href={`/dashboard/tags/${t.name}`}
- >
- <Badge
- variant="default"
- className="text-nowrap bg-gray-300 text-gray-500 hover:text-white"
- >
- #{t.name}
- </Badge>
- </Link>
- ))}
- </ImageCardBody>
+ {TagList(bookmark, isCrawling)}
<ImageCardFooter>
<div className="flex justify-between text-gray-500">
<div className="my-auto">