mirror of
https://github.com/zadam/trilium.git
synced 2025-10-20 15:19:01 +02:00
feat(collection/presentation): load themes
This commit is contained in:
parent
8a86fdcd43
commit
7c2c89d4e2
@ -2,7 +2,6 @@ import { ViewModeProps } from "../interface";
|
|||||||
import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
|
import { useEffect, useLayoutEffect, useRef, useState } from "preact/hooks";
|
||||||
import Reveal from "reveal.js";
|
import Reveal from "reveal.js";
|
||||||
import slideBaseStylesheet from "reveal.js/dist/reveal.css?raw";
|
import slideBaseStylesheet from "reveal.js/dist/reveal.css?raw";
|
||||||
import slideThemeStylesheet from "reveal.js/dist/theme/black.css?raw";
|
|
||||||
import slideCustomStylesheet from "./slidejs.css?raw";
|
import slideCustomStylesheet from "./slidejs.css?raw";
|
||||||
import { buildPresentationModel, PresentationModel, PresentationSlideBaseModel } from "./model";
|
import { buildPresentationModel, PresentationModel, PresentationSlideBaseModel } from "./model";
|
||||||
import ShadowDom from "../../react/ShadowDom";
|
import ShadowDom from "../../react/ShadowDom";
|
||||||
@ -10,19 +9,16 @@ import ActionButton from "../../react/ActionButton";
|
|||||||
import "./index.css";
|
import "./index.css";
|
||||||
import { RefObject } from "preact";
|
import { RefObject } from "preact";
|
||||||
import { openInCurrentNoteContext } from "../../../components/note_context";
|
import { openInCurrentNoteContext } from "../../../components/note_context";
|
||||||
import { useTriliumEvent } from "../../react/hooks";
|
import { useNoteLabelWithDefault, useTriliumEvent } from "../../react/hooks";
|
||||||
import { t } from "../../../services/i18n";
|
import { t } from "../../../services/i18n";
|
||||||
|
import { DEFAULT_THEME, loadPresentationTheme } from "./themes";
|
||||||
const stylesheets = [
|
import FNote from "../../../entities/fnote";
|
||||||
slideBaseStylesheet,
|
|
||||||
slideThemeStylesheet,
|
|
||||||
slideCustomStylesheet
|
|
||||||
].map(stylesheet => stylesheet.replace(/:root/g, ":host"));
|
|
||||||
|
|
||||||
export default function PresentationView({ note, noteIds }: ViewModeProps<{}>) {
|
export default function PresentationView({ note, noteIds }: ViewModeProps<{}>) {
|
||||||
const [ presentation, setPresentation ] = useState<PresentationModel>();
|
const [ presentation, setPresentation ] = useState<PresentationModel>();
|
||||||
const containerRef = useRef<HTMLDivElement>(null);
|
const containerRef = useRef<HTMLDivElement>(null);
|
||||||
const [ api, setApi ] = useState<Reveal.Api>();
|
const [ api, setApi ] = useState<Reveal.Api>();
|
||||||
|
const stylesheets = usePresentationStylesheets(note);
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
buildPresentationModel(note).then(setPresentation);
|
buildPresentationModel(note).then(setPresentation);
|
||||||
@ -36,7 +32,7 @@ export default function PresentationView({ note, noteIds }: ViewModeProps<{}>) {
|
|||||||
|
|
||||||
useLayoutEffect(refresh, [ note, noteIds ]);
|
useLayoutEffect(refresh, [ note, noteIds ]);
|
||||||
|
|
||||||
return presentation && (
|
return presentation && stylesheets && (
|
||||||
<>
|
<>
|
||||||
<ShadowDom
|
<ShadowDom
|
||||||
className="presentation-container"
|
className="presentation-container"
|
||||||
@ -50,6 +46,23 @@ export default function PresentationView({ note, noteIds }: ViewModeProps<{}>) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function usePresentationStylesheets(note: FNote) {
|
||||||
|
const [ themeName ] = useNoteLabelWithDefault(note, "presentation:theme", DEFAULT_THEME);
|
||||||
|
const [ stylesheets, setStylesheets ] = useState<string[]>();
|
||||||
|
|
||||||
|
useLayoutEffect(() => {
|
||||||
|
loadPresentationTheme(themeName).then((themeStylesheet) => {
|
||||||
|
setStylesheets([
|
||||||
|
slideBaseStylesheet,
|
||||||
|
themeStylesheet,
|
||||||
|
slideCustomStylesheet
|
||||||
|
].map(stylesheet => stylesheet.replace(/:root/g, ":host")));
|
||||||
|
});
|
||||||
|
}, [ themeName ]);
|
||||||
|
|
||||||
|
return stylesheets;
|
||||||
|
}
|
||||||
|
|
||||||
function ButtonOverlay({ containerRef, api }: { containerRef: RefObject<HTMLDivElement>, api: Reveal.Api | undefined }) {
|
function ButtonOverlay({ containerRef, api }: { containerRef: RefObject<HTMLDivElement>, api: Reveal.Api | undefined }) {
|
||||||
const [ isOverviewActive, setIsOverviewActive ] = useState(false);
|
const [ isOverviewActive, setIsOverviewActive ] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
import { it, describe } from "vitest";
|
||||||
|
import { getPresentationThemes, loadPresentationTheme } from "./themes";
|
||||||
|
|
||||||
|
describe("Presentation themes", () => {
|
||||||
|
it("can load all themes", async () => {
|
||||||
|
const themes = getPresentationThemes();
|
||||||
|
|
||||||
|
await Promise.all(themes.map(theme => loadPresentationTheme(theme.id)));
|
||||||
|
});
|
||||||
|
});
|
@ -1,3 +1,5 @@
|
|||||||
|
export const DEFAULT_THEME = "white";
|
||||||
|
|
||||||
interface ThemeDefinition {
|
interface ThemeDefinition {
|
||||||
name: string;
|
name: string;
|
||||||
loadTheme: () => Promise<typeof import("*.css?raw")>;
|
loadTheme: () => Promise<typeof import("*.css?raw")>;
|
||||||
@ -10,39 +12,39 @@ const themes: Record<string, ThemeDefinition> = {
|
|||||||
},
|
},
|
||||||
white: {
|
white: {
|
||||||
name: "White",
|
name: "White",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/white.css?raw")
|
||||||
},
|
},
|
||||||
beige: {
|
beige: {
|
||||||
name: "Beige",
|
name: "Beige",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/beige.css?raw")
|
||||||
},
|
},
|
||||||
serif: {
|
serif: {
|
||||||
name: "Serif",
|
name: "Serif",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/serif.css?raw")
|
||||||
},
|
},
|
||||||
simple: {
|
simple: {
|
||||||
name: "Simple",
|
name: "Simple",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/simple.css?raw")
|
||||||
},
|
},
|
||||||
solarized: {
|
solarized: {
|
||||||
name: "Solarized",
|
name: "Solarized",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/solarized.css?raw")
|
||||||
},
|
},
|
||||||
moon: {
|
moon: {
|
||||||
name: "Moon",
|
name: "Moon",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/moon.css?raw")
|
||||||
},
|
},
|
||||||
dracula: {
|
dracula: {
|
||||||
name: "Dracula",
|
name: "Dracula",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/dracula.css?raw")
|
||||||
},
|
},
|
||||||
sky: {
|
sky: {
|
||||||
name: "Sky",
|
name: "Sky",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/sky.css?raw")
|
||||||
},
|
},
|
||||||
blood: {
|
blood: {
|
||||||
name: "Blood",
|
name: "Blood",
|
||||||
loadTheme: () => import("reveal.js/dist/theme/black.css?raw")
|
loadTheme: () => import("reveal.js/dist/theme/blood.css?raw")
|
||||||
}
|
}
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
@ -54,8 +56,8 @@ export function getPresentationThemes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function loadPresentationTheme(name: keyof typeof themes) {
|
export async function loadPresentationTheme(name: keyof typeof themes) {
|
||||||
const theme = themes[name];
|
let theme = themes[name];
|
||||||
if (!theme) return;
|
if (!theme) theme = themes[DEFAULT_THEME];
|
||||||
|
|
||||||
return (await theme.loadTheme()).default;
|
return (await theme.loadTheme()).default;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user