Skip to content

Commit b51dd92

Browse files
committed
feat: display messages in status bar (including error ones)
ref #4, ref #5
1 parent 99b2581 commit b51dd92

File tree

1 file changed

+113
-79
lines changed

1 file changed

+113
-79
lines changed

main.ts

Lines changed: 113 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { Notice, Plugin, PluginSettingTab, Setting } from "obsidian";
22
import simpleGit, { CheckRepoActions, SimpleGit } from "simple-git";
3+
import { FileStatusResult } from "simple-git/typings/response";
34

45
enum PluginState {
56
idle,
6-
checkRepoClean,
7+
status,
78
pull,
89
add,
910
commit,
@@ -21,20 +22,24 @@ export default class ObsidianGit extends Plugin {
2122

2223
setState(state: PluginState) {
2324
this.state = state;
24-
this.statusBar.display(this);
25-
this.updateStatusBar();
25+
this.refreshStatusBar();
2626
}
2727

2828
getState(): PluginState {
2929
return this.state;
3030
}
3131

3232
async onload() {
33+
let statusBarEl = this.addStatusBarItem();
34+
this.statusBar = new StatusBar(statusBarEl);
35+
this.setState(PluginState.status);
36+
3337
const adapter: any = this.app.vault.adapter;
3438
const git = simpleGit(adapter.basePath);
39+
3540
let isValidRepo = git.checkIsRepo(CheckRepoActions.IS_REPO_ROOT);
3641
if (!isValidRepo) {
37-
new Notice("Valid git repository not found.");
42+
this.displayMessage("Valid git repository not found.", 0);
3843
return;
3944
}
4045

@@ -49,34 +54,27 @@ export default class ObsidianGit extends Plugin {
4954
if (typeof remote === "string") {
5055
this.settings.remote = remote.trim();
5156
} else {
52-
new Notice("Failed to detect remote.");
57+
this.displayMessage("Failed to detect remote.", 0);
5358
return;
5459
}
5560

56-
let statusBarEl = this.addStatusBarItem();
57-
this.statusBar = new StatusBar(statusBarEl);
58-
this.statusBar.displayIdle();
59-
this.setState(PluginState.idle);
60-
6161
if (this.settings.autoPullOnBoot) {
62-
setTimeout(
63-
async () =>
64-
await this.pull().then((filesUpdated) => {
65-
this.setState(PluginState.idle);
66-
this.maybeNotice(
67-
`Pulled new changes. ${filesUpdated} files updated.`
68-
);
69-
}),
70-
700
71-
);
62+
await this.pull().then((filesUpdated) => {
63+
this.setState(PluginState.idle);
64+
let message =
65+
filesUpdated > 0
66+
? `Pulled new changes. ${filesUpdated} files updated`
67+
: "Everything up-to-date";
68+
this.displayMessage(message);
69+
});
7270
}
7371

7472
if (this.settings.autoSaveInterval > 0) {
7573
this.enableAutoBackup();
7674
}
7775

7876
this.registerInterval(
79-
window.setInterval(() => this.updateStatusBar(), 10 * 1000)
77+
window.setInterval(() => this.refreshStatusBar(), 1000)
8078
);
8179

8280
this.addSettingTab(new ObsidianGitSettingsTab(this.app, this));
@@ -85,14 +83,15 @@ export default class ObsidianGit extends Plugin {
8583
id: "pull",
8684
name: "Pull from remote repository",
8785
callback: async () => {
88-
let filesUpdated = await this.pull();
89-
if (filesUpdated > 0) {
90-
this.maybeNotice(
91-
`Pulled new changes. ${filesUpdated} files updated.`
92-
);
93-
} else {
94-
this.maybeNotice("Everything is up-to-date");
95-
}
86+
await this.pull().then((filesUpdated) => {
87+
if (filesUpdated > 0) {
88+
this.displayMessage(
89+
`Pulled new changes. ${filesUpdated} files updated`
90+
);
91+
} else {
92+
this.displayMessage("Everything is up-to-date");
93+
}
94+
});
9695
this.setState(PluginState.idle);
9796
},
9897
});
@@ -101,19 +100,18 @@ export default class ObsidianGit extends Plugin {
101100
id: "push",
102101
name: "Commit *all* changes and push to remote repository",
103102
callback: async () =>
104-
await this.isRepoClean().then(async (isClean) => {
105-
if (isClean) {
106-
this.maybeNotice(
107-
"No updates detected. Nothing to push."
108-
);
103+
await this.getFilesChanged().then(async (files) => {
104+
if (!files.length) {
105+
this.displayMessage("No changes detected");
109106
} else {
110-
this.maybeNotice(
111-
"Pushing changes to remote repository.."
112-
);
113107
await this.add()
114108
.then(async () => await this.commit())
115-
.then(async () => await this.push());
116-
this.maybeNotice("Pushed!");
109+
.then(async () => await this.push())
110+
.then(() =>
111+
this.displayMessage(
112+
`Pushed ${files.length} files`
113+
)
114+
);
117115
}
118116
this.setState(PluginState.idle);
119117
}),
@@ -125,15 +123,19 @@ export default class ObsidianGit extends Plugin {
125123
}
126124

127125
// region: main methods
128-
async isRepoClean(): Promise<boolean> {
129-
this.setState(PluginState.checkRepoClean);
126+
async getFilesChanged(): Promise<FileStatusResult[]> {
127+
this.setState(PluginState.status);
130128
let status = await this.git.status();
131-
return status.isClean();
129+
return status.files;
132130
}
133131

134132
async add(): Promise<void> {
135133
this.setState(PluginState.add);
136-
await this.git.add("./*", (err: Error) => {});
134+
await this.git.add(
135+
"./*",
136+
(err: Error | null) =>
137+
err && this.displayError(`Cannot add files: ${err.message}`)
138+
);
137139
}
138140

139141
async commit(): Promise<void> {
@@ -146,34 +148,47 @@ export default class ObsidianGit extends Plugin {
146148

147149
async push(): Promise<void> {
148150
this.setState(PluginState.push);
149-
await this.git.push(this.settings.remote, this.settings.currentBranch);
151+
await this.git.push(
152+
this.settings.remote,
153+
this.settings.currentBranch,
154+
null,
155+
(err: Error | null) => {
156+
err && this.displayError(`Push failed ${err.message}`);
157+
}
158+
);
150159

151160
this.lastUpdate = Date.now();
152161
}
153162

154163
async pull(): Promise<number> {
155164
this.setState(PluginState.pull);
156-
let pullResult = await this.git.pull();
165+
let pullResult = await this.git.pull(
166+
null,
167+
null,
168+
null,
169+
(err: Error | null) =>
170+
err && this.displayError(`Pull failed ${err.message}`)
171+
);
157172
this.lastUpdate = Date.now();
158173
return pullResult.files.length;
159174
}
160175

161176
// endregion: main methods
162177

163-
isIdle(): boolean {
164-
return this.getState() === PluginState.idle;
165-
}
166-
167178
enableAutoBackup() {
168179
let minutes = this.settings.autoSaveInterval;
169180
this.intervalID = window.setInterval(
170181
async () =>
171-
await this.isRepoClean().then(async (isClean) => {
172-
if (!isClean) {
182+
await this.getFilesChanged().then(async (files) => {
183+
if (files.length > 0) {
173184
await this.add()
174185
.then(async () => await this.commit())
175-
.then(async () => await this.push());
176-
this.maybeNotice("Pushed changes to remote repository");
186+
.then(async () => await this.push())
187+
.then(() =>
188+
this.displayMessage(
189+
`Pushed ${files.length} files`
190+
)
191+
);
177192
}
178193
this.setState(PluginState.idle);
179194
}),
@@ -191,22 +206,24 @@ export default class ObsidianGit extends Plugin {
191206
return false;
192207
}
193208

194-
// region: displaying / formatting stuff
195-
maybeNotice(text: string): void {
209+
// region: displaying / formatting messages
210+
displayMessage(message: string, timeout: number = 4 * 1000): void {
211+
this.statusBar.displayMessage(message.toLowerCase(), timeout);
212+
196213
if (!this.settings.disablePopups) {
197-
new Notice(text);
198-
} else {
199-
// todo: replace this with a message in a status bar
200-
console.log(`git obsidian: ${text}`);
214+
new Notice(message);
201215
}
216+
217+
console.log(`git obsidian: ${message}`);
202218
}
203219

204-
updateStatusBar(): void {
205-
if (this.lastUpdate && this.isIdle()) {
206-
this.statusBar.displayFromNow(this.lastUpdate);
207-
} else if (!this.lastUpdate && this.isIdle()) {
208-
this.statusBar.displayIdle();
209-
}
220+
displayError(message: string, timeout: number = 0): void {
221+
new Notice(message);
222+
this.statusBar.displayMessage(message.toLowerCase(), timeout);
223+
}
224+
225+
refreshStatusBar(): void {
226+
this.statusBar.displayState(this.getState(), this.lastUpdate);
210227
}
211228

212229
async formatCommitMessage(template: string): Promise<string> {
@@ -377,25 +394,34 @@ class ObsidianGitSettingsTab extends PluginSettingTab {
377394

378395
class StatusBar {
379396
private statusBarEl: HTMLElement;
397+
private isDisplayingMessage: boolean = false;
380398

381399
constructor(statusBarEl: HTMLElement) {
382400
this.statusBarEl = statusBarEl;
383401
}
384402

385-
displayFromNow(timestamp: number): void {
386-
let moment = (window as any).moment;
387-
let fromNow = moment(timestamp).fromNow();
388-
this.statusBarEl.setText(`git: last update ${fromNow}..`);
389-
}
403+
displayMessage(message: string, timeout: number) {
404+
this.isDisplayingMessage = true;
405+
this.statusBarEl.setText(`git: ${message.slice(0, 100)}`);
390406

391-
displayIdle(): void {
392-
this.statusBarEl.setText("git: ready");
407+
if (timeout && timeout > 0) {
408+
window.setTimeout(() => {
409+
this.isDisplayingMessage = false;
410+
}, timeout);
411+
}
393412
}
394413

395-
display(plugin: ObsidianGit) {
396-
switch (plugin.getState()) {
397-
case PluginState.checkRepoClean:
398-
this.statusBarEl.setText("git: checking repo..");
414+
displayState(state: PluginState, lastUpdate: number) {
415+
if (this.isDisplayingMessage) {
416+
return;
417+
}
418+
419+
switch (state) {
420+
case PluginState.idle:
421+
this.displayFromNow(lastUpdate);
422+
break;
423+
case PluginState.status:
424+
this.statusBarEl.setText("git: checking repo status..");
399425
break;
400426
case PluginState.add:
401427
this.statusBarEl.setText("git: adding files to repo..");
@@ -407,10 +433,18 @@ class StatusBar {
407433
this.statusBarEl.setText("git: pushing changes..");
408434
break;
409435
case PluginState.pull:
410-
this.statusBarEl.setText(
411-
"git: pulling changes from remote repo.."
412-
);
436+
this.statusBarEl.setText("git: pulling changes..");
413437
break;
414438
}
415439
}
440+
441+
displayFromNow(timestamp: number): void {
442+
if (timestamp) {
443+
let moment = (window as any).moment;
444+
let fromNow = moment(timestamp).fromNow();
445+
this.statusBarEl.setText(`git: last update ${fromNow}..`);
446+
} else {
447+
this.statusBarEl.setText(`git: ready`);
448+
}
449+
}
416450
}

0 commit comments

Comments
 (0)