mirror of
https://github.com/uglyboy-tl/obsidian-ink-player.git
synced 2026-07-22 05:42:02 +00:00
feat(player): add StatusBar and frontmatter-driven layout switching
- Render StatusBar component from frontmatter statusBar config - Support layout switching via frontmatter display field - Register reignsPlugin layout via PluginRegistry - Refactor view lifecycle to read frontmatter on file load - Expose getPluginSettings for external access
This commit is contained in:
parent
672d91d5a4
commit
ee605e5bdc
4 changed files with 42 additions and 17 deletions
12
src/App.tsx
12
src/App.tsx
|
|
@ -1,12 +1,18 @@
|
||||||
import type { InkStory } from "@inkweave/core";
|
import type { InkStory, StatusBarConfig } from "@inkweave/core";
|
||||||
import { Image } from "@inkweave/plugins/solidjs";
|
import { Image } from "@inkweave/plugins/solidjs";
|
||||||
import { CommandBar, Story } from "@inkweave/solidjs";
|
import { CommandBar, StatusBar, Story } from "@inkweave/solidjs";
|
||||||
import { t } from "./locales/i18n";
|
import { t } from "./locales/i18n";
|
||||||
|
|
||||||
const App = (props: { ink: InkStory }) => {
|
interface AppProps {
|
||||||
|
ink: InkStory;
|
||||||
|
statusBar?: StatusBarConfig[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const App = (props: AppProps) => {
|
||||||
return (
|
return (
|
||||||
<div id="inkweave-player" class="container">
|
<div id="inkweave-player" class="container">
|
||||||
<nav class="view-header">
|
<nav class="view-header">
|
||||||
|
{props.statusBar && <StatusBar ink={props.ink} variables={props.statusBar} />}
|
||||||
<div class="view-header-title-container mod-at-start mod-fade" />
|
<div class="view-header-title-container mod-at-start mod-fade" />
|
||||||
<CommandBar
|
<CommandBar
|
||||||
ink={props.ink}
|
ink={props.ink}
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
import { PluginRegistry } from "@inkweave/core";
|
import { PluginRegistry } from "@inkweave/core";
|
||||||
|
|
||||||
import { Platform, Plugin, type TAbstractFile, type WorkspaceLeaf } from "obsidian";
|
import { Platform, Plugin, type TAbstractFile, type WorkspaceLeaf } from "obsidian";
|
||||||
import { setupCommands } from "./commands";
|
import { setupCommands } from "./commands";
|
||||||
import { I18n, type TransItemType } from "./locales/i18n";
|
import { I18n, type TransItemType } from "./locales/i18n";
|
||||||
import { SettingsTab } from "./settings";
|
import { SettingsTab } from "./settings";
|
||||||
import { DEFAULT_SETTINGS, type Settings } from "./types";
|
import { DEFAULT_SETTINGS, type Settings } from "./types";
|
||||||
import { plugins } from "./utils/plugins";
|
import { plugins, reignsPlugin } from "./utils/plugins";
|
||||||
import { StoryView, VIEW_TYPE } from "./view";
|
import { StoryView, VIEW_TYPE } from "./view";
|
||||||
|
|
||||||
export default class InkWeavePlugin extends Plugin {
|
export default class InkWeavePlugin extends Plugin {
|
||||||
|
|
@ -16,7 +15,7 @@ export default class InkWeavePlugin extends Plugin {
|
||||||
return this.i18n.t(x, vars);
|
return this.i18n.t(x, vars);
|
||||||
}
|
}
|
||||||
|
|
||||||
private getPluginSettings(): Record<string, boolean> {
|
getPluginSettings(): Record<string, boolean> {
|
||||||
const { linedelay, debug, ...pluginSettings } = this.settings;
|
const { linedelay, debug, ...pluginSettings } = this.settings;
|
||||||
return pluginSettings;
|
return pluginSettings;
|
||||||
}
|
}
|
||||||
|
|
@ -31,11 +30,11 @@ export default class InkWeavePlugin extends Plugin {
|
||||||
this.registerExtensions(["ink"], "markdown");
|
this.registerExtensions(["ink"], "markdown");
|
||||||
|
|
||||||
setupCommands(this);
|
setupCommands(this);
|
||||||
for (const p of plugins) PluginRegistry.register(p);
|
|
||||||
PluginRegistry.setEnabled(this.getPluginSettings());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadSettings() {
|
async loadSettings() {
|
||||||
|
PluginRegistry.registerLayout(reignsPlugin);
|
||||||
|
for (const p of plugins) PluginRegistry.register(p);
|
||||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, (await this.loadData()) ?? {});
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, (await this.loadData()) ?? {});
|
||||||
PluginRegistry.setEnabled(this.getPluginSettings());
|
PluginRegistry.setEnabled(this.getPluginSettings());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,3 +26,5 @@ export const plugins: Plugin[] = [
|
||||||
memoryPlugin,
|
memoryPlugin,
|
||||||
scrollAfterChoicePlugin,
|
scrollAfterChoicePlugin,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export { reignsPlugin } from "@inkweave/plugins/solidjs";
|
||||||
|
|
|
||||||
36
src/view.ts
36
src/view.ts
|
|
@ -2,7 +2,8 @@ import "@inkweave/solidjs/solidjs.css";
|
||||||
import "@inkweave/plugins/solidjs.css";
|
import "@inkweave/plugins/solidjs.css";
|
||||||
import "./styles/styles.custom.css";
|
import "./styles/styles.custom.css";
|
||||||
|
|
||||||
import type { InkStory } from "@inkweave/core";
|
import type { InkStory, StatusBarConfig } from "@inkweave/core";
|
||||||
|
import { PluginRegistry } from "@inkweave/core";
|
||||||
import { type EventRef, ItemView, type MarkdownView, TFile, type ViewStateResult } from "obsidian";
|
import { type EventRef, ItemView, type MarkdownView, TFile, type ViewStateResult } from "obsidian";
|
||||||
import { render } from "solid-js/web";
|
import { render } from "solid-js/web";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
|
@ -15,6 +16,11 @@ export class StoryView extends ItemView {
|
||||||
appInstance: (() => void) | null = null;
|
appInstance: (() => void) | null = null;
|
||||||
ink: InkStory | null = null;
|
ink: InkStory | null = null;
|
||||||
private watcher: EventRef | null = null;
|
private watcher: EventRef | null = null;
|
||||||
|
private frontmatter: {
|
||||||
|
title?: string;
|
||||||
|
display?: string;
|
||||||
|
statusBar?: StatusBarConfig[];
|
||||||
|
} = {};
|
||||||
|
|
||||||
override getViewType() {
|
override getViewType() {
|
||||||
return VIEW_TYPE;
|
return VIEW_TYPE;
|
||||||
|
|
@ -37,9 +43,8 @@ export class StoryView extends ItemView {
|
||||||
|
|
||||||
override async setState(state: { filePath?: string }, result: ViewStateResult) {
|
override async setState(state: { filePath?: string }, result: ViewStateResult) {
|
||||||
const filePath = state?.filePath;
|
const filePath = state?.filePath;
|
||||||
const currentFilePath = useFile.getState().filePath;
|
|
||||||
|
|
||||||
if (filePath && filePath !== currentFilePath) {
|
if (filePath) {
|
||||||
await this.loadFile(filePath);
|
await this.loadFile(filePath);
|
||||||
}
|
}
|
||||||
await super.setState(state, result);
|
await super.setState(state, result);
|
||||||
|
|
@ -60,7 +65,10 @@ export class StoryView extends ItemView {
|
||||||
|
|
||||||
if (this.ink) {
|
if (this.ink) {
|
||||||
const ink = this.ink;
|
const ink = this.ink;
|
||||||
this.appInstance = render(() => App({ ink }), container as HTMLElement);
|
this.appInstance = render(
|
||||||
|
() => App({ ink, statusBar: this.frontmatter.statusBar }),
|
||||||
|
container as HTMLElement,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,15 +93,20 @@ export class StoryView extends ItemView {
|
||||||
|
|
||||||
if (markdown !== currentMarkdown || this.ink?.title !== filePath) {
|
if (markdown !== currentMarkdown || this.ink?.title !== filePath) {
|
||||||
this.ink?.dispose();
|
this.ink?.dispose();
|
||||||
this.ink = compile();
|
this.ink = null;
|
||||||
this.render();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!this.ink) {
|
||||||
|
const cache = this.app.metadataCache.getFileCache(file);
|
||||||
|
this.frontmatter = cache?.frontmatter ?? {};
|
||||||
|
PluginRegistry.setLayout(this.frontmatter.display ?? null);
|
||||||
|
this.ink = compile();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
override async onOpen() {
|
override async onOpen() {
|
||||||
this.ink = compile();
|
|
||||||
this.render();
|
|
||||||
|
|
||||||
this.watcher = this.app.vault.on("modify", async (file) => {
|
this.watcher = this.app.vault.on("modify", async (file) => {
|
||||||
const filePath = useFile.getState().filePath;
|
const filePath = useFile.getState().filePath;
|
||||||
if (file.path === filePath && file instanceof TFile) {
|
if (file.path === filePath && file instanceof TFile) {
|
||||||
|
|
@ -103,6 +116,10 @@ export class StoryView extends ItemView {
|
||||||
if (markdown !== currentMarkdown) {
|
if (markdown !== currentMarkdown) {
|
||||||
const resourcePath = useFile.getState().resourcePath;
|
const resourcePath = useFile.getState().resourcePath;
|
||||||
useFile.getState().init(filePath, markdown, resourcePath);
|
useFile.getState().init(filePath, markdown, resourcePath);
|
||||||
|
const cache = this.app.metadataCache.getFileCache(file);
|
||||||
|
this.frontmatter = cache?.frontmatter ?? {};
|
||||||
|
PluginRegistry.setLayout(this.frontmatter.display ?? null);
|
||||||
|
this.ink?.dispose();
|
||||||
this.ink = compile();
|
this.ink = compile();
|
||||||
this.render();
|
this.render();
|
||||||
}
|
}
|
||||||
|
|
@ -115,6 +132,7 @@ export class StoryView extends ItemView {
|
||||||
this.app.vault.offref(this.watcher);
|
this.app.vault.offref(this.watcher);
|
||||||
}
|
}
|
||||||
this.ink?.dispose();
|
this.ink?.dispose();
|
||||||
|
this.ink = null;
|
||||||
if (this.appInstance) {
|
if (this.appInstance) {
|
||||||
this.appInstance();
|
this.appInstance();
|
||||||
this.appInstance = null;
|
this.appInstance = null;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue