mirror of
https://github.com/zadam/trilium.git
synced 2026-01-01 04:04:25 +01:00
Merge remote-tracking branch 'origin/main' into feature/pdfjs_sidebar_experiments
Some checks are pending
Checks / main (push) Waiting to run
Some checks are pending
Checks / main (push) Waiting to run
This commit is contained in:
commit
7182d32d9c
@ -1259,6 +1259,12 @@ body.layout-horizontal #rest-pane > .classic-toolbar-widget {
|
||||
#center-pane .note-split {
|
||||
padding-top: 2px;
|
||||
background-color: var(--note-split-background-color, var(--main-background-color));
|
||||
transition: border-color 250ms ease-in;
|
||||
border: 1px solid transparent;
|
||||
|
||||
&.active {
|
||||
border-color: var(--link-selection-outline-color);
|
||||
}
|
||||
}
|
||||
|
||||
body:not(.background-effects) #center-pane .note-split {
|
||||
|
||||
3
apps/client/src/types-pdfjs.d.ts
vendored
Normal file
3
apps/client/src/types-pdfjs.d.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
interface Window {
|
||||
TRILIUM_VIEW_HISTORY_STORE?: object;
|
||||
}
|
||||
@ -11,7 +11,8 @@ import froca from "../../services/froca";
|
||||
import { subscribeToMessages, unsubscribeToMessage as unsubscribeFromMessage } from "../../services/ws";
|
||||
import { useNoteContext, useNoteLabel, useNoteLabelBoolean, useNoteProperty, useTriliumEvent } from "../react/hooks";
|
||||
import { allViewTypes, ViewModeMedia, ViewModeProps, ViewTypeOptions } from "./interface";
|
||||
import ViewModeStorage from "./view_mode_storage";
|
||||
import ViewModeStorage, { type ViewModeStorageType } from "./view_mode_storage";
|
||||
|
||||
interface NoteListProps {
|
||||
note: FNote | null | undefined;
|
||||
notePath: string | null | undefined;
|
||||
@ -215,7 +216,7 @@ export function useNoteIds(note: FNote | null | undefined, viewType: ViewTypeOpt
|
||||
return noteIds;
|
||||
}
|
||||
|
||||
export function useViewModeConfig<T extends object>(note: FNote | null | undefined, viewType: ViewTypeOptions | undefined) {
|
||||
export function useViewModeConfig<T extends object>(note: FNote | null | undefined, viewType: ViewModeStorageType | undefined) {
|
||||
const [ viewConfig, setViewConfig ] = useState<{
|
||||
config: T | undefined;
|
||||
storeFn: (data: T) => void;
|
||||
|
||||
@ -4,14 +4,16 @@ import { ViewTypeOptions } from "../collections/interface";
|
||||
|
||||
const ATTACHMENT_ROLE = "viewConfig";
|
||||
|
||||
export type ViewModeStorageType = ViewTypeOptions | "pdfHistory";
|
||||
|
||||
export default class ViewModeStorage<T extends object> {
|
||||
|
||||
private note: FNote;
|
||||
private attachmentName: string;
|
||||
|
||||
constructor(note: FNote, viewType: ViewTypeOptions) {
|
||||
constructor(note: FNote, viewType: ViewModeStorageType) {
|
||||
this.note = note;
|
||||
this.attachmentName = viewType + ".json";
|
||||
this.attachmentName = `${viewType}.json`;
|
||||
}
|
||||
|
||||
async store(data: T) {
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import FlexContainer from "./flex_container.js";
|
||||
import appContext, { type CommandData, type CommandListenerData, type EventData, type EventNames, type NoteSwitchedContext } from "../../components/app_context.js";
|
||||
import type BasicWidget from "../basic_widget.js";
|
||||
import Component from "../../components/component.js";
|
||||
import NoteContext from "../../components/note_context.js";
|
||||
import splitService from "../../services/resizer.js";
|
||||
import { isMobile } from "../../services/utils.js";
|
||||
import NoteContext from "../../components/note_context.js";
|
||||
import type BasicWidget from "../basic_widget.js";
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import FlexContainer from "./flex_container.js";
|
||||
|
||||
interface SplitNoteWidget extends BasicWidget {
|
||||
hasBeenAlreadyShown?: boolean;
|
||||
@ -74,7 +75,7 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
|
||||
|
||||
|
||||
const subContexts = activeContext.getSubContexts();
|
||||
let noteContext: NoteContext | undefined = undefined;
|
||||
let noteContext: NoteContext | undefined;
|
||||
if (isMobile() && subContexts.length > 1) {
|
||||
noteContext = subContexts.find(s => s.ntxId !== ntxId);
|
||||
}
|
||||
@ -201,6 +202,11 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
|
||||
|
||||
async refresh() {
|
||||
this.toggleExt(true);
|
||||
|
||||
// Mark the active note context.
|
||||
for (const child of this.children as NoteContextAwareWidget[]) {
|
||||
child.$widget.toggleClass("active", !!child.noteContext?.isActive());
|
||||
}
|
||||
}
|
||||
|
||||
toggleInt(show: boolean) {} // not needed
|
||||
@ -239,16 +245,16 @@ export default class SplitNoteContainer extends FlexContainer<SplitNoteWidget> {
|
||||
widget.hasBeenAlreadyShown = true;
|
||||
|
||||
return [widget.handleEvent("noteSwitched", noteSwitchedContext), this.refreshNotShown(noteSwitchedContext)];
|
||||
} else {
|
||||
return Promise.resolve();
|
||||
}
|
||||
return Promise.resolve();
|
||||
|
||||
}
|
||||
|
||||
if (name === "activeContextChanged") {
|
||||
return this.refreshNotShown(data as EventData<"activeContextChanged">);
|
||||
} else {
|
||||
return super.handleEventInChildren(name, data);
|
||||
}
|
||||
return super.handleEventInChildren(name, data);
|
||||
|
||||
}
|
||||
|
||||
refreshNotShown(data: NoteSwitchedContext | EventData<"activeContextChanged">) {
|
||||
|
||||
@ -16,7 +16,7 @@ export default function FileTypeWidget({ note, parentComponent, noteContext }: T
|
||||
if (blob?.content) {
|
||||
return <TextPreview content={blob.content} />;
|
||||
} else if (note.mime === "application/pdf") {
|
||||
return <PdfPreview blob={blob} note={note} componentId={parentComponent?.componentId} noteContext={noteContext} />;
|
||||
return noteContext && <PdfPreview blob={blob} note={note} componentId={parentComponent?.componentId} noteContext={noteContext} />;
|
||||
} else if (note.mime.startsWith("video/")) {
|
||||
return <VideoPreview note={note} />;
|
||||
} else if (note.mime.startsWith("audio/")) {
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { RefObject } from "preact";
|
||||
import { useCallback, useEffect, useRef } from "preact/hooks";
|
||||
|
||||
import appContext from "../../../components/app_context";
|
||||
import type NoteContext from "../../../components/note_context";
|
||||
import FBlob from "../../../entities/fblob";
|
||||
import FNote from "../../../entities/fnote";
|
||||
@ -16,9 +17,9 @@ const VARIABLE_WHITELIST = new Set([
|
||||
]);
|
||||
|
||||
export default function PdfPreview({ note, blob, componentId, noteContext }: {
|
||||
note: FNote,
|
||||
noteContext: NoteContext
|
||||
blob: FBlob | null | undefined,
|
||||
note: FNote;
|
||||
noteContext: NoteContext;
|
||||
blob: FBlob | null | undefined;
|
||||
componentId: string | undefined;
|
||||
}) {
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
@ -150,9 +151,28 @@ export default function PdfPreview({ note, blob, componentId, noteContext }: {
|
||||
}
|
||||
}, [ blob ]);
|
||||
|
||||
// Trigger focus when iframe content is clicked (iframe focus doesn't bubble)
|
||||
useEffect(() => {
|
||||
const iframe = iframeRef.current;
|
||||
if (!iframe) return;
|
||||
|
||||
const handleIframeClick = () => {
|
||||
if (noteContext.ntxId) {
|
||||
appContext.tabManager.activateNoteContext(noteContext.ntxId);
|
||||
}
|
||||
};
|
||||
|
||||
// Listen for clicks on the iframe's content window
|
||||
const iframeDoc = iframe.contentWindow?.document;
|
||||
if (iframeDoc) {
|
||||
iframeDoc.addEventListener('click', handleIframeClick);
|
||||
return () => iframeDoc.removeEventListener('click', handleIframeClick);
|
||||
}
|
||||
}, [ iframeRef.current?.contentWindow, noteContext ]);
|
||||
|
||||
return (historyConfig &&
|
||||
<iframe
|
||||
tabIndex={300}
|
||||
ref={iframeRef}
|
||||
class="pdf-preview"
|
||||
src={`pdfjs/web/viewer.html?file=../../api/notes/${note.noteId}/open&lang=${locale}&sidebar=${newLayout ? "0" : "1"}`}
|
||||
@ -201,7 +221,7 @@ function useStyleInjection(iframeRef: RefObject<HTMLIFrameElement>) {
|
||||
|
||||
function getRootCssVariables() {
|
||||
const styles = getComputedStyle(document.documentElement);
|
||||
const vars = {};
|
||||
const vars: Record<string, string> = {};
|
||||
|
||||
for (let i = 0; i < styles.length; i++) {
|
||||
const prop = styles[i];
|
||||
@ -213,7 +233,7 @@ function getRootCssVariables() {
|
||||
return vars;
|
||||
}
|
||||
|
||||
function cssVarsToString(vars) {
|
||||
function cssVarsToString(vars: Record<string, string>) {
|
||||
return `:root {\n${Object.entries(vars)
|
||||
.map(([k, v]) => ` ${k}: ${v};`)
|
||||
.join('\n')}\n}`;
|
||||
|
||||
@ -4,8 +4,6 @@ import { setupPdfPages } from "./pages";
|
||||
import { setupPdfAttachments } from "./attachments";
|
||||
import { setupPdfLayers } from "./layers";
|
||||
|
||||
const LOG_EVENT_BUS = false;
|
||||
|
||||
async function main() {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.get("sidebar") === "0") {
|
||||
@ -20,9 +18,6 @@ async function main() {
|
||||
}
|
||||
const app = window.PDFViewerApplication;
|
||||
|
||||
if (LOG_EVENT_BUS) {
|
||||
patchEventBus();
|
||||
}
|
||||
app.eventBus.on("documentloaded", () => {
|
||||
manageSave();
|
||||
extractAndSendToc();
|
||||
@ -74,7 +69,7 @@ function manageSave() {
|
||||
window.parent.postMessage({
|
||||
type: "pdfjs-viewer-document-modified",
|
||||
data: data
|
||||
}, "*");
|
||||
}, window.location.origin);
|
||||
storage.resetModified();
|
||||
timeout = null;
|
||||
}, 2_000);
|
||||
@ -93,15 +88,4 @@ function manageSave() {
|
||||
});
|
||||
}
|
||||
|
||||
function patchEventBus() {
|
||||
const eventBus = window.PDFViewerApplication.eventBus;
|
||||
const originalDispatch = eventBus.dispatch.bind(eventBus);
|
||||
|
||||
eventBus.dispatch = (type: string, data?: any) => {
|
||||
console.log("PDF.js event:", type, data);
|
||||
return originalDispatch(type, data);
|
||||
};
|
||||
}
|
||||
|
||||
main();
|
||||
console.log("Custom script loaded");
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
export default function interceptViewHistory(customOptions?: object) {
|
||||
// We need to monkey-patch the localStorage used by PDF.js to store view history.
|
||||
// Other attempts to intercept the history saving/loading (like overriding methods on PDFViewerApplication) have failed.
|
||||
const originalSetItem = Storage.prototype.setItem;
|
||||
Storage.prototype.setItem = function (key: string, value: string) {
|
||||
if (key === "pdfjs.history") {
|
||||
@ -40,7 +42,7 @@ function saveHistory(value: string) {
|
||||
window.parent.postMessage({
|
||||
type: "pdfjs-viewer-save-view-history",
|
||||
data: JSON.stringify(history)
|
||||
}, "*");
|
||||
}, window.location.origin);
|
||||
saveTimeout = null;
|
||||
}, 2_000);
|
||||
}
|
||||
|
||||
@ -14,7 +14,8 @@
|
||||
"tsBuildInfoFile": "dist/tsconfig.app.tsbuildinfo"
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
"src/**/*.ts",
|
||||
"../../apps/client/src/types-pdfjs.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"eslint.config.js",
|
||||
@ -23,7 +24,7 @@
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../commons/tsconfig.app.json"
|
||||
"path": "../commons/tsconfig.lib.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -63,6 +63,9 @@
|
||||
{
|
||||
"path": "./packages/share-theme"
|
||||
},
|
||||
{
|
||||
"path": "./packages/pdfjs-viewer"
|
||||
},
|
||||
{
|
||||
"path": "./scripts"
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user