most-box 0.2.7 → 0.2.9
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 +9 -1
- package/electron/main.js +30 -420
- package/electron/preload.js +1 -16
- package/electron/updateChecker.js +6 -3
- package/electron/updateChecker.test.js +13 -97
- package/out/admin/index.html +0 -0
- package/out/app/index.html +0 -0
- package/out/assets/{FilePreviewOverlay-CW8lKJCw.js → FilePreviewOverlay-BYZIAMJ-.js} +1 -1
- package/out/assets/LanguageToggle-CSQtRZ3A.js +1 -0
- package/out/assets/MarketingHeader-ceWdRCpe.js +1 -0
- package/out/assets/MarketingLayout-Bun1d2wL.js +1 -0
- package/out/assets/{MarketingThemeToggle-Cl7PhFgv.js → MarketingThemeToggle-CIKP8x9W.js} +1 -1
- package/out/assets/{MilkdownEditor-B5SKAyjg.js → MilkdownEditor-CT6SHYKG.js} +1 -1
- package/out/assets/{OpenSidebarButton-Bdx86oG8.js → OpenSidebarButton-CLSCB7CG.js} +1 -1
- package/out/assets/{SidebarAccount-c8jirEMF.js → SidebarAccount-CNh0kvtB.js} +1 -1
- package/out/assets/SidebarHomeLink-DXv0c9Ob.js +1 -0
- package/out/assets/arrow-right-BU9c_SL4.js +1 -0
- package/out/assets/{circle-alert-Dkgyw_GE.js → circle-alert-iuHzciph.js} +1 -1
- package/out/assets/{copy-KIwotKoP.js → copy-DEzFUzeX.js} +1 -1
- package/out/assets/{download-DPA-3LpR.js → download-jEPn2njL.js} +1 -1
- package/out/assets/{downloadValidation-CH8BeY7_.js → downloadValidation-Bzl7cci9.js} +1 -1
- package/out/assets/{external-link-BmR2rZ80.js → external-link-BFaoZeK0.js} +1 -1
- package/out/assets/{file-text-BJQfDW9r.js → file-text-DPA1riJ_.js} +1 -1
- package/out/assets/{folder-Gb80aQnO.js → folder-Cfgc70_F.js} +1 -1
- package/out/assets/{hard-drive-P2dGA7FX.js → hard-drive-Dar_AZEq.js} +1 -1
- package/out/assets/i18n-NjvOSuV6.js +1 -0
- package/out/assets/index-BHZhApbo.css +1 -0
- package/out/assets/index-BI8oNSVC.js +31 -0
- package/out/assets/index.lazy-7omTRykl.js +2 -0
- package/out/assets/index.lazy-BOMHingE.js +3 -0
- package/out/assets/index.lazy-BSY5_gby.js +1 -0
- package/out/assets/{index.lazy-CIqPn0cy.js → index.lazy-C4ipXKZ7.js} +1 -1
- package/out/assets/index.lazy-CPZbEnJZ.js +1 -0
- package/out/assets/{index.lazy-Bh4jDrUl.js → index.lazy-Ch4Y17pJ.js} +1 -1
- package/out/assets/index.lazy-CvBIIYbm.js +1 -0
- package/out/assets/{index.lazy-B7u3Ztoe.js → index.lazy-Cz-OZwYL.js} +1 -1
- package/out/assets/index.lazy-D4zNn3D6.js +2 -0
- package/out/assets/index.lazy-DRY3xoQp.js +1 -0
- package/out/assets/{index.lazy-DAKkwnV2.js → index.lazy-_mEd0Q_u.js} +1 -1
- package/out/assets/index.lazy-bAp_Hgck.js +1 -0
- package/out/assets/index.lazy-ur0joIFl.js +1 -0
- package/out/assets/{key-round-DvpIlAJY.js → key-round-DNcpSuMw.js} +1 -1
- package/out/assets/{loader-8eVY8_SD.js → loader-BXQtdens.js} +1 -1
- package/out/assets/{lock-Cvtl60UJ.js → lock-CLIE8cct.js} +1 -1
- package/out/assets/{message-square-JK7ABH3O.js → message-square-Dp09WY1I.js} +1 -1
- package/out/assets/{mp-CMvgV1-c.js → mp-B6kdA94c.js} +1 -1
- package/out/assets/{music-YRSH1Jq6.js → music-B19Tg557.js} +1 -1
- package/out/assets/{notebook-pen-BjGx0coX.js → notebook-pen-C8TlK5sB.js} +1 -1
- package/out/assets/play-B-BjsTZz.js +1 -0
- package/out/assets/plus-4hygj-1Z.js +1 -0
- package/out/assets/{save-BcI68ZgS.js → save-BjrbPwhJ.js} +1 -1
- package/out/assets/search-DSkiWdvX.js +1 -0
- package/out/assets/{send-_ups0_3f.js → send-BL4d5iOt.js} +1 -1
- package/out/assets/{shield-check-Dzw5rdPe.js → shield-check-DzDuWO8r.js} +1 -1
- package/out/assets/{smartphone-DSQ5L_sr.js → smartphone-tRRFFO0a.js} +1 -1
- package/out/assets/{trash-2-BIrBn6Ce.js → trash-2-V12tJ8lI.js} +1 -1
- package/out/assets/triangle-alert-DGWc8ZHu.js +1 -0
- package/out/assets/{ui-u9yJHkb-.js → ui-BpDGD3IR.js} +2 -2
- package/out/assets/{upload-1jmNeGjH.js → upload-CoCptKya.js} +1 -1
- package/out/assets/{useChannelMessages-DNxfCew-.js → useChannelMessages-BeKF0gwo.js} +1 -1
- package/out/assets/{useGameRoom-Du07VEgb.js → useGameRoom-cs9YpYt7.js} +1 -1
- package/out/assets/{userProfile-CL1Ev2GK.js → userProfile-qcc60tHK.js} +1 -1
- package/out/assets/{wallet-BvM_X5nW.js → wallet-T7ONZ3Kg.js} +1 -1
- package/out/assets/{wifi-66t1dsgC.js → wifi-Bgo8eHY0.js} +1 -1
- package/out/chat/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 -8
- package/server/src/core/releaseManifest.js +1 -18
- package/server/src/index.js +34 -286
- package/out/assets/LanguageToggle-Cfh33R2h.js +0 -1
- package/out/assets/MarketingHeader-BKBngzf5.js +0 -1
- package/out/assets/MarketingLayout-C3xrXmfU.js +0 -1
- package/out/assets/SidebarHomeLink-LzYXrJRr.js +0 -1
- package/out/assets/arrow-right-BC_GWahx.js +0 -1
- package/out/assets/i18n-Cqyi6NZb.js +0 -1
- package/out/assets/index-CSBg7dZN.css +0 -1
- package/out/assets/index-CiHRnvMj.js +0 -31
- package/out/assets/index.lazy-BdOfbfjo.js +0 -2
- package/out/assets/index.lazy-Bo6McUf1.js +0 -1
- package/out/assets/index.lazy-BxUje7fk.js +0 -1
- package/out/assets/index.lazy-CfuoMz6P.js +0 -1
- package/out/assets/index.lazy-DRaxm9OS.js +0 -1
- package/out/assets/index.lazy-DkrwcEBu.js +0 -2
- package/out/assets/index.lazy-K6IB-5kb.js +0 -3
- package/out/assets/index.lazy-Uu9DCtrI.js +0 -1
- package/out/assets/index.lazy-mXESMo49.js +0 -1
- package/out/assets/play-Ds19moWN.js +0 -1
- package/out/assets/plus-CvGkRhJV.js +0 -1
- package/out/assets/search-BIa4RSPA.js +0 -1
- package/out/assets/triangle-alert-CgWIEl4u.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "most-box",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "MostBox - P2P file sharing application",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "electron/main.js",
|
|
@@ -164,13 +164,6 @@
|
|
|
164
164
|
"x64",
|
|
165
165
|
"arm64"
|
|
166
166
|
]
|
|
167
|
-
},
|
|
168
|
-
{
|
|
169
|
-
"target": "zip",
|
|
170
|
-
"arch": [
|
|
171
|
-
"x64",
|
|
172
|
-
"arm64"
|
|
173
|
-
]
|
|
174
167
|
}
|
|
175
168
|
],
|
|
176
169
|
"icon": "public/logo-512.png",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const RELEASE_PLATFORMS = ['windows', 'macos', 'linux']
|
|
2
2
|
export const RELEASE_ARCHES = ['x64', 'arm64']
|
|
3
|
-
export const RELEASE_ASSET_KINDS = ['installer'
|
|
3
|
+
export const RELEASE_ASSET_KINDS = ['installer']
|
|
4
4
|
|
|
5
5
|
export const RELEASE_TARGETS = Object.freeze([
|
|
6
6
|
{ platform: 'windows', arch: 'x64' },
|
|
@@ -89,20 +89,3 @@ export function resolveReleaseAssetDownload(asset, preferredSource = 'r2') {
|
|
|
89
89
|
: '',
|
|
90
90
|
}
|
|
91
91
|
}
|
|
92
|
-
|
|
93
|
-
export function findCompatibleUpdateAsset(manifest, platform, arch) {
|
|
94
|
-
if (!isReleaseManifest(manifest)) return null
|
|
95
|
-
|
|
96
|
-
const compatibleAssets = manifest.assets.filter(
|
|
97
|
-
asset =>
|
|
98
|
-
asset.platform === platform &&
|
|
99
|
-
asset.arch === arch &&
|
|
100
|
-
(asset.kind === 'updater' || asset.kind === 'installer')
|
|
101
|
-
)
|
|
102
|
-
|
|
103
|
-
return (
|
|
104
|
-
compatibleAssets.find(asset => asset.kind === 'updater') ||
|
|
105
|
-
compatibleAssets.find(asset => asset.kind === 'installer') ||
|
|
106
|
-
null
|
|
107
|
-
)
|
|
108
|
-
}
|
package/server/src/index.js
CHANGED
|
@@ -1940,290 +1940,6 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
1940
1940
|
return result
|
|
1941
1941
|
}
|
|
1942
1942
|
|
|
1943
|
-
/**
|
|
1944
|
-
* 按 CID 将内容下载到指定路径,不写入用户文件列表。
|
|
1945
|
-
* 用于桌面客户端更新等内部缓存场景。
|
|
1946
|
-
* @param {object} input - 下载参数
|
|
1947
|
-
* @param {string} input.cid - 文件 CID
|
|
1948
|
-
* @param {string} input.targetPath - 目标文件路径
|
|
1949
|
-
* @param {string} [input.fileName] - 持有记录展示名
|
|
1950
|
-
* @param {string} [input.taskId] - 下载任务 ID
|
|
1951
|
-
* @param {number} [input.timeout] - 等待 P2P 内容的超时时间
|
|
1952
|
-
* @param {number} [input.streamReadTimeout] - 下载流无进度超时时间
|
|
1953
|
-
* @param {boolean} [input.overwrite=true] - 是否覆盖已存在目标文件
|
|
1954
|
-
* @param {string} [input.source='update'] - holding 来源
|
|
1955
|
-
*/
|
|
1956
|
-
async downloadCidToPath(input = {}) {
|
|
1957
|
-
this.#ensureInitialized()
|
|
1958
|
-
|
|
1959
|
-
const cid = input.cid
|
|
1960
|
-
const targetPath = input.targetPath
|
|
1961
|
-
if (!cid) throw new ValidationError('cid is required')
|
|
1962
|
-
if (!targetPath) throw new ValidationError('targetPath is required')
|
|
1963
|
-
|
|
1964
|
-
this.#getCidInfo(cid)
|
|
1965
|
-
const taskId =
|
|
1966
|
-
input.taskId || `cid_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`
|
|
1967
|
-
const taskState = { aborted: false, readStream: null, writeStream: null }
|
|
1968
|
-
const timeout = input.timeout || this.#options.downloadTimeout
|
|
1969
|
-
const streamReadTimeout =
|
|
1970
|
-
input.streamReadTimeout ?? STREAM_READ_TIMEOUT
|
|
1971
|
-
const fileName = sanitizeFilename(input.fileName || path.basename(targetPath))
|
|
1972
|
-
const overwrite = input.overwrite !== false
|
|
1973
|
-
const resolvedTargetPath = path.resolve(targetPath)
|
|
1974
|
-
const targetDir = path.dirname(resolvedTargetPath)
|
|
1975
|
-
const tempPath = `${resolvedTargetPath}.part`
|
|
1976
|
-
|
|
1977
|
-
this.#activeDownloads.set(taskId, taskState)
|
|
1978
|
-
|
|
1979
|
-
try {
|
|
1980
|
-
const writableCheck = await checkDirectoryWritable(targetDir)
|
|
1981
|
-
if (!writableCheck.writable) {
|
|
1982
|
-
throw new PermissionError(writableCheck.error)
|
|
1983
|
-
}
|
|
1984
|
-
if (!overwrite && fs.existsSync(resolvedTargetPath)) {
|
|
1985
|
-
throw new ConflictError(`File already exists: ${resolvedTargetPath}`)
|
|
1986
|
-
}
|
|
1987
|
-
fs.rmSync(tempPath, { force: true })
|
|
1988
|
-
|
|
1989
|
-
const { driveName } = this.#getCidInfo(cid)
|
|
1990
|
-
let drive = this.#drives.get(driveName)
|
|
1991
|
-
if (!drive) {
|
|
1992
|
-
drive = await this.#getOrCreateDrive(driveName, {
|
|
1993
|
-
server: true,
|
|
1994
|
-
client: true,
|
|
1995
|
-
})
|
|
1996
|
-
this.emit('download:status', { taskId, status: 'connecting' })
|
|
1997
|
-
}
|
|
1998
|
-
|
|
1999
|
-
await this.#joinCidTopicInternal(cid, {
|
|
2000
|
-
server: false,
|
|
2001
|
-
client: true,
|
|
2002
|
-
})
|
|
2003
|
-
|
|
2004
|
-
if (taskState.aborted) throw new Error('Download cancelled')
|
|
2005
|
-
this.emit('download:status', { taskId, status: 'finding-peers' })
|
|
2006
|
-
|
|
2007
|
-
const driveKey = '/' + cid
|
|
2008
|
-
const entry = await this.#waitForDriveEntry(
|
|
2009
|
-
drive,
|
|
2010
|
-
driveKey,
|
|
2011
|
-
timeout,
|
|
2012
|
-
taskId,
|
|
2013
|
-
taskState
|
|
2014
|
-
)
|
|
2015
|
-
|
|
2016
|
-
if (!entry) {
|
|
2017
|
-
throw new PeerNotFoundError(
|
|
2018
|
-
'当前没有发现可下载的在线种子,请稍后重试或确认发布者在线'
|
|
2019
|
-
)
|
|
2020
|
-
}
|
|
2021
|
-
|
|
2022
|
-
let totalBytes = 0
|
|
2023
|
-
try {
|
|
2024
|
-
const stat = await drive.entry(entry.key)
|
|
2025
|
-
totalBytes = Number(stat?.value?.blob?.byteLength) || 0
|
|
2026
|
-
} catch {}
|
|
2027
|
-
|
|
2028
|
-
this.emit('download:status', {
|
|
2029
|
-
taskId,
|
|
2030
|
-
status: 'downloading',
|
|
2031
|
-
file: fileName,
|
|
2032
|
-
size: totalBytes ? formatFileSize(totalBytes) : null,
|
|
2033
|
-
})
|
|
2034
|
-
|
|
2035
|
-
const rs = drive.createReadStream(entry.key)
|
|
2036
|
-
const ws = fs.createWriteStream(tempPath)
|
|
2037
|
-
taskState.readStream = rs
|
|
2038
|
-
taskState.writeStream = ws
|
|
2039
|
-
|
|
2040
|
-
let loadedBytes = 0
|
|
2041
|
-
let lastProgressUpdate = 0
|
|
2042
|
-
|
|
2043
|
-
await new Promise((resolve, reject) => {
|
|
2044
|
-
let settled = false
|
|
2045
|
-
let readTimer = null
|
|
2046
|
-
|
|
2047
|
-
const clearReadTimer = () => {
|
|
2048
|
-
if (readTimer) {
|
|
2049
|
-
clearTimeout(readTimer)
|
|
2050
|
-
readTimer = null
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
|
|
2054
|
-
const fail = err => {
|
|
2055
|
-
if (settled) return
|
|
2056
|
-
settled = true
|
|
2057
|
-
clearReadTimer()
|
|
2058
|
-
rs.destroy(err)
|
|
2059
|
-
ws.destroy()
|
|
2060
|
-
fs.unlink(tempPath, () => {})
|
|
2061
|
-
reject(err)
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
const complete = () => {
|
|
2065
|
-
if (settled) return
|
|
2066
|
-
settled = true
|
|
2067
|
-
clearReadTimer()
|
|
2068
|
-
resolve()
|
|
2069
|
-
}
|
|
2070
|
-
|
|
2071
|
-
const resetReadTimer = () => {
|
|
2072
|
-
clearReadTimer()
|
|
2073
|
-
if (streamReadTimeout > 0) {
|
|
2074
|
-
readTimer = setTimeout(() => {
|
|
2075
|
-
fail(
|
|
2076
|
-
new Error(
|
|
2077
|
-
`Download stalled: no data received for ${streamReadTimeout / 1000}s`
|
|
2078
|
-
)
|
|
2079
|
-
)
|
|
2080
|
-
}, streamReadTimeout)
|
|
2081
|
-
}
|
|
2082
|
-
}
|
|
2083
|
-
|
|
2084
|
-
resetReadTimer()
|
|
2085
|
-
|
|
2086
|
-
rs.on('data', chunk => {
|
|
2087
|
-
if (taskState.aborted) {
|
|
2088
|
-
fail(new Error('Download cancelled'))
|
|
2089
|
-
return
|
|
2090
|
-
}
|
|
2091
|
-
resetReadTimer()
|
|
2092
|
-
loadedBytes += chunk.length
|
|
2093
|
-
const now = Date.now()
|
|
2094
|
-
if (
|
|
2095
|
-
totalBytes > 0 &&
|
|
2096
|
-
now - lastProgressUpdate > PROGRESS_THROTTLE
|
|
2097
|
-
) {
|
|
2098
|
-
lastProgressUpdate = now
|
|
2099
|
-
this.emit('download:progress', {
|
|
2100
|
-
taskId,
|
|
2101
|
-
loaded: loadedBytes,
|
|
2102
|
-
total: totalBytes,
|
|
2103
|
-
percent: Math.round((loadedBytes / totalBytes) * 100),
|
|
2104
|
-
})
|
|
2105
|
-
}
|
|
2106
|
-
})
|
|
2107
|
-
|
|
2108
|
-
rs.pipe(ws)
|
|
2109
|
-
ws.on('finish', complete)
|
|
2110
|
-
ws.on('error', fail)
|
|
2111
|
-
rs.on('error', fail)
|
|
2112
|
-
rs.on('close', () => {
|
|
2113
|
-
if (taskState.aborted) fail(new Error('Download cancelled'))
|
|
2114
|
-
})
|
|
2115
|
-
ws.on('close', () => {
|
|
2116
|
-
if (taskState.aborted) fail(new Error('Download cancelled'))
|
|
2117
|
-
})
|
|
2118
|
-
})
|
|
2119
|
-
|
|
2120
|
-
if (taskState.aborted) throw new Error('Download cancelled')
|
|
2121
|
-
|
|
2122
|
-
this.emit('download:status', { taskId, status: 'verifying' })
|
|
2123
|
-
const { cid: downloadedCid, size } = await calculateCid(tempPath)
|
|
2124
|
-
if (downloadedCid.toString() !== cid) {
|
|
2125
|
-
fs.unlinkSync(tempPath)
|
|
2126
|
-
throw new IntegrityError(
|
|
2127
|
-
`File content CID mismatch. Expected ${cid}, got ${downloadedCid.toString()}.`
|
|
2128
|
-
)
|
|
2129
|
-
}
|
|
2130
|
-
|
|
2131
|
-
if (fs.existsSync(resolvedTargetPath)) {
|
|
2132
|
-
fs.rmSync(resolvedTargetPath, { force: true })
|
|
2133
|
-
}
|
|
2134
|
-
fs.renameSync(tempPath, resolvedTargetPath)
|
|
2135
|
-
|
|
2136
|
-
await this.seedCidFileFromPath(cid, resolvedTargetPath, {
|
|
2137
|
-
fileName,
|
|
2138
|
-
source: input.source || 'update',
|
|
2139
|
-
})
|
|
2140
|
-
|
|
2141
|
-
const result = {
|
|
2142
|
-
taskId,
|
|
2143
|
-
cid,
|
|
2144
|
-
fileName,
|
|
2145
|
-
savedPath: resolvedTargetPath,
|
|
2146
|
-
size,
|
|
2147
|
-
}
|
|
2148
|
-
this.emit('download:success', result)
|
|
2149
|
-
return result
|
|
2150
|
-
} finally {
|
|
2151
|
-
this.#activeDownloads.delete(taskId)
|
|
2152
|
-
fs.rmSync(tempPath, { force: true })
|
|
2153
|
-
}
|
|
2154
|
-
}
|
|
2155
|
-
|
|
2156
|
-
/**
|
|
2157
|
-
* 将本地文件按既有 CID 写入 Hyperdrive 并记录 holding,不写入用户文件列表。
|
|
2158
|
-
* @param {string} cid - 文件 CID
|
|
2159
|
-
* @param {string} filePath - 本地文件路径
|
|
2160
|
-
* @param {object} [options] - 选项
|
|
2161
|
-
* @param {string} [options.fileName] - 持有记录展示名
|
|
2162
|
-
* @param {string} [options.source='update'] - holding 来源
|
|
2163
|
-
*/
|
|
2164
|
-
async seedCidFileFromPath(cid, filePath, options = {}) {
|
|
2165
|
-
this.#ensureInitialized()
|
|
2166
|
-
if (!cid) throw new ValidationError('cid is required')
|
|
2167
|
-
if (!filePath) throw new ValidationError('filePath is required')
|
|
2168
|
-
|
|
2169
|
-
this.#getCidInfo(cid)
|
|
2170
|
-
const sizeValidation = await validateFileSize(
|
|
2171
|
-
filePath,
|
|
2172
|
-
this.#options.maxFileSize
|
|
2173
|
-
)
|
|
2174
|
-
if (!sizeValidation.valid) {
|
|
2175
|
-
throw new FileSizeError(sizeValidation.error, sizeValidation.size)
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2178
|
-
const { cid: actualCid } = await calculateCid(filePath)
|
|
2179
|
-
const actualCidString = actualCid.toString()
|
|
2180
|
-
if (actualCidString !== cid) {
|
|
2181
|
-
throw new IntegrityError(
|
|
2182
|
-
`File content CID mismatch. Expected ${cid}, got ${actualCidString}.`
|
|
2183
|
-
)
|
|
2184
|
-
}
|
|
2185
|
-
|
|
2186
|
-
const existingHolding = this.#holdings.find(holding => holding.cid === cid)
|
|
2187
|
-
if (!existingHolding) {
|
|
2188
|
-
this.#checkCapacity(sizeValidation.size || 0)
|
|
2189
|
-
}
|
|
2190
|
-
|
|
2191
|
-
const { driveName } = this.#getCidInfo(cid)
|
|
2192
|
-
const drive = await this.#getOrCreateDrive(driveName, {
|
|
2193
|
-
server: true,
|
|
2194
|
-
client: false,
|
|
2195
|
-
})
|
|
2196
|
-
const driveKey = '/' + cid
|
|
2197
|
-
const localContent = await this.#getLocalCidContent(cid, {
|
|
2198
|
-
public: true,
|
|
2199
|
-
allowHoldingFallback: true,
|
|
2200
|
-
})
|
|
2201
|
-
|
|
2202
|
-
if (!localContent) {
|
|
2203
|
-
const readStream = fs.createReadStream(filePath)
|
|
2204
|
-
const writeStream = drive.createWriteStream(driveKey)
|
|
2205
|
-
await new Promise((resolve, reject) => {
|
|
2206
|
-
readStream.pipe(writeStream)
|
|
2207
|
-
writeStream.on('finish', resolve)
|
|
2208
|
-
writeStream.on('error', reject)
|
|
2209
|
-
readStream.on('error', reject)
|
|
2210
|
-
})
|
|
2211
|
-
}
|
|
2212
|
-
|
|
2213
|
-
await this.#joinCidTopicInternal(cid, {
|
|
2214
|
-
server: true,
|
|
2215
|
-
client: false,
|
|
2216
|
-
})
|
|
2217
|
-
|
|
2218
|
-
return this.#upsertHolding({
|
|
2219
|
-
cid,
|
|
2220
|
-
fileName: sanitizeFilename(options.fileName || path.basename(filePath)),
|
|
2221
|
-
size: sizeValidation.size || 0,
|
|
2222
|
-
driveName,
|
|
2223
|
-
source: options.source || 'update',
|
|
2224
|
-
})
|
|
2225
|
-
}
|
|
2226
|
-
|
|
2227
1943
|
/**
|
|
2228
1944
|
* 读取已发布文件的内容(用于预览)
|
|
2229
1945
|
* Hyperdrive 中用 CID 作为 key 存储
|
|
@@ -2872,7 +2588,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2872
2588
|
/**
|
|
2873
2589
|
* 获取频道内在线用户
|
|
2874
2590
|
* @param {string} channelKeyInput - 内部频道 key,或本地唯一短频道 ID
|
|
2875
|
-
* @returns {Array<{ peerId: string, authorName: string, lastSeen: number }>}
|
|
2591
|
+
* @returns {Array<{ peerId: string, authorName: string, lastSeen: number, memberAddresses: string[] }>}
|
|
2876
2592
|
*/
|
|
2877
2593
|
getChannelPeers(channelKeyInput, options = {}) {
|
|
2878
2594
|
this.#ensureInitialized()
|
|
@@ -2887,6 +2603,9 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
2887
2603
|
return [...peers.values()].map(p => ({
|
|
2888
2604
|
peerId: p.peerId,
|
|
2889
2605
|
authorName: p.authorName,
|
|
2606
|
+
memberAddresses: uniqueStrings(p.memberAddresses).map(address =>
|
|
2607
|
+
normalizeOwnerAddress(address)
|
|
2608
|
+
).filter(Boolean),
|
|
2890
2609
|
lastSeen: p.lastSeen,
|
|
2891
2610
|
}))
|
|
2892
2611
|
}
|
|
@@ -3385,6 +3104,13 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
3385
3104
|
)
|
|
3386
3105
|
}
|
|
3387
3106
|
|
|
3107
|
+
#getChannelMemberAddresses(channel) {
|
|
3108
|
+
const members = Array.isArray(channel?.members) ? channel.members : []
|
|
3109
|
+
return uniqueStrings(
|
|
3110
|
+
members.map(member => normalizeOwnerAddress(member?.address))
|
|
3111
|
+
)
|
|
3112
|
+
}
|
|
3113
|
+
|
|
3388
3114
|
async #getNextChannelMessageTimestamp(channelKey) {
|
|
3389
3115
|
const coresMap = this.#channelCores.get(channelKey)
|
|
3390
3116
|
let maxTimestamp = 0
|
|
@@ -4713,6 +4439,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4713
4439
|
type: channel.type,
|
|
4714
4440
|
createdAt: channel.createdAt,
|
|
4715
4441
|
lastMessageAt: channel.lastMessageAt || '',
|
|
4442
|
+
memberAddresses: this.#getChannelMemberAddresses(channel),
|
|
4716
4443
|
writerCoreKeys: uniqueStrings([
|
|
4717
4444
|
...(channel.writerCoreKeys || []),
|
|
4718
4445
|
this.#channelLocalCoreKey.get(channel.channelKey),
|
|
@@ -4749,6 +4476,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4749
4476
|
async #processChannelHelloMessage(msg) {
|
|
4750
4477
|
if (msg.type !== 'channel-hello') return null
|
|
4751
4478
|
|
|
4479
|
+
const onlineChannels = []
|
|
4752
4480
|
const remoteChannels = Array.isArray(msg.channels)
|
|
4753
4481
|
? msg.channels
|
|
4754
4482
|
.filter(channel => channel && typeof channel === 'object')
|
|
@@ -4764,6 +4492,13 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4764
4492
|
typeof channel.lastMessageAt === 'string'
|
|
4765
4493
|
? channel.lastMessageAt
|
|
4766
4494
|
: '',
|
|
4495
|
+
memberAddresses: uniqueStrings(
|
|
4496
|
+
Array.isArray(channel.memberAddresses)
|
|
4497
|
+
? channel.memberAddresses.map(address =>
|
|
4498
|
+
normalizeOwnerAddress(address)
|
|
4499
|
+
)
|
|
4500
|
+
: []
|
|
4501
|
+
),
|
|
4767
4502
|
writerCoreKeys: uniqueStrings(channel.writerCoreKeys),
|
|
4768
4503
|
}
|
|
4769
4504
|
})
|
|
@@ -4787,9 +4522,15 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4787
4522
|
peers.set(msg.peerId, {
|
|
4788
4523
|
peerId: msg.peerId,
|
|
4789
4524
|
authorName: msg.authorName,
|
|
4525
|
+
memberAddresses: remoteChannel.memberAddresses,
|
|
4790
4526
|
lastSeen: Date.now(),
|
|
4791
4527
|
})
|
|
4792
4528
|
}
|
|
4529
|
+
onlineChannels.push({
|
|
4530
|
+
channelKey: localChannel.channelKey,
|
|
4531
|
+
channelId: localChannel.channelId,
|
|
4532
|
+
memberAddresses: remoteChannel.memberAddresses,
|
|
4533
|
+
})
|
|
4793
4534
|
|
|
4794
4535
|
for (const writerCoreKey of remoteChannel.writerCoreKeys) {
|
|
4795
4536
|
if (
|
|
@@ -4807,6 +4548,7 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4807
4548
|
this.emit('channel:peer:online', {
|
|
4808
4549
|
peerId: msg.peerId,
|
|
4809
4550
|
authorName: msg.authorName,
|
|
4551
|
+
channels: onlineChannels,
|
|
4810
4552
|
})
|
|
4811
4553
|
|
|
4812
4554
|
return msg.peerId
|
|
@@ -4845,13 +4587,19 @@ export class MostBoxEngine extends EventEmitter {
|
|
|
4845
4587
|
closed = true
|
|
4846
4588
|
this.#channelStreams.delete(stream)
|
|
4847
4589
|
if (connectedPeerId) {
|
|
4848
|
-
for (const [, peers] of this.#channelPeers) {
|
|
4590
|
+
for (const [channelKey, peers] of this.#channelPeers) {
|
|
4849
4591
|
if (peers.has(connectedPeerId)) {
|
|
4850
4592
|
const peer = peers.get(connectedPeerId)
|
|
4851
4593
|
peers.delete(connectedPeerId)
|
|
4594
|
+
const channel = this.#channels.find(
|
|
4595
|
+
item => item.channelKey === channelKey
|
|
4596
|
+
)
|
|
4852
4597
|
this.emit('channel:peer:offline', {
|
|
4853
4598
|
peerId: connectedPeerId,
|
|
4854
4599
|
authorName: peer?.authorName,
|
|
4600
|
+
channelKey,
|
|
4601
|
+
channelId: channel?.channelId || '',
|
|
4602
|
+
memberAddresses: peer?.memberAddresses || [],
|
|
4855
4603
|
})
|
|
4856
4604
|
}
|
|
4857
4605
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{s as t,t as n,w as r}from"./ui-u9yJHkb-.js";import{a as i,c as a,o}from"./i18n-Cqyi6NZb.js";var s=r(`check`,[[`path`,{d:`M20 6 9 17l-5-5`,key:`1gmf2c`}]]),c=r(`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`}]]),l=r(`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`}]]),u=r(`refresh-cw`,[[`path`,{d:`M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8`,key:`v9h5vc`}],[`path`,{d:`M21 3v5h-5`,key:`1q7to0`}],[`path`,{d:`M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16`,key:`3uifl3`}],[`path`,{d:`M8 16H3v5`,key:`1cv678`}]]),d=r(`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`}]]),f=e();function p(){let{t:e}=i(),{state:n,installAndRestart:r}=t(),a=n.status===`checking`,o=n.status===`downloading`,s=n.status===`downloaded`,c=n.status===`installing`,l=a||o||c;if(!a&&!o&&!s&&!c)return null;let d=e(`desktopUpdate.install`);a?d=e(`desktopUpdate.checking`):o?d=n.progress>0?e(`desktopUpdate.downloadingProgress`,{progress:n.progress}):e(`desktopUpdate.downloading`):c&&(d=e(`desktopUpdate.installing`));let p=a||o?e(`desktopUpdate.downloadingTitle`):e(`desktopUpdate.readyTitle`,{version:n.version||n.filename});return(0,f.jsxs)(`button`,{type:`button`,className:`btn ${s||c?`btn-primary`:`btn-secondary`} desktop-update-button`,disabled:!s||c,title:p,"aria-live":l?`polite`:void 0,onClick:()=>{s&&r()},children:[(0,f.jsx)(u,{size:16,className:l?`spin`:void 0}),d]})}function m({className:e=``}){let{locale:t,localeName:r,setLocale:l,t:u}=i(),d=u(`common.locale.choose`),p=`${d} (${u(`common.locale.current`)}: ${r})`;return(0,f.jsx)(n,{ariaLabel:d,placement:`bottom-end`,items:o.map(e=>({key:e,label:a[e],icon:e===t?(0,f.jsx)(s,{size:16}):(0,f.jsx)(`span`,{"aria-hidden":`true`}),onSelect:()=>{e!==t&&l(e)}})),renderTrigger:t=>(0,f.jsx)(`button`,{...t,className:[`language-toggle`,e].filter(Boolean).join(` `),"aria-label":d,title:p,children:(0,f.jsx)(c,{size:16})})})}export{l as a,u as i,p as n,s as o,d as r,m as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{n as t,t as n}from"./LanguageToggle-Cfh33R2h.js";import{I as r,j as i}from"./index-CiHRnvMj.js";import{t as a}from"./MarketingThemeToggle-Cl7PhFgv.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:i(),children:[(0,o.jsx)(r,{size:18}),(0,o.jsx)(`span`,{children:`MOST PEOPLE`})]}),(0,o.jsxs)(`div`,{className:`mkt-nav-cta`,children:[(0,o.jsx)(a,{}),(0,o.jsx)(n,{className:`mkt-theme-toggle`}),(0,o.jsx)(t,{})]})]})})}export{s as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{t as e}from"./jsx-runtime-Bt-cYkS5.js";import{O as t,c as n,o as r}from"./ui-u9yJHkb-.js";import{a as i}from"./i18n-Cqyi6NZb.js";import{n as a,t as o}from"./LanguageToggle-Cfh33R2h.js";import{t as s}from"./download-DPA-3LpR.js";import{i as c}from"./index-CiHRnvMj.js";import{t as l}from"./MarketingThemeToggle-Cl7PhFgv.js";import{t as u}from"./LogoIcon-B2fFe0l1.js";var d={name:`most-box`,version:`0.2.7`,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`,dev:`vite`,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`,android:`npm --prefix mobile/android start`,"android:build":`npm --prefix mobile/android run apk`,"android:test":`npm --prefix mobile/android test`,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`]},{target:`zip`,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`}}},f=e(),p=[{to:`/`,labelKey:`footer.about`},{to:`/ping/`,labelKey:`footer.network`},{href:`https://github.com/most-people/most`,labelKey:null,label:`GitHub`,external:!0}],m=d.version;function h(){let{t:e}=i();return(0,f.jsx)(`footer`,{className:`mkt-footer`,children:(0,f.jsx)(`div`,{className:`mkt-container`,children:(0,f.jsxs)(`div`,{className:`mkt-footer-inner`,children:[(0,f.jsx)(`div`,{className:`mkt-footer-links`,children:p.map(n=>`external`in n?(0,f.jsx)(`a`,{href:n.href,target:`_blank`,rel:`noopener noreferrer`,children:n.label},n.href):(0,f.jsx)(t,{to:n.to,children:e(n.labelKey)},n.to))}),(0,f.jsxs)(`span`,{className:`mkt-footer-copy`,children:[`© `,new Date().getFullYear(),` MOST PEOPLE · MIT License`]}),(0,f.jsxs)(`span`,{className:`mkt-footer-build`,translate:`no`,children:[`v`,m]})]})})})}function g({children:e,header:t}){return(0,f.jsxs)(`div`,{className:`mkt-layout`,children:[t??(0,f.jsx)(_,{}),(0,f.jsx)(`main`,{className:`mkt-layout-main`,children:e}),(0,f.jsx)(h,{})]})}function _(){let e=n(e=>e.identity),d=n(e=>e.openLoginModal),{t:p}=i(),m=r(),h=e?.displayName||e?.username||p(`nav.openWeb`);return(0,f.jsx)(`nav`,{className:`mkt-nav`,children:(0,f.jsxs)(`div`,{className:`mkt-nav-inner`,children:[(0,f.jsxs)(t,{to:`/`,className:`mkt-nav-logo`,children:[(0,f.jsx)(u,{}),`MOST PEOPLE`]}),(0,f.jsxs)(`div`,{className:`mkt-nav-cta`,children:[(0,f.jsx)(l,{}),(0,f.jsx)(o,{className:`mkt-theme-toggle`}),(0,f.jsx)(a,{}),!m&&(0,f.jsxs)(t,{to:`/download/`,className:`btn btn-primary mkt-nav-preview`,children:[(0,f.jsx)(s,{size:16}),p(`nav.downloadClient`)]}),e?(0,f.jsx)(t,{to:`/profile/`,className:`mkt-nav-avatar-trigger`,"aria-label":p(`nav.profile`),title:h,children:(0,f.jsx)(`img`,{className:`mkt-nav-avatar`,src:c(e.address,e.avatar),alt:``,"aria-hidden":`true`})}):(0,f.jsx)(`button`,{type:`button`,className:`btn btn-secondary`,onClick:d,children:p(`nav.getStarted`)})]})]})})}export{g as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{n as e,o as t,t as n}from"./jsx-runtime-Bt-cYkS5.js";import{O as r,w as i}from"./ui-u9yJHkb-.js";import{a}from"./i18n-Cqyi6NZb.js";import{n as o,t as s}from"./LanguageToggle-Cfh33R2h.js";import{I as c}from"./index-CiHRnvMj.js";var l=i(`menu`,[[`path`,{d:`M4 5h16`,key:`1tepv9`}],[`path`,{d:`M4 12h16`,key:`1lakjw`}],[`path`,{d:`M4 19h16`,key:`1djgab`}]]),u=t(e(),1);function d(e,t){return typeof t==`boolean`?t:typeof window<`u`&&`matchMedia`in window?window.matchMedia(e).matches:!1}function f(e,t,{getInitialValueInEffect:n}={getInitialValueInEffect:!0}){let[r,i]=(0,u.useState)(n?t:d(e));return(0,u.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 p(e=!1,t={}){let[n,r]=(0,u.useState)(e),i=(0,u.useCallback)(()=>{r(e=>e||(t.onOpen?.(),!0))},[t.onOpen]),a=(0,u.useCallback)(()=>{r(e=>e&&(t.onClose?.(),!1))},[t.onClose]);return[n,{open:i,close:a,toggle:(0,u.useCallback)(()=>{n?a():i()},[a,i,n]),set:r}]}var m=n(),h=(0,u.createContext)(null);function g(){let e=(0,u.useContext)(h);if(!e)throw Error(`useAppShell must be used within AppShell`);return e}function _({sidebar:e,className:t=``,headerTitle:n,headerRight:r,sidebarToggleReplacement:i,defaultHide:c=!1,children:d}){let[g,_]=p(!1),[v,y]=(0,u.useState)(c),b=(0,u.useRef)(c),x=f(`(max-width: 768px)`),{t:S}=a(),C=(0,u.useCallback)((e={})=>{_.close(),e.collapse&&y(!0)},[_]);(0,u.useEffect)(()=>{c!==b.current&&(c?C({collapse:!0}):y(!1),b.current=c)},[c,C]);let w=()=>{x?_.toggle():y(!v)},T=()=>{x?_.open():y(!1)},E=x?g:!v;return(0,m.jsx)(h.Provider,{value:{closeSidebar:C,openSidebar:T,isSidebarVisible:E},children:(0,m.jsxs)(`div`,{className:[`app-layout`,t].filter(Boolean).join(` `),children:[(0,m.jsx)(`div`,{className:`sidebar-overlay ${g?`visible`:``}`,onClick:()=>C()}),(0,m.jsx)(`div`,{className:`sidebar ${g?`open`:``} ${v?`collapsed`:``}`,children:e({closeSidebar:C,openSidebar:T})}),(0,m.jsxs)(`div`,{className:`main-content`,children:[(0,m.jsxs)(`header`,{className:`app-header`,children:[(0,m.jsxs)(`div`,{className:`header-left`,children:[i??(0,m.jsx)(`button`,{onClick:w,className:`btn btn-icon sidebar-toggle-btn`,"aria-label":S(x?`appShell.openMenu`:v?`appShell.expandSidebar`:`appShell.collapseSidebar`),children:(0,m.jsx)(l,{size:16})}),n]}),(0,m.jsxs)(`div`,{className:`header-right`,children:[(0,m.jsx)(o,{}),(0,m.jsx)(s,{className:`btn btn-icon app-language-toggle`}),r]})]}),d]})]})})}function v({onNavigate:e}){let{t}=a(),n=t(`common.brand`);return(0,m.jsxs)(r,{to:`/`,className:`sidebar-header sidebar-header-link`,onClick:e,"aria-label":n,title:n,children:[(0,m.jsx)(c,{size:18}),(0,m.jsx)(`h1`,{children:n})]})}export{p as i,_ as n,g as r,v as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{w as e}from"./ui-u9yJHkb-.js";var t=e(`arrow-right`,[[`path`,{d:`M5 12h14`,key:`1ays0h`}],[`path`,{d:`m12 5 7 7-7 7`,key:`xquz4c`}]]);export{t};
|