most-box 0.3.1 → 0.3.2
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 +15 -14
- package/electron/main.js +1 -1
- package/out/admin/index.html +0 -0
- package/out/app/index.html +0 -0
- package/out/assets/AccountMenu-BgbcUc0m.js +1 -0
- package/out/assets/AppTop-DZFTO9-m.js +1 -0
- package/out/assets/CopyButton-B03fpFFc.js +1 -0
- package/out/assets/FilePreviewOverlay-CA04_Ved.js +1 -0
- package/out/assets/{MarketingHeader-7B-OT2XX.js → MarketingHeader-BVJy8hXd.js} +1 -1
- package/out/assets/MarketingLayout-Cltu-DRw.js +1 -0
- package/out/assets/{MilkdownEditor-WedhCoFH.js → MilkdownEditor-Dw_ze7EE.js} +92 -92
- package/out/assets/OpenSidebarButton-C2UJYXKh.js +1 -0
- package/out/assets/arrow-right-CXzRt0Fp.js +1 -0
- package/out/assets/chatJoinInvite-BcPz_IV5.js +1 -0
- package/out/assets/chatNoteDraft-CYbvcEvC.js +1 -0
- package/out/assets/check-iBCQl0yr.js +1 -0
- package/out/assets/circle-alert-dfN4T6Nq.js +1 -0
- package/out/assets/cobol-DHLQUbN7.js +1 -0
- package/out/assets/copy-B7pPZ2MP.js +1 -0
- package/out/assets/{dist-DCX0ws1K.js → dist-1jNICPWO.js} +1 -1
- package/out/assets/{dist-BAJKKN4w.js → dist-B3unnv5t.js} +1 -1
- package/out/assets/{dist-DJdv-Ma3.js → dist-B5MBMmGa.js} +1 -1
- package/out/assets/{dist-CMmmtl3f.js → dist-BAqJdUtV.js} +1 -1
- package/out/assets/{dist-C3lbe8SW.js → dist-BBJOmVU3.js} +1 -1
- package/out/assets/{dist-IN8WN7NI.js → dist-BV5CqsJD.js} +1 -1
- package/out/assets/{dist-DBnWo8ZP.js → dist-Ba7fxbV-.js} +1 -1
- package/out/assets/{dist-BzqqCPi2.js → dist-BxxtNKuo.js} +1 -1
- package/out/assets/{dist-DvWZsW-D.js → dist-C8Ue2rSs.js} +1 -1
- package/out/assets/{dist-C-Tg23jc.js → dist-CIn7Xx5U.js} +1 -1
- package/out/assets/{dist-CbTzBiwL.js → dist-CSyRxrry.js} +3 -3
- package/out/assets/{dist-DTL5jL08.js → dist-CZIuQqmV.js} +1 -1
- package/out/assets/{dist-8QDHqrPN.js → dist-CaaBTHCc.js} +1 -1
- package/out/assets/{dist-yZ96GF-e.js → dist-CgReC0ZE.js} +1 -1
- package/out/assets/{dist-D94V9Zlh.js → dist-Ct90qYA2.js} +1 -1
- package/out/assets/{dist-IGpXmkFm.js → dist-DIFFjNuO.js} +1 -1
- package/out/assets/{dist-CqQavSZV.js → dist-DUB2IhWu.js} +1 -1
- package/out/assets/{dist-B0JrbG7f.js → dist-DheA_Tyz.js} +1 -1
- package/out/assets/{dist-Br_5lLVO.js → dist-DyZh1ncm.js} +1 -1
- package/out/assets/{dist-BPs0Xns9.js → dist-E74uGTy3.js} +1 -1
- package/out/assets/{dist-BFSyuOuw.js → dist-K2s-Uj08.js} +1 -1
- package/out/assets/{dist-zyJb88Zz.js → dist-RU_cpjXQ.js} +1 -1
- package/out/assets/{dist-chOCTzB2.js → dist-eIeCvp_6.js} +1 -1
- package/out/assets/{dist-CfU9fwWz.js → dist-hEE2Ub__.js} +1 -1
- package/out/assets/download-COQOcPqI.js +1 -0
- package/out/assets/{downloadValidation-Ch966YTl.js → downloadValidation-Zvllo2SZ.js} +1 -1
- package/out/assets/external-link-D6tHlYgS.js +1 -0
- package/out/assets/file-text-DiyIGL1I.js +1 -0
- package/out/assets/folder-DAcox9xz.js +1 -0
- package/out/assets/folder-open-Di0oALaC.js +1 -0
- package/out/assets/hard-drive-Cqa7Rstj.js +1 -0
- package/out/assets/index-B6acG3-t.css +1 -0
- package/out/assets/index-DjBN7bZV.js +31 -0
- package/out/assets/index.lazy-BUODxlbz.js +1 -0
- package/out/assets/index.lazy-Ba2rqd32.js +3 -0
- package/out/assets/index.lazy-Bdh8QUOx.js +1 -0
- package/out/assets/index.lazy-BfAHB94y.js +1 -0
- package/out/assets/index.lazy-Bo0LfJNK.js +2 -0
- package/out/assets/index.lazy-C9-w4fAF.js +3 -0
- package/out/assets/index.lazy-CNQbNKyf.js +1 -0
- package/out/assets/index.lazy-Cd0znkpY.js +1 -0
- package/out/assets/index.lazy-CtUrBLS0.js +1 -0
- package/out/assets/index.lazy-CyNgk0ta.js +1 -0
- package/out/assets/index.lazy-D3HxQTg_.js +1 -0
- package/out/assets/index.lazy-DSsE3iyf.js +1 -0
- package/out/assets/index.lazy-DWXndrGa.js +1 -0
- package/out/assets/index.lazy-Dk7cmQ-j.js +2 -0
- package/out/assets/key-round-JR8M3aHl.js +1 -0
- package/out/assets/loader-CwyHYZdX.js +1 -0
- package/out/assets/lock-CuwwlXlx.js +1 -0
- package/out/assets/message-square-BgsNXPft.js +1 -0
- package/out/assets/mp-Dv12gDTx.js +1 -0
- package/out/assets/music-Dn9nm9Qb.js +1 -0
- package/out/assets/notebook-pen-SWT-zZ4v.js +1 -0
- package/out/assets/play-CvWKSMwY.js +1 -0
- package/out/assets/refresh-cw-D4BsHvhi.js +1 -0
- package/out/assets/save-B02sbO9Y.js +1 -0
- package/out/assets/scheme-tChLYBuY.js +1 -0
- package/out/assets/search-HW4oPOBP.js +1 -0
- package/out/assets/send-4dhnJGuS.js +1 -0
- package/out/assets/shield-check-Boae7Nc6.js +1 -0
- package/out/assets/smartphone-JXH-zQXB.js +1 -0
- package/out/assets/textile-CyzeGT9J.js +1 -0
- package/out/assets/trash-2-BLwoM0ME.js +1 -0
- package/out/assets/triangle-alert-B9sMiA9l.js +1 -0
- package/out/assets/upload-DVuXJt_o.js +1 -0
- package/out/assets/useAppStore-DOnk608w.js +4 -0
- package/out/assets/{useChannelMessages-Bs_RWgO4.js → useChannelMessages-CDvw-f_x.js} +1 -1
- package/out/assets/useGameRoom-B1_r6bc7.js +1 -0
- package/out/assets/userProfile-BZvkCuet.js +1 -0
- package/out/assets/wallet-D9Iw4YWE.js +1 -0
- package/out/assets/wifi-ljEI_ySA.js +1 -0
- package/out/chat/index.html +0 -0
- package/out/chat/join/demo/index.html +0 -0
- package/out/chat/join/index.html +0 -0
- package/out/download/index.html +2 -2
- package/out/game/gandengyan/index.html +0 -0
- package/out/game/index.html +0 -0
- package/out/game/zhajinhua/index.html +0 -0
- package/out/index.html +2 -2
- package/out/note/index.html +0 -0
- package/out/ping/index.html +2 -2
- package/out/profile/index.html +0 -0
- package/out/web3/index.html +0 -0
- package/package.json +27 -24
- package/server/index.js +3 -0
- package/server/src/config.js +0 -1
- package/server/src/core/gameRoom.js +12 -19
- package/server/src/http/routes/noteVaultRoutes.js +70 -0
- package/server/src/index.js +9 -0
- package/server/src/utils/accountBackup.js +8 -0
- package/server/src/utils/api.js +0 -14
- package/server/src/utils/auth.js +0 -7
- package/server/src/utils/avatar.js +6 -6
- package/server/src/utils/noteVault.js +197 -2
- package/out/assets/AccountMenu-NjOgag0d.js +0 -1
- package/out/assets/FilePreviewOverlay-CZp6F1s_.js +0 -1
- package/out/assets/MarketingLayout-CyiSCygk.js +0 -1
- package/out/assets/OpenSidebarButton-BoSmO8CY.js +0 -1
- package/out/assets/SidebarHomeLink-CkhGDvZ8.js +0 -1
- package/out/assets/arrow-right-DUxAoZqb.js +0 -1
- package/out/assets/avatar-BZwHW4ll.js +0 -4
- package/out/assets/circle-alert-DSZ0bG_3.js +0 -1
- package/out/assets/cobol-B_OZ4V-R.js +0 -1
- package/out/assets/copy-CK7HMulu.js +0 -1
- package/out/assets/download-Q1uCiwif.js +0 -1
- package/out/assets/external-link-DGzNJOqQ.js +0 -1
- package/out/assets/file-text-C3v0L_lQ.js +0 -1
- package/out/assets/folder-CwtLO09O.js +0 -1
- package/out/assets/hard-drive-B2V5USzR.js +0 -1
- package/out/assets/i18n-DZaOYCSO.js +0 -1
- package/out/assets/index-CBkHUp3F.css +0 -1
- package/out/assets/index-DluhgSHX.js +0 -31
- package/out/assets/index.lazy-B5TYRvFJ.js +0 -1
- package/out/assets/index.lazy-BeDctVci.js +0 -1
- package/out/assets/index.lazy-BjmAkVtV.js +0 -1
- package/out/assets/index.lazy-CHJbzlK6.js +0 -1
- package/out/assets/index.lazy-CITrkWMQ.js +0 -1
- package/out/assets/index.lazy-CTGE5fUt.js +0 -2
- package/out/assets/index.lazy-CUxcXUMy.js +0 -2
- package/out/assets/index.lazy-D84xQtPb.js +0 -3
- package/out/assets/index.lazy-DRqAgqpV.js +0 -1
- package/out/assets/index.lazy-DSAmY1q_.js +0 -1
- package/out/assets/index.lazy-DvbVQRSL.js +0 -1
- package/out/assets/index.lazy-gAJi-rJV.js +0 -1
- package/out/assets/index.lazy-rzyMd-Gz.js +0 -1
- package/out/assets/key-round-Dn5tud-4.js +0 -1
- package/out/assets/loader-CLoDCtNy.js +0 -1
- package/out/assets/lock-BEWKuIqK.js +0 -1
- package/out/assets/message-square-C8ZiYztG.js +0 -1
- package/out/assets/mp-CGBtY36n.js +0 -1
- package/out/assets/music-BsTA8b_M.js +0 -1
- package/out/assets/notebook-pen-DgWzxf2y.js +0 -1
- package/out/assets/play-CVkbAJJU.js +0 -1
- package/out/assets/plus-D1kCYb8G.js +0 -1
- package/out/assets/save-X5c7jlCg.js +0 -1
- package/out/assets/scheme-CyDdOh7e.js +0 -1
- package/out/assets/search-DAV9vDOq.js +0 -1
- package/out/assets/send-C5JjYo-A.js +0 -1
- package/out/assets/shield-check-DuD6OLde.js +0 -1
- package/out/assets/smartphone-gVFruyjO.js +0 -1
- package/out/assets/textile-DWBqthVk.js +0 -1
- package/out/assets/trash-2-CE-3Dc63.js +0 -1
- package/out/assets/triangle-alert-DnOxsFpB.js +0 -1
- package/out/assets/upload-CsnBv3pd.js +0 -1
- package/out/assets/useGameRoom-BxDxm3rp.js +0 -1
- package/out/assets/userProfile-UphvP_bG.js +0 -1
- package/out/assets/wallet-VDaoXwjI.js +0 -1
- package/out/assets/wifi-DfWbmlGE.js +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "most-box",
|
|
3
|
-
"version": "0.3.
|
|
4
|
-
"description": "MostBox - P2P
|
|
3
|
+
"version": "0.3.2",
|
|
4
|
+
"description": "MostBox - chat-first P2P toolbox for files, notes, and game rooms",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "electron/main.js",
|
|
7
7
|
"bin": {
|
|
@@ -44,29 +44,32 @@
|
|
|
44
44
|
},
|
|
45
45
|
"keywords": [
|
|
46
46
|
"p2p",
|
|
47
|
+
"chat",
|
|
47
48
|
"file-sharing",
|
|
49
|
+
"file-transfer",
|
|
48
50
|
"hyperswarm",
|
|
51
|
+
"hypercore",
|
|
49
52
|
"hyperdrive"
|
|
50
53
|
],
|
|
51
54
|
"license": "MIT",
|
|
52
55
|
"dependencies": {
|
|
53
|
-
"@dicebear/
|
|
54
|
-
"@dicebear/
|
|
55
|
-
"@hono/node-server": "^2.0.
|
|
56
|
-
"@tanstack/react-router": "^1.170.
|
|
57
|
-
"@tanstack/react-start": "^1.168.
|
|
56
|
+
"@dicebear/core": "^10.3.0",
|
|
57
|
+
"@dicebear/styles": "^10.2.0",
|
|
58
|
+
"@hono/node-server": "^2.0.6",
|
|
59
|
+
"@tanstack/react-router": "^1.170.16",
|
|
60
|
+
"@tanstack/react-start": "^1.168.26",
|
|
58
61
|
"b4a": "^1.8.1",
|
|
59
62
|
"busboy": "^1.6.0",
|
|
60
|
-
"corestore": "^7.
|
|
63
|
+
"corestore": "^7.11.0",
|
|
61
64
|
"dayjs": "^1.11.21",
|
|
62
|
-
"ethers": "^6.
|
|
65
|
+
"ethers": "^6.17.0",
|
|
63
66
|
"eventemitter3": "^5.0.4",
|
|
64
|
-
"hono": "^4.12.
|
|
65
|
-
"hypercore": "^11.33.
|
|
67
|
+
"hono": "^4.12.27",
|
|
68
|
+
"hypercore": "^11.33.2",
|
|
66
69
|
"hyperdrive": "^13.3.2",
|
|
67
70
|
"hyperswarm": "^4.17.0",
|
|
68
71
|
"ipfs-unixfs-importer": "^17.0.1",
|
|
69
|
-
"multiformats": "^14.0.
|
|
72
|
+
"multiformats": "^14.0.2",
|
|
70
73
|
"tweetnacl": "^1.0.3",
|
|
71
74
|
"ws": "^8.21.0"
|
|
72
75
|
},
|
|
@@ -74,26 +77,26 @@
|
|
|
74
77
|
"@electron/rebuild": "^4.0.4",
|
|
75
78
|
"@eslint/js": "^10.0.1",
|
|
76
79
|
"@iconify/react": "^6.0.2",
|
|
77
|
-
"@mantine/hooks": "^9.
|
|
80
|
+
"@mantine/hooks": "^9.4.0",
|
|
78
81
|
"@milkdown/crepe": "^7.21.2",
|
|
79
82
|
"@milkdown/utils": "^7.21.2",
|
|
80
|
-
"@types/react": "^19.2.
|
|
81
|
-
"@vitejs/plugin-react": "^6.0.
|
|
83
|
+
"@types/react": "^19.2.17",
|
|
84
|
+
"@vitejs/plugin-react": "^6.0.3",
|
|
82
85
|
"concurrently": "^10.0.3",
|
|
83
|
-
"electron": "^42.
|
|
84
|
-
"electron-builder": "^26.
|
|
85
|
-
"esbuild": "^0.28.
|
|
86
|
-
"eslint": "^10.
|
|
87
|
-
"globals": "^17.
|
|
86
|
+
"electron": "^42.5.0",
|
|
87
|
+
"electron-builder": "^26.15.3",
|
|
88
|
+
"esbuild": "^0.28.1",
|
|
89
|
+
"eslint": "^10.5.0",
|
|
90
|
+
"globals": "^17.7.0",
|
|
88
91
|
"ky": "^2.0.2",
|
|
89
|
-
"lucide-react": "^1.
|
|
90
|
-
"prettier": "^3.8.
|
|
92
|
+
"lucide-react": "^1.21.0",
|
|
93
|
+
"prettier": "^3.8.4",
|
|
91
94
|
"qrcode.react": "^4.2.0",
|
|
92
95
|
"react": "^19.2.7",
|
|
93
96
|
"react-dom": "^19.2.7",
|
|
94
97
|
"typescript": "6.0.3",
|
|
95
|
-
"typescript-eslint": "^8.
|
|
96
|
-
"vite": "^8.0
|
|
98
|
+
"typescript-eslint": "^8.62.0",
|
|
99
|
+
"vite": "^8.1.0",
|
|
97
100
|
"wait-on": "^9.0.10",
|
|
98
101
|
"zustand": "^5.0.14"
|
|
99
102
|
},
|
package/server/index.js
CHANGED
|
@@ -137,6 +137,9 @@ function bindEngineEvents({
|
|
|
137
137
|
engine.on('channel:peer:offline', data =>
|
|
138
138
|
wsBroadcast('channel:peer:offline', data)
|
|
139
139
|
)
|
|
140
|
+
engine.on('channel:sync:available', data =>
|
|
141
|
+
wsBroadcast('channel:sync:available', data)
|
|
142
|
+
)
|
|
140
143
|
engine.on('channel:presence', data =>
|
|
141
144
|
wsSendToChannel(data.channelKey, 'channel:presence', data)
|
|
142
145
|
)
|
package/server/src/config.js
CHANGED
|
@@ -19,7 +19,9 @@ export const GAME_IDS = ['gandengyan', 'zhajinhua']
|
|
|
19
19
|
const ROOM_CODE_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'
|
|
20
20
|
|
|
21
21
|
export function normalizeGameId(input) {
|
|
22
|
-
const value = String(input || '')
|
|
22
|
+
const value = String(input || '')
|
|
23
|
+
.trim()
|
|
24
|
+
.toLowerCase()
|
|
23
25
|
return GAME_IDS.includes(value) ? value : ''
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -47,7 +49,9 @@ export function gameRoomCodeToChannelName(gameId, roomCode) {
|
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
export function channelNameToGameRoom(input) {
|
|
50
|
-
const value = String(input || '')
|
|
52
|
+
const value = String(input || '')
|
|
53
|
+
.trim()
|
|
54
|
+
.toLowerCase()
|
|
51
55
|
const match = /^game\.([a-z0-9]+)\.([a-z0-9]+)$/.exec(value)
|
|
52
56
|
if (!match) return null
|
|
53
57
|
const gameId = normalizeGameId(match[1])
|
|
@@ -86,7 +90,8 @@ export function parseGameEvent(content, options = {}) {
|
|
|
86
90
|
const gameId = normalizeGameId(event.gameId)
|
|
87
91
|
const roomCode = normalizeGameRoomCode(event.roomCode)
|
|
88
92
|
if (!gameId || !isValidGameRoomCode(roomCode)) return null
|
|
89
|
-
if (options.gameId && gameId !== normalizeGameId(options.gameId))
|
|
93
|
+
if (options.gameId && gameId !== normalizeGameId(options.gameId))
|
|
94
|
+
return null
|
|
90
95
|
if (
|
|
91
96
|
options.roomCode &&
|
|
92
97
|
roomCode !== normalizeGameRoomCode(options.roomCode)
|
|
@@ -99,9 +104,7 @@ export function parseGameEvent(content, options = {}) {
|
|
|
99
104
|
gameId,
|
|
100
105
|
roomCode,
|
|
101
106
|
payload:
|
|
102
|
-
event.payload && typeof event.payload === 'object'
|
|
103
|
-
? event.payload
|
|
104
|
-
: {},
|
|
107
|
+
event.payload && typeof event.payload === 'object' ? event.payload : {},
|
|
105
108
|
}
|
|
106
109
|
} catch {
|
|
107
110
|
return null
|
|
@@ -132,7 +135,9 @@ export function deriveGameRoomLobby(messages = [], options = {}) {
|
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
if (event.event === 'player:leave') {
|
|
135
|
-
const address = normalizeAddress(
|
|
138
|
+
const address = normalizeAddress(
|
|
139
|
+
event.payload?.player?.address || message.author
|
|
140
|
+
)
|
|
136
141
|
if (address) {
|
|
137
142
|
const index = players.findIndex(p => p.address === address)
|
|
138
143
|
if (index !== -1) {
|
|
@@ -190,18 +195,6 @@ export function createPlayerFromPayload(input, messageOrAuthor) {
|
|
|
190
195
|
return player
|
|
191
196
|
}
|
|
192
197
|
|
|
193
|
-
export function normalizeGamePlayer(input) {
|
|
194
|
-
if (!input || typeof input !== 'object') return null
|
|
195
|
-
const address = normalizeAddress(input.address)
|
|
196
|
-
if (!address) return null
|
|
197
|
-
return {
|
|
198
|
-
...input,
|
|
199
|
-
address,
|
|
200
|
-
name: String(input.name || shortAddress(address)).slice(0, 50),
|
|
201
|
-
publicKey: String(input.publicKey || ''),
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
198
|
function upsertPlayer(players, playerMap, player) {
|
|
206
199
|
const existing = playerMap.get(player.address)
|
|
207
200
|
if (existing) {
|
|
@@ -2,10 +2,15 @@ import { errorJson } from '../errors.js'
|
|
|
2
2
|
import { PermissionError } from '../../utils/errors.js'
|
|
3
3
|
import {
|
|
4
4
|
configureNoteVault,
|
|
5
|
+
createMarkdownFile,
|
|
6
|
+
createNoteVaultSnapshot,
|
|
7
|
+
deleteMarkdownFile,
|
|
5
8
|
getConfiguredNoteVaultPath,
|
|
6
9
|
getNoteVaultStatus,
|
|
7
10
|
listMarkdownFiles,
|
|
11
|
+
moveMarkdownFile,
|
|
8
12
|
readMarkdownFile,
|
|
13
|
+
restoreNoteVaultSnapshot,
|
|
9
14
|
writeMarkdownFile,
|
|
10
15
|
} from '../../utils/noteVault.js'
|
|
11
16
|
|
|
@@ -67,6 +72,22 @@ export function registerNoteVaultRoutes(app, { configStore, isRemoteRequest }) {
|
|
|
67
72
|
}
|
|
68
73
|
})
|
|
69
74
|
|
|
75
|
+
app.post('/api/note-vault/file', async c => {
|
|
76
|
+
try {
|
|
77
|
+
assertNoteVaultAccess(c, isRemoteRequest)
|
|
78
|
+
const body = await c.req.json()
|
|
79
|
+
const vaultPath = await getConfiguredNoteVaultPath(configStore.configDir)
|
|
80
|
+
const file = await createMarkdownFile(
|
|
81
|
+
vaultPath,
|
|
82
|
+
String(body.path || ''),
|
|
83
|
+
String(body.content || '')
|
|
84
|
+
)
|
|
85
|
+
return c.json({ success: true, file })
|
|
86
|
+
} catch (err) {
|
|
87
|
+
return errorJson(c, err)
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
|
|
70
91
|
app.put('/api/note-vault/file', async c => {
|
|
71
92
|
try {
|
|
72
93
|
assertNoteVaultAccess(c, isRemoteRequest)
|
|
@@ -82,4 +103,53 @@ export function registerNoteVaultRoutes(app, { configStore, isRemoteRequest }) {
|
|
|
82
103
|
return errorJson(c, err)
|
|
83
104
|
}
|
|
84
105
|
})
|
|
106
|
+
|
|
107
|
+
app.patch('/api/note-vault/file', async c => {
|
|
108
|
+
try {
|
|
109
|
+
assertNoteVaultAccess(c, isRemoteRequest)
|
|
110
|
+
const body = await c.req.json()
|
|
111
|
+
const vaultPath = await getConfiguredNoteVaultPath(configStore.configDir)
|
|
112
|
+
const file = await moveMarkdownFile(
|
|
113
|
+
vaultPath,
|
|
114
|
+
String(body.path || body.fromPath || ''),
|
|
115
|
+
String(body.newPath || body.toPath || '')
|
|
116
|
+
)
|
|
117
|
+
return c.json({ success: true, file })
|
|
118
|
+
} catch (err) {
|
|
119
|
+
return errorJson(c, err)
|
|
120
|
+
}
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
app.delete('/api/note-vault/file', async c => {
|
|
124
|
+
try {
|
|
125
|
+
assertNoteVaultAccess(c, isRemoteRequest)
|
|
126
|
+
const vaultPath = await getConfiguredNoteVaultPath(configStore.configDir)
|
|
127
|
+
const result = await deleteMarkdownFile(vaultPath, c.req.query('path'))
|
|
128
|
+
return c.json({ success: true, ...result })
|
|
129
|
+
} catch (err) {
|
|
130
|
+
return errorJson(c, err)
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
app.get('/api/note-vault/snapshot', async c => {
|
|
135
|
+
try {
|
|
136
|
+
assertNoteVaultAccess(c, isRemoteRequest)
|
|
137
|
+
const vaultPath = await getConfiguredNoteVaultPath(configStore.configDir)
|
|
138
|
+
return c.json(await createNoteVaultSnapshot(vaultPath))
|
|
139
|
+
} catch (err) {
|
|
140
|
+
return errorJson(c, err)
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
|
|
144
|
+
app.post('/api/note-vault/restore', async c => {
|
|
145
|
+
try {
|
|
146
|
+
assertNoteVaultAccess(c, isRemoteRequest)
|
|
147
|
+
const body = await c.req.json()
|
|
148
|
+
const vaultPath = await getConfiguredNoteVaultPath(configStore.configDir)
|
|
149
|
+
const result = await restoreNoteVaultSnapshot(vaultPath, body)
|
|
150
|
+
return c.json({ success: true, result })
|
|
151
|
+
} catch (err) {
|
|
152
|
+
return errorJson(c, err)
|
|
153
|
+
}
|
|
154
|
+
})
|
|
85
155
|
}
|
package/server/src/index.js
CHANGED
|
@@ -4818,6 +4818,15 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4818
4818
|
])
|
|
4819
4819
|
this.#saveChannelsMetadata()
|
|
4820
4820
|
}
|
|
4821
|
+
if (channel) {
|
|
4822
|
+
this.emit('channel:sync:available', {
|
|
4823
|
+
channel: channelKey,
|
|
4824
|
+
channelKey,
|
|
4825
|
+
channelId: channel.channelId || '',
|
|
4826
|
+
writerCoreKey: normalizedCoreKey,
|
|
4827
|
+
writerCoreKeys: uniqueStrings(channel.writerCoreKeys),
|
|
4828
|
+
})
|
|
4829
|
+
}
|
|
4821
4830
|
console.log(
|
|
4822
4831
|
`[MostBox] Opened remote channel core ${normalizedCoreKey.slice(0, 8)}... for ${channelKey}`
|
|
4823
4832
|
)
|
|
@@ -29,6 +29,14 @@ export function validateAccountBackupPayload(input) {
|
|
|
29
29
|
if (!Array.isArray(input.notes)) {
|
|
30
30
|
throw new Error('账号备份缺少 notes')
|
|
31
31
|
}
|
|
32
|
+
if (
|
|
33
|
+
input.noteVault !== undefined &&
|
|
34
|
+
(!input.noteVault ||
|
|
35
|
+
typeof input.noteVault !== 'object' ||
|
|
36
|
+
!Array.isArray(input.noteVault.files))
|
|
37
|
+
) {
|
|
38
|
+
throw new Error('账号备份 noteVault 格式无效')
|
|
39
|
+
}
|
|
32
40
|
return input
|
|
33
41
|
}
|
|
34
42
|
|
package/server/src/utils/api.js
CHANGED
|
@@ -413,10 +413,6 @@ export function getBackendUrlExport() {
|
|
|
413
413
|
return getBackendUrl()
|
|
414
414
|
}
|
|
415
415
|
|
|
416
|
-
export function getConfiguredBackendUrlExport() {
|
|
417
|
-
return getConfiguredBackendUrl()
|
|
418
|
-
}
|
|
419
|
-
|
|
420
416
|
export function getSameOriginBackendUrlExport() {
|
|
421
417
|
return getSameOriginBackendUrl()
|
|
422
418
|
}
|
|
@@ -437,10 +433,6 @@ export function getNodeHistoryExport() {
|
|
|
437
433
|
return getNodeHistory()
|
|
438
434
|
}
|
|
439
435
|
|
|
440
|
-
export function getBackendInviteExport() {
|
|
441
|
-
return getBackendInvite()
|
|
442
|
-
}
|
|
443
|
-
|
|
444
436
|
export function getApiUrl(path) {
|
|
445
437
|
const url = getBackendUrl()
|
|
446
438
|
return `${url}${normalizePath(path)}`
|
|
@@ -510,12 +502,6 @@ export async function getAuthenticatedWebSocketUrl(path = '/ws') {
|
|
|
510
502
|
return url.toString()
|
|
511
503
|
}
|
|
512
504
|
|
|
513
|
-
export async function checkBackendConnection() {
|
|
514
|
-
const url = getBackendUrl() || getSameOriginBackendUrl()
|
|
515
|
-
const invite = shouldAttachBackendInvite(url) ? getBackendInvite() : ''
|
|
516
|
-
return checkBackendConnectionTarget({ url, invite })
|
|
517
|
-
}
|
|
518
|
-
|
|
519
505
|
async function probeHttp(cleanedUrl, invite, identity) {
|
|
520
506
|
try {
|
|
521
507
|
const headers = {}
|
package/server/src/utils/auth.js
CHANGED
|
@@ -51,10 +51,3 @@ export function verifyAuthHeader(header, method, path, options = {}) {
|
|
|
51
51
|
return { ok: false, error: 'Invalid authorization signature' }
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
export function parseInviteList(value = '') {
|
|
56
|
-
return String(value || '')
|
|
57
|
-
.split(',')
|
|
58
|
-
.map(item => item.trim())
|
|
59
|
-
.filter(Boolean)
|
|
60
|
-
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
1
|
+
import { Avatar, Style } from '@dicebear/core'
|
|
2
|
+
import botttsNeutralDefinition from '@dicebear/styles/bottts-neutral.json' with { type: 'json' }
|
|
3
3
|
|
|
4
4
|
export const defaultAvatarIds = [
|
|
5
5
|
'panda',
|
|
@@ -50,11 +50,11 @@ export function normalizeDefaultAvatarValue(avatar) {
|
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function createAddressAvatar(address) {
|
|
53
|
-
|
|
53
|
+
const avatar = new Avatar(new Style(botttsNeutralDefinition), {
|
|
54
54
|
seed: 'most.box@' + address,
|
|
55
|
-
flip:
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
flip: 'horizontal',
|
|
56
|
+
})
|
|
57
|
+
return avatar.toDataUri()
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
export function generateAvatar(address, avatar) {
|
|
@@ -2,7 +2,7 @@ import crypto from 'node:crypto'
|
|
|
2
2
|
import fs from 'node:fs/promises'
|
|
3
3
|
import fsSync from 'node:fs'
|
|
4
4
|
import path from 'node:path'
|
|
5
|
-
import { PathSecurityError, ValidationError } from './errors.js'
|
|
5
|
+
import { ConflictError, PathSecurityError, ValidationError } from './errors.js'
|
|
6
6
|
|
|
7
7
|
const CONFIG_FILE_NAME = 'note-vault.json'
|
|
8
8
|
const MARKDOWN_EXTENSION = '.md'
|
|
@@ -37,6 +37,19 @@ async function pathExists(filePath) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
async function removeEmptyParentDirectories(vaultRealPath, startPath) {
|
|
41
|
+
let currentPath = startPath
|
|
42
|
+
|
|
43
|
+
while (isPathInside(vaultRealPath, currentPath) && currentPath !== vaultRealPath) {
|
|
44
|
+
try {
|
|
45
|
+
await fs.rmdir(currentPath)
|
|
46
|
+
} catch {
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
currentPath = path.dirname(currentPath)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
40
53
|
async function getVaultDirectoryInfo(vaultPath, options = {}) {
|
|
41
54
|
const rawPath = String(vaultPath || '').trim()
|
|
42
55
|
if (!rawPath) {
|
|
@@ -277,7 +290,7 @@ export async function readMarkdownFile(vaultPath, relativePath) {
|
|
|
277
290
|
}
|
|
278
291
|
}
|
|
279
292
|
|
|
280
|
-
|
|
293
|
+
async function getWritableMarkdownTarget(vaultPath, relativePath) {
|
|
281
294
|
const info = await getVaultDirectoryInfo(vaultPath, { requireWritable: true })
|
|
282
295
|
const normalizedPath = normalizeNoteVaultRelativePath(relativePath)
|
|
283
296
|
const targetPath = path.resolve(info.realPath, toNativePath(normalizedPath))
|
|
@@ -308,6 +321,22 @@ export async function writeMarkdownFile(vaultPath, relativePath, content) {
|
|
|
308
321
|
}
|
|
309
322
|
}
|
|
310
323
|
|
|
324
|
+
return { info, normalizedPath, targetPath, parentPath }
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export async function createMarkdownFile(vaultPath, relativePath, content) {
|
|
328
|
+
const { info, normalizedPath, targetPath } =
|
|
329
|
+
await getWritableMarkdownTarget(vaultPath, relativePath)
|
|
330
|
+
if (await pathExists(targetPath)) {
|
|
331
|
+
throw new ConflictError('note vault file already exists')
|
|
332
|
+
}
|
|
333
|
+
return writeMarkdownFile(info.realPath, normalizedPath, content)
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
export async function writeMarkdownFile(vaultPath, relativePath, content) {
|
|
337
|
+
const { info, normalizedPath, targetPath, parentPath } =
|
|
338
|
+
await getWritableMarkdownTarget(vaultPath, relativePath)
|
|
339
|
+
|
|
311
340
|
const tempPath = path.join(
|
|
312
341
|
parentPath,
|
|
313
342
|
`.${path.basename(targetPath)}.${process.pid}.${Date.now()}.${crypto
|
|
@@ -325,3 +354,169 @@ export async function writeMarkdownFile(vaultPath, relativePath, content) {
|
|
|
325
354
|
|
|
326
355
|
return readMarkdownFile(info.realPath, normalizedPath)
|
|
327
356
|
}
|
|
357
|
+
|
|
358
|
+
export async function moveMarkdownFile(
|
|
359
|
+
vaultPath,
|
|
360
|
+
fromRelativePath,
|
|
361
|
+
toRelativePath
|
|
362
|
+
) {
|
|
363
|
+
const info = await getVaultDirectoryInfo(vaultPath, { requireWritable: true })
|
|
364
|
+
const fromPath = normalizeNoteVaultRelativePath(fromRelativePath)
|
|
365
|
+
const toPath = normalizeNoteVaultRelativePath(toRelativePath)
|
|
366
|
+
if (fromPath === toPath) return readMarkdownFile(info.realPath, fromPath)
|
|
367
|
+
|
|
368
|
+
const sourcePath = path.resolve(info.realPath, toNativePath(fromPath))
|
|
369
|
+
const targetPath = path.resolve(info.realPath, toNativePath(toPath))
|
|
370
|
+
const targetParentPath = path.dirname(targetPath)
|
|
371
|
+
|
|
372
|
+
let sourceStat
|
|
373
|
+
try {
|
|
374
|
+
sourceStat = await fs.lstat(sourcePath)
|
|
375
|
+
} catch {
|
|
376
|
+
throw new ValidationError(
|
|
377
|
+
'note vault file not found',
|
|
378
|
+
'NOTE_VAULT_FILE_NOT_FOUND'
|
|
379
|
+
)
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
if (sourceStat.isSymbolicLink()) {
|
|
383
|
+
throw new PathSecurityError('Symlink Markdown files are not writable')
|
|
384
|
+
}
|
|
385
|
+
if (!sourceStat.isFile()) {
|
|
386
|
+
throw new ValidationError(
|
|
387
|
+
'note vault path is not a file',
|
|
388
|
+
'NOTE_VAULT_NOT_FILE'
|
|
389
|
+
)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
const realSourcePath = await fs.realpath(sourcePath)
|
|
393
|
+
if (!isPathInside(info.realPath, realSourcePath)) {
|
|
394
|
+
throw new PathSecurityError('Note vault file escapes the configured vault')
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (await pathExists(targetPath)) {
|
|
398
|
+
throw new ConflictError('note vault target already exists')
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
await fs.mkdir(targetParentPath, { recursive: true })
|
|
402
|
+
const realTargetParentPath = await fs.realpath(targetParentPath)
|
|
403
|
+
if (!isPathInside(info.realPath, realTargetParentPath)) {
|
|
404
|
+
throw new PathSecurityError('Note vault file escapes the configured vault')
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
await fs.rename(realSourcePath, targetPath)
|
|
408
|
+
await removeEmptyParentDirectories(info.realPath, path.dirname(realSourcePath))
|
|
409
|
+
return readMarkdownFile(info.realPath, toPath)
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
export async function deleteMarkdownFile(vaultPath, relativePath) {
|
|
413
|
+
const info = await getVaultDirectoryInfo(vaultPath, { requireWritable: true })
|
|
414
|
+
const normalizedPath = normalizeNoteVaultRelativePath(relativePath)
|
|
415
|
+
const targetPath = path.resolve(info.realPath, toNativePath(normalizedPath))
|
|
416
|
+
|
|
417
|
+
let stat
|
|
418
|
+
try {
|
|
419
|
+
stat = await fs.lstat(targetPath)
|
|
420
|
+
} catch {
|
|
421
|
+
throw new ValidationError(
|
|
422
|
+
'note vault file not found',
|
|
423
|
+
'NOTE_VAULT_FILE_NOT_FOUND'
|
|
424
|
+
)
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
if (stat.isSymbolicLink()) {
|
|
428
|
+
throw new PathSecurityError('Symlink Markdown files are not writable')
|
|
429
|
+
}
|
|
430
|
+
if (!stat.isFile()) {
|
|
431
|
+
throw new ValidationError(
|
|
432
|
+
'note vault path is not a file',
|
|
433
|
+
'NOTE_VAULT_NOT_FILE'
|
|
434
|
+
)
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const realFilePath = await fs.realpath(targetPath)
|
|
438
|
+
if (!isPathInside(info.realPath, realFilePath)) {
|
|
439
|
+
throw new PathSecurityError('Note vault file escapes the configured vault')
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
await fs.unlink(realFilePath)
|
|
443
|
+
await removeEmptyParentDirectories(info.realPath, path.dirname(realFilePath))
|
|
444
|
+
return { path: normalizedPath, deleted: true }
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export async function createNoteVaultSnapshot(vaultPath) {
|
|
448
|
+
const files = await listMarkdownFiles(vaultPath)
|
|
449
|
+
const snapshotFiles = []
|
|
450
|
+
|
|
451
|
+
for (const file of files) {
|
|
452
|
+
const content = await readMarkdownFile(vaultPath, file.path)
|
|
453
|
+
snapshotFiles.push({
|
|
454
|
+
path: content.path,
|
|
455
|
+
content: content.content,
|
|
456
|
+
size: content.size,
|
|
457
|
+
mtimeMs: content.mtimeMs,
|
|
458
|
+
})
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return { files: snapshotFiles }
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
function normalizeSnapshotFiles(input) {
|
|
465
|
+
const files = Array.isArray(input?.files) ? input.files : []
|
|
466
|
+
const byPath = new Map()
|
|
467
|
+
|
|
468
|
+
for (const file of files) {
|
|
469
|
+
if (!file || typeof file !== 'object') continue
|
|
470
|
+
const normalizedPath = normalizeNoteVaultRelativePath(file.path)
|
|
471
|
+
byPath.set(normalizedPath, {
|
|
472
|
+
path: normalizedPath,
|
|
473
|
+
content: String(file.content ?? ''),
|
|
474
|
+
})
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
return [...byPath.values()].sort((left, right) =>
|
|
478
|
+
left.path.localeCompare(right.path)
|
|
479
|
+
)
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export async function restoreNoteVaultSnapshot(vaultPath, snapshotInput) {
|
|
483
|
+
const info = await getVaultDirectoryInfo(vaultPath, { requireWritable: true })
|
|
484
|
+
const snapshotFiles = normalizeSnapshotFiles(snapshotInput)
|
|
485
|
+
const snapshotPaths = new Set(snapshotFiles.map(file => file.path))
|
|
486
|
+
const currentFiles = await listMarkdownFiles(info.realPath)
|
|
487
|
+
const result = {
|
|
488
|
+
created: 0,
|
|
489
|
+
updated: 0,
|
|
490
|
+
deleted: 0,
|
|
491
|
+
skipped: 0,
|
|
492
|
+
files: snapshotFiles.length,
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
for (const currentFile of currentFiles) {
|
|
496
|
+
if (snapshotPaths.has(currentFile.path)) continue
|
|
497
|
+
await deleteMarkdownFile(info.realPath, currentFile.path)
|
|
498
|
+
result.deleted += 1
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
for (const snapshotFile of snapshotFiles) {
|
|
502
|
+
let existing = null
|
|
503
|
+
try {
|
|
504
|
+
existing = await readMarkdownFile(info.realPath, snapshotFile.path)
|
|
505
|
+
} catch {}
|
|
506
|
+
|
|
507
|
+
if (existing?.content === snapshotFile.content) {
|
|
508
|
+
result.skipped += 1
|
|
509
|
+
continue
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
await writeMarkdownFile(
|
|
513
|
+
info.realPath,
|
|
514
|
+
snapshotFile.path,
|
|
515
|
+
snapshotFile.content
|
|
516
|
+
)
|
|
517
|
+
if (existing) result.updated += 1
|
|
518
|
+
else result.created += 1
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
return result
|
|
522
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{$ as t,R as n,f as r,n as i,o as a,rt as o}from"./avatar-BZwHW4ll.js";import{a as s,c,o as l}from"./i18n-DZaOYCSO.js";var u=t(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]),d=t(`languages`,[[`path`,{d:`m5 8 6 6`,key:`1wu5hv`}],[`path`,{d:`m4 14 6-6 2-3`,key:`1k1g8d`}],[`path`,{d:`M2 5h12`,key:`or177f`}],[`path`,{d:`M7 2h1`,key:`1t2jsx`}],[`path`,{d:`m22 22-5-10-5 10`,key:`don7ne`}],[`path`,{d:`M14 18h6`,key:`1m8k6r`}]]),f=t(`moon`,[[`path`,{d:`M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401`,key:`kfwtm`}]]),p=t(`sun`,[[`circle`,{cx:`12`,cy:`12`,r:`4`,key:`4exip2`}],[`path`,{d:`M12 2v2`,key:`tus03m`}],[`path`,{d:`M12 20v2`,key:`1lh1kg`}],[`path`,{d:`m4.93 4.93 1.41 1.41`,key:`149t6j`}],[`path`,{d:`m17.66 17.66 1.41 1.41`,key:`ptbguv`}],[`path`,{d:`M2 12h2`,key:`1t8f8n`}],[`path`,{d:`M20 12h2`,key:`1q8mjw`}],[`path`,{d:`m6.34 17.66-1.41 1.41`,key:`1m8zz5`}],[`path`,{d:`m19.07 4.93-1.41 1.41`,key:`1shlcs`}]]),m=t(`user`,[[`path`,{d:`M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2`,key:`975kel`}],[`circle`,{cx:`12`,cy:`7`,r:`4`,key:`17ys0d`}]]),h=e();function g(){let{locale:e,setLocale:t,t:n}=s(),r=n(`common.locale.choose`);return(0,h.jsx)(a,{ariaLabel:r,className:`language-toggle`,items:l.map(n=>({key:n,label:c[n],icon:n===e?(0,h.jsx)(u,{size:16}):(0,h.jsx)(`span`,{className:`language-toggle-placeholder`,"aria-hidden":`true`}),onSelect:()=>{n!==e&&t(n)}})),renderTrigger:e=>(0,h.jsx)(`button`,{...e,className:`header-tool-btn`,title:r,"aria-label":r,children:(0,h.jsx)(d,{size:16})})})}function _(){let{t:e}=s(),t=r(e=>e.isDarkMode),n=r(e=>e.setIsDarkMode),i=e(`common.theme.toggle`);return(0,h.jsx)(`button`,{type:`button`,className:`header-tool-btn`,title:i,"aria-label":i,"aria-pressed":t,onClick:()=>n(!t),children:t?(0,h.jsx)(p,{size:16}):(0,h.jsx)(f,{size:16})})}function v(){let{t:e}=s(),t=n(e=>e.identity),r=i(t?.address,t?.avatar),a=e(`nav.profile`);return(0,h.jsx)(o,{to:`/profile/`,className:`account-profile-link`,title:a,"aria-label":a,children:t?(0,h.jsx)(`img`,{className:`account-profile-link-avatar`,src:r,alt:``,"aria-hidden":`true`}):(0,h.jsx)(m,{size:18})})}export{u as a,m as i,_ as n,g as r,v as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,o as t,t as n}from"./jsx-runtime-Bt-cYkS5.js";import{$ as r,Q as i,y as a}from"./avatar-BZwHW4ll.js";import{a as o}from"./i18n-DZaOYCSO.js";import{t as s}from"./file-text-C3v0L_lQ.js";import{t as c}from"./loader-CLoDCtNy.js";import{t as l}from"./music-BsTA8b_M.js";var u=r(`film`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M7 3v18`,key:`bbkbws`}],[`path`,{d:`M3 7.5h4`,key:`zfgn84`}],[`path`,{d:`M3 12h18`,key:`1i2n21`}],[`path`,{d:`M3 16.5h4`,key:`1230mu`}],[`path`,{d:`M17 3v18`,key:`in4fa5`}],[`path`,{d:`M17 7.5h4`,key:`myr1c1`}],[`path`,{d:`M17 16.5h4`,key:`go4c1d`}]]),d=r(`image`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,ry:`2`,key:`1m3agn`}],[`circle`,{cx:`9`,cy:`9`,r:`2`,key:`af1f0g`}],[`path`,{d:`m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21`,key:`1xmnt7`}]]),f=r(`pen`,[[`path`,{d:`M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z`,key:`1a8usu`}]]);function p(e){let t=String(e||``).split(`.`).pop()?.toLowerCase()||``,n=[`jpg`,`jpeg`,`png`,`gif`,`webp`,`svg`,`bmp`,`ico`,`tiff`,`heic`,`heif`],r=[`mp4`,`webm`,`mov`,`avi`,`mkv`,`flv`,`wmv`,`m4v`,`mpeg`,`3gp`],i=[`mp3`,`wav`,`ogg`,`flac`,`aac`,`m4a`,`wma`,`opus`],a=`txt.md.js.ts.jsx.tsx.css.scss.less.json.xml.html.htm.yaml.yml.toml.ini.cfg.conf.log.sh.bash.py.rb.go.rs.java.c.cpp.h.hpp.cs.php.sql.graphql.env.gitignore.dockerfile.readme`.split(`.`);return n.includes(t)?`image`:r.includes(t)?`video`:i.includes(t)?`audio`:a.includes(t)?`text`:`file`}var m=t(e(),1),h=n();function g(e){return e===`image`||e===`video`||e===`audio`}function _({item:e,isBackendReady:t,getFileDownloadUrl:n,onClose:r}){let{t:u}=o(),[d,f]=(0,m.useState)(``),[p,_]=(0,m.useState)(!1),[v,y]=(0,m.useState)(``),[b,x]=(0,m.useState)(``);return(0,m.useEffect)(()=>{if(e.subtype!==`text`)return;let r=!1;if(f(``),x(``),!t){f(u(`preview.loadFailed`));return}return _(!0),(async()=>{try{let t=await fetch(n(e.cid),{headers:{...await a(`GET`,`/api/files/${e.cid}/download`),Range:`bytes=0-9999`}});if(!t.ok)throw Error(u(`preview.loadFailed`));let i=await t.text();r||f(i||u(`preview.emptyFile`))}catch{r||f(u(`preview.loadFailed`))}finally{r||_(!1)}})(),()=>{r=!0}},[n,t,e.cid,e.subtype]),(0,m.useEffect)(()=>{if(!g(e.subtype)){y(``);return}if(y(``),x(``),!t){x(u(`preview.loadFailed`));return}let r=``,i=!1;return(async()=>{try{let t=await fetch(n(e.cid),{headers:await a(`GET`,`/api/files/${e.cid}/download`)});if(!t.ok)throw Error(u(`preview.loadFailed`));let o=URL.createObjectURL(await t.blob());r=o,i||y(o)}catch{i||x(u(`preview.loadFailed`))}})(),()=>{i=!0,r&&URL.revokeObjectURL(r)}},[n,t,e.cid,e.subtype]),(0,h.jsxs)(`div`,{className:`preview-overlay`,onClick:r,children:[(0,h.jsx)(`button`,{type:`button`,className:`preview-close`,onClick:r,"aria-label":u(`preview.close`),children:(0,h.jsx)(i,{size:20})}),(0,h.jsxs)(`div`,{onClick:e=>e.stopPropagation(),children:[e.subtype===`image`&&(0,h.jsx)(`div`,{className:`preview-media-wrapper`,children:v?(0,h.jsx)(`img`,{src:v,alt:e.fileName,translate:`no`}):b?(0,h.jsxs)(`div`,{className:`preview-unsupported`,children:[(0,h.jsx)(s,{size:48,className:`preview-file-icon`}),(0,h.jsx)(`p`,{translate:`no`,children:e.fileName}),(0,h.jsx)(`p`,{className:`preview-unsupported-hint`,children:b})]}):(0,h.jsx)(`div`,{className:`preview-loading`,children:(0,h.jsx)(`div`,{className:`preview-loading-spinner`})})}),e.subtype===`video`&&(0,h.jsx)(`div`,{className:`preview-media-wrapper`,children:v?(0,h.jsx)(`video`,{src:v,controls:!0}):b?(0,h.jsxs)(`div`,{className:`preview-unsupported`,children:[(0,h.jsx)(s,{size:48,className:`preview-file-icon`}),(0,h.jsx)(`p`,{translate:`no`,children:e.fileName}),(0,h.jsx)(`p`,{className:`preview-unsupported-hint`,children:b})]}):(0,h.jsx)(`div`,{className:`preview-loading`,children:(0,h.jsx)(`div`,{className:`preview-loading-spinner`})})}),e.subtype===`audio`&&(0,h.jsxs)(`div`,{className:`preview-audio`,children:[(0,h.jsx)(`div`,{className:`preview-audio-icon`,children:(0,h.jsx)(l,{size:36,color:`var(--accent)`})}),(0,h.jsx)(`p`,{className:`preview-audio-filename`,translate:`no`,children:e.fileName}),v?(0,h.jsx)(`audio`,{className:`preview-audio-player`,src:v,controls:!0}):(0,h.jsx)(`div`,{className:`preview-text-loading`,children:b?(0,h.jsx)(`p`,{children:b}):(0,h.jsxs)(h.Fragment,{children:[(0,h.jsx)(c,{size:24,className:`preview-text-spinner`}),(0,h.jsx)(`p`,{children:u(`preview.audioLoading`)})]})})]}),e.subtype===`file`&&(0,h.jsxs)(`div`,{className:`preview-unsupported`,children:[(0,h.jsx)(s,{size:48,className:`preview-file-icon`}),(0,h.jsx)(`p`,{translate:`no`,children:e.fileName}),(0,h.jsx)(`p`,{className:`preview-unsupported-hint`,children:u(`preview.unsupported`)})]}),e.subtype===`text`&&(0,h.jsxs)(`div`,{className:`preview-text-container`,children:[(0,h.jsx)(`div`,{className:`preview-text-header`,children:(0,h.jsx)(`span`,{translate:`no`,children:e.fileName})}),p?(0,h.jsxs)(`div`,{className:`preview-text-loading`,children:[(0,h.jsx)(c,{size:24,className:`preview-text-spinner`}),(0,h.jsx)(`p`,{children:u(`preview.textLoading`)}),(0,h.jsx)(`p`,{className:`preview-text-loading-hint`,children:u(`preview.firstSyncHint`)})]}):(0,h.jsx)(`pre`,{className:`preview-text`,translate:`no`,children:d||u(`preview.emptyFile`)})]})]})]})}export{u as a,d as i,p as n,f as r,_ as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{d as t,rt as n}from"./avatar-BZwHW4ll.js";import{a as r}from"./i18n-DZaOYCSO.js";import{n as i,r as a,t as o}from"./AccountMenu-NjOgag0d.js";import{t as s}from"./download-Q1uCiwif.js";import"./index-DluhgSHX.js";import{t as c}from"./LogoIcon-B2fFe0l1.js";var l={name:`most-box`,version:`0.3.1`,description:`MostBox - P2P file sharing application`,type:`module`,main:`electron/main.js`,bin:{"most-box":`server/cli.js`},files:[`out`,`public`,`electron`,`server/src`,`server/index.js`,`server/cli.js`],scripts:{start:`vite`,server:`node --watch server/index.js`,desktop:`npm run electron:dev`,build:`vite build && node scripts/prepare-start-static.mjs`,preview:`vite preview`,serve:`npm run build && node server/index.js`,test:`node --test server/tests/**/*.test.js`,"test:unit":`node --test server/tests/unit/*.test.js`,"test:desktop":`node --test electron/*.test.js`,"test:frontend":`node --test src/tests/*.test.js`,"test:protocol":`node --test --test-name-pattern "extracts CID and filename|matches golden CID samples|publishes a file from Buffer|lists published files|pulls through local seed nodes" server/tests/unit/cid.test.js server/tests/integration/cid.test.js server/tests/integration/engine.test.js`,typecheck:`tsc -p tsconfig.typecheck.json`,"typecheck:strict-router":`tsc -p tsconfig.strict-router.json`,"check:static-output":`node scripts/check-static-output.mjs`,format:`npx prettier --write .`,lint:`npx eslint .`,"r2:cors":`node scripts/configure-r2-cors.mjs`,"electron:dev":`concurrently "npm run build" "wait-on out/index.html && electron ."`,"electron:rebuild":`electron-rebuild -f -w sodium-native`,"electron:build":`npm run build && npm run electron:rebuild && electron-builder`,"electron:build:win":`npm run build && npm run electron:rebuild && electron-builder --win`,"electron:build:win:x64":`npm run electron:build:win -- --x64`,"electron:build:win:arm64":`npm run electron:build:win -- --arm64`,"electron:build:mac":`npm run build && npm run electron:rebuild && electron-builder --mac`,"electron:build:linux":`npm run build && npm run electron:rebuild && electron-builder --linux`},keywords:[`p2p`,`file-sharing`,`hyperswarm`,`hyperdrive`],license:`MIT`,dependencies:{"@dicebear/collection":`^9.4.2`,"@dicebear/core":`^9.4.2`,"@hono/node-server":`^2.0.4`,"@tanstack/react-router":`^1.170.15`,"@tanstack/react-start":`^1.168.25`,b4a:`^1.8.1`,busboy:`^1.6.0`,corestore:`^7.10.0`,dayjs:`^1.11.21`,ethers:`^6.16.0`,eventemitter3:`^5.0.4`,hono:`^4.12.23`,hypercore:`^11.33.1`,hyperdrive:`^13.3.2`,hyperswarm:`^4.17.0`,"ipfs-unixfs-importer":`^17.0.1`,multiformats:`^14.0.0`,tweetnacl:`^1.0.3`,ws:`^8.21.0`},devDependencies:{"@electron/rebuild":`^4.0.4`,"@eslint/js":`^10.0.1`,"@iconify/react":`^6.0.2`,"@mantine/hooks":`^9.3.0`,"@milkdown/crepe":`^7.21.2`,"@milkdown/utils":`^7.21.2`,"@types/react":`^19.2.16`,"@vitejs/plugin-react":`^6.0.2`,concurrently:`^10.0.3`,electron:`^42.3.3`,"electron-builder":`^26.8.1`,esbuild:`^0.28.0`,eslint:`^10.4.1`,globals:`^17.6.0`,ky:`^2.0.2`,"lucide-react":`^1.17.0`,prettier:`^3.8.3`,"qrcode.react":`^4.2.0`,react:`^19.2.7`,"react-dom":`^19.2.7`,typescript:`6.0.3`,"typescript-eslint":`^8.60.1`,vite:`^8.0.16`,"wait-on":`^9.0.10`,zustand:`^5.0.14`},overrides:{"brace-expansion":`5.0.6`,postcss:`8.5.15`,ws:`$ws`},build:{appId:`com.mostbox.app`,productName:`MostBox`,publish:[{provider:`github`,releaseType:`release`}],directories:{output:`dist`},afterPack:`electron/afterPack.cjs`,files:[`out/**/*`,`electron/**/*`,`server/src/**/*`,`server/index.js`,`server/cli.js`,`package.json`,`!**/*.map`,`!electron/**/*.test.js`,`!server/tests/**/*`],asarUnpack:[`**/*.node`,`**/sodium-native/**`],protocols:[{name:`MostBox Link`,schemes:[`most`]}],win:{target:[`nsis`],artifactName:"${productName}-${version}-win-${arch}-setup.${ext}",icon:`public/logo.ico`},nsis:{oneClick:!1,allowToChangeInstallationDirectory:!0,createDesktopShortcut:!0,createStartMenuShortcut:!0,shortcutName:`MostBox`},mac:{artifactName:"${productName}-${version}-mac-${arch}.${ext}",target:[{target:`dmg`,arch:[`x64`,`arm64`]}],icon:`public/logo-512.png`,category:`public.app-category.utilities`},dmg:{contents:[{x:130,y:220},{x:410,y:220,type:`link`,path:`/Applications`}]},linux:{artifactName:"${productName}-${version}-linux-${arch}.${ext}",target:[{target:`AppImage`,arch:[`x64`,`arm64`]}],icon:`public/logo-512.png`,category:`Utility`}}},u=e(),d=[{to:`/`,labelKey:`footer.about`},{to:`/ping/`,labelKey:`footer.network`},{href:`https://github.com/most-people/most`,labelKey:null,label:`GitHub`,external:!0}],f=l.version;function p(){let{t:e}=r();return(0,u.jsx)(`footer`,{className:`mkt-footer`,children:(0,u.jsx)(`div`,{className:`mkt-container`,children:(0,u.jsxs)(`div`,{className:`mkt-footer-inner`,children:[(0,u.jsx)(`div`,{className:`mkt-footer-links`,children:d.map(t=>`external`in t?(0,u.jsx)(`a`,{href:t.href,target:`_blank`,rel:`noopener noreferrer`,children:t.label},t.href):(0,u.jsx)(n,{to:t.to,children:e(t.labelKey)},t.to))}),(0,u.jsxs)(`span`,{className:`mkt-footer-copy`,children:[`© `,new Date().getFullYear(),` MOST PEOPLE · MIT License`]}),(0,u.jsxs)(`span`,{className:`mkt-footer-build`,translate:`no`,children:[`v`,f]})]})})})}function m({children:e,header:t}){return(0,u.jsxs)(`div`,{className:`mkt-layout`,children:[t??(0,u.jsx)(h,{}),(0,u.jsx)(`main`,{className:`mkt-layout-main`,children:e}),(0,u.jsx)(p,{})]})}function h(){let{t:e}=r(),l=t();return(0,u.jsx)(`nav`,{className:`mkt-nav`,children:(0,u.jsxs)(`div`,{className:`mkt-nav-inner`,children:[(0,u.jsxs)(n,{to:`/`,className:`mkt-nav-logo`,children:[(0,u.jsx)(c,{}),`MOST PEOPLE`]}),(0,u.jsxs)(`div`,{className:`mkt-nav-cta`,children:[(0,u.jsx)(i,{}),(0,u.jsx)(a,{}),!l&&(0,u.jsxs)(n,{to:`/download/`,className:`btn btn-primary mkt-nav-preview`,children:[(0,u.jsx)(s,{size:16}),e(`nav.downloadClient`)]}),(0,u.jsx)(o,{})]})]})})}export{m as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{$ as t}from"./avatar-BZwHW4ll.js";import{a as n}from"./i18n-DZaOYCSO.js";import{r}from"./SidebarHomeLink-CkhGDvZ8.js";var i=t(`panel-left-open`,[[`rect`,{width:`18`,height:`18`,x:`3`,y:`3`,rx:`2`,key:`afitv7`}],[`path`,{d:`M9 3v18`,key:`fh3hqa`}],[`path`,{d:`m14 9 3 3-3 3`,key:`8010ee`}]]),a=e();function o({label:e,className:t=``,variant:o=`primary`}){let{isSidebarVisible:s,openSidebar:c}=r(),{t:l}=n(),u=o===`primary`?`btn-primary`:``,d=e||l(`appShell.openSidebar`);return s?null:(0,a.jsxs)(`button`,{type:`button`,className:`btn ${u} sidebar-open-hint ${t}`.trim(),onClick:c,children:[(0,a.jsx)(i,{size:16}),d]})}export{o as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,o as t,t as n}from"./jsx-runtime-Bt-cYkS5.js";import{$ as r,rt as i}from"./avatar-BZwHW4ll.js";import{a}from"./i18n-DZaOYCSO.js";import{n as o,r as s,t as c}from"./AccountMenu-NjOgag0d.js";import{c as l}from"./index-DluhgSHX.js";var u=r(`menu`,[[`path`,{d:`M4 5h16`,key:`1tepv9`}],[`path`,{d:`M4 12h16`,key:`1lakjw`}],[`path`,{d:`M4 19h16`,key:`1djgab`}]]),d=t(e(),1);function f(e,t){return typeof t==`boolean`?t:typeof window<`u`&&`matchMedia`in window?window.matchMedia(e).matches:!1}function p(e,t,{getInitialValueInEffect:n}={getInitialValueInEffect:!0}){let[r,i]=(0,d.useState)(n?t:f(e));return(0,d.useEffect)(()=>{try{if(`matchMedia`in window){let t=window.matchMedia(e);i(t.matches);let n=e=>i(e.matches);return t.addEventListener(`change`,n),()=>{t.removeEventListener(`change`,n)}}}catch{return}},[e]),r||!1}function m(e=!1,t={}){let[n,r]=(0,d.useState)(e),i=(0,d.useCallback)(()=>{r(e=>e||(t.onOpen?.(),!0))},[t.onOpen]),a=(0,d.useCallback)(()=>{r(e=>e&&(t.onClose?.(),!1))},[t.onClose]);return[n,{open:i,close:a,toggle:(0,d.useCallback)(()=>{n?a():i()},[a,i,n]),set:r}]}var h=n(),g=(0,d.createContext)(null);function _(){let e=(0,d.useContext)(g);if(!e)throw Error(`useAppShell must be used within AppShell`);return e}function v({sidebar:e,className:t=``,headerTitle:n,headerRight:r,sidebarToggleReplacement:i,defaultHide:l=!1,children:f}){let[_,v]=m(!1),[y,b]=(0,d.useState)(l),x=(0,d.useRef)(l),S=p(`(max-width: 768px)`),{t:C}=a(),w=(0,d.useCallback)((e={})=>{v.close(),e.collapse&&b(!0)},[v]);(0,d.useEffect)(()=>{l!==x.current&&(l?w({collapse:!0}):b(!1),x.current=l)},[l,w]);let T=()=>{S?v.toggle():b(!y)},E=()=>{S?v.open():b(!1)},D=S?_:!y;return(0,h.jsx)(g.Provider,{value:{closeSidebar:w,openSidebar:E,isSidebarVisible:D},children:(0,h.jsxs)(`div`,{className:[`app-layout`,t].filter(Boolean).join(` `),children:[(0,h.jsx)(`div`,{className:`sidebar-overlay ${_?`visible`:``}`,onClick:()=>w()}),(0,h.jsx)(`div`,{className:`sidebar ${_?`open`:``} ${y?`collapsed`:``}`,children:e({closeSidebar:w,openSidebar:E})}),(0,h.jsxs)(`div`,{className:`main-content`,children:[(0,h.jsxs)(`header`,{className:`app-header`,children:[(0,h.jsxs)(`div`,{className:`header-left`,children:[i??(0,h.jsx)(`button`,{onClick:T,className:`btn btn-icon sidebar-toggle-btn`,"aria-label":C(S?`appShell.openMenu`:y?`appShell.expandSidebar`:`appShell.collapseSidebar`),children:(0,h.jsx)(u,{size:16})}),n]}),(0,h.jsxs)(`div`,{className:`header-right`,children:[r,(0,h.jsx)(o,{}),(0,h.jsx)(s,{}),(0,h.jsx)(c,{})]})]}),f]})]})})}function y({onNavigate:e}){let{t}=a(),n=t(`common.brand`);return(0,h.jsxs)(i,{to:`/`,className:`sidebar-header sidebar-header-link`,onClick:e,"aria-label":n,title:n,children:[(0,h.jsx)(l,{size:18}),(0,h.jsx)(`h1`,{children:n})]})}export{m as i,v as n,_ as r,y as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{$ as e}from"./avatar-BZwHW4ll.js";var t=e(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]);export{t};
|