Reactivity and preset saving fixes

This commit is contained in:
Erez Shermer 2026-03-25 18:15:50 +02:00
parent 1f5961372f
commit 40d44777fb
5 changed files with 21 additions and 14 deletions

View file

@ -4,6 +4,12 @@ All notable changes to Map View are documented here.
---
## Unreleased
### Fixed
- Fixed issues with saving a new default preset and a few other UI quirks.
## 6.1.4
### Added

View file

@ -241,3 +241,5 @@ This project has limited automated test coverage. When making changes:
- **Settings changes require plugin reload**: No hot-reload for plugin settings
- **Svelte 5 runes syntax**: Use `$state`, `$derived`, `$effect` for reactivity
- All new UI should use Svelte 5, and not the vanilla JS style on which I started the plugin with, and slowly replacing.
- **`plugin.settings` is a `$state` reactive proxy**: `loadSettings()` wraps settings via `makeSettingsReactive()` (`src/settingsReactive.svelte.ts`). This means deep mutations like `settings.mapControlsSections.foo = true` are automatically tracked by Svelte components that receive `settings` as a prop — no need for `settings = { ...settings }` hacks to trigger re-renders.
- **Never use `settings = { ...settings }` to trigger reactivity**: This creates a shallow copy and breaks the reference to `plugin.settings`. Any subsequent mutation to the copy (e.g. `settings.defaultState = x`) will not reach `plugin.settings` and will not be saved.

View file

@ -106,8 +106,6 @@
noteToEdit = file;
editModeTools.noteToEdit = noteToEdit;
}
// Trigger reactivity
settings = { ...settings };
}
export function openChooseNote() {
@ -137,8 +135,6 @@
for (const key in settings.mapControlsSections) {
settings.mapControlsSections[key] = false;
}
// Trigger reactivity
settings = { ...settings };
}
settings.mapControlsSections[path] = value;
plugin.saveSettings();
@ -224,13 +220,10 @@
}
async function saveAsDefault() {
settings.defaultState = {
...mapState,
name: 'Default',
};
view.defaultState = settings.defaultState;
const newDefault = { ...mapState, name: 'Default' };
settings.defaultState = newDefault;
view.defaultState = newDefault;
presets = [view.defaultState, ...(settings.savedStates || [])];
onChangePreset();
await plugin.saveSettings();
new Notice('Default preset updated');
}
@ -285,11 +278,9 @@
? 'Expand controls'
: 'Minimize controls'}
onclick={() => {
setMapControl(
'minimized',
!settings.mapControlsMinimized,
);
minimized = !minimized;
settings.mapControlsMinimized = minimized;
plugin.saveSettings();
}}
>
{@html getIcon(minimized ? 'maximize-2' : 'minimize-2')

View file

@ -73,6 +73,7 @@ import { findOpenMapView } from 'src/pluginHelpers';
import { MapPreviewPopup } from 'src/mapPreviewPopup';
import { LayerCache } from 'src/layerCache';
import { BaseGeoLayer, cacheTagsFromLayers } from 'src/baseGeoLayer';
import { makeSettingsReactive } from 'src/settingsReactive.svelte';
export default class MapViewPlugin extends Plugin {
settings: PluginSettings;
@ -1037,6 +1038,7 @@ export default class MapViewPlugin extends Plugin {
async loadSettings() {
this.settings = Object.assign({}, structuredClone(DEFAULT_SETTINGS));
Object.assign(this.settings, await this.loadData());
this.settings = makeSettingsReactive(this.settings);
}
/** Save the plugin settings to Obsidian's cache so it can be reused later. */

View file

@ -0,0 +1,6 @@
import type { PluginSettings } from './settings';
export function makeSettingsReactive(settings: PluginSettings): PluginSettings {
let reactive: PluginSettings = $state(settings);
return reactive;
}