@yiln-dsh/dsh-plugin-file-explorer 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/client.js +259 -80
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ A DSH `dsh.bundle` that contributes a workspace file explorer page to the
|
|
|
36
36
|
|
|
37
37
|
## Install
|
|
38
38
|
|
|
39
|
-
The package version is `@yiln-dsh/dsh-plugin-file-explorer@0.5.
|
|
39
|
+
The package version is `@yiln-dsh/dsh-plugin-file-explorer@0.5.1`.
|
|
40
40
|
|
|
41
41
|
The right-panel package must be installed in the same `web` profile:
|
|
42
42
|
|
|
@@ -53,7 +53,7 @@ pnpm pack
|
|
|
53
53
|
```
|
|
54
54
|
|
|
55
55
|
```bash
|
|
56
|
-
dsh plugin --profile web add ./yiln-dsh-dsh-plugin-file-explorer-0.5.
|
|
56
|
+
dsh plugin --profile web add ./yiln-dsh-dsh-plugin-file-explorer-0.5.1.tgz
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
### npm package
|
package/client.js
CHANGED
|
@@ -21,11 +21,180 @@ window.__ModuleLoader__.load({
|
|
|
21
21
|
|
|
22
22
|
const inject = ["slots", "rightPanel"];
|
|
23
23
|
|
|
24
|
+
const LOCALE_NS = "file-explorer";
|
|
25
|
+
const ZH_DICT = {
|
|
26
|
+
"files.title": "文件",
|
|
27
|
+
"git.title": "Git 图谱",
|
|
28
|
+
"workspace": "工作区",
|
|
29
|
+
"files.refresh": "刷新",
|
|
30
|
+
"files.refreshList": "刷新文件列表",
|
|
31
|
+
"git.refreshGraph": "刷新图谱",
|
|
32
|
+
"files.up": "上一级",
|
|
33
|
+
"files.goUp": "返回上级目录",
|
|
34
|
+
"files.delete": "删除",
|
|
35
|
+
"files.deleteFile": "删除 {name}",
|
|
36
|
+
"files.confirmDelete": "确认删除 {name}",
|
|
37
|
+
"files.clickAgain": "再次点击确认删除",
|
|
38
|
+
"files.deleteFailed": "删除失败",
|
|
39
|
+
"files.view": "查看",
|
|
40
|
+
"files.viewFile": "查看 {name}",
|
|
41
|
+
"files.download": "下载",
|
|
42
|
+
"files.downloadFile": "下载 {name}",
|
|
43
|
+
"files.downloadFailed": "下载失败",
|
|
44
|
+
"files.closePreview": "关闭预览",
|
|
45
|
+
"files.preview": "预览",
|
|
46
|
+
"files.fullscreen": "全屏",
|
|
47
|
+
"files.enterFullscreen": "进入全屏",
|
|
48
|
+
"files.exitFullscreen": "退出全屏",
|
|
49
|
+
"files.imageControls": "图片控制",
|
|
50
|
+
"files.zoomIn": "放大",
|
|
51
|
+
"files.zoomOut": "缩小",
|
|
52
|
+
"files.resetZoom": "重置缩放",
|
|
53
|
+
"files.resetImageZoom": "重置图片缩放",
|
|
54
|
+
"files.imagePreview": "图片预览",
|
|
55
|
+
"files.previewDialog": "文件预览",
|
|
56
|
+
"files.workspaceRoot": "工作区根目录",
|
|
57
|
+
"files.loading": "加载中…",
|
|
58
|
+
"git.loading": "加载中…",
|
|
59
|
+
"files.empty": "空文件夹",
|
|
60
|
+
"files.listFailed": "文件列表加载失败",
|
|
61
|
+
"files.readFailed": "文件读取失败",
|
|
62
|
+
"files.imageMeta": "图片 / {size}",
|
|
63
|
+
"files.binary": "二进制文件",
|
|
64
|
+
"files.fileTooLarge": "文件过大,无法在此预览",
|
|
65
|
+
"files.imageTooLarge": "图片过大,无法在此预览",
|
|
66
|
+
"files.noPreview": "(无预览)",
|
|
67
|
+
"files.binaryNoPreview": "二进制文件无法预览",
|
|
68
|
+
"git.logFailed": "Git 提交记录加载失败",
|
|
69
|
+
"git.commitFailed": "提交详情加载失败",
|
|
70
|
+
"git.diffFailed": "差异加载失败",
|
|
71
|
+
"git.loadingChanges": "加载变更…",
|
|
72
|
+
"git.noDiff": "(无差异)",
|
|
73
|
+
"git.noMessage": "(无提交信息)",
|
|
74
|
+
"git.diffTruncated": "…(差异已截断)",
|
|
75
|
+
"git.uncommitted": "未提交的更改",
|
|
76
|
+
"git.workingTree": "工作区",
|
|
77
|
+
"git.workingTreeLabel": "工作区",
|
|
78
|
+
"git.noCommitsYet": "暂无提交",
|
|
79
|
+
"git.noCommitsYetSuffix": "(暂无提交)",
|
|
80
|
+
"git.noData": "暂无数据",
|
|
81
|
+
"git.detachedHead": "游离 HEAD",
|
|
82
|
+
"git.allBranches": "所有分支",
|
|
83
|
+
"git.branchFilter": "分支筛选",
|
|
84
|
+
"git.currentBranch": "当前分支",
|
|
85
|
+
"git.diff": "差异",
|
|
86
|
+
"git.closeDiff": "关闭差异",
|
|
87
|
+
"git.authorUnknown": "未知",
|
|
88
|
+
"git.changedFiles.one": "共 {count} 个变更文件",
|
|
89
|
+
"git.changedFiles.other": "共 {count} 个变更文件",
|
|
90
|
+
"git.changedVsHead.one": "共 {count} 个变更文件(对比 HEAD)",
|
|
91
|
+
"git.changedVsHead.other": "共 {count} 个变更文件(对比 HEAD)",
|
|
92
|
+
"git.changesCount.one": "{count} 个变更",
|
|
93
|
+
"git.changesCount.other": "{count} 个变更",
|
|
94
|
+
"time.justNow": "刚刚",
|
|
95
|
+
"time.minutesAgo": "{n} 分钟前",
|
|
96
|
+
"time.hoursAgo": "{n} 小时前",
|
|
97
|
+
"time.daysAgo": "{n} 天前",
|
|
98
|
+
"time.weeksAgo": "{n} 周前",
|
|
99
|
+
"time.monthsAgo": "{n} 个月前",
|
|
100
|
+
"time.yearsAgo": "{n} 年前",
|
|
101
|
+
};
|
|
102
|
+
const EN_DICT = {
|
|
103
|
+
"files.title": "Files",
|
|
104
|
+
"git.title": "Git Graph",
|
|
105
|
+
"workspace": "Workspace",
|
|
106
|
+
"files.refresh": "Refresh",
|
|
107
|
+
"files.refreshList": "Refresh file list",
|
|
108
|
+
"git.refreshGraph": "Refresh graph",
|
|
109
|
+
"files.up": "Up",
|
|
110
|
+
"files.goUp": "Go to parent directory",
|
|
111
|
+
"files.delete": "Delete",
|
|
112
|
+
"files.deleteFile": "Delete {name}",
|
|
113
|
+
"files.confirmDelete": "Confirm deleting {name}",
|
|
114
|
+
"files.clickAgain": "Click again to delete",
|
|
115
|
+
"files.deleteFailed": "Delete failed",
|
|
116
|
+
"files.view": "View",
|
|
117
|
+
"files.viewFile": "View {name}",
|
|
118
|
+
"files.download": "Download",
|
|
119
|
+
"files.downloadFile": "Download {name}",
|
|
120
|
+
"files.downloadFailed": "Download failed",
|
|
121
|
+
"files.closePreview": "Close preview",
|
|
122
|
+
"files.preview": "Preview",
|
|
123
|
+
"files.fullscreen": "Fullscreen",
|
|
124
|
+
"files.enterFullscreen": "Enter fullscreen",
|
|
125
|
+
"files.exitFullscreen": "Exit fullscreen",
|
|
126
|
+
"files.imageControls": "Image controls",
|
|
127
|
+
"files.zoomIn": "Zoom in",
|
|
128
|
+
"files.zoomOut": "Zoom out",
|
|
129
|
+
"files.resetZoom": "Reset zoom",
|
|
130
|
+
"files.resetImageZoom": "Reset image zoom",
|
|
131
|
+
"files.imagePreview": "Image preview",
|
|
132
|
+
"files.previewDialog": "File preview",
|
|
133
|
+
"files.workspaceRoot": "workspace root",
|
|
134
|
+
"files.loading": "Loading...",
|
|
135
|
+
"git.loading": "Loading…",
|
|
136
|
+
"files.empty": "Empty folder",
|
|
137
|
+
"files.listFailed": "Failed to list files",
|
|
138
|
+
"files.readFailed": "Failed to read file",
|
|
139
|
+
"files.imageMeta": "Image / {size}",
|
|
140
|
+
"files.binary": "Binary",
|
|
141
|
+
"files.fileTooLarge": "File is too large to preview here",
|
|
142
|
+
"files.imageTooLarge": "Image is too large to preview here",
|
|
143
|
+
"files.noPreview": "(No preview)",
|
|
144
|
+
"files.binaryNoPreview": "Binary file cannot be previewed",
|
|
145
|
+
"git.logFailed": "Failed to load git log",
|
|
146
|
+
"git.commitFailed": "Failed to load commit",
|
|
147
|
+
"git.diffFailed": "Failed to load diff",
|
|
148
|
+
"git.loadingChanges": "Loading changes…",
|
|
149
|
+
"git.noDiff": "(no diff)",
|
|
150
|
+
"git.noMessage": "(no message)",
|
|
151
|
+
"git.diffTruncated": "… (diff truncated)",
|
|
152
|
+
"git.uncommitted": "Uncommitted changes",
|
|
153
|
+
"git.workingTree": "Working tree",
|
|
154
|
+
"git.workingTreeLabel": "working tree",
|
|
155
|
+
"git.noCommitsYet": "No commits yet",
|
|
156
|
+
"git.noCommitsYetSuffix": " (no commits yet)",
|
|
157
|
+
"git.noData": "No data",
|
|
158
|
+
"git.detachedHead": "detached HEAD",
|
|
159
|
+
"git.allBranches": "All branches",
|
|
160
|
+
"git.branchFilter": "Branch filter",
|
|
161
|
+
"git.currentBranch": "Current branch",
|
|
162
|
+
"git.diff": "Diff",
|
|
163
|
+
"git.closeDiff": "Close diff",
|
|
164
|
+
"git.authorUnknown": "unknown",
|
|
165
|
+
"git.changedFiles.one": "{count} changed file",
|
|
166
|
+
"git.changedFiles.other": "{count} changed files",
|
|
167
|
+
"git.changedVsHead.one": "{count} changed file (vs HEAD)",
|
|
168
|
+
"git.changedVsHead.other": "{count} changed files (vs HEAD)",
|
|
169
|
+
"git.changesCount.one": "{count} change",
|
|
170
|
+
"git.changesCount.other": "{count} changes",
|
|
171
|
+
"time.justNow": "just now",
|
|
172
|
+
"time.minutesAgo": "{n}m ago",
|
|
173
|
+
"time.hoursAgo": "{n}h ago",
|
|
174
|
+
"time.daysAgo": "{n}d ago",
|
|
175
|
+
"time.weeksAgo": "{n}w ago",
|
|
176
|
+
"time.monthsAgo": "{n}mo ago",
|
|
177
|
+
"time.yearsAgo": "{n}y ago",
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
function applyParams(template, params) {
|
|
181
|
+
if (!params) return template;
|
|
182
|
+
return template.replace(/\{(\w+)\}/g, (match, name) => name in params ? String(params[name]) : match);
|
|
183
|
+
}
|
|
184
|
+
|
|
24
185
|
function apply(ctx) {
|
|
25
186
|
const slots = ctx.get('slots')
|
|
26
187
|
const rightPanel = ctx.get('rightPanel')
|
|
27
188
|
if (slots === undefined || rightPanel === undefined) return
|
|
28
189
|
|
|
190
|
+
const locale = ctx.get("locale");
|
|
191
|
+
if (locale !== undefined) {
|
|
192
|
+
ctx.effect(() => locale.register(LOCALE_NS, { zh: ZH_DICT, en: EN_DICT }), "file-explorer: locale");
|
|
193
|
+
}
|
|
194
|
+
const t = locale !== undefined
|
|
195
|
+
? locale.bind(LOCALE_NS)
|
|
196
|
+
: (key, params) => applyParams(ZH_DICT[key] ?? EN_DICT[key] ?? key, params);
|
|
197
|
+
|
|
29
198
|
const style = document.createElement("style");
|
|
30
199
|
style.id = "dsh-plugin-file-explorer-style";
|
|
31
200
|
style.setAttribute("data-plugin", "dsh-plugin-file-explorer");
|
|
@@ -703,16 +872,16 @@ window.__ModuleLoader__.load({
|
|
|
703
872
|
return STATUS_COLORS[letter] || '#6b7280'
|
|
704
873
|
}
|
|
705
874
|
|
|
706
|
-
function relTime(epochSeconds) {
|
|
875
|
+
function relTime(epochSeconds, t) {
|
|
707
876
|
if (typeof epochSeconds !== 'number' || !Number.isFinite(epochSeconds) || epochSeconds <= 0) return ''
|
|
708
877
|
const s = Math.max(0, Date.now() / 1000 - epochSeconds)
|
|
709
|
-
if (s < 60) return '
|
|
710
|
-
if (s < 3600) return
|
|
711
|
-
if (s < 86400) return
|
|
712
|
-
if (s < 604800) return
|
|
713
|
-
if (s < 2592000) return
|
|
714
|
-
if (s < 31536000) return
|
|
715
|
-
return
|
|
878
|
+
if (s < 60) return t('time.justNow')
|
|
879
|
+
if (s < 3600) return t('time.minutesAgo', { n: Math.floor(s / 60) })
|
|
880
|
+
if (s < 86400) return t('time.hoursAgo', { n: Math.floor(s / 3600) })
|
|
881
|
+
if (s < 604800) return t('time.daysAgo', { n: Math.floor(s / 86400) })
|
|
882
|
+
if (s < 2592000) return t('time.weeksAgo', { n: Math.floor(s / 604800) })
|
|
883
|
+
if (s < 31536000) return t('time.monthsAgo', { n: Math.floor(s / 2592000) })
|
|
884
|
+
return t('time.yearsAgo', { n: Math.floor(s / 31536000) })
|
|
716
885
|
}
|
|
717
886
|
|
|
718
887
|
function shortHash(hash) {
|
|
@@ -927,7 +1096,8 @@ window.__ModuleLoader__.load({
|
|
|
927
1096
|
// line, the commit lane rows with an expandable per-commit detail, and a
|
|
928
1097
|
// diff modal. Data comes entirely from the /_dsh/file-explorer/git-*
|
|
929
1098
|
// JSON API.
|
|
930
|
-
function
|
|
1099
|
+
function createGitGraphView(t) {
|
|
1100
|
+
return function GitGraphView(props) {
|
|
931
1101
|
const api = props.api
|
|
932
1102
|
const cwd = props.cwd
|
|
933
1103
|
const [scope, setScope] = React.useState('all')
|
|
@@ -955,7 +1125,7 @@ window.__ModuleLoader__.load({
|
|
|
955
1125
|
if (raw && raw.ok === true) {
|
|
956
1126
|
setLog(raw)
|
|
957
1127
|
} else {
|
|
958
|
-
setError(raw && typeof raw.error === 'string' ? raw.error : '
|
|
1128
|
+
setError(raw && typeof raw.error === 'string' ? raw.error : t('git.logFailed'))
|
|
959
1129
|
}
|
|
960
1130
|
})
|
|
961
1131
|
.catch((err) => {
|
|
@@ -981,7 +1151,7 @@ window.__ModuleLoader__.load({
|
|
|
981
1151
|
if (raw && raw.ok === true) {
|
|
982
1152
|
setDetails((prev) => ({ ...prev, [selected]: raw }))
|
|
983
1153
|
} else {
|
|
984
|
-
setDetails((prev) => ({ ...prev, [selected]: { error: raw && typeof raw.error === 'string' ? raw.error : '
|
|
1154
|
+
setDetails((prev) => ({ ...prev, [selected]: { error: raw && typeof raw.error === 'string' ? raw.error : t('git.commitFailed') } }))
|
|
985
1155
|
}
|
|
986
1156
|
})
|
|
987
1157
|
.catch((err) => {
|
|
@@ -1000,10 +1170,10 @@ window.__ModuleLoader__.load({
|
|
|
1000
1170
|
api('git-diff', { path: cwd, hash, file: file.path })
|
|
1001
1171
|
.then((raw) => {
|
|
1002
1172
|
if (raw && raw.ok === true) {
|
|
1003
|
-
const note = raw.truncated ? '\n\n
|
|
1173
|
+
const note = raw.truncated ? '\n\n' + t('git.diffTruncated') : ''
|
|
1004
1174
|
setDiff({ title: file.path, hash, loading: false, text: (raw.patch || '') + note, error: null })
|
|
1005
1175
|
} else {
|
|
1006
|
-
setDiff({ title: file.path, hash, loading: false, text: null, error: raw && typeof raw.error === 'string' ? raw.error : '
|
|
1176
|
+
setDiff({ title: file.path, hash, loading: false, text: null, error: raw && typeof raw.error === 'string' ? raw.error : t('git.diffFailed') })
|
|
1007
1177
|
}
|
|
1008
1178
|
})
|
|
1009
1179
|
.catch((err) => {
|
|
@@ -1017,7 +1187,7 @@ window.__ModuleLoader__.load({
|
|
|
1017
1187
|
const renderCommitDetail = (hash, d) => {
|
|
1018
1188
|
if (d === undefined) {
|
|
1019
1189
|
return React.createElement('div', { className: 'dsh-git-detail' },
|
|
1020
|
-
React.createElement('div', { className: 'dsh-git-files-title' }, '
|
|
1190
|
+
React.createElement('div', { className: 'dsh-git-files-title' }, t('git.loadingChanges')))
|
|
1021
1191
|
}
|
|
1022
1192
|
if (d.error) {
|
|
1023
1193
|
return React.createElement('div', { className: 'dsh-git-detail' },
|
|
@@ -1025,9 +1195,9 @@ window.__ModuleLoader__.load({
|
|
|
1025
1195
|
}
|
|
1026
1196
|
const files = Array.isArray(d.files) ? d.files : []
|
|
1027
1197
|
return React.createElement('div', { className: 'dsh-git-detail' },
|
|
1028
|
-
React.createElement('div', { className: 'dsh-git-msg' }, d.message ||
|
|
1198
|
+
React.createElement('div', { className: 'dsh-git-msg' }, d.message || t('git.noMessage')),
|
|
1029
1199
|
React.createElement('div', { className: 'dsh-git-files-title' },
|
|
1030
|
-
|
|
1200
|
+
files.length === 1 ? t('git.changedFiles.one', { count: files.length }) : t('git.changedFiles.other', { count: files.length })),
|
|
1031
1201
|
files.length === 0 ? null : files.map((f, i) =>
|
|
1032
1202
|
React.createElement(GitFileRow, { key: i, file: f, onOpen: (file) => openDiff(hash, file) })),
|
|
1033
1203
|
)
|
|
@@ -1035,7 +1205,7 @@ window.__ModuleLoader__.load({
|
|
|
1035
1205
|
|
|
1036
1206
|
const rows = []
|
|
1037
1207
|
if (loading) {
|
|
1038
|
-
rows.push(React.createElement('div', { key: 'loading', className: 'dsh-fe-status' }, '
|
|
1208
|
+
rows.push(React.createElement('div', { key: 'loading', className: 'dsh-fe-status' }, t('git.loading')))
|
|
1039
1209
|
} else if (error) {
|
|
1040
1210
|
rows.push(React.createElement('div', { key: 'error', className: 'dsh-fe-status dsh-fe-status-error' }, error))
|
|
1041
1211
|
} else if (graph !== null) {
|
|
@@ -1049,21 +1219,21 @@ window.__ModuleLoader__.load({
|
|
|
1049
1219
|
className: 'dsh-git-row',
|
|
1050
1220
|
onClick: () => toggle('WORKING'),
|
|
1051
1221
|
role: 'button',
|
|
1052
|
-
title: '
|
|
1222
|
+
title: t('git.uncommitted'),
|
|
1053
1223
|
},
|
|
1054
1224
|
React.createElement(WorkTreeCell, { lane: first !== null ? first.lane : 0, connectorColor }),
|
|
1055
1225
|
React.createElement('div', { className: 'dsh-git-main' },
|
|
1056
1226
|
React.createElement('div', { className: 'dsh-git-line1' },
|
|
1057
|
-
React.createElement('span', { className: 'dsh-git-subject' }, '
|
|
1227
|
+
React.createElement('span', { className: 'dsh-git-subject' }, t('git.uncommitted')),
|
|
1058
1228
|
React.createElement('span', { className: 'dsh-git-pill dsh-git-pill-branch' }, String(changes.length)),
|
|
1059
1229
|
),
|
|
1060
|
-
React.createElement('div', { className: 'dsh-git-line2' }, '
|
|
1230
|
+
React.createElement('div', { className: 'dsh-git-line2' }, t('git.workingTree')),
|
|
1061
1231
|
),
|
|
1062
1232
|
),
|
|
1063
1233
|
selected === 'WORKING'
|
|
1064
1234
|
? React.createElement('div', { className: 'dsh-git-detail' },
|
|
1065
1235
|
React.createElement('div', { className: 'dsh-git-files-title' },
|
|
1066
|
-
|
|
1236
|
+
changes.length === 1 ? t('git.changedVsHead.one', { count: changes.length }) : t('git.changedVsHead.other', { count: changes.length })),
|
|
1067
1237
|
changes.map((f, i) =>
|
|
1068
1238
|
React.createElement(GitFileRow, { key: i, file: f, onOpen: (file) => openDiff('WORKING', file) })),
|
|
1069
1239
|
)
|
|
@@ -1086,23 +1256,23 @@ window.__ModuleLoader__.load({
|
|
|
1086
1256
|
React.createElement('span', { className: 'dsh-git-subject' }, c.subject),
|
|
1087
1257
|
),
|
|
1088
1258
|
React.createElement('div', { className: 'dsh-git-line2' },
|
|
1089
|
-
`${c.author || '
|
|
1259
|
+
`${c.author || t('git.authorUnknown')} · ${relTime(c.date, t)} · ${shortHash(c.hash)}`),
|
|
1090
1260
|
),
|
|
1091
1261
|
),
|
|
1092
1262
|
selected === c.hash ? renderCommitDetail(c.hash, details[c.hash]) : null,
|
|
1093
1263
|
))
|
|
1094
1264
|
})
|
|
1095
1265
|
if (rows.length === 0) {
|
|
1096
|
-
rows.push(React.createElement('div', { key: 'empty', className: 'dsh-fe-status' }, '
|
|
1266
|
+
rows.push(React.createElement('div', { key: 'empty', className: 'dsh-fe-status' }, t('git.noCommitsYet')))
|
|
1097
1267
|
}
|
|
1098
1268
|
} else {
|
|
1099
|
-
rows.push(React.createElement('div', { key: 'none', className: 'dsh-fe-status' }, '
|
|
1269
|
+
rows.push(React.createElement('div', { key: 'none', className: 'dsh-fe-status' }, t('git.noData')))
|
|
1100
1270
|
}
|
|
1101
1271
|
|
|
1102
1272
|
const branchLabel = status
|
|
1103
1273
|
? (status.branch === null
|
|
1104
|
-
? '
|
|
1105
|
-
: status.branch + (status.unborn ? '
|
|
1274
|
+
? t('git.detachedHead')
|
|
1275
|
+
: status.branch + (status.unborn ? t('git.noCommitsYetSuffix') : ''))
|
|
1106
1276
|
: null
|
|
1107
1277
|
const upstreamBits = []
|
|
1108
1278
|
if (status && status.ahead > 0) upstreamBits.push('↑' + status.ahead)
|
|
@@ -1114,17 +1284,17 @@ window.__ModuleLoader__.load({
|
|
|
1114
1284
|
type: 'button',
|
|
1115
1285
|
className: 'dsh-fe-toolbutton',
|
|
1116
1286
|
onClick: reload,
|
|
1117
|
-
'aria-label': '
|
|
1118
|
-
title: '
|
|
1287
|
+
'aria-label': t('git.refreshGraph'),
|
|
1288
|
+
title: t('files.refresh'),
|
|
1119
1289
|
}, svgIcon(refreshIcon, 15)),
|
|
1120
1290
|
React.createElement('select', {
|
|
1121
1291
|
className: 'dsh-git-scope',
|
|
1122
1292
|
value: scope,
|
|
1123
|
-
'aria-label': '
|
|
1293
|
+
'aria-label': t('git.branchFilter'),
|
|
1124
1294
|
onChange: (event) => setScope(event.target.value),
|
|
1125
1295
|
},
|
|
1126
|
-
React.createElement('option', { value: 'all' }, '
|
|
1127
|
-
React.createElement('option', { value: 'current' }, '
|
|
1296
|
+
React.createElement('option', { value: 'all' }, t('git.allBranches')),
|
|
1297
|
+
React.createElement('option', { value: 'current' }, t('git.currentBranch')),
|
|
1128
1298
|
),
|
|
1129
1299
|
),
|
|
1130
1300
|
branchLabel !== null
|
|
@@ -1132,7 +1302,7 @@ window.__ModuleLoader__.load({
|
|
|
1132
1302
|
svgIcon(branchIcon, 12),
|
|
1133
1303
|
React.createElement('span', { className: 'dsh-git-info-name' }, branchLabel),
|
|
1134
1304
|
upstreamBits.length > 0 ? React.createElement('span', null, upstreamBits.join(' ')) : null,
|
|
1135
|
-
React.createElement('span', null,
|
|
1305
|
+
React.createElement('span', null, changes.length === 1 ? t('git.changesCount.one', { count: changes.length }) : t('git.changesCount.other', { count: changes.length })),
|
|
1136
1306
|
)
|
|
1137
1307
|
: null,
|
|
1138
1308
|
React.createElement('div', { className: 'dsh-git-list' }, rows),
|
|
@@ -1144,29 +1314,31 @@ window.__ModuleLoader__.load({
|
|
|
1144
1314
|
React.createElement('div', {
|
|
1145
1315
|
className: 'dsh-fe-modal',
|
|
1146
1316
|
role: 'dialog',
|
|
1147
|
-
'aria-label': '
|
|
1317
|
+
'aria-label': t('git.diff'),
|
|
1148
1318
|
onClick: (event) => event.stopPropagation(),
|
|
1149
1319
|
},
|
|
1150
1320
|
React.createElement('div', { className: 'dsh-fe-modal-head' },
|
|
1151
1321
|
React.createElement('div', { className: 'dsh-fe-modal-title' }, diff.title),
|
|
1152
1322
|
React.createElement('div', { className: 'dsh-fe-modal-meta' },
|
|
1153
|
-
diff.hash === 'WORKING' ? '
|
|
1323
|
+
diff.hash === 'WORKING' ? t('git.workingTreeLabel') : shortHash(diff.hash)),
|
|
1154
1324
|
React.createElement('button', {
|
|
1155
1325
|
type: 'button',
|
|
1156
1326
|
className: 'dsh-fe-icon',
|
|
1157
1327
|
onClick: () => setDiff(null),
|
|
1158
|
-
'aria-label': '
|
|
1328
|
+
'aria-label': t('git.closeDiff'),
|
|
1159
1329
|
}, svgIcon(closeIcon, 14)),
|
|
1160
1330
|
),
|
|
1161
1331
|
React.createElement('div', { className: 'dsh-fe-modal-body' },
|
|
1162
|
-
diff.loading ? '
|
|
1332
|
+
diff.loading ? t('git.loading') : (diff.error || diff.text || t('git.noDiff'))),
|
|
1163
1333
|
),
|
|
1164
1334
|
)
|
|
1165
1335
|
: null,
|
|
1166
1336
|
)
|
|
1167
1337
|
}
|
|
1338
|
+
}
|
|
1168
1339
|
|
|
1169
|
-
function
|
|
1340
|
+
function createFileExplorerPage(t) {
|
|
1341
|
+
return function FileExplorerPage(props) {
|
|
1170
1342
|
if (typeof props.useSessions !== 'function') return null
|
|
1171
1343
|
|
|
1172
1344
|
const sessionId = props.useSessions((state) => {
|
|
@@ -1231,7 +1403,7 @@ window.__ModuleLoader__.load({
|
|
|
1231
1403
|
setCurrentPath(requestPath)
|
|
1232
1404
|
setParentPath(null)
|
|
1233
1405
|
setEntries([])
|
|
1234
|
-
setError(raw && typeof raw.error === 'string' ? raw.error : '
|
|
1406
|
+
setError(raw && typeof raw.error === 'string' ? raw.error : t('files.listFailed'))
|
|
1235
1407
|
}
|
|
1236
1408
|
})
|
|
1237
1409
|
.catch((err) => {
|
|
@@ -1333,7 +1505,7 @@ window.__ModuleLoader__.load({
|
|
|
1333
1505
|
setPreview(null)
|
|
1334
1506
|
api('read', { path: entry.path })
|
|
1335
1507
|
.then((raw) => {
|
|
1336
|
-
setPreview(raw && raw.ok === true ? raw : { ok: false, error: raw && typeof raw.error === 'string' ? raw.error : '
|
|
1508
|
+
setPreview(raw && raw.ok === true ? raw : { ok: false, error: raw && typeof raw.error === 'string' ? raw.error : t('files.readFailed') })
|
|
1337
1509
|
})
|
|
1338
1510
|
.catch((err) => {
|
|
1339
1511
|
setPreview({ ok: false, error: err && typeof err.message === 'string' ? err.message : String(err) })
|
|
@@ -1346,7 +1518,7 @@ window.__ModuleLoader__.load({
|
|
|
1346
1518
|
api('download', { path: entry.path })
|
|
1347
1519
|
.then((raw) => {
|
|
1348
1520
|
if (!raw || raw.ok !== true) {
|
|
1349
|
-
const message = raw && typeof raw.error === 'string' ? raw.error : '
|
|
1521
|
+
const message = raw && typeof raw.error === 'string' ? raw.error : t('files.downloadFailed')
|
|
1350
1522
|
setError(message)
|
|
1351
1523
|
return
|
|
1352
1524
|
}
|
|
@@ -1373,7 +1545,7 @@ window.__ModuleLoader__.load({
|
|
|
1373
1545
|
api('delete', { path: entry.path })
|
|
1374
1546
|
.then((raw) => {
|
|
1375
1547
|
if (!raw || raw.ok !== true) {
|
|
1376
|
-
setError(raw && typeof raw.error === 'string' ? raw.error : '
|
|
1548
|
+
setError(raw && typeof raw.error === 'string' ? raw.error : t('files.deleteFailed'))
|
|
1377
1549
|
return
|
|
1378
1550
|
}
|
|
1379
1551
|
reload()
|
|
@@ -1397,9 +1569,9 @@ window.__ModuleLoader__.load({
|
|
|
1397
1569
|
: React.createElement('button', {
|
|
1398
1570
|
type: 'button',
|
|
1399
1571
|
className: 'dsh-fe-path',
|
|
1400
|
-
title: currentPath || '
|
|
1572
|
+
title: currentPath || t('files.workspaceRoot'),
|
|
1401
1573
|
onClick: startEditPath,
|
|
1402
|
-
}, currentPath || '
|
|
1574
|
+
}, currentPath || t('files.workspaceRoot'))
|
|
1403
1575
|
|
|
1404
1576
|
const filesView = React.createElement(React.Fragment, null,
|
|
1405
1577
|
pathControl,
|
|
@@ -1411,24 +1583,24 @@ window.__ModuleLoader__.load({
|
|
|
1411
1583
|
onClick: () => {
|
|
1412
1584
|
if (parentPath !== null && parentPath !== currentPath) setRequestPath(parentPath)
|
|
1413
1585
|
},
|
|
1414
|
-
'aria-label': '
|
|
1415
|
-
title: '
|
|
1586
|
+
'aria-label': t('files.goUp'),
|
|
1587
|
+
title: t('files.up'),
|
|
1416
1588
|
}, svgIcon(upIcon, 15)),
|
|
1417
1589
|
React.createElement('button', {
|
|
1418
1590
|
type: 'button',
|
|
1419
1591
|
className: 'dsh-fe-toolbutton',
|
|
1420
1592
|
onClick: reload,
|
|
1421
|
-
'aria-label': '
|
|
1422
|
-
title: '
|
|
1593
|
+
'aria-label': t('files.refreshList'),
|
|
1594
|
+
title: t('files.refresh'),
|
|
1423
1595
|
}, svgIcon(refreshIcon, 15)),
|
|
1424
1596
|
),
|
|
1425
1597
|
React.createElement('div', { className: 'dsh-fe-list' },
|
|
1426
1598
|
loading
|
|
1427
|
-
? React.createElement('div', { className: 'dsh-fe-status' }, '
|
|
1599
|
+
? React.createElement('div', { className: 'dsh-fe-status' }, t('files.loading'))
|
|
1428
1600
|
: error
|
|
1429
1601
|
? React.createElement('div', { className: 'dsh-fe-status dsh-fe-status-error' }, error)
|
|
1430
1602
|
: sorted.length === 0
|
|
1431
|
-
? React.createElement('div', { className: 'dsh-fe-status' }, '
|
|
1603
|
+
? React.createElement('div', { className: 'dsh-fe-status' }, t('files.empty'))
|
|
1432
1604
|
: sorted.map((entry) => {
|
|
1433
1605
|
const isDir = entry.type === 'directory'
|
|
1434
1606
|
return React.createElement('div', {
|
|
@@ -1449,22 +1621,22 @@ window.__ModuleLoader__.load({
|
|
|
1449
1621
|
type: 'button',
|
|
1450
1622
|
className: 'dsh-fe-action',
|
|
1451
1623
|
onClick: (event) => { event.stopPropagation(); openPreview(entry) },
|
|
1452
|
-
'aria-label':
|
|
1453
|
-
title: '
|
|
1624
|
+
'aria-label': t('files.viewFile', { name: entry.name }),
|
|
1625
|
+
title: t('files.view'),
|
|
1454
1626
|
}, svgIcon(eyeIcon, 14)),
|
|
1455
1627
|
!isDir && React.createElement('button', {
|
|
1456
1628
|
type: 'button',
|
|
1457
1629
|
className: 'dsh-fe-action',
|
|
1458
1630
|
onClick: (event) => { event.stopPropagation(); downloadFile(entry) },
|
|
1459
|
-
'aria-label':
|
|
1460
|
-
title: '
|
|
1631
|
+
'aria-label': t('files.downloadFile', { name: entry.name }),
|
|
1632
|
+
title: t('files.download'),
|
|
1461
1633
|
}, svgIcon(downloadIcon, 14)),
|
|
1462
1634
|
React.createElement('button', {
|
|
1463
1635
|
type: 'button',
|
|
1464
1636
|
className: pendingDelete === entry.path ? 'dsh-fe-action dsh-fe-action-confirm' : 'dsh-fe-action dsh-fe-action-danger',
|
|
1465
1637
|
onClick: (event) => { event.stopPropagation(); requestDelete(entry) },
|
|
1466
|
-
'aria-label': pendingDelete === entry.path ?
|
|
1467
|
-
title: pendingDelete === entry.path ? '
|
|
1638
|
+
'aria-label': pendingDelete === entry.path ? t('files.confirmDelete', { name: entry.name }) : t('files.deleteFile', { name: entry.name }),
|
|
1639
|
+
title: pendingDelete === entry.path ? t('files.clickAgain') : t('files.delete'),
|
|
1468
1640
|
}, svgIcon(trashIcon, 14)),
|
|
1469
1641
|
),
|
|
1470
1642
|
),
|
|
@@ -1477,7 +1649,7 @@ window.__ModuleLoader__.load({
|
|
|
1477
1649
|
React.createElement('div', {
|
|
1478
1650
|
className: 'dsh-fe-page',
|
|
1479
1651
|
role: 'region',
|
|
1480
|
-
'aria-label': '
|
|
1652
|
+
'aria-label': t('files.title'),
|
|
1481
1653
|
},
|
|
1482
1654
|
filesView,
|
|
1483
1655
|
),
|
|
@@ -1489,50 +1661,50 @@ window.__ModuleLoader__.load({
|
|
|
1489
1661
|
React.createElement('div', {
|
|
1490
1662
|
className: preview.kind === 'image' && imageFullscreen ? 'dsh-fe-modal dsh-fe-modal-fullscreen' : 'dsh-fe-modal',
|
|
1491
1663
|
role: 'dialog',
|
|
1492
|
-
'aria-label': '
|
|
1664
|
+
'aria-label': t('files.previewDialog'),
|
|
1493
1665
|
'aria-modal': true,
|
|
1494
1666
|
tabIndex: -1,
|
|
1495
1667
|
onKeyDown: handlePreviewKeyDown,
|
|
1496
1668
|
onClick: (event) => event.stopPropagation(),
|
|
1497
1669
|
},
|
|
1498
1670
|
React.createElement('div', { className: 'dsh-fe-modal-head' },
|
|
1499
|
-
React.createElement('div', { className: 'dsh-fe-modal-title' }, preview.name || '
|
|
1500
|
-
React.createElement('div', { className: 'dsh-fe-modal-meta' }, preview.kind === 'image' ?
|
|
1671
|
+
React.createElement('div', { className: 'dsh-fe-modal-title' }, preview.name || t('files.preview')),
|
|
1672
|
+
React.createElement('div', { className: 'dsh-fe-modal-meta' }, preview.kind === 'image' ? t('files.imageMeta', { size: formatSize(preview.size) }) : preview.binary ? t('files.binary') : formatSize(preview.size)),
|
|
1501
1673
|
preview.kind === 'image' && preview.dataUrl
|
|
1502
1674
|
? React.createElement('div', {
|
|
1503
1675
|
className: 'dsh-fe-image-tools',
|
|
1504
1676
|
role: 'toolbar',
|
|
1505
|
-
'aria-label': '
|
|
1677
|
+
'aria-label': t('files.imageControls'),
|
|
1506
1678
|
},
|
|
1507
1679
|
React.createElement('button', {
|
|
1508
1680
|
type: 'button',
|
|
1509
1681
|
className: 'dsh-fe-icon dsh-fe-image-tool',
|
|
1510
1682
|
disabled: imageScale <= 0.25,
|
|
1511
1683
|
onClick: () => changeImageZoom(-0.25),
|
|
1512
|
-
'aria-label': '
|
|
1513
|
-
title: '
|
|
1684
|
+
'aria-label': t('files.zoomOut'),
|
|
1685
|
+
title: t('files.zoomOut'),
|
|
1514
1686
|
}, svgIcon(zoomOutIcon, 14)),
|
|
1515
1687
|
React.createElement('button', {
|
|
1516
1688
|
type: 'button',
|
|
1517
1689
|
className: 'dsh-fe-icon dsh-fe-image-tool',
|
|
1518
1690
|
onClick: resetImageZoom,
|
|
1519
|
-
'aria-label': '
|
|
1520
|
-
title: '
|
|
1691
|
+
'aria-label': t('files.resetImageZoom'),
|
|
1692
|
+
title: t('files.resetZoom'),
|
|
1521
1693
|
}, React.createElement('span', { className: 'dsh-fe-image-zoom-label' }, `${Math.round(imageScale * 100)}%`)),
|
|
1522
1694
|
React.createElement('button', {
|
|
1523
1695
|
type: 'button',
|
|
1524
1696
|
className: 'dsh-fe-icon dsh-fe-image-tool',
|
|
1525
1697
|
disabled: imageScale >= 4,
|
|
1526
1698
|
onClick: () => changeImageZoom(0.25),
|
|
1527
|
-
'aria-label': '
|
|
1528
|
-
title: '
|
|
1699
|
+
'aria-label': t('files.zoomIn'),
|
|
1700
|
+
title: t('files.zoomIn'),
|
|
1529
1701
|
}, svgIcon(zoomInIcon, 14)),
|
|
1530
1702
|
React.createElement('button', {
|
|
1531
1703
|
type: 'button',
|
|
1532
1704
|
className: 'dsh-fe-icon dsh-fe-image-tool',
|
|
1533
1705
|
onClick: () => setImageFullscreen((value) => !value),
|
|
1534
|
-
'aria-label': imageFullscreen ? '
|
|
1535
|
-
title: imageFullscreen ? '
|
|
1706
|
+
'aria-label': imageFullscreen ? t('files.exitFullscreen') : t('files.enterFullscreen'),
|
|
1707
|
+
title: imageFullscreen ? t('files.exitFullscreen') : t('files.fullscreen'),
|
|
1536
1708
|
}, svgIcon(imageFullscreen ? fullscreenExitIcon : fullscreenIcon, 14)),
|
|
1537
1709
|
)
|
|
1538
1710
|
: null,
|
|
@@ -1540,7 +1712,7 @@ window.__ModuleLoader__.load({
|
|
|
1540
1712
|
type: 'button',
|
|
1541
1713
|
className: 'dsh-fe-icon',
|
|
1542
1714
|
onClick: closePreview,
|
|
1543
|
-
'aria-label': '
|
|
1715
|
+
'aria-label': t('files.closePreview'),
|
|
1544
1716
|
}, svgIcon(closeIcon, 14)),
|
|
1545
1717
|
),
|
|
1546
1718
|
React.createElement('div', {
|
|
@@ -1552,7 +1724,7 @@ window.__ModuleLoader__.load({
|
|
|
1552
1724
|
onPointerCancel: preview.kind === 'image' && preview.dataUrl ? endImageDrag : undefined,
|
|
1553
1725
|
},
|
|
1554
1726
|
previewLoading
|
|
1555
|
-
? '
|
|
1727
|
+
? t('files.loading')
|
|
1556
1728
|
: preview.error
|
|
1557
1729
|
? preview.error
|
|
1558
1730
|
: preview.kind === 'image'
|
|
@@ -1562,23 +1734,25 @@ window.__ModuleLoader__.load({
|
|
|
1562
1734
|
className: 'dsh-fe-preview-image' + (imageScale > 1 ? ' dsh-fe-preview-image-pannable' : '') + (imageDragging ? ' dsh-fe-preview-image-dragging' : ''),
|
|
1563
1735
|
style: { transform: `translate3d(${imageOffset.x}px, ${imageOffset.y}px, 0) scale(${imageScale})` },
|
|
1564
1736
|
src: preview.dataUrl,
|
|
1565
|
-
alt: preview.name || '
|
|
1737
|
+
alt: preview.name || t('files.imagePreview'),
|
|
1566
1738
|
draggable: false,
|
|
1567
1739
|
})
|
|
1568
1740
|
)
|
|
1569
|
-
: preview.tooLarge ? '
|
|
1741
|
+
: preview.tooLarge ? t('files.imageTooLarge') : t('files.noPreview')
|
|
1570
1742
|
: preview.text !== undefined && preview.text !== null
|
|
1571
1743
|
? preview.text
|
|
1572
1744
|
: preview.tooLarge
|
|
1573
|
-
? '
|
|
1574
|
-
: preview.binary ? '
|
|
1745
|
+
? t('files.fileTooLarge')
|
|
1746
|
+
: preview.binary ? t('files.binaryNoPreview') : t('files.noPreview'),
|
|
1575
1747
|
),
|
|
1576
1748
|
),
|
|
1577
1749
|
),
|
|
1578
1750
|
)
|
|
1579
1751
|
}
|
|
1752
|
+
}
|
|
1580
1753
|
|
|
1581
|
-
function
|
|
1754
|
+
function createFileExplorerGitPage(t) {
|
|
1755
|
+
return function FileExplorerGitPage(props) {
|
|
1582
1756
|
if (typeof props.useSessions !== 'function') return null
|
|
1583
1757
|
|
|
1584
1758
|
const sessionId = props.useSessions((state) => {
|
|
@@ -1599,23 +1773,28 @@ window.__ModuleLoader__.load({
|
|
|
1599
1773
|
return React.createElement('div', {
|
|
1600
1774
|
className: 'dsh-fe-page',
|
|
1601
1775
|
role: 'region',
|
|
1602
|
-
'aria-label': '
|
|
1776
|
+
'aria-label': t('git.title'),
|
|
1603
1777
|
}, React.createElement(GitGraphView, { api, cwd }))
|
|
1604
1778
|
}
|
|
1779
|
+
}
|
|
1780
|
+
|
|
1781
|
+
const GitGraphView = createGitGraphView(t);
|
|
1782
|
+
const FileExplorerPage = createFileExplorerPage(t);
|
|
1783
|
+
const FileExplorerGitPage = createFileExplorerGitPage(t);
|
|
1605
1784
|
|
|
1606
1785
|
ctx.effect(() => {
|
|
1607
1786
|
const disposeFilesPage = rightPanel.registerPage({
|
|
1608
1787
|
id: 'file-explorer.files',
|
|
1609
|
-
title: '
|
|
1610
|
-
group: '
|
|
1788
|
+
title: t('files.title'),
|
|
1789
|
+
group: t('workspace'),
|
|
1611
1790
|
order: 20,
|
|
1612
1791
|
placement: 'rail',
|
|
1613
1792
|
icon: (size) => svgIcon(folderIcon, size),
|
|
1614
1793
|
})
|
|
1615
1794
|
const disposeGitPage = rightPanel.registerPage({
|
|
1616
1795
|
id: 'file-explorer.git',
|
|
1617
|
-
title: '
|
|
1618
|
-
group: '
|
|
1796
|
+
title: t('git.title'),
|
|
1797
|
+
group: t('workspace'),
|
|
1619
1798
|
order: 21,
|
|
1620
1799
|
placement: 'rail',
|
|
1621
1800
|
icon: (size) => svgIcon(branchIcon, size),
|