diff --git a/apps/client/src/components/note_context.ts b/apps/client/src/components/note_context.ts index 1bc4e5498..4b77e4965 100644 --- a/apps/client/src/components/note_context.ts +++ b/apps/client/src/components/note_context.ts @@ -438,4 +438,22 @@ class NoteContext extends Component implements EventListener<"entitiesReloaded"> } } +export function openInCurrentNoteContext(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent | React.PointerEvent | null, notePath: string, viewScope?: ViewScope) { + const ntxId = $(evt?.target as any) + .closest("[data-ntx-id]") + .attr("data-ntx-id"); + + const noteContext = ntxId ? appContext.tabManager.getNoteContextById(ntxId) : appContext.tabManager.getActiveContext(); + + if (noteContext) { + noteContext.setNote(notePath, { viewScope }).then(() => { + if (noteContext !== appContext.tabManager.getActiveContext()) { + appContext.tabManager.activateNoteContext(noteContext.ntxId); + } + }); + } else { + appContext.tabManager.openContextWithNote(notePath, { viewScope, activate: true }); + } +} + export default NoteContext; diff --git a/apps/client/src/services/link.ts b/apps/client/src/services/link.ts index 16ca48bd7..b0ab04d07 100644 --- a/apps/client/src/services/link.ts +++ b/apps/client/src/services/link.ts @@ -4,6 +4,7 @@ import appContext, { type NoteCommandData } from "../components/app_context.js"; import froca from "./froca.js"; import utils from "./utils.js"; import { ALLOWED_PROTOCOLS } from "@triliumnext/commons"; +import { openInCurrentNoteContext } from "../components/note_context.js"; function getNotePathFromUrl(url: string) { const notePathMatch = /#(root[A-Za-z0-9_/]*)$/.exec(url); @@ -316,21 +317,7 @@ function goToLinkExt(evt: MouseEvent | JQuery.ClickEvent | JQuery.MouseDownEvent viewScope }); } else if (isLeftClick) { - const ntxId = $(evt?.target as any) - .closest("[data-ntx-id]") - .attr("data-ntx-id"); - - const noteContext = ntxId ? appContext.tabManager.getNoteContextById(ntxId) : appContext.tabManager.getActiveContext(); - - if (noteContext) { - noteContext.setNote(notePath, { viewScope }).then(() => { - if (noteContext !== appContext.tabManager.getActiveContext()) { - appContext.tabManager.activateNoteContext(noteContext.ntxId); - } - }); - } else { - appContext.tabManager.openContextWithNote(notePath, { viewScope, activate: true }); - } + openInCurrentNoteContext(evt, notePath, viewScope); } } else if (hrefLink) { const withinEditLink = $link?.hasClass("ck-link-actions__preview"); diff --git a/apps/client/src/widgets/collections/presentation/index.tsx b/apps/client/src/widgets/collections/presentation/index.tsx index 47348ea65..1d086fef7 100644 --- a/apps/client/src/widgets/collections/presentation/index.tsx +++ b/apps/client/src/widgets/collections/presentation/index.tsx @@ -9,6 +9,7 @@ import ShadowDom from "../../react/ShadowDom"; import ActionButton from "../../react/ActionButton"; import "./index.css"; import { RefObject } from "preact"; +import { openInCurrentNoteContext } from "../../../components/note_context"; const stylesheets = [ slideBaseStylesheet, @@ -19,6 +20,7 @@ const stylesheets = [ export default function PresentationView({ note }: ViewModeProps<{}>) { const [ presentation, setPresentation ] = useState(); const containerRef = useRef(null); + const apiRef = useRef(null); useLayoutEffect(() => { buildPresentationModel(note).then(setPresentation); @@ -31,29 +33,41 @@ export default function PresentationView({ note }: ViewModeProps<{}>) { containerRef={containerRef} > {stylesheets.map(stylesheet => )} - + - + ) } -function ButtonOverlay({ containerRef }: { containerRef: RefObject }) { +function ButtonOverlay({ containerRef, apiRef }: { containerRef: RefObject, apiRef: RefObject }) { return (
{ - containerRef.current?.requestFullscreen(); + icon="bx bx-edit" + text="Edit this slide" + onClick={e => { + const currentSlide = apiRef.current?.getCurrentSlide(); + const noteId = getNoteIdFromSlide(currentSlide); + + if (noteId) { + openInCurrentNoteContext(e, noteId); + } }} /> + + containerRef.current?.requestFullscreen()} + />
) } -function Presentation({ presentation } : { presentation: PresentationModel }) { +function Presentation({ presentation, apiRef: externalApiRef } : { presentation: PresentationModel, apiRef: RefObject }) { const containerRef = useRef(null); - const apiRef = useRef(null); + const apiRef = useRef(null); useEffect(() => { if (apiRef.current || !containerRef.current) return; @@ -70,8 +84,9 @@ function Presentation({ presentation } : { presentation: PresentationModel }) { return true; }, }); + externalApiRef.current = apiRef.current; apiRef.current.initialize().then(() => { - console.log("Slide.js initialized."); + // Initialization logic. }); return () => { @@ -97,16 +112,21 @@ function Presentation({ presentation } : { presentation: PresentationModel }) { function Slide({ slide }: { slide: PresentationSlideModel }) { if (!slide.verticalSlides) { // Normal slide. - return
; + return
; } else { // Slide with sub notes (show as vertical slides). return (
-
+
{slide.verticalSlides.map((slide) => ( -
+
))}
) } } + +function getNoteIdFromSlide(slide: HTMLElement | undefined) { + if (!slide) return; + return slide.dataset.noteId; +} diff --git a/apps/client/src/widgets/collections/presentation/model.ts b/apps/client/src/widgets/collections/presentation/model.ts index 838cf7a4c..ba95dbc9f 100644 --- a/apps/client/src/widgets/collections/presentation/model.ts +++ b/apps/client/src/widgets/collections/presentation/model.ts @@ -2,12 +2,14 @@ import FNote from "../../../entities/fnote"; type DangerouslySetInnerHTML = { __html: string; }; -export interface PresentationSlideModel { - content: DangerouslySetInnerHTML; - verticalSlides: PresentationVerticalSlideModel[] | undefined; +/** A top-level slide with optional vertical slides. */ +export interface PresentationSlideModel extends PresentationSlideBaseModel { + verticalSlides: PresentationSlideBaseModel[] | undefined; } -interface PresentationVerticalSlideModel { +/** Either a top-level slide or a vertical slide. */ +interface PresentationSlideBaseModel { + noteId: string; content: DangerouslySetInnerHTML; } @@ -22,6 +24,7 @@ export async function buildPresentationModel(note: FNote): Promise { +async function buildVerticalSlides(parentSlideNote: FNote): Promise { const children = await parentSlideNote.getChildNotes(); if (!children.length) return; - const slides: PresentationVerticalSlideModel[] = []; + const slides: PresentationSlideBaseModel[] = []; for (const child of children) { slides.push({ + noteId: child.noteId, content: processContent(await child.getContent()) }); }