most-box 0.3.3 → 0.3.5
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 +7 -6
- package/out/about/index.html +20 -0
- package/out/admin/index.html +0 -0
- package/out/app/index.html +0 -0
- package/out/assets/AccountMenu-D-wa5tux.js +1 -0
- package/out/assets/AppShell-BdRKZIZ9.js +1 -0
- package/out/assets/AppTop-BE5kKBYH.js +1 -0
- package/out/assets/CopyButton-DnFqfCN9.js +1 -0
- package/out/assets/MarketingHeader-8gNzHawY.js +1 -0
- package/out/assets/MarketingLayout-BPdjpEfc.js +1 -0
- package/out/assets/{MilkdownEditor-DXVbZsH_.js → MilkdownEditor-C388llV6.js} +1 -1
- package/out/assets/OpenSidebarButton-OP8zl7ad.js +1 -0
- package/out/assets/arrow-right-BsHzC0ZL.js +1 -0
- package/out/assets/{arrow-up-down-B-677ip8.js → arrow-up-down-DvLSz6Ma.js} +1 -1
- package/out/assets/{userProfile-BZvkCuet.js → channelApi-C5eHetoJ.js} +1 -1
- package/out/assets/chatJoinInvite-CeC6H6t8.js +1 -0
- package/out/assets/{chatNoteDraft-CYbvcEvC.js → chatNoteDraft-DTy6In5R.js} +1 -1
- package/out/assets/{circle-alert-dfN4T6Nq.js → circle-alert-DXVkx8p8.js} +1 -1
- package/out/assets/{copy-B7pPZ2MP.js → copy-OwXDsstV.js} +1 -1
- package/out/assets/{download-COQOcPqI.js → download-Cy2BlfKM.js} +1 -1
- package/out/assets/downloadValidation-Dd43i9_9.js +1 -0
- package/out/assets/{external-link-D6tHlYgS.js → external-link-D_AQSgxW.js} +1 -1
- package/out/assets/{file-text-DiyIGL1I.js → file-text-zvTER2mN.js} +1 -1
- package/out/assets/fingerprint-pattern-BT73ASEB.js +1 -0
- package/out/assets/{folder-BS_GbpPQ.js → folder-6pYYnS2-.js} +1 -1
- package/out/assets/folder-open-DOJ4bB58.js +1 -0
- package/out/assets/format-CAKfypjK.js +1 -0
- package/out/assets/gamepad-2-BYqNgCQr.js +1 -0
- package/out/assets/{hard-drive-Cqa7Rstj.js → hard-drive-DL1KJHmG.js} +1 -1
- package/out/assets/i18n-C6yaqRst.js +1 -0
- package/out/assets/index-C6IjeTBh.css +1 -0
- package/out/assets/index-D1mozno-.js +31 -0
- package/out/assets/index.lazy-59kmyNMW.js +1 -0
- package/out/assets/index.lazy-B1iJsXQ8.js +3 -0
- package/out/assets/index.lazy-Bz77Jlzu.js +1 -0
- package/out/assets/index.lazy-CVFcovqX.js +1 -0
- package/out/assets/index.lazy-CX2l1_Gi.js +1 -0
- package/out/assets/index.lazy-C_J9afOY.js +1 -0
- package/out/assets/index.lazy-CazlK1-Y.js +3 -0
- package/out/assets/index.lazy-CflWbocP.js +1 -0
- package/out/assets/index.lazy-ClrSkRx5.js +1 -0
- package/out/assets/index.lazy-CsTaY5WS.js +1 -0
- package/out/assets/index.lazy-D7E1pb1S.js +5 -0
- package/out/assets/index.lazy-DzaN9qwA.js +2 -0
- package/out/assets/index.lazy-FvXAYdEO.js +1 -0
- package/out/assets/index.lazy-JwrS2vDI.js +1 -0
- package/out/assets/index.lazy-m9XAzMt1.js +1 -0
- package/out/assets/{loader-CwyHYZdX.js → loader-C4pED_QP.js} +1 -1
- package/out/assets/lock-yG7M7GkB.js +1 -0
- package/out/assets/{message-square-BgsNXPft.js → message-square-CfApq8Ou.js} +1 -1
- package/out/assets/mp-cEQteKUC.js +1 -0
- package/out/assets/{music-Dn9nm9Qb.js → music-Br2x8TKX.js} +1 -1
- package/out/assets/notebook-pen-Bcd3MrtD.js +1 -0
- package/out/assets/play-DSHtNcOe.js +1 -0
- package/out/assets/{refresh-cw-D4BsHvhi.js → refresh-cw-CfkUlTK9.js} +1 -1
- package/out/assets/{save-B02sbO9Y.js → save-CfYzXcxH.js} +1 -1
- package/out/assets/saveLocalFile-2CNt4X0T.js +1 -0
- package/out/assets/search-DLBOUfny.js +1 -0
- package/out/assets/{send-4dhnJGuS.js → send-Bie9hgHI.js} +1 -1
- package/out/assets/{shield-check-Boae7Nc6.js → shield-check-2-h_eEXp.js} +1 -1
- package/out/assets/{smartphone-JXH-zQXB.js → smartphone-CrsocYJo.js} +1 -1
- package/out/assets/trash-2-B9gno5q6.js +1 -0
- package/out/assets/{triangle-alert-B9sMiA9l.js → triangle-alert-BhNtjKm2.js} +1 -1
- package/out/assets/{upload-DVuXJt_o.js → upload-BmufnMFu.js} +1 -1
- package/out/assets/{useAppStore-DOnk608w.js → useAppStore-DNhyhD20.js} +1 -1
- package/out/assets/useChannelMessages-DDBqKBXU.js +4 -0
- package/out/assets/useGameRoom-asr2gyY6.js +1 -0
- package/out/assets/{wallet-D9Iw4YWE.js → wallet-D6HZocla.js} +1 -1
- package/out/assets/{wifi-ljEI_ySA.js → wifi-CILQyKk0.js} +1 -1
- 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 +1 -1
- package/server/index.js +18 -1
- package/server/src/core/channelVoice.js +164 -0
- package/server/src/core/mostLink.js +30 -13
- package/server/src/core/releaseManifest.js +10 -3
- package/server/src/http/nodeStatus.js +2 -2
- package/server/src/http/routes/fileRoutes.js +10 -8
- package/server/src/http/uploads.js +53 -15
- package/server/src/index.js +126 -57
- package/server/src/node/config.js +4 -4
- package/server/src/utils/api.js +9 -1
- package/server/src/utils/avatar.js +1 -10
- package/server/src/utils/downloadMessages.js +7 -7
- package/server/src/utils/errors.js +11 -1
- package/server/src/utils/userIdentity.js +0 -1
- package/out/assets/AccountMenu-D36x3rKH.js +0 -1
- package/out/assets/AppTop-qtp-3wqv.js +0 -1
- package/out/assets/CopyButton-C00LHzxo.js +0 -1
- package/out/assets/FilePreviewOverlay-BvOCftIV.js +0 -1
- package/out/assets/MarketingHeader-D7AjEmWU.js +0 -1
- package/out/assets/MarketingLayout-BVw4vr-u.js +0 -1
- package/out/assets/OpenSidebarButton-DI6Ld8um.js +0 -1
- package/out/assets/arrow-right-CXzRt0Fp.js +0 -1
- package/out/assets/chatJoinInvite-aCHhLrlm.js +0 -1
- package/out/assets/check-iBCQl0yr.js +0 -1
- package/out/assets/chevron-right-D75NRNNs.js +0 -1
- package/out/assets/downloadValidation-UPgpJbKz.js +0 -1
- package/out/assets/format-CR8oUWq6.js +0 -1
- package/out/assets/index-CUzbruyP.js +0 -31
- package/out/assets/index-FV6RZlVI.css +0 -1
- package/out/assets/index.lazy-08bEbzIk.js +0 -1
- package/out/assets/index.lazy-6b-8jxXI.js +0 -1
- package/out/assets/index.lazy-B4pxVFWK.js +0 -2
- package/out/assets/index.lazy-Bi5KZylP.js +0 -5
- package/out/assets/index.lazy-CJnFeoy4.js +0 -1
- package/out/assets/index.lazy-CRV2-Y6z.js +0 -3
- package/out/assets/index.lazy-CzCHV559.js +0 -1
- package/out/assets/index.lazy-DrfZ9XTR.js +0 -1
- package/out/assets/index.lazy-DuvCRtpm.js +0 -1
- package/out/assets/index.lazy-DxOIgf3c.js +0 -1
- package/out/assets/index.lazy-FNVWBYth.js +0 -1
- package/out/assets/index.lazy-Itk05ouU.js +0 -1
- package/out/assets/index.lazy-_CazgyO7.js +0 -1
- package/out/assets/index.lazy-odd8ydDw.js +0 -3
- package/out/assets/key-round-JR8M3aHl.js +0 -1
- package/out/assets/lock-CuwwlXlx.js +0 -1
- package/out/assets/mp-Dv12gDTx.js +0 -1
- package/out/assets/notebook-pen-BzrCXQJE.js +0 -1
- package/out/assets/play-CvWKSMwY.js +0 -1
- package/out/assets/search-HW4oPOBP.js +0 -1
- package/out/assets/trash-2-BLwoM0ME.js +0 -1
- package/out/assets/useChannelMessages-CDvw-f_x.js +0 -4
- package/out/assets/useGameRoom-CATo4XWU.js +0 -1
package/server/src/index.js
CHANGED
|
@@ -20,9 +20,9 @@ import { Duplex } from 'node:stream'
|
|
|
20
20
|
|
|
21
21
|
import { calculateCid, parseMostLink, buildMostLink } from './core/cid.js'
|
|
22
22
|
import { normalizeChannelAttachment } from './core/channelAttachment.js'
|
|
23
|
+
import { normalizeChannelVoiceEvent } from './core/channelVoice.js'
|
|
23
24
|
import { getCidInfo } from './core/cidTopic.js'
|
|
24
25
|
import {
|
|
25
|
-
CHAT_FILE_ROOT,
|
|
26
26
|
TRANSIENT_CHANNEL_TYPES,
|
|
27
27
|
CHANNEL_DISCOVERY_TIMEOUT,
|
|
28
28
|
CHANNEL_CANDIDATE_TTL,
|
|
@@ -95,7 +95,11 @@ import {
|
|
|
95
95
|
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms))
|
|
96
96
|
const CHANNEL_PRESENCE_HEARTBEAT_MS = 15 * 1000
|
|
97
97
|
const CHANNEL_PRESENCE_TIMEOUT_MS = 45 * 1000
|
|
98
|
-
const
|
|
98
|
+
const CHANNEL_MEMBER_JOINED_EVENT = 'channel.member.joined'
|
|
99
|
+
|
|
100
|
+
function isChannelHistoryEntry(entry) {
|
|
101
|
+
return entry?.type === 'message' || entry?.type === 'system'
|
|
102
|
+
}
|
|
99
103
|
|
|
100
104
|
function createMemoryDuplexPair() {
|
|
101
105
|
let left
|
|
@@ -203,6 +207,16 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
203
207
|
return this.#getChannelPresenceList(channel.channelKey)
|
|
204
208
|
}
|
|
205
209
|
|
|
210
|
+
sendChannelVoiceEvent(channelKeyInput, input = {}, options = {}) {
|
|
211
|
+
this.#ensureInitialized()
|
|
212
|
+
this.#assertChannelMember(channelKeyInput, options.ownerAddress)
|
|
213
|
+
const channel = this.#resolveChannel(channelKeyInput, options.ownerAddress)
|
|
214
|
+
const event = normalizeChannelVoiceEvent(channel.channelKey, input, options)
|
|
215
|
+
this.#broadcastChannelVoice(event)
|
|
216
|
+
this.emit('channel:voice', event)
|
|
217
|
+
return event
|
|
218
|
+
}
|
|
219
|
+
|
|
206
220
|
joinChannelPresence(channelKeyInput, options = {}) {
|
|
207
221
|
this.#ensureInitialized()
|
|
208
222
|
this.#assertChannelMember(channelKeyInput, options.ownerAddress)
|
|
@@ -728,7 +742,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
728
742
|
* @param {object} [options] - 下载选项
|
|
729
743
|
* @param {number} [options.timeout] - 等待 P2P 内容的超时时间(毫秒)
|
|
730
744
|
* @param {number} [options.streamReadTimeout] - 下载流无进度超时时间(毫秒)
|
|
731
|
-
* @returns {Promise<{ taskId: string, fileName: string, savedPath
|
|
745
|
+
* @returns {Promise<{ taskId: string, fileName: string, savedPath?: string, localAvailable?: boolean, alreadyExists?: boolean }>}
|
|
732
746
|
*/
|
|
733
747
|
async downloadFile(link, taskId = null, options = {}) {
|
|
734
748
|
this.#ensureInitialized()
|
|
@@ -767,12 +781,38 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
767
781
|
})
|
|
768
782
|
if (localContent) {
|
|
769
783
|
const existingFile = localContent.fileRecord
|
|
784
|
+
const publishedBucket = this.#getPublishedBucket(ownerAddress, true)
|
|
785
|
+
const existingIndex = publishedBucket.findIndex(
|
|
786
|
+
f => f.cid === cidString
|
|
787
|
+
)
|
|
788
|
+
const alreadyInOwnerLibrary = existingIndex !== -1
|
|
770
789
|
console.log(
|
|
771
790
|
`[MostBox] CID content already exists locally: ${cidString}`
|
|
772
791
|
)
|
|
773
792
|
const existingHolding = this.#holdings.find(
|
|
774
793
|
item => item.cid === cidString
|
|
775
794
|
)
|
|
795
|
+
const localSize =
|
|
796
|
+
Number(existingHolding?.size) ||
|
|
797
|
+
(Number.isFinite(localContent.size) ? localContent.size : 0)
|
|
798
|
+
if (!alreadyInOwnerLibrary) {
|
|
799
|
+
this.#assertDisplayNameAvailable(linkFileName, {
|
|
800
|
+
ownerAddress,
|
|
801
|
+
excludeCid: cidString,
|
|
802
|
+
})
|
|
803
|
+
const syncUpdatedAt = Date.now()
|
|
804
|
+
publishedBucket.push({
|
|
805
|
+
fileName: linkFileName,
|
|
806
|
+
cid: cidString,
|
|
807
|
+
driveName: existingFile?.driveName || name,
|
|
808
|
+
size: localSize,
|
|
809
|
+
source: 'downloaded',
|
|
810
|
+
publishedAt: new Date(syncUpdatedAt).toISOString(),
|
|
811
|
+
starred: false,
|
|
812
|
+
syncUpdatedAt,
|
|
813
|
+
})
|
|
814
|
+
this.#savePublishedMetadata()
|
|
815
|
+
}
|
|
776
816
|
await this.#joinCidTopicInternal(cidString, {
|
|
777
817
|
server: true,
|
|
778
818
|
client: false,
|
|
@@ -780,17 +820,21 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
780
820
|
this.#upsertHolding({
|
|
781
821
|
cid: cidString,
|
|
782
822
|
fileName:
|
|
783
|
-
existingHolding?.fileName ||
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
823
|
+
existingHolding?.fileName ||
|
|
824
|
+
(alreadyInOwnerLibrary ? existingFile?.fileName : linkFileName) ||
|
|
825
|
+
linkFileName,
|
|
826
|
+
size: localSize,
|
|
787
827
|
driveName: existingFile?.driveName || name,
|
|
788
|
-
source:
|
|
828
|
+
source:
|
|
829
|
+
existingHolding?.source ||
|
|
830
|
+
(alreadyInOwnerLibrary ? existingFile?.source : 'downloaded') ||
|
|
831
|
+
'downloaded',
|
|
789
832
|
})
|
|
790
833
|
return {
|
|
791
834
|
taskId,
|
|
792
835
|
fileName: linkFileName,
|
|
793
|
-
|
|
836
|
+
localAvailable: true,
|
|
837
|
+
alreadyExists: alreadyInOwnerLibrary,
|
|
794
838
|
}
|
|
795
839
|
}
|
|
796
840
|
|
|
@@ -1120,7 +1164,10 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1120
1164
|
cid: parsed.cid,
|
|
1121
1165
|
fileName: sanitizeFilename(parsed.fileName),
|
|
1122
1166
|
size: localContent.size,
|
|
1123
|
-
|
|
1167
|
+
localAvailable: true,
|
|
1168
|
+
alreadyExists: this.#getPublishedBucket(ownerAddress).some(
|
|
1169
|
+
f => f.cid === parsed.cid
|
|
1170
|
+
),
|
|
1124
1171
|
}
|
|
1125
1172
|
}
|
|
1126
1173
|
|
|
@@ -1129,7 +1176,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1129
1176
|
* @param {string} link - most:// 链接
|
|
1130
1177
|
* @param {object} [options] - 检测选项
|
|
1131
1178
|
* @param {number} [options.timeout] - 等待 P2P 内容的超时时间(毫秒)
|
|
1132
|
-
* @returns {Promise<{ available: boolean, cid: string, fileName: string, size: number|null, alreadyExists?: boolean }>}
|
|
1179
|
+
* @returns {Promise<{ available: boolean, cid: string, fileName: string, size: number|null, localAvailable?: boolean, alreadyExists?: boolean }>}
|
|
1133
1180
|
*/
|
|
1134
1181
|
async checkDownloadAvailability(link, options = {}) {
|
|
1135
1182
|
this.#ensureInitialized()
|
|
@@ -1158,7 +1205,10 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1158
1205
|
cid: cidString,
|
|
1159
1206
|
fileName: sanitizeFilename(parsed.fileName),
|
|
1160
1207
|
size: localContent.size,
|
|
1161
|
-
|
|
1208
|
+
localAvailable: true,
|
|
1209
|
+
alreadyExists: this.#getPublishedBucket(ownerAddress).some(
|
|
1210
|
+
f => f.cid === cidString
|
|
1211
|
+
),
|
|
1162
1212
|
}
|
|
1163
1213
|
}
|
|
1164
1214
|
|
|
@@ -2567,7 +2617,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2567
2617
|
for (let i = 0; i < core.length; i++) {
|
|
2568
2618
|
try {
|
|
2569
2619
|
const entry = await core.get(i)
|
|
2570
|
-
if (entry
|
|
2620
|
+
if (isChannelHistoryEntry(entry)) {
|
|
2571
2621
|
allMessages.push({
|
|
2572
2622
|
...entry,
|
|
2573
2623
|
_coreKey: coreKeyHex,
|
|
@@ -2582,7 +2632,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2582
2632
|
|
|
2583
2633
|
const seen = new Set()
|
|
2584
2634
|
const unique = allMessages.filter(m => {
|
|
2585
|
-
const key = `${m._coreKey}:${m.author}:${m.timestamp}:${m.content}`
|
|
2635
|
+
const key = `${m._coreKey}:${m.type}:${m.event || ''}:${m.author}:${m.timestamp}:${m.content}`
|
|
2586
2636
|
if (seen.has(key)) return false
|
|
2587
2637
|
seen.add(key)
|
|
2588
2638
|
return true
|
|
@@ -2649,7 +2699,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2649
2699
|
|
|
2650
2700
|
const normalizedAvatar = normalizeChannelAvatar(options.avatar)
|
|
2651
2701
|
const message = {
|
|
2652
|
-
type: 'message',
|
|
2702
|
+
type: options.type === 'system' ? 'system' : 'message',
|
|
2653
2703
|
author,
|
|
2654
2704
|
authorName: normalizeChannelDisplayName(
|
|
2655
2705
|
authorName,
|
|
@@ -2666,6 +2716,10 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2666
2716
|
if (attachment) {
|
|
2667
2717
|
message.attachment = attachment
|
|
2668
2718
|
}
|
|
2719
|
+
if (message.type === 'system') {
|
|
2720
|
+
const event = String(options.event || '').trim()
|
|
2721
|
+
if (event) message.event = event
|
|
2722
|
+
}
|
|
2669
2723
|
|
|
2670
2724
|
await core.append(message)
|
|
2671
2725
|
if (channel) {
|
|
@@ -3158,11 +3212,13 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
3158
3212
|
|
|
3159
3213
|
await this.sendMessage(
|
|
3160
3214
|
channel.channelKey,
|
|
3161
|
-
|
|
3215
|
+
CHANNEL_MEMBER_JOINED_EVENT,
|
|
3162
3216
|
ownerAddress,
|
|
3163
3217
|
normalizeChannelDisplayName(options.displayName, ownerAddress),
|
|
3164
3218
|
{
|
|
3165
3219
|
ownerAddress,
|
|
3220
|
+
type: 'system',
|
|
3221
|
+
event: CHANNEL_MEMBER_JOINED_EVENT,
|
|
3166
3222
|
...(Object.prototype.hasOwnProperty.call(options, 'avatar')
|
|
3167
3223
|
? { avatar: options.avatar }
|
|
3168
3224
|
: {}),
|
|
@@ -3517,7 +3573,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
3517
3573
|
for (let i = 0; i < core.length; i++) {
|
|
3518
3574
|
try {
|
|
3519
3575
|
const entry = await core.get(i)
|
|
3520
|
-
if (entry
|
|
3576
|
+
if (isChannelHistoryEntry(entry)) {
|
|
3521
3577
|
maxTimestamp = Math.max(
|
|
3522
3578
|
maxTimestamp,
|
|
3523
3579
|
Number(entry.timestamp) || 0
|
|
@@ -3555,42 +3611,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
3555
3611
|
baseMessage = { ...baseMessage, avatar }
|
|
3556
3612
|
}
|
|
3557
3613
|
}
|
|
3558
|
-
|
|
3559
|
-
if (!attachment?.cid || !attachment.fileName) {
|
|
3560
|
-
return baseMessage
|
|
3561
|
-
}
|
|
3562
|
-
|
|
3563
|
-
const oldFileName = sanitizeFilename(String(attachment.fileName))
|
|
3564
|
-
const channelPathName = channel?.channelId || channelKey
|
|
3565
|
-
const channelPrefix = `${CHAT_FILE_ROOT}/${channelPathName}/`
|
|
3566
|
-
const fileName = oldFileName.startsWith(channelPrefix)
|
|
3567
|
-
? oldFileName
|
|
3568
|
-
: `${channelPrefix}${getPathBaseName(oldFileName)}`
|
|
3569
|
-
const link = buildMostLink(attachment.cid, fileName)
|
|
3570
|
-
const content =
|
|
3571
|
-
typeof baseMessage.content === 'string' &&
|
|
3572
|
-
(baseMessage.content === attachment.link ||
|
|
3573
|
-
parseMostLink(baseMessage.content).cid === attachment.cid)
|
|
3574
|
-
? link
|
|
3575
|
-
: baseMessage.content
|
|
3576
|
-
|
|
3577
|
-
if (
|
|
3578
|
-
fileName === attachment.fileName &&
|
|
3579
|
-
link === attachment.link &&
|
|
3580
|
-
content === baseMessage.content
|
|
3581
|
-
) {
|
|
3582
|
-
return baseMessage
|
|
3583
|
-
}
|
|
3584
|
-
|
|
3585
|
-
return {
|
|
3586
|
-
...baseMessage,
|
|
3587
|
-
content,
|
|
3588
|
-
attachment: {
|
|
3589
|
-
...attachment,
|
|
3590
|
-
fileName,
|
|
3591
|
-
link,
|
|
3592
|
-
},
|
|
3593
|
-
}
|
|
3614
|
+
return baseMessage
|
|
3594
3615
|
}
|
|
3595
3616
|
|
|
3596
3617
|
#getCidInfo(cid) {
|
|
@@ -4549,7 +4570,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4549
4570
|
err.message
|
|
4550
4571
|
)
|
|
4551
4572
|
}
|
|
4552
|
-
return
|
|
4573
|
+
return {}
|
|
4553
4574
|
}
|
|
4554
4575
|
|
|
4555
4576
|
#savePublishedMetadata() {
|
|
@@ -4603,7 +4624,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4603
4624
|
err.message
|
|
4604
4625
|
)
|
|
4605
4626
|
}
|
|
4606
|
-
return
|
|
4627
|
+
return {}
|
|
4607
4628
|
}
|
|
4608
4629
|
|
|
4609
4630
|
#saveTrashMetadata() {
|
|
@@ -4760,7 +4781,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4760
4781
|
for (let i = lastCoreLength; i < core.length; i++) {
|
|
4761
4782
|
try {
|
|
4762
4783
|
const entry = await core.get(i)
|
|
4763
|
-
if (entry
|
|
4784
|
+
if (isChannelHistoryEntry(entry)) {
|
|
4764
4785
|
const channel = this.#channels.find(
|
|
4765
4786
|
c => c.channelKey === channelKey
|
|
4766
4787
|
)
|
|
@@ -4913,6 +4934,32 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4913
4934
|
}
|
|
4914
4935
|
}
|
|
4915
4936
|
|
|
4937
|
+
#sendChannelVoice(stream, event) {
|
|
4938
|
+
if (!stream || stream.destroyed || stream.writableEnded || !event) {
|
|
4939
|
+
this.#channelStreams.delete(stream)
|
|
4940
|
+
return false
|
|
4941
|
+
}
|
|
4942
|
+
try {
|
|
4943
|
+
stream.write(
|
|
4944
|
+
`${JSON.stringify({
|
|
4945
|
+
type: 'channel-voice',
|
|
4946
|
+
peerId: this.getNodeId(),
|
|
4947
|
+
...event,
|
|
4948
|
+
})}\n`
|
|
4949
|
+
)
|
|
4950
|
+
return true
|
|
4951
|
+
} catch {
|
|
4952
|
+
this.#channelStreams.delete(stream)
|
|
4953
|
+
return false
|
|
4954
|
+
}
|
|
4955
|
+
}
|
|
4956
|
+
|
|
4957
|
+
#broadcastChannelVoice(event) {
|
|
4958
|
+
for (const stream of [...this.#channelStreams]) {
|
|
4959
|
+
this.#sendChannelVoice(stream, event)
|
|
4960
|
+
}
|
|
4961
|
+
}
|
|
4962
|
+
|
|
4916
4963
|
async #processChannelHelloMessage(msg) {
|
|
4917
4964
|
if (msg.type !== 'channel-hello') return null
|
|
4918
4965
|
|
|
@@ -5033,6 +5080,26 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
5033
5080
|
return peerId
|
|
5034
5081
|
}
|
|
5035
5082
|
|
|
5083
|
+
#processChannelVoiceMessage(msg) {
|
|
5084
|
+
if (msg.type !== 'channel-voice') return null
|
|
5085
|
+
const peerId = String(msg.peerId || '').trim()
|
|
5086
|
+
if (!peerId || peerId === this.getNodeId()) return null
|
|
5087
|
+
const channelId = normalizeChannelId(msg.channelId || msg.channelKey)
|
|
5088
|
+
const channelKey = buildChannelKey(channelId)
|
|
5089
|
+
const localChannel = this.#channels.find(
|
|
5090
|
+
channel => channel.channelKey === channelKey
|
|
5091
|
+
)
|
|
5092
|
+
if (!localChannel) return peerId
|
|
5093
|
+
|
|
5094
|
+
try {
|
|
5095
|
+
const event = normalizeChannelVoiceEvent(channelKey, msg, {
|
|
5096
|
+
timestamp: msg.timestamp,
|
|
5097
|
+
})
|
|
5098
|
+
this.emit('channel:voice', event)
|
|
5099
|
+
} catch {}
|
|
5100
|
+
return peerId
|
|
5101
|
+
}
|
|
5102
|
+
|
|
5036
5103
|
async #handleChannelConnection(conn) {
|
|
5037
5104
|
const stream = conn
|
|
5038
5105
|
let connectedPeerId = null
|
|
@@ -5055,7 +5122,9 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
5055
5122
|
const peerId =
|
|
5056
5123
|
message.type === 'channel-presence'
|
|
5057
5124
|
? this.#processChannelPresenceMessage(message)
|
|
5058
|
-
:
|
|
5125
|
+
: message.type === 'channel-voice'
|
|
5126
|
+
? this.#processChannelVoiceMessage(message)
|
|
5127
|
+
: await this.#processChannelHelloMessage(message)
|
|
5059
5128
|
if (peerId) connectedPeerId = peerId
|
|
5060
5129
|
} catch (err) {
|
|
5061
5130
|
console.warn(`[MostBox] Failed to process channel data:`, err.message)
|
|
@@ -40,17 +40,17 @@ export function normalizeNodeConfig(raw = {}) {
|
|
|
40
40
|
const rawNode = raw.node && typeof raw.node === 'object' ? raw.node : {}
|
|
41
41
|
|
|
42
42
|
const capacityBytes = normalizePositiveInteger(
|
|
43
|
-
rawNode.capacityBytes
|
|
43
|
+
rawNode.capacityBytes,
|
|
44
44
|
defaults.capacityBytes
|
|
45
45
|
)
|
|
46
46
|
const maxFileSizeBytes = normalizePositiveInteger(
|
|
47
|
-
rawNode.maxFileSizeBytes
|
|
47
|
+
rawNode.maxFileSizeBytes,
|
|
48
48
|
defaults.maxFileSizeBytes
|
|
49
49
|
)
|
|
50
50
|
const remoteInvites = normalizeRemoteInvites(
|
|
51
|
-
rawNode.remoteInvites ??
|
|
51
|
+
rawNode.remoteInvites ?? defaults.remoteInvites
|
|
52
52
|
)
|
|
53
|
-
const host = normalizeHost(rawNode.host
|
|
53
|
+
const host = normalizeHost(rawNode.host, defaults.host)
|
|
54
54
|
return {
|
|
55
55
|
dataPath:
|
|
56
56
|
typeof raw.dataPath === 'string'
|
package/server/src/utils/api.js
CHANGED
|
@@ -348,6 +348,10 @@ export async function getApiErrorPayload(err) {
|
|
|
348
348
|
return {
|
|
349
349
|
status: response.status,
|
|
350
350
|
code: typeof data?.code === 'string' ? data.code : undefined,
|
|
351
|
+
details:
|
|
352
|
+
data?.details && typeof data.details === 'object'
|
|
353
|
+
? data.details
|
|
354
|
+
: undefined,
|
|
351
355
|
error:
|
|
352
356
|
typeof data?.error === 'string'
|
|
353
357
|
? data.error
|
|
@@ -398,7 +402,11 @@ export function setBackendInvite(invite) {
|
|
|
398
402
|
export function configureBackend({ url, invite }) {
|
|
399
403
|
setBackendUrl(url)
|
|
400
404
|
setBackendInvite(invite)
|
|
401
|
-
|
|
405
|
+
if (isRemoteBackendUrl(url)) {
|
|
406
|
+
saveRemoteNode(url, invite)
|
|
407
|
+
} else if (typeof window !== 'undefined') {
|
|
408
|
+
clearActiveRemoteNode()
|
|
409
|
+
}
|
|
402
410
|
}
|
|
403
411
|
|
|
404
412
|
export function clearBackendConnection() {
|
|
@@ -10,19 +10,10 @@ export const defaultAvatarIds = [
|
|
|
10
10
|
'snow-mountain',
|
|
11
11
|
]
|
|
12
12
|
|
|
13
|
-
const legacyDefaultAvatarIdAliases = {
|
|
14
|
-
mint: 'panda',
|
|
15
|
-
violet: 'owl',
|
|
16
|
-
ocean: 'dolphin',
|
|
17
|
-
ember: 'tiger',
|
|
18
|
-
sage: 'turtle',
|
|
19
|
-
dusk: 'snow-mountain',
|
|
20
|
-
}
|
|
21
|
-
|
|
22
13
|
function normalizeDefaultAvatarId(id) {
|
|
23
14
|
const value = typeof id === 'string' ? id.trim() : ''
|
|
24
15
|
if (defaultAvatarIds.includes(value)) return value
|
|
25
|
-
return
|
|
16
|
+
return ''
|
|
26
17
|
}
|
|
27
18
|
|
|
28
19
|
export function getDefaultAvatarValue(id) {
|
|
@@ -6,7 +6,7 @@ const DOWNLOAD_CHECK_MESSAGES = {
|
|
|
6
6
|
offline: '无法连接本地节点,请确认 MostBox 后端正在运行后再检测。',
|
|
7
7
|
missingApi: '当前后端还没有检测接口,请重启 MostBox 后端后再试。',
|
|
8
8
|
validation:
|
|
9
|
-
'
|
|
9
|
+
'链接格式不正确,请粘贴 most://、网页入口或 CID。',
|
|
10
10
|
nameConflict: '下载目录已有同名文件,请先重命名或移走后再检测。',
|
|
11
11
|
noPeer:
|
|
12
12
|
'暂时没有发现在线种子。请确认分享者或其他下载者仍在线做种,稍后再检测。',
|
|
@@ -18,15 +18,15 @@ const DOWNLOAD_CHECK_MESSAGES = {
|
|
|
18
18
|
|
|
19
19
|
const LINK_VALIDATION_MESSAGES = {
|
|
20
20
|
[MOST_LINK_ERROR_CODES.INVALID_URL]:
|
|
21
|
-
'
|
|
21
|
+
'链接无法解析,请粘贴 most://、网页入口或 CID。',
|
|
22
22
|
[MOST_LINK_ERROR_CODES.INVALID_PROTOCOL]:
|
|
23
|
-
'
|
|
23
|
+
'链接格式不正确,请确认输入末尾是有效的 CID 或 CID?filename=...。',
|
|
24
24
|
[MOST_LINK_ERROR_CODES.UNSUPPORTED_PATH]:
|
|
25
|
-
'
|
|
25
|
+
'链接路径不受支持,请确认输入末尾是 CID 或 CID?filename=...。',
|
|
26
26
|
[MOST_LINK_ERROR_CODES.CID_EMPTY]:
|
|
27
|
-
'CID
|
|
27
|
+
'CID 无效,请确认输入末尾是有效的 CID 或 CID?filename=...。',
|
|
28
28
|
[MOST_LINK_ERROR_CODES.INVALID_CID_FORMAT]:
|
|
29
|
-
'CID
|
|
29
|
+
'CID 无效,请确认输入末尾是有效的 CID 或 CID?filename=...。',
|
|
30
30
|
[MOST_LINK_ERROR_CODES.CID_V1_REQUIRED]:
|
|
31
31
|
'CID 格式不符合 MostBox 要求,请确认分享链接完整。',
|
|
32
32
|
[MOST_LINK_ERROR_CODES.CID_DIGEST_LENGTH]:
|
|
@@ -69,7 +69,7 @@ export function getDownloadCheckErrorMessageFromPayload(
|
|
|
69
69
|
|
|
70
70
|
export function getDownloadLinkValidationMessage(link = '') {
|
|
71
71
|
const value = String(link || '').trim()
|
|
72
|
-
if (!value) return '
|
|
72
|
+
if (!value) return '请先粘贴分享链接或 CID。'
|
|
73
73
|
|
|
74
74
|
const result = parseMostLink(value)
|
|
75
75
|
if (!result.errorCode) return null
|
|
@@ -21,10 +21,20 @@ export class ValidationError extends AppError {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
export class FileSizeError extends AppError {
|
|
24
|
-
constructor(message, size) {
|
|
24
|
+
constructor(message, size, maxFileSizeBytes) {
|
|
25
25
|
super(message, 'FILE_SIZE_ERROR')
|
|
26
26
|
this.name = 'FileSizeError'
|
|
27
27
|
this.size = size
|
|
28
|
+
const details = {}
|
|
29
|
+
if (Number.isFinite(Number(size))) {
|
|
30
|
+
details.sizeBytes = Number(size)
|
|
31
|
+
}
|
|
32
|
+
if (Number.isFinite(Number(maxFileSizeBytes))) {
|
|
33
|
+
details.maxFileSizeBytes = Number(maxFileSizeBytes)
|
|
34
|
+
}
|
|
35
|
+
if (Object.keys(details).length > 0) {
|
|
36
|
+
this.details = details
|
|
37
|
+
}
|
|
28
38
|
}
|
|
29
39
|
}
|
|
30
40
|
|
|
@@ -29,7 +29,6 @@ export function saveIdentity(identity) {
|
|
|
29
29
|
export function clearIdentity() {
|
|
30
30
|
if (typeof localStorage === 'undefined') return
|
|
31
31
|
localStorage.removeItem('mostbox_identity')
|
|
32
|
-
localStorage.removeItem('mostbox_guest_identity')
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
export function getDisplayName(address, username) {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{B as t,E as n,W as r,t as i}from"./useAppStore-DOnk608w.js";import{t as a}from"./check-iBCQl0yr.js";import{A as o,M as s,f as c,g as l,j as u}from"./index-CUzbruyP.js";var 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}=o(),r=n(`common.locale.choose`);return(0,h.jsx)(l,{ariaLabel:r,className:`language-toggle`,items:u.map(n=>({key:n,label:s[n],icon:n===e?(0,h.jsx)(a,{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}=o(),t=i(e=>e.isDarkMode),n=i(e=>e.setIsDarkMode),r=e(`common.theme.toggle`);return(0,h.jsx)(`button`,{type:`button`,className:`header-tool-btn`,title:r,"aria-label":r,"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}=o(),t=n(e=>e.identity),i=c(t?.address,t?.avatar),a=e(`nav.profile`);return(0,h.jsx)(r,{to:`/profile/`,className:`account-profile-link`,title:a,"aria-label":a,children:t?(0,h.jsx)(`img`,{className:`account-profile-link-avatar`,src:i,alt:``,"aria-hidden":`true`}):(0,h.jsx)(m,{size:18})})}export{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{B as r,W as i}from"./useAppStore-DOnk608w.js";import{n as a,r as o,t as s}from"./AccountMenu-D36x3rKH.js";import{A as c,E as l}from"./index-CUzbruyP.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,hideAccountMenu:f=!1,children:_}){let[v,y]=m(!1),[b,x]=(0,d.useState)(l),S=(0,d.useRef)(l),C=p(`(max-width: 768px)`),{t:w}=c(),T=(0,d.useCallback)((e={})=>{y.close(),e.collapse&&x(!0)},[y]);(0,d.useEffect)(()=>{l!==S.current&&(l?T({collapse:!0}):x(!1),S.current=l)},[l,T]);let E=()=>{C?y.toggle():x(!b)},D=()=>{C?y.open():x(!1)},O=C?v:!b;return(0,h.jsx)(g.Provider,{value:{closeSidebar:T,openSidebar:D,isSidebarVisible:O},children:(0,h.jsxs)(`div`,{className:[`app-layout`,t].filter(Boolean).join(` `),children:[(0,h.jsx)(`div`,{className:`sidebar-overlay ${v?`visible`:``}`,onClick:()=>T()}),(0,h.jsx)(`div`,{className:`sidebar ${v?`open`:``} ${b?`collapsed`:``}`,children:e({closeSidebar:T,openSidebar:D})}),(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:E,className:`btn btn-icon sidebar-toggle-btn`,"aria-label":w(C?`appShell.openMenu`:b?`appShell.expandSidebar`:`appShell.collapseSidebar`),children:(0,h.jsx)(u,{size:16})}),n]}),(0,h.jsxs)(`div`,{className:`header-right`,children:[r,(0,h.jsx)(a,{}),(0,h.jsx)(o,{}),!f&&(0,h.jsx)(s,{})]})]}),_]})]})})}function y({onNavigate:e}){let{t}=c(),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{n as e,o as t,t as n}from"./jsx-runtime-Bt-cYkS5.js";import{t as r}from"./check-iBCQl0yr.js";import{t as i}from"./copy-B7pPZ2MP.js";import{A as a}from"./index-CUzbruyP.js";var o=t(e(),1),s=n();function c({text:e,label:t,copiedLabel:n,className:c=`btn btn-icon`,iconSize:l=14}){let{t:u}=a(),[d,f]=(0,o.useState)(!1),p=n||u(`common.copied`),m=t||u(`common.copy`);async function h(){try{await navigator.clipboard.writeText(e),f(!0),setTimeout(()=>f(!1),1500)}catch{}}return(0,s.jsxs)(`button`,{type:`button`,className:c,onClick:h,title:d?p:m,children:[d?(0,s.jsx)(r,{size:l}):(0,s.jsx)(i,{size:l}),t?d?p:t:null]})}export{c as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,o as t,t as n}from"./jsx-runtime-Bt-cYkS5.js";import{B as r,c as i}from"./useAppStore-DOnk608w.js";import{t as a}from"./file-text-DiyIGL1I.js";import{t as o}from"./loader-CwyHYZdX.js";import{t as s}from"./music-Dn9nm9Qb.js";import{A as c,S as l}from"./index-CUzbruyP.js";var u=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`}]]),d=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`}]]),f=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`}]]);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}=c(),[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 i(`GET`,`/api/files/${e.cid}/download`),Range:`bytes=0-9999`}});if(!t.ok)throw Error(u(`preview.loadFailed`));let a=await t.text();r||f(a||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=``,a=!1;return(async()=>{try{let t=await fetch(n(e.cid),{headers:await i(`GET`,`/api/files/${e.cid}/download`)});if(!t.ok)throw Error(u(`preview.loadFailed`));let o=URL.createObjectURL(await t.blob());r=o,a||y(o)}catch{a||x(u(`preview.loadFailed`))}})(),()=>{a=!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)(l,{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)(a,{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)(a,{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)(s,{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)(o,{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)(a,{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)(o,{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{n as t,r as n,t as r}from"./AccountMenu-D36x3rKH.js";import{E as i,x as a}from"./index-CUzbruyP.js";var o=e();function s(){return(0,o.jsx)(`nav`,{className:`mkt-nav`,children:(0,o.jsxs)(`div`,{className:`mkt-nav-inner`,children:[(0,o.jsxs)(`button`,{type:`button`,className:`mkt-nav-logo`,onClick:a(),children:[(0,o.jsx)(i,{size:18}),(0,o.jsx)(`span`,{children:`MOST PEOPLE`})]}),(0,o.jsxs)(`div`,{className:`mkt-nav-cta`,children:[(0,o.jsx)(t,{}),(0,o.jsx)(n,{}),(0,o.jsx)(r,{})]})]})})}export{s as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{W as t}from"./useAppStore-DOnk608w.js";import{t as n}from"./download-COQOcPqI.js";import{n as r,r as i,t as a}from"./AccountMenu-D36x3rKH.js";import{A as o,b as s}from"./index-CUzbruyP.js";import{t as c}from"./LogoIcon-B2fFe0l1.js";var l={name:`most-box`,version:`0.3.3`,description:`MostBox - chat-first P2P toolbox for files, notes, and game rooms`,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:`prettier --write .`,lint:`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`,`chat`,`file-sharing`,`file-transfer`,`hyperswarm`,`hypercore`,`hyperdrive`],license:`MIT`,dependencies:{"@dicebear/core":`^10.3.0`,"@dicebear/styles":`^10.2.0`,"@hono/node-server":`^2.0.6`,"@tanstack/react-router":`^1.170.16`,"@tanstack/react-start":`^1.168.26`,"@tanstack/react-table":`^8.21.3`,b4a:`^1.8.1`,busboy:`^1.6.0`,corestore:`^7.11.0`,dayjs:`^1.11.21`,ethers:`^6.17.0`,eventemitter3:`^5.0.4`,hono:`^4.12.27`,hypercore:`^11.33.2`,hyperdrive:`^13.3.2`,hyperswarm:`^4.17.0`,"ipfs-unixfs-importer":`^17.0.1`,multiformats:`^14.0.2`,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.4.0`,"@milkdown/crepe":`^7.21.2`,"@milkdown/utils":`^7.21.2`,"@types/react":`^19.2.17`,"@vitejs/plugin-react":`^6.0.3`,concurrently:`^10.0.3`,electron:`^42.5.0`,"electron-builder":`^26.15.3`,esbuild:`^0.28.1`,eslint:`^10.5.0`,globals:`^17.7.0`,ky:`^2.0.2`,"lucide-react":`^1.21.0`,prettier:`^3.8.4`,"qrcode.react":`^4.2.0`,react:`^19.2.7`,"react-dom":`^19.2.7`,typescript:`6.0.3`,"typescript-eslint":`^8.62.0`,vite:`^8.1.0`,"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}=o();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(n=>`external`in n?(0,u.jsx)(`a`,{href:n.href,target:`_blank`,rel:`noopener noreferrer`,children:n.label},n.href):(0,u.jsx)(t,{to:n.to,children:e(n.labelKey)},n.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}=o(),l=s();return(0,u.jsx)(`nav`,{className:`mkt-nav`,children:(0,u.jsxs)(`div`,{className:`mkt-nav-inner`,children:[(0,u.jsxs)(t,{to:`/`,className:`mkt-nav-logo`,children:[(0,u.jsx)(c,{}),`MOST PEOPLE`]}),(0,u.jsxs)(`div`,{className:`mkt-nav-cta`,children:[(0,u.jsx)(r,{}),(0,u.jsx)(i,{}),!l&&(0,u.jsxs)(t,{to:`/download/`,className:`btn btn-primary mkt-nav-preview`,children:[(0,u.jsx)(n,{size:16}),e(`nav.downloadClient`)]}),(0,u.jsx)(a,{})]})]})})}export{m as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{B as t}from"./useAppStore-DOnk608w.js";import{r as n}from"./AppTop-qtp-3wqv.js";import{A as r}from"./index-CUzbruyP.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}=n(),{t:l}=r(),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{B as e}from"./useAppStore-DOnk608w.js";var t=e(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]);export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{O as e}from"./index-CUzbruyP.js";var t=`0x955fe80bdb8312165471fcacd6a8f83df88a770dda6f38657ca4e62ec28d5b54`,n=`https://api.most.box`;function r(t){let n=typeof t==`string`?t.trim():t;return e(n)?n:void 0}function i(e){return!!e&&typeof e==`object`&&!Array.isArray(e)}function a(e){try{return JSON.parse(e)}catch{return null}}function o(e){return typeof e==`string`?a(e):e}function s(e){return typeof e==`string`?e.trim():``}function c(e){return s(e)===`sparkbit`?`sparkbit`:void 0}function l(e){let t=o(e);if(!i(t))return null;let n=s(t.uid),a=(Array.isArray(t.channels)?t.channels:[]).filter(i).map(e=>({id:s(e.id),name:s(e.name)||void 0})).filter(e=>e.id);return!n||a.length===0?null:{node_url:s(t.node_url)||void 0,node_invite:s(t.node_invite)||void 0,locale:r(t.locale),uid:n,theme:c(t.theme),logo:s(t.logo)||void 0,logo_dark:s(t.logo_dark)||void 0,data:s(t.data)||void 0,avatar:s(t.avatar)||void 0,name:s(t.name)||void 0,channels:a}}export{t as n,l as r,n as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{B as e}from"./useAppStore-DOnk608w.js";var t=e(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]);export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{B as e}from"./useAppStore-DOnk608w.js";var t=e(`chevron-right`,[[`path`,{d:`m9 18 6-6-6-6`,key:`mthhwq`}]]);export{t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{T as e,l as t,n,s as r}from"./useAppStore-DOnk608w.js";var i={CID_EMPTY:`cid_empty`,INVALID_CID_FORMAT:`invalid_cid_format`,CID_V1_REQUIRED:`cid_v1_required`,CID_DIGEST_LENGTH:`cid_digest_length`,LINK_EMPTY:`link_empty`,INVALID_URL:`invalid_url`,INVALID_PROTOCOL:`invalid_protocol`,UNSUPPORTED_PATH:`unsupported_path`,UNSUPPORTED_QUERY_PARAM:`unsupported_query_param`};function a(e){return{valid:!1,errorCode:e}}function o(e,t){return{cid:``,errorCode:e,...t?{details:t}:{}}}function s(t){if(!t||typeof t!=`string`)return a(i.CID_EMPTY);let n;try{n=e.parse(t)}catch{return a(i.INVALID_CID_FORMAT)}return n.version===1?n.multihash.digest.length===32?{valid:!0}:a(i.CID_DIGEST_LENGTH):a(i.CID_V1_REQUIRED)}function c(e){if(!e||typeof e!=`string`)return o(i.LINK_EMPTY);let t;try{t=new URL(e)}catch{return o(i.INVALID_URL)}if(t.protocol!==`most:`)return o(i.INVALID_PROTOCOL);if(t.pathname&&t.pathname!==`/`)return o(i.UNSUPPORTED_PATH);let n=t.hostname,r=t.searchParams.get(`filename`),a=[...t.searchParams.keys()].find(e=>e!==`filename`),c=s(n);return c.valid?a?o(i.UNSUPPORTED_QUERY_PARAM,{param:a}):{cid:n,fileName:r?.trim()||n}:o(c.errorCode)}function l(e,t){let n=String(t||``).trim();return n?`most://${e}?filename=${encodeURIComponent(n)}`:`most://${e}`}var u={timeout:`检测等待超时,暂时没有等到在线种子响应。请确认分享者或其他下载者仍在线做种,稍后再检测。`,offline:`无法连接本地节点,请确认 MostBox 后端正在运行后再检测。`,missingApi:`当前后端还没有检测接口,请重启 MostBox 后端后再试。`,validation:`链接格式不正确,请粘贴完整的 most://<cid>?filename=... 分享链接。`,nameConflict:`下载目录已有同名文件,请先重命名或移走后再检测。`,noPeer:`暂时没有发现在线种子。请确认分享者或其他下载者仍在线做种,稍后再检测。`,permission:`下载目录不可写,请检查目录权限后再检测。`,starting:`本地节点还没有启动完成,请稍等几秒后重新检测。`,server:`本地节点检测时出错,请稍后重试或查看节点日志。`,fallback:`检测未通过,请确认链接完整、发布者在线且本机网络正常。`};i.INVALID_URL,i.INVALID_PROTOCOL,i.UNSUPPORTED_PATH,i.CID_EMPTY,i.INVALID_CID_FORMAT,i.CID_V1_REQUIRED,i.CID_DIGEST_LENGTH;function d(e={},t=``){if(t===`TimeoutError`)return u.timeout;if(!e.status)return u.offline;if(e.status===404)return u.missingApi;switch(e.code){case`VALIDATION_ERROR`:return u.validation;case`CONFLICT`:return e.error?`${e.error},请先处理同名文件后再下载。`:u.nameConflict;case`PEER_NOT_FOUND`:return u.noPeer;case`PERMISSION_ERROR`:return e.error?`下载目录不可写:${e.error}`:u.permission;case`ENGINE_NOT_INITIALIZED`:return u.starting;default:break}return e.status===503?u.noPeer:e.status>=500?u.server:e.error?`检测未通过:${e.error}`:u.fallback}async function f(e,t){let r=new FormData;r.append(`file`,e,t||e.name);let i=await n.post(`/api/publish`,{body:r});if(!i.ok){let e=await i.json().catch(()=>({error:i.statusText}));throw Error(e.error||`Request failed`)}return i.json()}async function p(e){return d(await r(e),e&&typeof e==`object`&&`name`in e?String(e.name):``)}var m={listPublishedFiles:()=>n.get(`/api/files`).json(),listTrashFiles:()=>n.get(`/api/trash`).json(),deletePublishedFile:e=>n.delete(`/api/files/${e}`).json(),restoreTrashFile:e=>n.post(`/api/trash/${e}/restore`).json(),permanentDeleteTrashFile:e=>n.delete(`/api/trash/${e}`).json(),emptyTrash:()=>n.delete(`/api/trash`).json(),toggleStar:e=>n.post(`/api/files/${e}/star`).json(),getConfig:()=>n.get(`/api/config`).json(),getDataPath:()=>n.get(`/api/config/data-path`).json(),getNetworkAddresses:()=>n.get(`/api/network`).json(),saveConfig:e=>n.post(`/api/config`,{json:e}).json(),publishFile:f,checkDownload:(e,t={})=>{let r=typeof t.timeout==`number`?{link:e,timeout:t.timeout}:{link:e};return n.post(`/api/download/check`,{json:r,timeout:t.requestTimeout??15e3}).json()},downloadFile:e=>n.post(`/api/download`,{json:{link:e}}).json(),cacheFile:e=>n.post(`/api/files/${e}/cache`).json(),cancelDownload:e=>n.post(`/api/download/cancel`,{json:{taskId:e}}).json(),getFileDownloadUrl:e=>t(`/api/files/${e}/download`),moveFile:(e,t)=>n.post(`/api/move`,{json:{cid:e,newFileName:t}}).json(),renameFolder:(e,t)=>n.post(`/api/folder/rename`,{json:{oldPath:e,newPath:t}}).json()},h={[i.LINK_EMPTY]:`app.download.validation.empty`,[i.INVALID_URL]:`app.download.validation.invalidUrl`,[i.INVALID_PROTOCOL]:`app.download.validation.protocol`,[i.UNSUPPORTED_PATH]:`app.download.validation.path`,[i.CID_EMPTY]:`app.download.validation.invalidCid`,[i.INVALID_CID_FORMAT]:`app.download.validation.invalidCid`,[i.CID_V1_REQUIRED]:`app.download.validation.cidV1`,[i.CID_DIGEST_LENGTH]:`app.download.validation.cidDigest`};function g(e){if(!e)return{key:`app.download.validation.empty`};let t=c(e);return t.errorCode?t.errorCode===i.UNSUPPORTED_QUERY_PARAM?{key:`app.download.validation.unsupportedParam`,params:{param:t.details?.param||``}}:{key:h[t.errorCode||``]||`app.download.validation.generic`}:null}function _(e,t){let n=g(e);return n?t(n.key,n.params):null}export{c as a,l as i,m as n,p as r,_ as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function e(e){let t=Number(e);return!Number.isFinite(t)||t<=0?`0 B`:t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:t<1024*1024*1024?`${(t/(1024*1024)).toFixed(1)} MB`:`${(t/(1024*1024*1024)).toFixed(2)} GB`}function t(e){let t=Number(e);if(!Number.isFinite(t)||t<=0)return``;let n=t/1024/1024;return`${n.toFixed(n>=100?0:1)} MB`}export{t as n,e as t};
|