diff --git a/apps/client/src/widgets/attachment_detail.ts b/apps/client/src/widgets/attachment_detail.ts
index 1d2eab902..9030245d8 100644
--- a/apps/client/src/widgets/attachment_detail.ts
+++ b/apps/client/src/widgets/attachment_detail.ts
@@ -11,89 +11,8 @@ import type FAttachment from "../entities/fattachment.js";
import type { EventData } from "../components/app_context.js";
const TPL = /*html*/`
-
`;
@@ -125,21 +44,6 @@ export default class AttachmentDetailWidget extends BasicWidget {
this.$wrapper = this.$widget.find(".attachment-detail-wrapper");
this.$wrapper.addClass(this.isFullDetail ? "full-detail" : "list-view");
- if (!this.isFullDetail) {
- const $link = await linkService.createLink(this.attachment.ownerId, {
- title: this.attachment.title,
- viewScope: {
- viewMode: "attachments",
- attachmentId: this.attachment.attachmentId
- }
- });
- $link.addClass("use-tn-links");
-
- this.$wrapper.find(".attachment-title").append($link);
- } else {
- this.$wrapper.find(".attachment-title").text(this.attachment.title);
- }
-
const $deletionWarning = this.$wrapper.find(".attachment-deletion-warning");
const { utcDateScheduledForErasureSince } = this.attachment;
@@ -166,10 +70,9 @@ export default class AttachmentDetailWidget extends BasicWidget {
$deletionWarning.hide();
}
- this.$wrapper.find(".attachment-details").text(t("attachment_detail_2.role_and_size", { role: this.attachment.role, size: utils.formatSize(this.attachment.contentLength) }));
this.$wrapper.find(".attachment-actions-container").append(this.attachmentActionsWidget.render());
- const { $renderedContent } = await contentRenderer.getRenderedContent(this.attachment, { imageHasZoom: this.isFullDetail });
+ const { $renderedContent } = await );
this.$wrapper.find(".attachment-content-wrapper").append($renderedContent);
}
diff --git a/apps/client/src/widgets/react/NoteLink.tsx b/apps/client/src/widgets/react/NoteLink.tsx
index 2a9ec199d..18cd2a0c2 100644
--- a/apps/client/src/widgets/react/NoteLink.tsx
+++ b/apps/client/src/widgets/react/NoteLink.tsx
@@ -1,5 +1,5 @@
import { useEffect, useRef, useState } from "preact/hooks";
-import link from "../../services/link";
+import link, { ViewScope } from "../../services/link";
import { useImperativeSearchHighlighlighting } from "./hooks";
interface NoteLinkOpts {
@@ -11,18 +11,25 @@ interface NoteLinkOpts {
noPreview?: boolean;
noTnLink?: boolean;
highlightedTokens?: string[] | null | undefined;
+ // Override the text of the link, otherwise the note title is used.
+ title?: string;
+ viewScope?: ViewScope;
}
-export default function NoteLink({ className, notePath, showNotePath, showNoteIcon, style, noPreview, noTnLink, highlightedTokens }: NoteLinkOpts) {
+export default function NoteLink({ className, notePath, showNotePath, showNoteIcon, style, noPreview, noTnLink, highlightedTokens, title, viewScope }: NoteLinkOpts) {
const stringifiedNotePath = Array.isArray(notePath) ? notePath.join("/") : notePath;
const ref = useRef(null);
const [ jqueryEl, setJqueryEl ] = useState>();
const highlightSearch = useImperativeSearchHighlighlighting(highlightedTokens);
useEffect(() => {
- link.createLink(stringifiedNotePath, { showNotePath, showNoteIcon })
- .then(setJqueryEl);
- }, [ stringifiedNotePath, showNotePath ]);
+ link.createLink(stringifiedNotePath, {
+ title,
+ showNotePath,
+ showNoteIcon,
+ viewScope
+ }).then(setJqueryEl);
+ }, [ stringifiedNotePath, showNotePath, title, viewScope ]);
useEffect(() => {
if (!ref.current || !jqueryEl) return;
diff --git a/apps/client/src/widgets/type_widgets/Attachment.css b/apps/client/src/widgets/type_widgets/Attachment.css
index 56a9b32e6..499f10508 100644
--- a/apps/client/src/widgets/type_widgets/Attachment.css
+++ b/apps/client/src/widgets/type_widgets/Attachment.css
@@ -11,4 +11,75 @@
justify-content: space-between;
align-items: baseline;
}
+/* #endregion */
+
+/* #region Attachment detail */
+.attachment-detail-widget {
+ height: 100%;
+}
+
+.attachment-detail-wrapper {
+ margin-bottom: 20px;
+ display: flex;
+ flex-direction: column;
+}
+
+.attachment-title-line {
+ display: flex;
+ align-items: baseline;
+ gap: 1em;
+}
+
+.attachment-details {
+ margin-left: 10px;
+}
+
+.attachment-content-wrapper {
+ flex-grow: 1;
+}
+
+.attachment-content-wrapper .rendered-content {
+ height: 100%;
+}
+
+.attachment-content-wrapper pre {
+ padding: 10px;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+
+.attachment-detail-wrapper.list-view .attachment-content-wrapper {
+ max-height: 300px;
+}
+
+.attachment-detail-wrapper.full-detail {
+ height: 100%;
+}
+
+.attachment-detail-wrapper.full-detail .attachment-content-wrapper {
+ height: 100%;
+}
+
+.attachment-detail-wrapper.list-view .attachment-content-wrapper pre {
+ max-height: 400px;
+}
+
+.attachment-content-wrapper img {
+ margin: 10px;
+}
+
+.attachment-detail-wrapper.list-view .attachment-content-wrapper img, .attachment-detail-wrapper.list-view .attachment-content-wrapper video {
+ max-height: 300px;
+ max-width: 90%;
+ object-fit: contain;
+}
+
+.attachment-detail-wrapper.full-detail .attachment-content-wrapper img {
+ max-width: 90%;
+ object-fit: contain;
+}
+
+.attachment-detail-wrapper.scheduled-for-deletion .attachment-content-wrapper img {
+ filter: contrast(10%);
+}
/* #endregion */
\ No newline at end of file
diff --git a/apps/client/src/widgets/type_widgets/Attachment.tsx b/apps/client/src/widgets/type_widgets/Attachment.tsx
index a2577e7ab..3169c53a8 100644
--- a/apps/client/src/widgets/type_widgets/Attachment.tsx
+++ b/apps/client/src/widgets/type_widgets/Attachment.tsx
@@ -3,14 +3,36 @@ import { TypeWidgetProps } from "./type_widget";
import "./Attachment.css";
import NoteLink from "../react/NoteLink";
import Button from "../react/Button";
-import { useContext } from "preact/hooks";
+import { useContext, useEffect, useRef, useState } from "preact/hooks";
import { ParentComponent } from "../react/react_utils";
import HelpButton from "../react/HelpButton";
+import FAttachment from "../../entities/fattachment";
+import Alert from "../react/Alert";
+import utils from "../../services/utils";
+import content_renderer from "../../services/content_renderer";
export function AttachmentList({ note }: TypeWidgetProps) {
+ const [ attachments, setAttachments ] = useState([]);
+
+ function refresh() {
+ note.getAttachments().then(setAttachments);
+ }
+
+ useEffect(refresh, [ note ]);
+
return (
+
+
+ {attachments.length ? (
+ attachments.map(attachment =>
)
+ ) : (
+
+ {t("attachment_list.no_attachments")}
+
+ )}
+
)
}
@@ -39,3 +61,42 @@ function AttachmentListHeader({ noteId }: { noteId: string }) {
)
}
+
+function AttachmentDetail({ attachment, isFullDetail }: { attachment: FAttachment, isFullDetail: boolean }) {
+ const contentWrapper = useRef(null);
+
+ useEffect(() => {
+ content_renderer.getRenderedContent(attachment, { imageHasZoom: isFullDetail })
+ .then(({ $renderedContent }) => {
+ contentWrapper.current?.replaceChildren(...$renderedContent);
+ })
+ }, [ attachment ]);
+
+ return (
+
+
+
+
+
+ {!isFullDetail ? (
+
+ ) : (attachment.title)}
+
+
+ {t("attachment_detail_2.role_and_size", { role: attachment.role, size: utils.formatSize(attachment.contentLength) })}
+
+
+
+
+
+
+
+ )
+}
diff --git a/apps/client/src/widgets/type_widgets_old/attachment_list.ts b/apps/client/src/widgets/type_widgets_old/attachment_list.ts
index 8f1037631..318ddf457 100644
--- a/apps/client/src/widgets/type_widgets_old/attachment_list.ts
+++ b/apps/client/src/widgets/type_widgets_old/attachment_list.ts
@@ -6,7 +6,6 @@ import { t } from "../../services/i18n.js";
import type { EventData } from "../../components/app_context.js";
const TPL = /*html*/`
-
`;
export default class AttachmentListTypeWidget extends TypeWidget {
@@ -27,28 +26,12 @@ export default class AttachmentListTypeWidget extends TypeWidget {
}
async doRefresh(note: Parameters[0]) {
- const $helpButton = $(`
-
- `);
- utils.initHelpButtons($helpButton);
-
- const noteLink = await linkService.createLink(this.noteId); // do separately to avoid race condition between empty() and .append()
- noteLink.addClass("use-tn-links");
-
this.$list.empty();
this.children = [];
this.renderedAttachmentIds = new Set();
const attachments = await note.getAttachments();
- if (attachments.length === 0) {
- this.$list.html('' + t("attachment_list.no_attachments") + "
");
- return;
- }
-
for (const attachment of attachments) {
const attachmentDetailWidget = new AttachmentDetailWidget(attachment, false);