mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	feat(client/print): print presentations with waiting for slides to load
This commit is contained in:
		
							parent
							
								
									89dac52f49
								
							
						
					
					
						commit
						64576458b7
					
				@ -2,6 +2,7 @@ import FNote from "./entities/fnote";
 | 
			
		||||
import { render } from "preact";
 | 
			
		||||
import { CustomNoteList } from "./widgets/collections/NoteList";
 | 
			
		||||
import "./print.css";
 | 
			
		||||
import { useCallback, useRef } from "preact/hooks";
 | 
			
		||||
 | 
			
		||||
async function main() {
 | 
			
		||||
    const notePath = window.location.hash.substring(1);
 | 
			
		||||
@ -12,10 +13,25 @@ async function main() {
 | 
			
		||||
    const note = await froca.getNote(noteId);
 | 
			
		||||
 | 
			
		||||
    if (!note) return;
 | 
			
		||||
    render(getElementForNote(note), document.body);
 | 
			
		||||
    render(<App note={note} />, document.body);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getElementForNote(note: FNote) {
 | 
			
		||||
function App({ note }: { note: FNote }) {
 | 
			
		||||
    return (
 | 
			
		||||
        <>
 | 
			
		||||
            <ContentRenderer note={note} />
 | 
			
		||||
        </>
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function ContentRenderer({ note }: { note: FNote }) {
 | 
			
		||||
    const sentReadyEvent = useRef(false);
 | 
			
		||||
    const onReady = useCallback(() => {
 | 
			
		||||
        if (sentReadyEvent.current) return;
 | 
			
		||||
        window.dispatchEvent(new Event("note-ready"));
 | 
			
		||||
        sentReadyEvent.current = true;
 | 
			
		||||
    }, []);
 | 
			
		||||
 | 
			
		||||
    // Collections.
 | 
			
		||||
    if (note.type === "book") {
 | 
			
		||||
        return <CustomNoteList
 | 
			
		||||
@ -25,6 +41,7 @@ function getElementForNote(note: FNote) {
 | 
			
		||||
            ntxId="print"
 | 
			
		||||
            highlightedTokens={null}
 | 
			
		||||
            media="print"
 | 
			
		||||
            onReady={onReady}
 | 
			
		||||
        />;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -2423,3 +2423,13 @@ footer.webview-footer button {
 | 
			
		||||
    background: rgba(255, 100, 100, 0.5);
 | 
			
		||||
    text-decoration: line-through;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
iframe.print-iframe {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    left: -600px;
 | 
			
		||||
    right: -600px;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    width: 0;
 | 
			
		||||
    height: 0;
 | 
			
		||||
}
 | 
			
		||||
@ -23,9 +23,10 @@ interface NoteListProps {
 | 
			
		||||
    isEnabled: boolean;
 | 
			
		||||
    ntxId: string | null | undefined;
 | 
			
		||||
    media: ViewModeMedia;
 | 
			
		||||
    onReady: () => void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default function NoteList<T extends object>(props: Pick<NoteListProps, "displayOnlyCollections" | "media">) {
 | 
			
		||||
export default function NoteList<T extends object>(props: Pick<NoteListProps, "displayOnlyCollections" | "media" | "onReady">) {
 | 
			
		||||
    const { note, noteContext, notePath, ntxId } = useNoteContext();
 | 
			
		||||
    const isEnabled = noteContext?.hasNoteList();
 | 
			
		||||
    return <CustomNoteList note={note} isEnabled={!!isEnabled} notePath={notePath} ntxId={ntxId} {...props} />
 | 
			
		||||
 | 
			
		||||
@ -16,4 +16,5 @@ export interface ViewModeProps<T extends object> {
 | 
			
		||||
    viewConfig: T | undefined;
 | 
			
		||||
    saveConfig(newConfig: T): void;
 | 
			
		||||
    media: ViewModeMedia;
 | 
			
		||||
    onReady(): void;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ import { t } from "../../../services/i18n";
 | 
			
		||||
import { DEFAULT_THEME, loadPresentationTheme } from "./themes";
 | 
			
		||||
import FNote from "../../../entities/fnote";
 | 
			
		||||
 | 
			
		||||
export default function PresentationView({ note, noteIds, media }: ViewModeProps<{}>) {
 | 
			
		||||
export default function PresentationView({ note, noteIds, media, onReady }: ViewModeProps<{}>) {
 | 
			
		||||
    const [ presentation, setPresentation ] = useState<PresentationModel>();
 | 
			
		||||
    const containerRef = useRef<HTMLDivElement>(null);
 | 
			
		||||
    const [ api, setApi ] = useState<Reveal.Api>();
 | 
			
		||||
@ -33,6 +33,14 @@ export default function PresentationView({ note, noteIds, media }: ViewModeProps
 | 
			
		||||
 | 
			
		||||
    useLayoutEffect(refresh, [ note, noteIds ]);
 | 
			
		||||
 | 
			
		||||
    useEffect(() => {
 | 
			
		||||
        // We need to wait for Reveal.js to initialize (by setting api) and for the presentation to become available.
 | 
			
		||||
        if (api && presentation) {
 | 
			
		||||
            // Timeout is necessary because it otherwise can cause flakiness by rendering only the first slide.
 | 
			
		||||
            setTimeout(onReady, 200);
 | 
			
		||||
        }
 | 
			
		||||
    }, [ api, presentation ]);
 | 
			
		||||
 | 
			
		||||
    if (!presentation || !stylesheets) return;
 | 
			
		||||
    const content = (
 | 
			
		||||
        <>
 | 
			
		||||
 | 
			
		||||
@ -297,8 +297,19 @@ export default class NoteDetailWidget extends NoteContextAwareWidget {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Trigger in timeout to dismiss the menu while printing.
 | 
			
		||||
        setTimeout(window.print, 0);
 | 
			
		||||
        const iframe = document.createElement('iframe');
 | 
			
		||||
        iframe.src = `?print#${this.notePath}`;
 | 
			
		||||
        iframe.className = "print-iframe";
 | 
			
		||||
        document.body.appendChild(iframe);
 | 
			
		||||
        iframe.onload = () => {
 | 
			
		||||
            console.log("Got ", iframe, iframe.contentWindow);
 | 
			
		||||
            if (iframe.contentWindow) {
 | 
			
		||||
                iframe.contentWindow.addEventListener("note-ready", () => {
 | 
			
		||||
                    iframe.contentWindow?.print();
 | 
			
		||||
                    document.body.removeChild(iframe);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async exportAsPdfEvent() {
 | 
			
		||||
 | 
			
		||||
@ -47,7 +47,7 @@ function NoteContextMenu({ note, noteContext }: { note: FNote, noteContext?: Not
 | 
			
		||||
  const canBeConvertedToAttachment = note?.isEligibleForConversionToAttachment();
 | 
			
		||||
  const isSearchable = ["text", "code", "book", "mindMap", "doc"].includes(note.type);
 | 
			
		||||
  const isInOptions = note.noteId.startsWith("_options");
 | 
			
		||||
  const isPrintable = ["text", "code"].includes(note.type);
 | 
			
		||||
  const isPrintable = ["text", "code", "book"].includes(note.type);
 | 
			
		||||
  const isElectron = getIsElectron();
 | 
			
		||||
  const isMac = getIsMac();
 | 
			
		||||
  const hasSource = ["text", "code", "relationMap", "mermaid", "canvas", "mindMap"].includes(note.type);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user