mirror of
https://github.com/jsmorabito/obsidian-commander.git
synced 2026-07-22 06:40:31 +00:00
fix: use a real Preact hook to force re-renders, not this.forceUpdate()
The previous fix (61f15f0) restored this.forceUpdate() based on
tracing through preact's diff/component internals, which showed
function components are invoked as c.render(...) - a method call
that should bind `this` to a real Component instance with a working
forceUpdate(). That trace was confirmed against the library source,
but you tested it and the settings list still didn't update in place
after adding a command, so something in that chain isn't panning out
in practice (possibly the setTimeout-based render scheduling, possibly
something else) - not worth continuing to debug blind.
Replacing it with the standard, unambiguous approach: a useState
counter bumped to force a re-render, the documented Preact/React
idiom that doesn't depend on any internal `this` plumbing. Applied to
CommandViewer, MacroViewer, and MobileModifyComponent everywhere they
previously called this.forceUpdate().
Please rebuild and re-test: add/remove/reorder/rename/recolor a
command from the settings list without switching tabs, same for
macros, and the mobile icon-picker modal.
This commit is contained in:
parent
61f15f04e0
commit
5da385da2b
3 changed files with 39 additions and 30 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
import { Platform } from "obsidian";
|
import { Platform } from "obsidian";
|
||||||
import { Fragment, h } from "preact";
|
import { Fragment, h } from "preact";
|
||||||
|
import { useState } from "preact/hooks";
|
||||||
import t from "src/l10n";
|
import t from "src/l10n";
|
||||||
import CommanderPlugin from "src/main";
|
import CommanderPlugin from "src/main";
|
||||||
import { Macro } from "src/types";
|
import { Macro } from "src/types";
|
||||||
|
|
@ -12,10 +13,13 @@ interface MacroBuilderProps {
|
||||||
plugin: CommanderPlugin;
|
plugin: CommanderPlugin;
|
||||||
macros: Macro[];
|
macros: Macro[];
|
||||||
}
|
}
|
||||||
export default function MacroViewer(
|
export default function MacroViewer({
|
||||||
this: { forceUpdate: () => void },
|
plugin,
|
||||||
{ plugin, macros }: MacroBuilderProps
|
macros,
|
||||||
): h.JSX.Element {
|
}: MacroBuilderProps): h.JSX.Element {
|
||||||
|
const [, setUpdateTick] = useState(0);
|
||||||
|
const forceUpdate = (): void => setUpdateTick((tick) => tick + 1);
|
||||||
|
|
||||||
const handleBuilder = (macro: Macro, idx?: number): void => {
|
const handleBuilder = (macro: Macro, idx?: number): void => {
|
||||||
const onClose = (updatedMacro: Macro): void => {
|
const onClose = (updatedMacro: Macro): void => {
|
||||||
macros.splice(
|
macros.splice(
|
||||||
|
|
@ -25,7 +29,7 @@ export default function MacroViewer(
|
||||||
);
|
);
|
||||||
|
|
||||||
void plugin.saveSettings();
|
void plugin.saveSettings();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
updateMacroCommands(plugin);
|
updateMacroCommands(plugin);
|
||||||
modal.close();
|
modal.close();
|
||||||
};
|
};
|
||||||
|
|
@ -36,7 +40,7 @@ export default function MacroViewer(
|
||||||
const handleDelete = (idx: number): void => {
|
const handleDelete = (idx: number): void => {
|
||||||
macros.splice(idx, 1);
|
macros.splice(idx, 1);
|
||||||
void plugin.saveSettings();
|
void plugin.saveSettings();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
updateMacroCommands(plugin);
|
updateMacroCommands(plugin);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import { createContext, Fragment, h } from "preact";
|
import { createContext, Fragment, h } from "preact";
|
||||||
|
import { useState } from "preact/hooks";
|
||||||
import CommanderPlugin from "src/main";
|
import CommanderPlugin from "src/main";
|
||||||
import CommandComponent from "./commandComponent";
|
import CommandComponent from "./commandComponent";
|
||||||
import CommandManagerBase from "src/manager/commands/commandManager";
|
import CommandManagerBase from "src/manager/commands/commandManager";
|
||||||
|
|
@ -18,10 +19,15 @@ interface CommandViewerProps {
|
||||||
children?: h.JSX.Element | h.JSX.Element[];
|
children?: h.JSX.Element | h.JSX.Element[];
|
||||||
sortable?: boolean;
|
sortable?: boolean;
|
||||||
}
|
}
|
||||||
export default function CommandViewer(
|
export default function CommandViewer({
|
||||||
this: { forceUpdate: () => void },
|
manager,
|
||||||
{ manager, plugin, children, sortable = true }: CommandViewerProps
|
plugin,
|
||||||
): h.JSX.Element {
|
children,
|
||||||
|
sortable = true,
|
||||||
|
}: CommandViewerProps): h.JSX.Element {
|
||||||
|
const [, setUpdateTick] = useState(0);
|
||||||
|
const forceUpdate = (): void => setUpdateTick((tick) => tick + 1);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<Fragment>
|
||||||
<ManagerContext.Provider value={manager}>
|
<ManagerContext.Provider value={manager}>
|
||||||
|
|
@ -45,7 +51,7 @@ export default function CommandViewer(
|
||||||
).didChooseRemove())
|
).didChooseRemove())
|
||||||
) {
|
) {
|
||||||
await manager.removeCommand(cmd);
|
await manager.removeCommand(cmd);
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
handleUp={(): void => {
|
handleUp={(): void => {
|
||||||
|
|
@ -55,7 +61,7 @@ export default function CommandViewer(
|
||||||
idx - 1
|
idx - 1
|
||||||
);
|
);
|
||||||
void manager.reorder();
|
void manager.reorder();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
}}
|
}}
|
||||||
handleDown={(): void => {
|
handleDown={(): void => {
|
||||||
arrayMoveMutable(
|
arrayMoveMutable(
|
||||||
|
|
@ -64,7 +70,7 @@ export default function CommandViewer(
|
||||||
idx + 1
|
idx + 1
|
||||||
);
|
);
|
||||||
void manager.reorder();
|
void manager.reorder();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
}}
|
}}
|
||||||
handleRename={async (
|
handleRename={async (
|
||||||
name
|
name
|
||||||
|
|
@ -72,7 +78,7 @@ export default function CommandViewer(
|
||||||
cmd.name = name;
|
cmd.name = name;
|
||||||
await plugin.saveSettings();
|
await plugin.saveSettings();
|
||||||
await manager.reorder();
|
await manager.reorder();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
}}
|
}}
|
||||||
handleNewIcon={async (): Promise<void> => {
|
handleNewIcon={async (): Promise<void> => {
|
||||||
const newIcon =
|
const newIcon =
|
||||||
|
|
@ -83,7 +89,7 @@ export default function CommandViewer(
|
||||||
cmd.icon = newIcon;
|
cmd.icon = newIcon;
|
||||||
await plugin.saveSettings();
|
await plugin.saveSettings();
|
||||||
await manager.reorder();
|
await manager.reorder();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
}
|
}
|
||||||
dispatchEvent(
|
dispatchEvent(
|
||||||
new Event("cmdr-icon-changed")
|
new Event("cmdr-icon-changed")
|
||||||
|
|
@ -108,7 +114,7 @@ export default function CommandViewer(
|
||||||
mode || modes[currentIdx + 1];
|
mode || modes[currentIdx + 1];
|
||||||
await plugin.saveSettings();
|
await plugin.saveSettings();
|
||||||
await manager.reorder();
|
await manager.reorder();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
}}
|
}}
|
||||||
handleColorChange={async (
|
handleColorChange={async (
|
||||||
color?: string
|
color?: string
|
||||||
|
|
@ -116,7 +122,7 @@ export default function CommandViewer(
|
||||||
cmd.color = color;
|
cmd.color = color;
|
||||||
await plugin.saveSettings();
|
await plugin.saveSettings();
|
||||||
await manager.reorder();
|
await manager.reorder();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
@ -146,7 +152,7 @@ export default function CommandViewer(
|
||||||
const pair = await chooseNewCommand(plugin);
|
const pair = await chooseNewCommand(plugin);
|
||||||
await manager.addCommand(pair);
|
await manager.addCommand(pair);
|
||||||
await manager.reorder();
|
await manager.reorder();
|
||||||
this.forceUpdate();
|
forceUpdate();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{t("Add command")}
|
{t("Add command")}
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,23 @@
|
||||||
import { h } from "preact";
|
import { h } from "preact";
|
||||||
import { useEffect } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import t from "src/l10n";
|
import t from "src/l10n";
|
||||||
import { ObsidianIcon } from "src/util";
|
import { ObsidianIcon } from "src/util";
|
||||||
import MobileModifyModal from "../mobileModifyModal";
|
import MobileModifyModal from "../mobileModifyModal";
|
||||||
import { ColorPicker } from "./ColorPicker";
|
import { ColorPicker } from "./ColorPicker";
|
||||||
import CommanderPlugin from "src/main";
|
import CommanderPlugin from "src/main";
|
||||||
|
|
||||||
export default function MobileModifyComponent(
|
export default function MobileModifyComponent({
|
||||||
this: { forceUpdate: () => void },
|
plugin,
|
||||||
{
|
modal: controller,
|
||||||
plugin,
|
}: {
|
||||||
modal: controller,
|
plugin: CommanderPlugin;
|
||||||
}: {
|
modal: MobileModifyModal;
|
||||||
plugin: CommanderPlugin;
|
}): h.JSX.Element {
|
||||||
modal: MobileModifyModal;
|
const [, setUpdateTick] = useState(0);
|
||||||
}
|
|
||||||
): h.JSX.Element {
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const update = (): void => {
|
const update = (): void => {
|
||||||
this.forceUpdate();
|
setUpdateTick((tick) => tick + 1);
|
||||||
};
|
};
|
||||||
addEventListener("cmdr-icon-changed", update);
|
addEventListener("cmdr-icon-changed", update);
|
||||||
return (): void => removeEventListener("cmdr-icon-changed", update);
|
return (): void => removeEventListener("cmdr-icon-changed", update);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue