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.
Corrects commit b83e10a. I removed these calls on the assumption
that `this` is undefined in a Preact function component, based on
standard JS semantics. That's wrong for Preact specifically: its
diff implementation invokes function components as `c.render(props,
state, context)` (see node_modules/preact/src/diff/index.js), which
is a method call and therefore binds `this` to Preact's internal
per-instance "PFC backing instance" - a real object with a working
forceUpdate(). So this.forceUpdate() was live code all along, and
removing it broke in-place re-rendering: adding/removing/renaming/
recoloring a command or macro would save correctly but the settings
list wouldn't visually update until you switched tabs and back
(reported by the user after testing).
Restores the calls, now with an explicit `this: { forceUpdate: () =>
void }` parameter on each component function so TypeScript actually
knows the type instead of silently treating it as `any` like the
original code did.
CommandViewer, MacroViewer, and MobileModifyComponent are all plain
function components (not classes), so `this` inside their handlers
is undefined - this.forceUpdate() has never been able to succeed
since the plugin's first release, it just throws before Preact ever
gets a chance to visually update in place. The actual state mutation
and settings.save() on each of these handlers already happens before
the throwing line, so removing it doesn't change what the UI shows;
it removes a guaranteed, silently-swallowed error on every add/
remove/reorder/rename/recolor action.
Also drops mobileModifyComponent's cmdr-icon-changed listener, whose
only job was calling the broken forceUpdate.
Given this changes real code paths, worth a manual pass: add/remove/
reorder/rename commands and macros from the settings tab, and check
the mobile icon-picker modal, to confirm nothing regresses now that
the throw is gone.
- Add explicit `(): void` return types to several useEffect cleanup
callbacks (settingTabComponent, ColorPicker, AdvancedToolbarSettings,
mobileModifyComponent).
- Widen Mode's literal union with `(string & {})` instead of a bare
string constituent, preserving autocomplete without the redundant
type warning.
- Drop an unnecessary `as ItemView` cast in pageHeaderManager now that
the preceding instanceof guard already narrows the type.
- Switch eslint.config.mts from the deprecated tseslint.config() to
eslint's own defineConfig().
Type-level only, no runtime behavior change.