-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.ts
More file actions
156 lines (140 loc) · 4.49 KB
/
Copy pathindex.ts
File metadata and controls
156 lines (140 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/**
* Git Sync extension — VS-Code-style source control for the notes folder.
*
* Syncs via the user's LOCAL git binary (no tokens, no OAuth): the user's
* own git config (user.name/user.email) and SSH agent / credential helper
* do auth. git's stderr is surfaced verbatim with friendly hints, exactly
* like VS Code.
*
* The heavy lifting lives in useGitSync (state + ops) and GitSyncPanel (UI);
* this file only wires the manifest, panel, and commands. Commands share one
* GitEngine built on the bridge runner so palette actions behave identically
* to panel actions.
*/
import { GitEngine } from "@/core/git/engine"
import { gitRunner } from "@/core/bridge/gitRunner"
import { isTauri } from "@/core/bridge/runtime"
import type { OpenNotesExtension, OpenNotesExtensionAPI } from "@/core/extensions/types"
import { GIT_SYNC_COPY as C } from "./copy"
import { GitSyncPanel } from "./GitSyncPanel"
const REPO_PATH_STORAGE_KEY = "repoPath"
/** One engine for all palette commands; stateless and cheap to construct. */
const engine = new GitEngine(gitRunner)
function repoPathOrToast(api: OpenNotesExtensionAPI): string | null {
const path = api.storage.get(REPO_PATH_STORAGE_KEY)
if (!path) api.showToast(C.commands.noRepo)
return path
}
function guardDesktop(api: OpenNotesExtensionAPI): boolean {
if (!isTauri()) {
api.showToast(C.commands.unavailable)
return false
}
return true
}
export const gitSyncExtension: OpenNotesExtension = {
manifest: {
id: "git-sync",
name: "Git Sync",
version: "0.1.0",
description:
"Sync your notes folder with your local git — VS Code-style, no tokens.",
author: "OpenNotes",
defaultEnabled: true,
},
activate(ctx) {
ctx.registerPanel({
id: "git-sync",
title: C.panelTitle,
icon: "FolderGit2",
side: "right",
component: GitSyncPanel,
})
ctx.registerCommand({
id: "open",
title: "Git Sync: Open panel",
run(api) {
// The host owns panel visibility; the command can only point the way.
api.showToast(C.commands.openToast)
},
})
ctx.registerCommand({
id: "commit",
title: "Git Sync: Commit all changes",
async run(api) {
if (!guardDesktop(api)) return
const cwd = repoPathOrToast(api)
if (!cwd) return
const message =
api.storage.get("lastCommitMessage")?.trim() ||
window.prompt("Commit message")?.trim() ||
""
if (!message) {
api.showToast(C.commit.emptyMessage)
return
}
try {
const result = await engine.commitAll(cwd, message)
if (result.nothingToCommit) {
api.showToast(C.commit.nothingToCommit)
return
}
api.storage.set("lastCommitMessage", message)
api.showToast(C.commit.success)
} catch (e) {
api.showToast(e instanceof Error ? e.message : String(e))
}
},
})
ctx.registerCommand({
id: "push",
title: "Git Sync: Push",
async run(api) {
if (!guardDesktop(api)) return
const cwd = repoPathOrToast(api)
if (!cwd) return
try {
await engine.push(cwd, { setUpstream: true, remote: "origin" })
api.showToast(C.sync.pushSuccess)
} catch (e) {
api.showToast(e instanceof Error ? e.message : String(e))
}
},
})
ctx.registerCommand({
id: "pull",
title: "Git Sync: Pull",
async run(api) {
if (!guardDesktop(api)) return
const cwd = repoPathOrToast(api)
if (!cwd) return
try {
const { changed } = await engine.pull(cwd)
api.showToast(changed ? C.sync.pullUpdated : C.sync.pullUpToDate)
} catch (e) {
api.showToast(e instanceof Error ? e.message : String(e))
}
},
})
ctx.registerCommand({
id: "refresh",
title: "Git Sync: Refresh status",
async run(api) {
if (!guardDesktop(api)) return
const cwd = repoPathOrToast(api)
if (!cwd) return
try {
const status = await engine.status(cwd)
api.showToast(
status.clean
? C.changes.empty
: `${C.changes.title}: ${status.staged.length + status.modified.length + status.untracked.length + status.conflicted.length}`
)
} catch (e) {
api.showToast(e instanceof Error ? e.message : String(e))
}
},
})
},
}
export default gitSyncExtension