Skip to content

Commit e755fb8

Browse files
bigfix(686) opening the Breadcrumbs settings tab
1 parent f8cd6cd commit e755fb8

7 files changed

Lines changed: 65 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. See [standa
44

55
## 4.X
66

7+
### [4.9.2](https://github.com/SkepticMystic/breadcrumbs/compare/4.9.1...4.9.2) (2026-05-12)
8+
9+
### Bug Fixes
10+
11+
* Fix [#686](https://github.com/SkepticMystic/breadcrumbs/issues/686) — opening the Breadcrumbs settings tab on some Android/Windows installs could freeze Obsidian's settings modal. The settings tab now wraps its render in a try/catch, logs the underlying error to the developer console, and shows a recoverable fallback UI with a "Reload settings" button instead of bricking the modal. Also serialised Svelte component teardown so `containerEl.empty()` no longer races pending `unmount()` promises, and `reactive_settings.current` falls back to defaults (with a warning) if read before init.
12+
713
### [4.9.1](https://github.com/SkepticMystic/breadcrumbs/compare/4.9.0...4.9.1) (2026-05-11)
814

915
### Bug Fixes

manifest-beta.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "breadcrumbs",
33
"name": "Breadcrumbs",
4-
"version": "4.9.1",
4+
"version": "4.9.2",
55
"minAppVersion": "1.12.0",
66
"description": "Add structured hierarchies to your notes",
77
"author": "SkepticMystic",

manifest.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"id": "breadcrumbs",
33
"name": "Breadcrumbs",
4-
"version": "4.9.1",
4+
"version": "4.9.2",
55
"minAppVersion": "1.12.0",
66
"description": "Add structured hierarchies to your notes",
77
"author": "SkepticMystic",

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "breadcrumbs",
3-
"version": "4.9.1",
3+
"version": "4.9.2",
44
"description": "Add typed-links to your Obsidian notes",
55
"main": "main.js",
66
"scripts": {

src/settings/SettingsTab.ts

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { App } from "obsidian";
2-
import { PluginSettingTab } from "obsidian";
2+
import { Notice, PluginSettingTab } from "obsidian";
3+
import { log } from "src/logger";
34
import type BreadcrumbsPlugin from "src/main";
45
import { mount, unmount } from "svelte";
56
import EdgeFieldSettings from "../components/settings/EdgeFieldSettings.svelte";
@@ -60,13 +61,50 @@ export class BreadcrumbsSettingTab extends PluginSettingTab {
6061
display(): void {
6162
const { containerEl, plugin } = this;
6263

63-
for (const c of this.components) void unmount(c);
64+
const old_components = this.components;
6465
this.components = [];
6566

66-
containerEl.empty();
67+
void Promise.all(old_components.map((c) => unmount(c))).catch(
68+
(error) => {
69+
log.error("BreadcrumbsSettingTab.unmount threw >", error);
70+
},
71+
);
6772

73+
containerEl.empty();
6874
containerEl.addClass("BC-settings-tab");
6975

76+
try {
77+
this._build(containerEl, plugin);
78+
} catch (error) {
79+
log.error("BreadcrumbsSettingTab.display threw >", error);
80+
new Notice(
81+
"Breadcrumbs: failed to render settings tab. See developer console and report at https://github.com/SkepticMystic/breadcrumbs/issues",
82+
);
83+
84+
containerEl.empty();
85+
containerEl.addClass("BC-settings-tab");
86+
87+
const fallback = containerEl.createDiv({ cls: "p-4" });
88+
fallback.createEl("h3", {
89+
text: "Breadcrumbs settings failed to load",
90+
});
91+
fallback.createEl("p", {
92+
text: String(
93+
(error as Error)?.stack ??
94+
(error as Error)?.message ??
95+
error,
96+
),
97+
cls: "text-muted",
98+
});
99+
100+
const retry = fallback.createEl("button", {
101+
text: "Reload settings",
102+
});
103+
retry.onclick = () => this.display();
104+
}
105+
}
106+
107+
private _build(containerEl: HTMLElement, plugin: BreadcrumbsPlugin): void {
70108
this.components.push(
71109
mount(EdgeFieldSettings, {
72110
props: { plugin },
@@ -215,7 +253,13 @@ export class BreadcrumbsSettingTab extends PluginSettingTab {
215253
hide() {
216254
void this.plugin.flushPendingSettings();
217255

218-
for (const c of this.components) void unmount(c);
256+
const old_components = this.components;
219257
this.components = [];
258+
259+
void Promise.all(old_components.map((c) => unmount(c))).catch(
260+
(error) => {
261+
log.error("BreadcrumbsSettingTab.unmount threw >", error);
262+
},
263+
);
220264
}
221265
}

src/stores/reactive_settings.svelte.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
import { DEFAULT_SETTINGS } from "src/const/settings";
12
import type { BreadcrumbsSettings } from "src/interfaces/settings";
3+
import { log } from "src/logger";
24

35
let _settings = $state<BreadcrumbsSettings | null>(null);
46

57
export const reactive_settings = {
68
get current(): BreadcrumbsSettings {
79
if (!_settings) {
8-
throw new Error("reactive_settings accessed before init");
10+
log.warn(
11+
"reactive_settings accessed before init — returning defaults",
12+
);
13+
_settings = structuredClone(DEFAULT_SETTINGS);
914
}
1015
return _settings;
1116
},

versions.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,5 +270,6 @@
270270
"4.9.0-beta.0": "1.12.0",
271271
"4.9.0-beta.1": "1.12.0",
272272
"4.9.0": "1.12.0",
273-
"4.9.1": "1.12.0"
273+
"4.9.1": "1.12.0",
274+
"4.9.2": "1.12.0"
274275
}

0 commit comments

Comments
 (0)