@electerm/electerm-react 3.0.18 → 3.1.16

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.
Files changed (35) hide show
  1. package/client/common/constants.js +4 -4
  2. package/client/common/db.js +20 -10
  3. package/client/components/file-transfer/conflict-resolve.jsx +38 -4
  4. package/client/components/file-transfer/transfer-queue.jsx +10 -4
  5. package/client/components/file-transfer/transfer.jsx +7 -4
  6. package/client/components/file-transfer/transports-action-store.jsx +14 -2
  7. package/client/components/footer/cmd-history.jsx +2 -4
  8. package/client/components/quick-commands/qm.styl +8 -0
  9. package/client/components/quick-commands/quick-command-item.jsx +4 -0
  10. package/client/components/quick-commands/quick-commands-box.jsx +10 -0
  11. package/client/components/quick-commands/quick-commands-form-elem.jsx +1 -1
  12. package/client/components/quick-commands/quick-commands-list-form.jsx +59 -4
  13. package/client/components/quick-commands/quick-commands-list.jsx +33 -3
  14. package/client/components/setting-panel/list.styl +5 -1
  15. package/client/components/setting-sync/server-data-status.jsx +2 -1
  16. package/client/components/setting-sync/setting-sync-form.jsx +93 -15
  17. package/client/components/setting-sync/setting-sync.jsx +5 -1
  18. package/client/components/sidebar/transfer-history-modal.jsx +2 -2
  19. package/client/components/tabs/tabs.styl +1 -0
  20. package/client/components/tabs/window-control.jsx +2 -0
  21. package/client/components/terminal/terminal-command-dropdown.jsx +1 -1
  22. package/client/components/terminal/terminal.jsx +14 -1
  23. package/client/components/terminal/transfer-client-base.js +38 -17
  24. package/client/components/terminal-info/network.jsx +0 -1
  25. package/client/components/tree-list/tree-list-item.jsx +5 -0
  26. package/client/components/tree-list/tree-list.jsx +17 -4
  27. package/client/components/tree-list/tree-list.styl +1 -1
  28. package/client/store/common.js +15 -15
  29. package/client/store/init-state.js +6 -31
  30. package/client/store/mcp-handler.js +315 -129
  31. package/client/store/store.js +1 -1
  32. package/client/store/sync.js +129 -3
  33. package/client/store/transfer-list.js +3 -2
  34. package/client/store/watch.js +1 -25
  35. package/package.json +1 -1
@@ -67,6 +67,13 @@ export default (Store) => {
67
67
  }
68
68
  ).join('####')
69
69
  }
70
+ if (type === syncTypes.webdav) {
71
+ // WebDAV token format: serverUrl####username####password
72
+ const serverUrl = get(window.store.config, 'syncSetting.webdavServerUrl')
73
+ const username = get(window.store.config, 'syncSetting.webdavUsername')
74
+ const password = get(window.store.config, 'syncSetting.webdavPassword')
75
+ return [serverUrl, username, password].join('####')
76
+ }
70
77
  return get(window.store.config, 'syncSetting.' + type + 'AccessToken')
71
78
  }
72
79
 
@@ -158,7 +165,13 @@ export default (Store) => {
158
165
  const types = Object.keys(syncTypes)
159
166
  for (const type of types) {
160
167
  const gistId = store.getSyncGistId(type)
161
- if (gistId) {
168
+ // For WebDAV, check if server URL is configured
169
+ if (type === syncTypes.webdav) {
170
+ const serverUrl = get(window.store.config, 'syncSetting.webdavServerUrl')
171
+ if (serverUrl) {
172
+ await store.uploadSetting(type)
173
+ }
174
+ } else if (gistId) {
162
175
  await store.uploadSetting(type)
163
176
  }
164
177
  }
@@ -183,6 +196,24 @@ export default (Store) => {
183
196
  const { store } = window
184
197
  const token = store.getSyncToken(type)
185
198
  const gistId = store.getSyncGistId(type)
199
+
200
+ // Handle WebDAV preview differently
201
+ if (type === syncTypes.webdav) {
202
+ const gist = await fetchData(
203
+ type,
204
+ 'download',
205
+ [],
206
+ token,
207
+ store.getSyncProxy(type)
208
+ )
209
+ if (gist && gist.files) {
210
+ const statusContent = get(gist, 'files["electerm-status.json"].content')
211
+ const status = statusContent ? parseJsonSafe(statusContent) : undefined
212
+ store.syncServerStatus[type] = status
213
+ }
214
+ return
215
+ }
216
+
186
217
  const gist = await fetchData(
187
218
  type,
188
219
  'getOne',
@@ -201,7 +232,7 @@ export default (Store) => {
201
232
  // await store.createGist(type)
202
233
  // gistId = store.getSyncGistId(type)
203
234
  // }
204
- if (!gistId && type !== syncTypes.custom && type !== syncTypes.cloud) {
235
+ if (!gistId && type !== syncTypes.custom && type !== syncTypes.cloud && type !== syncTypes.webdav) {
205
236
  return
206
237
  }
207
238
  const pass = store.getSyncPassword(type)
@@ -244,6 +275,31 @@ export default (Store) => {
244
275
  electermVersion: packVer,
245
276
  deviceName: window.pre.osInfo().find(r => r.k === 'hostname')?.v || 'unknown'
246
277
  }
278
+
279
+ // Handle WebDAV upload differently
280
+ if (type === syncTypes.webdav) {
281
+ const uploadData = {}
282
+ for (const [key, value] of Object.entries(objs)) {
283
+ uploadData[key] = value.content
284
+ }
285
+ uploadData['electerm-status.json'] = JSON.stringify(status)
286
+
287
+ const res = await fetchData(
288
+ type,
289
+ 'upload',
290
+ [uploadData],
291
+ token,
292
+ store.getSyncProxy(type)
293
+ )
294
+ if (res && !res.error) {
295
+ store.updateSyncSetting({
296
+ [type + 'LastSyncTime']: now
297
+ })
298
+ store.syncServerStatus[type] = status
299
+ }
300
+ return
301
+ }
302
+
247
303
  const gistData = {
248
304
  description: 'sync electerm data',
249
305
  files: {
@@ -285,10 +341,80 @@ export default (Store) => {
285
341
  // await store.createGist(type)
286
342
  // gistId = store.getSyncGistId(type)
287
343
  // }
288
- if (!gistId && type !== syncTypes.custom && type !== syncTypes.cloud) {
344
+ if (!gistId && type !== syncTypes.custom && type !== syncTypes.cloud && type !== syncTypes.webdav) {
289
345
  return
290
346
  }
291
347
  const pass = store.getSyncPassword(type)
348
+
349
+ // Handle WebDAV download differently
350
+ if (type === syncTypes.webdav) {
351
+ const gist = await fetchData(
352
+ type,
353
+ 'download',
354
+ [],
355
+ token,
356
+ store.getSyncProxy(type)
357
+ )
358
+ if (gist && gist.files) {
359
+ const statusContent = get(gist, 'files["electerm-status.json"].content')
360
+ const status = statusContent ? parseJsonSafe(statusContent) : undefined
361
+ store.syncServerStatus[type] = status
362
+
363
+ const { names, syncConfig } = store.getDataSyncNames()
364
+ for (const n of names) {
365
+ let str = get(gist, `files["${n}.json"].content`)
366
+ if (!str) {
367
+ if (n === settingMap.bookmarks) {
368
+ throw new Error(('Seems you have a empty WebDAV folder, you can try upload first'))
369
+ } else {
370
+ continue
371
+ }
372
+ }
373
+ if (!isJSON(str)) {
374
+ str = await window.pre.runGlobalAsync('decryptAsync', str, pass)
375
+ }
376
+ let arr = JSON.parse(str)
377
+ if (n === settingMap.terminalThemes) {
378
+ arr = store.fixThemes(arr)
379
+ } else if (n === settingMap.bookmarks) {
380
+ arr = fixBookmarks(arr)
381
+ }
382
+ let strOrder = get(gist, `files["${n}.order.json"].content`)
383
+ if (isJSON(strOrder)) {
384
+ strOrder = JSON.parse(strOrder)
385
+ arr.sort((a, b) => {
386
+ const ai = strOrder.findIndex(r => r === a.id)
387
+ const bi = strOrder.findIndex(r => r === b.id)
388
+ return ai - bi
389
+ })
390
+ }
391
+ store.setItems(n, arr)
392
+ }
393
+ if (syncConfig) {
394
+ const userConfig = parseJsonSafe(
395
+ get(gist, 'files["userConfig.json"].content')
396
+ )
397
+ if (userConfig) {
398
+ store.setConfig(userConfig)
399
+ }
400
+ if (userConfig && userConfig.theme) {
401
+ store.setTheme(userConfig.theme)
402
+ }
403
+ }
404
+
405
+ const up = {
406
+ [type + 'LastSyncTime']: Date.now()
407
+ }
408
+ if (pass) {
409
+ up[type + 'SyncPassword'] = pass
410
+ }
411
+ store.updateSyncSetting(up)
412
+ }
413
+ store.isSyncingSetting = false
414
+ store.isSyncDownload = false
415
+ return
416
+ }
417
+
292
418
  const gist = await fetchData(
293
419
  type,
294
420
  'getOne',
@@ -24,10 +24,11 @@ export default Store => {
24
24
  // console.log('addTransferList', JSON.stringify(items, null, 2))
25
25
  const { fileTransfers } = window.store
26
26
  const transferBatch = uid()
27
- fileTransfers.push(...items.map(t => {
27
+ const nextItems = items.map(t => {
28
28
  t.transferBatch = transferBatch
29
29
  return t
30
- }))
30
+ })
31
+ fileTransfers.push(...nextItems)
31
32
  }
32
33
 
33
34
  Store.prototype.pauseAll = function () {
@@ -11,9 +11,7 @@ import {
11
11
  expandedKeysLsKey,
12
12
  resolutionsLsKey,
13
13
  localAddrBookmarkLsKey,
14
- syncServerDataKey,
15
- aiChatHistoryKey,
16
- cmdHistoryKey
14
+ syncServerDataKey
17
15
  } from '../common/constants'
18
16
  import * as ls from '../common/safe-local-storage'
19
17
  import { debounce, isEmpty } from 'lodash-es'
@@ -134,28 +132,6 @@ export default store => {
134
132
  return store.syncServerStatus
135
133
  }).start()
136
134
 
137
- autoRun(() => {
138
- ls.safeSetItemJSON('history', store.history)
139
- return store.history
140
- }).start()
141
-
142
- autoRun(() => {
143
- ls.safeSetItemJSON(aiChatHistoryKey, store.aiChatHistory)
144
- return store.aiChatHistory
145
- }).start()
146
-
147
- autoRun(() => {
148
- const history = store.terminalCommandHistory
149
- // Save in new format: array of {cmd, count, lastUseTime}
150
- const data = Array.from(history.entries()).map(([cmd, info]) => ({
151
- cmd,
152
- count: info.count,
153
- lastUseTime: info.lastUseTime
154
- }))
155
- ls.safeSetItemJSON(cmdHistoryKey, data)
156
- return store.terminalCommandHistory
157
- }).start()
158
-
159
135
  autoRun(() => {
160
136
  store.updateBatchInputSelectedTabIds()
161
137
  const tabs = store.getTabs()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "3.0.18",
3
+ "version": "3.1.16",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",