Skip to content

Commit d453c6f

Browse files
committed
feat: reload settings on file change
close #779
1 parent 27d817a commit d453c6f

File tree

7 files changed

+167
-87
lines changed

7 files changed

+167
-87
lines changed

src/main.ts

Lines changed: 133 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import { Errors } from "isomorphic-git";
2-
import type {
3-
Debouncer,
4-
EventRef,
5-
Menu,
6-
TAbstractFile,
7-
WorkspaceLeaf,
8-
} from "obsidian";
2+
import type { Debouncer, Menu, TAbstractFile, WorkspaceLeaf } from "obsidian";
93
import {
104
debounce,
115
MarkdownView,
@@ -77,11 +71,7 @@ export default class ObsidianGit extends Plugin {
7771
cachedStatus: Status | undefined;
7872
// Used to store the path of the file that is currently shown in the diff view.
7973
lastDiffViewState: Record<string, unknown> | undefined;
80-
openEvent: EventRef;
81-
modifyEvent: EventRef;
82-
deleteEvent: EventRef;
83-
createEvent: EventRef;
84-
renameEvent: EventRef;
74+
intervalsToClear: number[] = [];
8575
lineAuthoringFeature: LineAuthoringFeature = new LineAuthoringFeature(this);
8676

8777
debRefresh: Debouncer<[], void>;
@@ -156,11 +146,62 @@ export default class ObsidianGit extends Plugin {
156146
this.addSettingTab(this.settingsTab);
157147

158148
if (!this.localStorage.getPluginDisabled()) {
159-
this.loadPlugin();
149+
this.registerStuff();
150+
151+
this.app.workspace.onLayoutReady(() =>
152+
this.init({ fromReload: false }).catch((e) =>
153+
this.displayError(e)
154+
)
155+
);
160156
}
161157
}
162158

163-
loadPlugin() {
159+
onExternalSettingsChange() {
160+
this.reloadSettings().catch((e) => this.displayError(e));
161+
}
162+
163+
/** Reloads the settings from disk and applies them by unloading the plugin
164+
* and initializing it again.
165+
*/
166+
async reloadSettings(): Promise<void> {
167+
const previousSettings = JSON.stringify(this.settings);
168+
169+
await this.loadSettings();
170+
171+
const newSettings = JSON.stringify(this.settings);
172+
173+
// Only reload plugin if the settings have actually changed
174+
if (previousSettings !== newSettings) {
175+
this.log("Reloading settings");
176+
177+
this.unloadPlugin();
178+
179+
await this.init({ fromReload: true });
180+
181+
this.app.workspace
182+
.getLeavesOfType(SOURCE_CONTROL_VIEW_CONFIG.type)
183+
.forEach((leaf) => {
184+
if (!(leaf.isDeferred ?? false))
185+
return (leaf.view as GitView).reload();
186+
});
187+
188+
this.app.workspace
189+
.getLeavesOfType(HISTORY_VIEW_CONFIG.type)
190+
.forEach((leaf) => {
191+
if (!(leaf.isDeferred ?? false))
192+
return (leaf.view as HistoryView).reload();
193+
});
194+
}
195+
}
196+
197+
/** This method only registers events, views, commands and more.
198+
*
199+
* This only needs to be called once since the registered events are
200+
* unregistered when the plugin is unloaded.
201+
*
202+
* This mustn't depend on the plugin's settings.
203+
*/
204+
registerStuff(): void {
164205
this.registerEvent(
165206
this.app.workspace.on("obsidian-git:refresh", () => {
166207
this.refresh().catch((e) => this.displayError(e));
@@ -172,9 +213,46 @@ export default class ObsidianGit extends Plugin {
172213
})
173214
);
174215

216+
this.registerEvent(
217+
this.app.workspace.on("file-menu", (menu, file, source) => {
218+
this.handleFileMenu(menu, file, source);
219+
})
220+
);
221+
222+
this.registerEvent(
223+
this.app.workspace.on("active-leaf-change", (leaf) => {
224+
this.handleViewActiveState(leaf);
225+
})
226+
);
227+
this.registerEvent(
228+
this.app.vault.on("modify", () => {
229+
this.debRefresh();
230+
this.autoCommitDebouncer?.();
231+
})
232+
);
233+
this.registerEvent(
234+
this.app.vault.on("delete", () => {
235+
this.debRefresh();
236+
this.autoCommitDebouncer?.();
237+
})
238+
);
239+
this.registerEvent(
240+
this.app.vault.on("create", () => {
241+
this.debRefresh();
242+
this.autoCommitDebouncer?.();
243+
})
244+
);
245+
this.registerEvent(
246+
this.app.vault.on("rename", () => {
247+
this.debRefresh();
248+
this.autoCommitDebouncer?.();
249+
})
250+
);
251+
175252
this.registerView(SOURCE_CONTROL_VIEW_CONFIG.type, (leaf) => {
176253
return new GitView(leaf, this);
177254
});
255+
178256
this.registerView(HISTORY_VIEW_CONFIG.type, (leaf) => {
179257
return new HistoryView(leaf, this);
180258
});
@@ -207,44 +285,16 @@ export default class ObsidianGit extends Plugin {
207285
}
208286
);
209287

210-
this.lineAuthoringFeature.onLoadPlugin();
211-
212288
this.registerHoverLinkSource(SOURCE_CONTROL_VIEW_CONFIG.type, {
213289
display: "Git View",
214290
defaultMod: true,
215291
});
216292

293+
this.lineAuthoringFeature.onLoadPlugin();
294+
217295
this.setRefreshDebouncer();
218296

219297
addCommmands(this);
220-
221-
this.registerEvent(
222-
this.app.workspace.on("file-menu", (menu, file, source) => {
223-
this.handleFileMenu(menu, file, source);
224-
})
225-
);
226-
227-
if (this.settings.showStatusBar) {
228-
// init statusBar
229-
const statusBarEl = this.addStatusBarItem();
230-
this.statusBar = new StatusBar(statusBarEl, this);
231-
this.registerInterval(
232-
window.setInterval(() => this.statusBar?.display(), 1000)
233-
);
234-
}
235-
236-
if (Platform.isDesktop && this.settings.showBranchStatusBar) {
237-
const branchStatusBarEl = this.addStatusBarItem();
238-
this.branchBar = new BranchStatusBar(branchStatusBarEl, this);
239-
this.registerInterval(
240-
window.setInterval(
241-
() => void this.branchBar?.display().catch(console.error),
242-
60000
243-
)
244-
);
245-
}
246-
247-
this.app.workspace.onLayoutReady(() => this.init());
248298
}
249299

250300
setRefreshDebouncer(): void {
@@ -373,11 +423,14 @@ export default class ObsidianGit extends Plugin {
373423

374424
this.lineAuthoringFeature.deactivateFeature();
375425
this.automaticsManager.unload();
376-
this.app.workspace.offref(this.openEvent);
377-
this.app.metadataCache.offref(this.modifyEvent);
378-
this.app.metadataCache.offref(this.deleteEvent);
379-
this.app.metadataCache.offref(this.createEvent);
380-
this.app.metadataCache.offref(this.renameEvent);
426+
this.branchBar?.remove();
427+
this.statusBar?.remove();
428+
429+
for (const interval of this.intervalsToClear) {
430+
window.clearInterval(interval);
431+
}
432+
this.intervalsToClear = [];
433+
381434
this.debRefresh.cancel();
382435
}
383436

@@ -406,7 +459,15 @@ export default class ObsidianGit extends Plugin {
406459
return Platform.isDesktopApp;
407460
}
408461

409-
async init(): Promise<void> {
462+
async init({ fromReload = false }): Promise<void> {
463+
if (this.settings.showStatusBar) {
464+
const statusBarEl = this.addStatusBarItem();
465+
this.statusBar = new StatusBar(statusBarEl, this);
466+
this.intervalsToClear.push(
467+
window.setInterval(() => this.statusBar?.display(), 1000)
468+
);
469+
}
470+
410471
try {
411472
if (this.useSimpleGit) {
412473
this.gitManager = new SimpleGit(this);
@@ -432,40 +493,32 @@ export default class ObsidianGit extends Plugin {
432493
this.gitReady = true;
433494
this.setPluginState({ gitAction: CurrentGitAction.idle });
434495

435-
this.openEvent = this.app.workspace.on(
436-
"active-leaf-change",
437-
(leaf) => this.handleViewActiveState(leaf)
438-
);
439-
440-
this.modifyEvent = this.app.vault.on("modify", () => {
441-
this.debRefresh();
442-
this.autoCommitDebouncer?.();
443-
});
444-
this.deleteEvent = this.app.vault.on("delete", () => {
445-
this.debRefresh();
446-
this.autoCommitDebouncer?.();
447-
});
448-
this.createEvent = this.app.vault.on("create", () => {
449-
this.debRefresh();
450-
this.autoCommitDebouncer?.();
451-
});
452-
this.renameEvent = this.app.vault.on("rename", () => {
453-
this.debRefresh();
454-
this.autoCommitDebouncer?.();
455-
});
456-
457-
this.registerEvent(this.modifyEvent);
458-
this.registerEvent(this.deleteEvent);
459-
this.registerEvent(this.createEvent);
460-
this.registerEvent(this.renameEvent);
461-
496+
if (
497+
Platform.isDesktop &&
498+
this.settings.showBranchStatusBar
499+
) {
500+
const branchStatusBarEl = this.addStatusBarItem();
501+
this.branchBar = new BranchStatusBar(
502+
branchStatusBarEl,
503+
this
504+
);
505+
this.intervalsToClear.push(
506+
window.setInterval(
507+
() =>
508+
void this.branchBar
509+
?.display()
510+
.catch(console.error),
511+
60000
512+
)
513+
);
514+
}
462515
await this.branchBar?.display();
463516

464517
this.lineAuthoringFeature.conditionallyActivateBySettings();
465518

466519
this.app.workspace.trigger("obsidian-git:refresh");
467520

468-
if (this.settings.autoPullOnBoot) {
521+
if (!fromReload && this.settings.autoPullOnBoot) {
469522
this.promiseQueue.addTask(() =>
470523
this.pullChangesFromRemote()
471524
);
@@ -490,7 +543,7 @@ export default class ObsidianGit extends Plugin {
490543
try {
491544
await this.gitManager.init();
492545
new Notice("Initialized new repo");
493-
await this.init();
546+
await this.init({ fromReload: true });
494547
} catch (e) {
495548
this.displayError(e);
496549
}
@@ -595,7 +648,7 @@ export default class ObsidianGit extends Plugin {
595648
*/
596649
async isAllInitialized(): Promise<boolean> {
597650
if (!this.gitReady) {
598-
await this.init();
651+
await this.init({ fromReload: true });
599652
}
600653
return this.gitReady;
601654
}

src/setting/settings.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ export class ObsidianGitSettingsTab extends PluginSettingTab {
777777
if (value) {
778778
plugin.unloadPlugin();
779779
} else {
780-
plugin.loadPlugin();
780+
plugin.init().catch((e) => plugin.displayError(e));
781781
}
782782
new Notice(
783783
"Obsidian must be restarted for the changes to take affect."

src/statusBar.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,4 +166,8 @@ export class StatusBar {
166166
this.unPushedCommits =
167167
await this.plugin.gitManager.getUnpushedCommits();
168168
}
169+
170+
public remove() {
171+
this.statusBarEl.remove();
172+
}
169173
}

src/ui/history/historyView.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import HistoryViewComponent from "./historyView.svelte";
66

77
export default class HistoryView extends ItemView implements HoverParent {
88
plugin: ObsidianGit;
9-
private _view: HistoryViewComponent;
9+
private _view: HistoryViewComponent | undefined;
1010
hoverPopover: HoverPopover | null;
1111

1212
constructor(leaf: WorkspaceLeaf, plugin: ObsidianGit) {
@@ -28,18 +28,30 @@ export default class HistoryView extends ItemView implements HoverParent {
2828
}
2929

3030
onClose(): Promise<void> {
31-
this._view.$destroy();
31+
this._view?.$destroy();
3232
return super.onClose();
3333
}
3434

35-
onOpen(): Promise<void> {
35+
reload(): void {
36+
this._view?.$destroy();
3637
this._view = new HistoryViewComponent({
3738
target: this.contentEl,
3839
props: {
3940
plugin: this.plugin,
4041
view: this,
4142
},
4243
});
44+
this._view = new HistoryViewComponent({
45+
target: this.contentEl,
46+
props: {
47+
plugin: this.plugin,
48+
view: this,
49+
},
50+
});
51+
}
52+
53+
onOpen(): Promise<void> {
54+
this.reload();
4355
return super.onOpen();
4456
}
4557
}

src/ui/sourceControl/sourceControl.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@
104104
const unPushedCommits = await plugin.gitManager.getUnpushedCommits();
105105
106106
buttons.forEach((btn) => {
107+
// when reloading the view from settings change, the btn are null at first
108+
if (!btn) return;
107109
if (Platform.isMobile) {
108110
btn.removeClass("button-border");
109111
if (btn.id == "push" && unPushedCommits > 0) {

0 commit comments

Comments
 (0)