aboutsummaryrefslogtreecommitdiffstats
path: root/apps/web/components/dashboard/preview
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/components/dashboard/preview')
-rw-r--r--apps/web/components/dashboard/preview/AttachmentBox.tsx66
-rw-r--r--apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx6
-rw-r--r--apps/web/components/dashboard/preview/BookmarkPreview.tsx17
-rw-r--r--apps/web/components/dashboard/preview/HighlightsBox.tsx14
-rw-r--r--apps/web/components/dashboard/preview/LinkContentSection.tsx4
-rw-r--r--apps/web/components/dashboard/preview/NoteEditor.tsx10
-rw-r--r--apps/web/components/dashboard/preview/ReaderView.tsx3
7 files changed, 82 insertions, 38 deletions
diff --git a/apps/web/components/dashboard/preview/AttachmentBox.tsx b/apps/web/components/dashboard/preview/AttachmentBox.tsx
index e24cc646..73eea640 100644
--- a/apps/web/components/dashboard/preview/AttachmentBox.tsx
+++ b/apps/web/components/dashboard/preview/AttachmentBox.tsx
@@ -27,7 +27,13 @@ import {
isAllowedToDetachAsset,
} from "@karakeep/trpc/lib/attachments";
-export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
+export default function AttachmentBox({
+ bookmark,
+ readOnly = false,
+}: {
+ bookmark: ZBookmark;
+ readOnly?: boolean;
+}) {
const { t } = useTranslation();
const { mutate: attachAsset, isPending: isAttaching } =
useAttachBookmarkAsset({
@@ -122,7 +128,8 @@ export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
>
<Download className="size-4" />
</Link>
- {isAllowedToAttachAsset(asset.assetType) &&
+ {!readOnly &&
+ isAllowedToAttachAsset(asset.assetType) &&
asset.assetType !== "userUploaded" && (
<FilePickerButton
title="Replace"
@@ -147,7 +154,7 @@ export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
<Pencil className="size-4" />
</FilePickerButton>
)}
- {isAllowedToDetachAsset(asset.assetType) && (
+ {!readOnly && isAllowedToDetachAsset(asset.assetType) && (
<ActionConfirmingDialog
title="Delete Attachment?"
description={`Are you sure you want to delete the attachment of the bookmark?`}
@@ -175,7 +182,8 @@ export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
</div>
</div>
))}
- {!bookmark.assets.some((asset) => asset.assetType == "bannerImage") &&
+ {!readOnly &&
+ !bookmark.assets.some((asset) => asset.assetType == "bannerImage") &&
bookmark.content.type != BookmarkTypes.ASSET && (
<FilePickerButton
title="Attach a Banner"
@@ -203,30 +211,32 @@ export default function AttachmentBox({ bookmark }: { bookmark: ZBookmark }) {
Attach a Banner
</FilePickerButton>
)}
- <FilePickerButton
- title="Upload File"
- loading={isAttaching}
- multiple={false}
- variant="ghost"
- size="none"
- className="flex w-full items-center justify-center gap-2"
- onFileSelect={(file) =>
- uploadAsset(file, {
- onSuccess: (resp) => {
- attachAsset({
- bookmarkId: bookmark.id,
- asset: {
- id: resp.assetId,
- assetType: "userUploaded",
- },
- });
- },
- })
- }
- >
- <Plus className="size-4" />
- Upload File
- </FilePickerButton>
+ {!readOnly && (
+ <FilePickerButton
+ title="Upload File"
+ loading={isAttaching}
+ multiple={false}
+ variant="ghost"
+ size="none"
+ className="flex w-full items-center justify-center gap-2"
+ onFileSelect={(file) =>
+ uploadAsset(file, {
+ onSuccess: (resp) => {
+ attachAsset({
+ bookmarkId: bookmark.id,
+ asset: {
+ id: resp.assetId,
+ assetType: "userUploaded",
+ },
+ });
+ },
+ })
+ }
+ >
+ <Plus className="size-4" />
+ Upload File
+ </FilePickerButton>
+ )}
</CollapsibleContent>
</Collapsible>
);
diff --git a/apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx b/apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx
index 19499d3e..e0f20ea2 100644
--- a/apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx
+++ b/apps/web/components/dashboard/preview/BookmarkHtmlHighlighter.tsx
@@ -95,6 +95,7 @@ interface HTMLHighlighterProps {
style?: React.CSSProperties;
className?: string;
highlights?: Highlight[];
+ readOnly?: boolean;
onHighlight?: (highlight: Highlight) => void;
onUpdateHighlight?: (highlight: Highlight) => void;
onDeleteHighlight?: (highlight: Highlight) => void;
@@ -105,6 +106,7 @@ function BookmarkHTMLHighlighter({
className,
style,
highlights = [],
+ readOnly = false,
onHighlight,
onUpdateHighlight,
onDeleteHighlight,
@@ -173,6 +175,10 @@ function BookmarkHTMLHighlighter({
}, [pendingHighlight, contentRef]);
const handlePointerUp = (e: React.PointerEvent) => {
+ if (readOnly) {
+ return;
+ }
+
const selection = window.getSelection();
// Check if we clicked on an existing highlight
diff --git a/apps/web/components/dashboard/preview/BookmarkPreview.tsx b/apps/web/components/dashboard/preview/BookmarkPreview.tsx
index 4766bd32..7e6bf814 100644
--- a/apps/web/components/dashboard/preview/BookmarkPreview.tsx
+++ b/apps/web/components/dashboard/preview/BookmarkPreview.tsx
@@ -17,6 +17,7 @@ import useRelativeTime from "@/lib/hooks/relative-time";
import { useTranslation } from "@/lib/i18n/client";
import { api } from "@/lib/trpc";
import { Building, CalendarDays, ExternalLink, User } from "lucide-react";
+import { useSession } from "next-auth/react";
import { BookmarkTypes, ZBookmark } from "@karakeep/shared/types/bookmarks";
import {
@@ -117,6 +118,7 @@ export default function BookmarkPreview({
}) {
const { t } = useTranslation();
const [activeTab, setActiveTab] = useState<string>("content");
+ const { data: session } = useSession();
const { data: bookmark } = api.bookmarks.getBookmark.useQuery(
{
@@ -138,6 +140,9 @@ export default function BookmarkPreview({
return <FullPageSpinner />;
}
+ // Check if the current user owns this bookmark
+ const isOwner = session?.user?.id === bookmark.userId;
+
let content;
switch (bookmark.content.type) {
case BookmarkTypes.LINK: {
@@ -186,18 +191,18 @@ export default function BookmarkPreview({
</div>
<CreationTime createdAt={bookmark.createdAt} />
<BookmarkMetadata bookmark={bookmark} />
- <SummarizeBookmarkArea bookmark={bookmark} />
+ <SummarizeBookmarkArea bookmark={bookmark} readOnly={!isOwner} />
<div className="flex items-center gap-4">
<p className="text-sm text-gray-400">{t("common.tags")}</p>
- <BookmarkTagsEditor bookmark={bookmark} />
+ <BookmarkTagsEditor bookmark={bookmark} disabled={!isOwner} />
</div>
<div className="flex gap-4">
<p className="pt-2 text-sm text-gray-400">{t("common.note")}</p>
- <NoteEditor bookmark={bookmark} />
+ <NoteEditor bookmark={bookmark} disabled={!isOwner} />
</div>
- <AttachmentBox bookmark={bookmark} />
- <HighlightsBox bookmarkId={bookmark.id} />
- <ActionBar bookmark={bookmark} />
+ <AttachmentBox bookmark={bookmark} readOnly={!isOwner} />
+ <HighlightsBox bookmarkId={bookmark.id} readOnly={!isOwner} />
+ {isOwner && <ActionBar bookmark={bookmark} />}
</div>
);
diff --git a/apps/web/components/dashboard/preview/HighlightsBox.tsx b/apps/web/components/dashboard/preview/HighlightsBox.tsx
index 4da22d04..41ab7d74 100644
--- a/apps/web/components/dashboard/preview/HighlightsBox.tsx
+++ b/apps/web/components/dashboard/preview/HighlightsBox.tsx
@@ -11,7 +11,13 @@ import { ChevronsDownUp } from "lucide-react";
import HighlightCard from "../highlights/HighlightCard";
-export default function HighlightsBox({ bookmarkId }: { bookmarkId: string }) {
+export default function HighlightsBox({
+ bookmarkId,
+ readOnly,
+}: {
+ bookmarkId: string;
+ readOnly: boolean;
+}) {
const { t } = useTranslation();
const { data: highlights, isPending: isLoading } =
@@ -30,7 +36,11 @@ export default function HighlightsBox({ bookmarkId }: { bookmarkId: string }) {
<CollapsibleContent className="group flex flex-col py-3 text-sm">
{highlights.highlights.map((highlight) => (
<Fragment key={highlight.id}>
- <HighlightCard highlight={highlight} clickable />
+ <HighlightCard
+ highlight={highlight}
+ clickable
+ readOnly={readOnly}
+ />
<Separator className="m-2 h-0.5 bg-gray-200 last:hidden" />
</Fragment>
))}
diff --git a/apps/web/components/dashboard/preview/LinkContentSection.tsx b/apps/web/components/dashboard/preview/LinkContentSection.tsx
index 53559aa0..64b62df6 100644
--- a/apps/web/components/dashboard/preview/LinkContentSection.tsx
+++ b/apps/web/components/dashboard/preview/LinkContentSection.tsx
@@ -25,6 +25,7 @@ import {
ExpandIcon,
Video,
} from "lucide-react";
+import { useSession } from "next-auth/react";
import { useQueryState } from "nuqs";
import { ErrorBoundary } from "react-error-boundary";
@@ -111,6 +112,8 @@ export default function LinkContentSection({
const [section, setSection] = useQueryState("section", {
defaultValue: defaultSection,
});
+ const { data: session } = useSession();
+ const isOwner = session?.user?.id === bookmark.userId;
if (bookmark.content.type != BookmarkTypes.LINK) {
throw new Error("Invalid content type");
@@ -133,6 +136,7 @@ export default function LinkContentSection({
<ReaderView
className="prose mx-auto dark:prose-invert"
bookmarkId={bookmark.id}
+ readOnly={!isOwner}
/>
</ScrollArea>
);
diff --git a/apps/web/components/dashboard/preview/NoteEditor.tsx b/apps/web/components/dashboard/preview/NoteEditor.tsx
index 393628b5..538aff2e 100644
--- a/apps/web/components/dashboard/preview/NoteEditor.tsx
+++ b/apps/web/components/dashboard/preview/NoteEditor.tsx
@@ -5,7 +5,13 @@ import { useClientConfig } from "@/lib/clientConfig";
import type { ZBookmark } from "@karakeep/shared/types/bookmarks";
import { useUpdateBookmark } from "@karakeep/shared-react/hooks/bookmarks";
-export function NoteEditor({ bookmark }: { bookmark: ZBookmark }) {
+export function NoteEditor({
+ bookmark,
+ disabled,
+}: {
+ bookmark: ZBookmark;
+ disabled?: boolean;
+}) {
const demoMode = !!useClientConfig().demoMode;
const updateBookmarkMutator = useUpdateBookmark({
@@ -26,7 +32,7 @@ export function NoteEditor({ bookmark }: { bookmark: ZBookmark }) {
<Textarea
className="h-44 w-full overflow-auto rounded bg-background p-2 text-sm text-gray-400 dark:text-gray-300"
defaultValue={bookmark.note ?? ""}
- disabled={demoMode}
+ disabled={demoMode || disabled}
placeholder="Write some notes ..."
onBlur={(e) => {
if (e.currentTarget.value == bookmark.note) {
diff --git a/apps/web/components/dashboard/preview/ReaderView.tsx b/apps/web/components/dashboard/preview/ReaderView.tsx
index bf4c27a5..1974626a 100644
--- a/apps/web/components/dashboard/preview/ReaderView.tsx
+++ b/apps/web/components/dashboard/preview/ReaderView.tsx
@@ -15,10 +15,12 @@ export default function ReaderView({
bookmarkId,
className,
style,
+ readOnly,
}: {
bookmarkId: string;
className?: string;
style?: React.CSSProperties;
+ readOnly: boolean;
}) {
const { data: highlights } = api.highlights.getForBookmark.useQuery({
bookmarkId,
@@ -93,6 +95,7 @@ export default function ReaderView({
style={style}
htmlContent={cachedContent || ""}
highlights={highlights?.highlights ?? []}
+ readOnly={readOnly}
onDeleteHighlight={(h) =>
deleteHighlight({
highlightId: h.id,