most-box 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/README.md +39 -19
  2. package/electron/afterPack.cjs +87 -0
  3. package/electron/main.js +156 -8
  4. package/electron/preload.js +6 -0
  5. package/electron/updateChecker.js +97 -0
  6. package/electron/updateChecker.test.js +147 -0
  7. package/out/404/index.html +2 -2
  8. package/out/404.html +2 -2
  9. package/out/__next.__PAGE__.txt +6 -6
  10. package/out/__next._full.txt +16 -16
  11. package/out/__next._head.txt +3 -3
  12. package/out/__next._index.txt +8 -8
  13. package/out/__next._tree.txt +5 -5
  14. package/out/_next/static/chunks/04mo7rr..0_1q.js +1 -0
  15. package/out/_next/static/chunks/06rf3qq5ggs6v.js +1 -0
  16. package/out/_next/static/chunks/07td.jq7xff84.css +1 -0
  17. package/out/_next/static/chunks/0_0oph_z1az14.js +1 -0
  18. package/out/_next/static/chunks/{0qou.u2e2dy48.css → 0adx~d-j05c9d.css} +2 -2
  19. package/out/_next/static/chunks/0cl7d~7abnk_p.css +1 -0
  20. package/out/_next/static/chunks/0d306t1wvjpdx.js +1 -0
  21. package/out/_next/static/chunks/0g_a~e050bgzg.css +1 -0
  22. package/out/_next/static/chunks/{0o6lrkxy4jwag.js → 0gcsdf57gcm6h.js} +1 -1
  23. package/out/_next/static/chunks/0hpev4am9jpmu.css +1 -0
  24. package/out/_next/static/chunks/0m_5nb6x8qy._.js +1 -0
  25. package/out/_next/static/chunks/0n.ayxmsar6e5.js +1 -0
  26. package/out/_next/static/chunks/{0usvo~vu7r8np.js → 0o9ce4cyf76by.js} +1 -1
  27. package/out/_next/static/chunks/0olqjomda37-e.js +1 -0
  28. package/out/_next/static/chunks/{0o98f1yq..o.8.js → 0pt.5cg1t09qs.js} +1 -1
  29. package/out/_next/static/chunks/0qgx9t4jx16ua.css +1 -0
  30. package/out/_next/static/chunks/0s~g.l~x049o2.js +1 -0
  31. package/out/_next/static/chunks/0ukyg~tkm~h2m.css +1 -0
  32. package/out/_next/static/chunks/0voe1.ttrh84k.css +1 -0
  33. package/out/_next/static/chunks/0wtf0xsiicxx6.js +1 -0
  34. package/out/_next/static/chunks/0x.ky97owcxxs.js +1 -0
  35. package/out/_next/static/chunks/0xdwau5k2augv.css +4 -0
  36. package/out/_next/static/chunks/0ysj5b94vu4ri.js +1 -0
  37. package/out/_next/static/chunks/12nr19.nnn6s3.js +5 -0
  38. package/out/_next/static/chunks/{0qub_r0x_r-e9.css → 12pep-2t-qg4n.css} +1 -1
  39. package/out/_next/static/chunks/14_inksek_rth.js +2 -0
  40. package/out/_next/static/chunks/153-sz7s.qml2.js +1 -0
  41. package/out/_next/static/chunks/17cwkb2yn_akx.js +1 -0
  42. package/out/_next/static/chunks/184hxsuf-5c84.js +1 -0
  43. package/out/_next/static/chunks/{turbopack-0xs6mybc~5t_3.js → turbopack-0xta0kqwzkf28.js} +1 -1
  44. package/out/_not-found/__next._full.txt +13 -13
  45. package/out/_not-found/__next._head.txt +3 -3
  46. package/out/_not-found/__next._index.txt +8 -8
  47. package/out/_not-found/__next._not-found.__PAGE__.txt +4 -4
  48. package/out/_not-found/__next._not-found.txt +3 -3
  49. package/out/_not-found/__next._tree.txt +3 -3
  50. package/out/_not-found/index.html +2 -2
  51. package/out/_not-found/index.txt +13 -13
  52. package/out/admin/__next._full.txt +15 -15
  53. package/out/admin/__next._head.txt +3 -3
  54. package/out/admin/__next._index.txt +8 -8
  55. package/out/admin/__next._tree.txt +4 -4
  56. package/out/admin/__next.admin.__PAGE__.txt +4 -4
  57. package/out/admin/__next.admin.txt +4 -4
  58. package/out/admin/index.html +2 -2
  59. package/out/admin/index.txt +15 -15
  60. package/out/app/__next._full.txt +14 -14
  61. package/out/app/__next._head.txt +3 -3
  62. package/out/app/__next._index.txt +8 -8
  63. package/out/app/__next._tree.txt +3 -3
  64. package/out/app/__next.app.__PAGE__.txt +4 -4
  65. package/out/app/__next.app.txt +3 -3
  66. package/out/app/index.html +2 -2
  67. package/out/app/index.txt +14 -14
  68. package/out/chat/__next._full.txt +15 -15
  69. package/out/chat/__next._head.txt +3 -3
  70. package/out/chat/__next._index.txt +8 -8
  71. package/out/chat/__next._tree.txt +4 -4
  72. package/out/chat/__next.chat.__PAGE__.txt +4 -4
  73. package/out/chat/__next.chat.txt +4 -4
  74. package/out/chat/index.html +2 -2
  75. package/out/chat/index.txt +15 -15
  76. package/out/chat/join/__next._full.txt +25 -0
  77. package/out/chat/join/__next._head.txt +5 -0
  78. package/out/{changelog → chat/join}/__next._index.txt +8 -8
  79. package/out/chat/join/__next._tree.txt +5 -0
  80. package/out/chat/join/__next.chat.join.__PAGE__.txt +9 -0
  81. package/out/chat/join/__next.chat.join.txt +5 -0
  82. package/out/chat/join/__next.chat.txt +5 -0
  83. package/out/chat/join/index.html +15 -0
  84. package/out/chat/join/index.txt +25 -0
  85. package/out/download/__next._full.txt +37 -33
  86. package/out/download/__next._head.txt +3 -3
  87. package/out/download/__next._index.txt +8 -8
  88. package/out/download/__next._tree.txt +5 -5
  89. package/out/download/__next.download.__PAGE__.txt +9 -14
  90. package/out/download/__next.download.txt +3 -3
  91. package/out/download/index.html +2 -2
  92. package/out/download/index.txt +37 -33
  93. package/out/favicon.ico +0 -0
  94. package/out/gandengyan/__next._full.txt +25 -0
  95. package/out/{changelog → gandengyan}/__next._head.txt +3 -3
  96. package/out/{docs → gandengyan}/__next._index.txt +8 -8
  97. package/out/gandengyan/__next._tree.txt +5 -0
  98. package/out/gandengyan/__next.gandengyan.__PAGE__.txt +10 -0
  99. package/out/gandengyan/__next.gandengyan.txt +5 -0
  100. package/out/gandengyan/index.html +15 -0
  101. package/out/gandengyan/index.txt +25 -0
  102. package/out/index.html +2 -2
  103. package/out/index.txt +16 -16
  104. package/out/note/__next._full.txt +14 -14
  105. package/out/note/__next._head.txt +3 -3
  106. package/out/note/__next._index.txt +8 -8
  107. package/out/note/__next._tree.txt +3 -3
  108. package/out/note/__next.note.__PAGE__.txt +4 -4
  109. package/out/note/__next.note.txt +3 -3
  110. package/out/note/index.html +2 -2
  111. package/out/note/index.txt +14 -14
  112. package/out/ping/__next._full.txt +16 -16
  113. package/out/ping/__next._head.txt +3 -3
  114. package/out/ping/__next._index.txt +8 -8
  115. package/out/ping/__next._tree.txt +5 -5
  116. package/out/ping/__next.ping.__PAGE__.txt +5 -5
  117. package/out/ping/__next.ping.txt +4 -4
  118. package/out/ping/index.html +2 -2
  119. package/out/ping/index.txt +16 -16
  120. package/out/web3/__next._full.txt +15 -15
  121. package/out/web3/__next._head.txt +3 -3
  122. package/out/web3/__next._index.txt +8 -8
  123. package/out/web3/__next._tree.txt +4 -4
  124. package/out/web3/__next.web3.__PAGE__.txt +4 -4
  125. package/out/web3/__next.web3.txt +4 -4
  126. package/out/web3/ed25519/__next._full.txt +13 -13
  127. package/out/web3/ed25519/__next._head.txt +3 -3
  128. package/out/web3/ed25519/__next._index.txt +8 -8
  129. package/out/web3/ed25519/__next._tree.txt +4 -4
  130. package/out/web3/ed25519/__next.web3.ed25519.__PAGE__.txt +2 -2
  131. package/out/web3/ed25519/__next.web3.ed25519.txt +3 -3
  132. package/out/web3/ed25519/__next.web3.txt +4 -4
  133. package/out/web3/ed25519/index.html +1 -1
  134. package/out/web3/ed25519/index.txt +13 -13
  135. package/out/web3/index.html +2 -2
  136. package/out/web3/index.txt +15 -15
  137. package/out/web3/tools/__next._full.txt +13 -13
  138. package/out/web3/tools/__next._head.txt +3 -3
  139. package/out/web3/tools/__next._index.txt +8 -8
  140. package/out/web3/tools/__next._tree.txt +4 -4
  141. package/out/web3/tools/__next.web3.tools.__PAGE__.txt +2 -2
  142. package/out/web3/tools/__next.web3.tools.txt +3 -3
  143. package/out/web3/tools/__next.web3.txt +4 -4
  144. package/out/web3/tools/index.html +1 -1
  145. package/out/web3/tools/index.txt +13 -13
  146. package/package.json +44 -35
  147. package/public/favicon.ico +0 -0
  148. package/server/index.js +142 -1304
  149. package/server/src/config.js +1 -1
  150. package/server/src/core/channelAttachment.js +68 -0
  151. package/server/src/core/cid.js +2 -88
  152. package/server/src/core/cidTopic.js +29 -0
  153. package/server/src/core/mostLink.js +88 -0
  154. package/server/src/games/gandengyan.js +675 -0
  155. package/server/src/http/access.js +127 -0
  156. package/server/src/http/app.js +1102 -0
  157. package/server/src/http/errors.js +35 -0
  158. package/server/src/http/nodeLogs.js +53 -0
  159. package/server/src/http/nodeStatus.js +146 -0
  160. package/server/src/http/staticFiles.js +84 -0
  161. package/server/src/http/uploads.js +114 -0
  162. package/server/src/index.js +799 -211
  163. package/server/src/node/config.js +38 -6
  164. package/server/src/utils/api.js +305 -14
  165. package/server/src/utils/auth.js +63 -0
  166. package/server/src/utils/dateTime.js +30 -0
  167. package/server/src/utils/downloadMessages.js +89 -0
  168. package/server/src/utils/errors.js +7 -0
  169. package/server/src/utils/mostWallet.js +151 -0
  170. package/server/src/utils/mp.js +2 -26
  171. package/server/src/utils/noteBackup.js +2 -5
  172. package/server/src/utils/noteUtils.js +11 -3
  173. package/server/src/utils/userIdentity.js +0 -1
  174. package/out/_next/static/chunks/00-u5nq76f0.j.js +0 -1
  175. package/out/_next/static/chunks/00fm8lijienf1.js +0 -1
  176. package/out/_next/static/chunks/00o9ht.f2qm00.css +0 -4
  177. package/out/_next/static/chunks/00zi-erhjrny2.js +0 -2
  178. package/out/_next/static/chunks/084xf0edl9sfo.js +0 -1
  179. package/out/_next/static/chunks/09f1gfke9m5wg.css +0 -1
  180. package/out/_next/static/chunks/09xyi6fpro_d-.css +0 -1
  181. package/out/_next/static/chunks/0_npg_pcoywti.js +0 -5
  182. package/out/_next/static/chunks/0_r_mk1~6bosc.js +0 -1
  183. package/out/_next/static/chunks/0arm0a6adt7cc.css +0 -1
  184. package/out/_next/static/chunks/0c9j3eq_14vv2.css +0 -1
  185. package/out/_next/static/chunks/0d4bueddmcnca.js +0 -1
  186. package/out/_next/static/chunks/0gtwvy1z9ksa7.css +0 -1
  187. package/out/_next/static/chunks/0ho~log~~-jwp.css +0 -1
  188. package/out/_next/static/chunks/0j27tcmtt4ly7.js +0 -1
  189. package/out/_next/static/chunks/0j3v4mq67wtnh.js +0 -1
  190. package/out/_next/static/chunks/0lkmf5ry.s_7w.js +0 -1
  191. package/out/_next/static/chunks/0p486m03-zfoi.js +0 -1
  192. package/out/_next/static/chunks/0r1~k82nji8sf.js +0 -1
  193. package/out/_next/static/chunks/0v7qp4hv-_._r.js +0 -1
  194. package/out/_next/static/chunks/0wuwlgcn6gxqt.js +0 -1
  195. package/out/_next/static/chunks/0xl5_avhu._i8.js +0 -1
  196. package/out/_next/static/chunks/10kvl8vj_plm-.js +0 -1
  197. package/out/_next/static/chunks/16m27azcs4k6w.js +0 -1
  198. package/out/changelog/__next._full.txt +0 -25
  199. package/out/changelog/__next._tree.txt +0 -5
  200. package/out/changelog/__next.changelog.__PAGE__.txt +0 -10
  201. package/out/changelog/__next.changelog.txt +0 -5
  202. package/out/changelog/index.html +0 -15
  203. package/out/changelog/index.txt +0 -25
  204. package/out/docs/__next._full.txt +0 -25
  205. package/out/docs/__next._head.txt +0 -5
  206. package/out/docs/__next._tree.txt +0 -5
  207. package/out/docs/__next.docs.__PAGE__.txt +0 -10
  208. package/out/docs/__next.docs.txt +0 -5
  209. package/out/docs/getting-started/__next._full.txt +0 -25
  210. package/out/docs/getting-started/__next._head.txt +0 -5
  211. package/out/docs/getting-started/__next._index.txt +0 -9
  212. package/out/docs/getting-started/__next._tree.txt +0 -5
  213. package/out/docs/getting-started/__next.docs.getting-started.__PAGE__.txt +0 -10
  214. package/out/docs/getting-started/__next.docs.getting-started.txt +0 -5
  215. package/out/docs/getting-started/__next.docs.txt +0 -5
  216. package/out/docs/getting-started/index.html +0 -15
  217. package/out/docs/getting-started/index.txt +0 -25
  218. package/out/docs/index.html +0 -15
  219. package/out/docs/index.txt +0 -25
  220. package/out/note/edit/__next._full.txt +0 -24
  221. package/out/note/edit/__next._head.txt +0 -5
  222. package/out/note/edit/__next._index.txt +0 -9
  223. package/out/note/edit/__next._tree.txt +0 -4
  224. package/out/note/edit/__next.note.edit.__PAGE__.txt +0 -9
  225. package/out/note/edit/__next.note.edit.txt +0 -5
  226. package/out/note/edit/__next.note.txt +0 -5
  227. package/out/note/edit/index.html +0 -15
  228. package/out/note/edit/index.txt +0 -24
  229. /package/out/_next/static/{sIuUKxnnGU7K9Tu9UDKE8 → aPEZ4zaaR5W3WpSZ0dFsa}/_buildManifest.js +0 -0
  230. /package/out/_next/static/{sIuUKxnnGU7K9Tu9UDKE8 → aPEZ4zaaR5W3WpSZ0dFsa}/_clientMiddlewareManifest.js +0 -0
  231. /package/out/_next/static/{sIuUKxnnGU7K9Tu9UDKE8 → aPEZ4zaaR5W3WpSZ0dFsa}/_ssgManifest.js +0 -0
@@ -14,6 +14,13 @@ import nacl from 'tweetnacl'
14
14
  const SALT_PREFIX = '/most.box/'
15
15
  const PBKDF2_ITERATIONS = 50_000
16
16
  const PBKDF2_KEY_LENGTH = 32
17
+ const BOX_TOKEN_VERSION = 1
18
+ const BOX_TIMESTAMP_BYTES = 8
19
+ const BOX_TOKEN_HEADER_BYTES =
20
+ 1 + BOX_TIMESTAMP_BYTES + nacl.secretbox.nonceLength
21
+ const BOX_TOKEN_MIN_BYTES =
22
+ BOX_TOKEN_HEADER_BYTES + nacl.secretbox.overheadLength
23
+ const BOX_LABEL = new TextEncoder().encode('MP-AE')
17
24
 
18
25
  export function mostWallet(username, password) {
19
26
  const salt = toUtf8Bytes(SALT_PREFIX + username)
@@ -73,3 +80,147 @@ export function mostDecode(data, danger) {
73
80
 
74
81
  return decrypted ? new TextDecoder().decode(decrypted) : ''
75
82
  }
83
+
84
+ function concatBytes(parts) {
85
+ const total = parts.reduce((sum, part) => sum + part.length, 0)
86
+ const output = new Uint8Array(total)
87
+ let offset = 0
88
+ for (const part of parts) {
89
+ output.set(part, offset)
90
+ offset += part.length
91
+ }
92
+ return output
93
+ }
94
+
95
+ function encodeBase64Url(bytes) {
96
+ return encodeBase64(bytes)
97
+ .replaceAll('+', '-')
98
+ .replaceAll('/', '_')
99
+ .replaceAll('=', '')
100
+ }
101
+
102
+ function decodeBase64Url(value) {
103
+ const token = String(value || '').trim()
104
+ if (!token || !/^[A-Za-z0-9_-]+$/.test(token)) return null
105
+
106
+ try {
107
+ const standard = token
108
+ .replaceAll('-', '+')
109
+ .replaceAll('_', '/')
110
+ .padEnd(Math.ceil(token.length / 4) * 4, '=')
111
+ return decodeBase64(standard)
112
+ } catch {
113
+ return null
114
+ }
115
+ }
116
+
117
+ function encodeTimestampMs(value) {
118
+ const output = new Uint8Array(BOX_TIMESTAMP_BYTES)
119
+ const view = new DataView(output.buffer)
120
+ view.setBigUint64(0, BigInt(value), false)
121
+ return output
122
+ }
123
+
124
+ function decodeTimestampMs(bytes) {
125
+ const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
126
+ return Number(view.getBigUint64(0, false))
127
+ }
128
+
129
+ function readBoxTokenPayload(data) {
130
+ const payload = decodeBase64Url(data)
131
+ if (
132
+ !payload ||
133
+ payload.length < BOX_TOKEN_MIN_BYTES ||
134
+ payload[0] !== BOX_TOKEN_VERSION
135
+ ) {
136
+ return null
137
+ }
138
+
139
+ const timestampBytes = payload.slice(1, 1 + BOX_TIMESTAMP_BYTES)
140
+ const nonce = payload.slice(1 + BOX_TIMESTAMP_BYTES, BOX_TOKEN_HEADER_BYTES)
141
+ const encrypted = payload.slice(BOX_TOKEN_HEADER_BYTES)
142
+
143
+ return {
144
+ version: payload[0],
145
+ timestampMs: decodeTimestampMs(timestampBytes),
146
+ nonce,
147
+ encrypted,
148
+ }
149
+ }
150
+
151
+ function deriveDirectionalBoxKey(
152
+ senderPublicKey,
153
+ recipientPublicKey,
154
+ sharedKey
155
+ ) {
156
+ return nacl
157
+ .hash(
158
+ concatBytes([BOX_LABEL, senderPublicKey, recipientPublicKey, sharedKey])
159
+ )
160
+ .slice(0, nacl.secretbox.keyLength)
161
+ }
162
+
163
+ export function mostBoxEncrypt(text, { senderPrivateKey, recipientPublicKey }) {
164
+ const senderSecretKey = getBytes(senderPrivateKey)
165
+ const senderPublicKey =
166
+ nacl.box.keyPair.fromSecretKey(senderSecretKey).publicKey
167
+ const recipientPublicKeyBytes = getBytes(recipientPublicKey)
168
+ const sharedKey = nacl.box.before(recipientPublicKeyBytes, senderSecretKey)
169
+ const boxKey = deriveDirectionalBoxKey(
170
+ senderPublicKey,
171
+ recipientPublicKeyBytes,
172
+ sharedKey
173
+ )
174
+ const nonce = nacl.randomBytes(nacl.secretbox.nonceLength)
175
+ const encrypted = nacl.secretbox(
176
+ new TextEncoder().encode(text),
177
+ nonce,
178
+ boxKey
179
+ )
180
+ const payload = concatBytes([
181
+ new Uint8Array([BOX_TOKEN_VERSION]),
182
+ encodeTimestampMs(Date.now()),
183
+ nonce,
184
+ encrypted,
185
+ ])
186
+
187
+ return encodeBase64Url(payload)
188
+ }
189
+
190
+ export function parseMostBoxToken(data) {
191
+ const payload = readBoxTokenPayload(data)
192
+ if (!payload) return null
193
+
194
+ return {
195
+ version: payload.version,
196
+ timestampMs: payload.timestampMs,
197
+ nonce: encodeBase64Url(payload.nonce),
198
+ }
199
+ }
200
+
201
+ export function mostBoxDecrypt(data, { senderPublicKey, recipientPrivateKey }) {
202
+ const payload = readBoxTokenPayload(data)
203
+ if (!payload) return ''
204
+
205
+ try {
206
+ const recipientSecretKey = getBytes(recipientPrivateKey)
207
+ const recipientPublicKey =
208
+ nacl.box.keyPair.fromSecretKey(recipientSecretKey).publicKey
209
+ const senderPublicKeyBytes = getBytes(senderPublicKey)
210
+ const sharedKey = nacl.box.before(senderPublicKeyBytes, recipientSecretKey)
211
+ const boxKey = deriveDirectionalBoxKey(
212
+ senderPublicKeyBytes,
213
+ recipientPublicKey,
214
+ sharedKey
215
+ )
216
+ const decrypted = nacl.secretbox.open(
217
+ payload.encrypted,
218
+ payload.nonce,
219
+ boxKey
220
+ )
221
+
222
+ return decrypted ? new TextDecoder().decode(decrypted) : ''
223
+ } catch {
224
+ return ''
225
+ }
226
+ }
@@ -1,7 +1,7 @@
1
1
  import { getBytes } from 'ethers'
2
- import dayjs from 'dayjs'
3
2
  import nacl from 'tweetnacl'
4
3
  import { generateAvatar } from './avatar.js'
4
+ import { formatTime } from './dateTime.js'
5
5
 
6
6
  const BASE36_ALPHABET = '0123456789abcdefghijklmnopqrstuvwxyz'
7
7
 
@@ -77,29 +77,5 @@ export const getIPNS = (private_key, ed_public_key) => {
77
77
  return 'k' + baseXEncode(cidBytes, BASE36_ALPHABET)
78
78
  }
79
79
 
80
- export const formatTime = time => {
81
- if (!time) return ''
82
- const date = dayjs(Number(time))
83
- const hour = date.hour()
84
- let timeOfDay
85
- if (hour >= 0 && hour < 3) {
86
- timeOfDay = '凌晨'
87
- } else if (hour >= 3 && hour < 6) {
88
- timeOfDay = '拂晓'
89
- } else if (hour >= 6 && hour < 9) {
90
- timeOfDay = '早晨'
91
- } else if (hour >= 9 && hour < 12) {
92
- timeOfDay = '上午'
93
- } else if (hour >= 12 && hour < 15) {
94
- timeOfDay = '下午'
95
- } else if (hour >= 15 && hour < 18) {
96
- timeOfDay = '傍晚'
97
- } else if (hour >= 18 && hour < 21) {
98
- timeOfDay = '薄暮'
99
- } else {
100
- timeOfDay = '深夜'
101
- }
102
- return date.format(`YYYY年M月D日 ${timeOfDay}h点`)
103
- }
104
-
105
80
  export const avatar = generateAvatar
81
+ export { formatTime }
@@ -1,7 +1,7 @@
1
1
  import { mostDecode, mostEncode, mostSignMessage } from './mostWallet.js'
2
2
  import { calculateNoteCid } from './noteUtils.js'
3
3
 
4
- export const NOTE_BACKUP_API_URL = 'https://api.most.box/api/backup'
4
+ export const NOTE_BACKUP_API_URL = 'https://api.most.box/auth/backup'
5
5
 
6
6
  async function readBackupApiError(response, fallback) {
7
7
  const data = await response
@@ -84,10 +84,7 @@ export async function uploadNotesBackup(
84
84
  }
85
85
  }
86
86
 
87
- export async function downloadNotesBackup(
88
- wallet,
89
- url = NOTE_BACKUP_API_URL
90
- ) {
87
+ export async function downloadNotesBackup(wallet, url = NOTE_BACKUP_API_URL) {
91
88
  const response = await fetch(url, {
92
89
  method: 'GET',
93
90
  headers: await getBackupAuthHeaders(wallet, 'GET', url),
@@ -39,7 +39,11 @@ export function filterNotesByPath(notes, currentPath = '', query = '') {
39
39
 
40
40
  if (normalizedQuery) {
41
41
  return files
42
- .filter(note => String(note.name || '').toLowerCase().includes(normalizedQuery))
42
+ .filter(note =>
43
+ String(note.name || '')
44
+ .toLowerCase()
45
+ .includes(normalizedQuery)
46
+ )
43
47
  .sort(sortNotesForExplorer)
44
48
  }
45
49
 
@@ -99,7 +103,9 @@ export function renameNotesByPath(notes, oldFullPath, targetPath, targetName) {
99
103
 
100
104
  if (fullPath.startsWith(`${oldPath}/`)) {
101
105
  const relativePath = fullPath.slice(oldPath.length + 1)
102
- const nextFullPath = normalizeNotePath(`${targetFullPath}/${relativePath}`)
106
+ const nextFullPath = normalizeNotePath(
107
+ `${targetFullPath}/${relativePath}`
108
+ )
103
109
  const lastSlash = nextFullPath.lastIndexOf('/')
104
110
  return {
105
111
  ...note,
@@ -116,5 +122,7 @@ export function renameNotesByPath(notes, oldFullPath, targetPath, targetName) {
116
122
  function sortNotesForExplorer(a, b) {
117
123
  if (a.type === 'directory' && b.type !== 'directory') return -1
118
124
  if (a.type !== 'directory' && b.type === 'directory') return 1
119
- return (b.updated_at || b.created_at || 0) - (a.updated_at || a.created_at || 0)
125
+ return (
126
+ (b.updated_at || b.created_at || 0) - (a.updated_at || a.created_at || 0)
127
+ )
120
128
  }
@@ -4,7 +4,6 @@ export function createLoginIdentity(username, password) {
4
4
  const { address, danger } = mostWallet(username, password)
5
5
  return {
6
6
  username,
7
- password,
8
7
  address,
9
8
  danger,
10
9
  displayName: `${username}#${address.slice(-4).toUpperCase()}`,
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,35965,e=>{"use strict";let t=(0,e.i(56420).default)("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"}]]);e.s(["Sun",0,t],35965)},96699,e=>{"use strict";let t=(0,e.i(56420).default)("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"}]]);e.s(["Moon",0,t],96699)},93583,e=>{"use strict";let t=(0,e.i(56420).default)("menu",[["path",{d:"M4 5h16",key:"1tepv9"}],["path",{d:"M4 12h16",key:"1lakjw"}],["path",{d:"M4 19h16",key:"1djgab"}]]);e.s(["Menu",0,t],93583)},40983,e=>{"use strict";var t=e.i(18050),l=e.i(71645),s=e.i(22016),n=e.i(35965),i=e.i(96699),r=e.i(93583);function a({size:e=24}){return(0,t.jsxs)("svg",{width:e,height:e,viewBox:"0 0 24 24",fill:"none",xmlns:"http://www.w3.org/2000/svg",children:[(0,t.jsx)("rect",{x:"2",y:"2",width:"8",height:"8",rx:"2",fill:"var(--accent)",opacity:"0.4"}),(0,t.jsx)("rect",{x:"14",y:"2",width:"8",height:"8",rx:"2",fill:"var(--accent)",opacity:"0.7"}),(0,t.jsx)("rect",{x:"2",y:"14",width:"8",height:"8",rx:"2",fill:"var(--accent)",opacity:"0.7"}),(0,t.jsx)("rect",{x:"14",y:"14",width:"8",height:"8",rx:"2",fill:"var(--accent)"})]})}let o=[{href:"/docs/getting-started/",label:"文档"},{href:"/changelog/",label:"更新日志"}];function c(){let[e,c]=(0,l.useState)(!1),[d,h]=(0,l.useState)(!1);return(0,l.useEffect)(()=>{let e=localStorage.getItem("theme"),t=window.matchMedia("(prefers-color-scheme: dark)").matches;("dark"===e||!e&&t)&&h(!0)},[]),(0,l.useEffect)(()=>{document.documentElement.setAttribute("data-theme",d?"dark":"light"),localStorage.setItem("theme",d?"dark":"light")},[d]),(0,t.jsx)(t.Fragment,{children:(0,t.jsx)("nav",{className:"mkt-nav",children:(0,t.jsxs)("div",{className:"mkt-nav-inner",children:[(0,t.jsxs)(s.default,{href:"/",className:"mkt-nav-logo",children:[(0,t.jsx)(a,{}),"MOST PEOPLE"]}),(0,t.jsxs)("div",{className:`mkt-nav-links ${e?"open":""}`,children:[o.map(e=>(0,t.jsx)(s.default,{href:e.href,onClick:()=>c(!1),children:e.label},e.href)),(0,t.jsxs)("button",{className:"mkt-theme-toggle mkt-mobile-only",onClick:()=>{h(!d),c(!1)},"aria-label":"切换主题",children:[d?(0,t.jsx)(n.Sun,{size:16}):(0,t.jsx)(i.Moon,{size:16}),d?" 亮色模式":" 暗色模式"]})]}),(0,t.jsxs)("div",{className:"mkt-nav-cta",children:[(0,t.jsx)("button",{className:"mkt-theme-toggle mkt-desktop-only",onClick:()=>h(!d),"aria-label":"切换主题",children:d?(0,t.jsx)(n.Sun,{size:16}):(0,t.jsx)(i.Moon,{size:16})}),(0,t.jsx)(s.default,{href:"/app/",className:"btn btn-primary",children:"开始使用"}),(0,t.jsx)("button",{className:"btn btn-icon sidebar-toggle-btn mkt-mobile-only",onClick:()=>c(!e),"aria-label":"菜单",children:(0,t.jsx)(r.Menu,{size:16})})]})]})})})}let d=[{href:"/",label:"关于"},{href:"/docs/getting-started/",label:"文档"},{href:"/changelog/",label:"更新日志"},{href:"/ping/",label:"网络"},{href:"https://github.com/most-people/most",label:"GitHub",external:!0}];function h(){return(0,t.jsx)("footer",{className:"mkt-footer",children:(0,t.jsx)("div",{className:"mkt-container",children:(0,t.jsxs)("div",{className:"mkt-footer-inner",children:[(0,t.jsx)("div",{className:"mkt-footer-links",children:d.map(e=>(0,t.jsx)(s.default,{href:e.href,...e.external?{target:"_blank",rel:"noopener noreferrer"}:{},children:e.label},e.href))}),(0,t.jsxs)("span",{className:"mkt-footer-copy",children:["© ",new Date().getFullYear()," MOST PEOPLE · MIT License"]})]})})})}e.s(["MarketingLayout",0,function({children:e}){return(0,t.jsxs)("div",{className:"mkt-layout",children:[(0,t.jsx)(c,{}),(0,t.jsx)("main",{className:"mkt-layout-main",children:e}),(0,t.jsx)(h,{})]})}],40983)},89664,e=>{"use strict";let t=(0,e.i(56420).default)("check",[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]]);e.s(["Check",0,t],89664)},14287,e=>{"use strict";var t=e.i(18050),l=e.i(22016),s=e.i(89664),n=e.i(40983);let i=[{title:"无需注册",desc:"打开浏览器即用,没有账号、没有登录、没有隐私收集"},{title:"P2P 直连",desc:"Hyperswarm 网络发现,点对点传输,不限速不限量"},{title:"大文件流式传输",desc:"GB 级文件轻松传,流式处理,内存占用低"},{title:"确定性链接",desc:"相同文件 = 相同 CID,链接可反复校验"},{title:"频道聊天",desc:"P2P 加密即时通讯,创建频道与朋友实时聊天"},{title:"开源免费",desc:"MIT 协议,自托管,数据完全由自己掌控"}],r=[{num:"1",title:"下载桌面客户端",desc:"支持 Windows、macOS 和 Linux。",link:"/download",linkText:"前往下载页"},{num:"2",title:"安装并运行",desc:"安装后打开应用,即可使用 P2P 文件分享和加密聊天。"},{num:"3",title:"开始分享",desc:"发布文件生成链接,或创建频道与朋友聊天。"}],a=[{feature:"注册登录",wechat:"需要",cloud:"需要",mostbox:"不需要"},{feature:"传输限速",wechat:"有限制",cloud:"有限制",mostbox:"不限速"},{feature:"文件大小",wechat:"有限制",cloud:"有限制",mostbox:"无限制"},{feature:"中心化",wechat:"是",cloud:"是",mostbox:"否 (P2P)"},{feature:"私密分享",wechat:"否",cloud:"部分",mostbox:"自行加密"},{feature:"开源",wechat:"否",cloud:"否",mostbox:"MIT 协议"},{feature:"自托管",wechat:"否",cloud:"否",mostbox:"可以"}];e.s(["default",0,function(){return(0,t.jsx)(n.MarketingLayout,{children:(0,t.jsx)("main",{style:{paddingTop:64},children:(0,t.jsxs)("div",{style:{maxWidth:960,margin:"0 auto",padding:"48px 24px 80px"},children:[(0,t.jsx)("h1",{style:{fontSize:32,fontWeight:700,marginBottom:16,textAlign:"center"},children:"MostBox 文档"}),(0,t.jsx)("p",{style:{textAlign:"center",color:"var(--text-secondary)",marginBottom:48,maxWidth:"50ch",margin:"0 auto 48px"},children:"P2P 文件分享应用。基于 Hyperswarm/Hyperdrive 的去中心化文件分发。"}),(0,t.jsxs)("section",{style:{marginBottom:64},children:[(0,t.jsx)("h2",{style:{fontSize:20,fontWeight:600,marginBottom:16},children:"快速开始"}),(0,t.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:24},children:r.map(e=>(0,t.jsxs)("div",{style:{display:"flex",gap:16,alignItems:"flex-start"},children:[(0,t.jsx)("span",{style:{flexShrink:0,width:36,height:36,borderRadius:9999,background:"var(--accent)",color:"#fff",display:"flex",alignItems:"center",justifyContent:"center",fontSize:13,fontWeight:700},children:e.num}),(0,t.jsxs)("div",{style:{flex:1},children:[(0,t.jsx)("h4",{style:{fontSize:15,fontWeight:600,marginBottom:8},children:e.title}),(0,t.jsx)("p",{style:{fontSize:13,color:"var(--text-secondary)"},children:e.desc}),e.link&&(0,t.jsx)("p",{style:{marginTop:8},children:(0,t.jsxs)("a",{href:e.link,target:"_blank",rel:"noopener noreferrer",style:{fontSize:13,color:"var(--accent)"},children:[e.linkText," →"]})})]})]},e.num))})]}),(0,t.jsxs)("section",{style:{marginBottom:64},children:[(0,t.jsx)("h2",{style:{fontSize:20,fontWeight:600,marginBottom:16},children:"核心功能"}),(0,t.jsx)("div",{style:{display:"flex",flexDirection:"column",gap:16},children:i.map(e=>(0,t.jsxs)("div",{style:{display:"flex",gap:12,alignItems:"flex-start"},children:[(0,t.jsx)("span",{style:{color:"var(--accent)",marginTop:2,flexShrink:0},children:(0,t.jsx)(s.Check,{size:16,strokeWidth:2})}),(0,t.jsxs)("div",{children:[(0,t.jsx)("strong",{style:{display:"block",fontWeight:600,marginBottom:2},children:e.title}),(0,t.jsx)("span",{style:{color:"var(--text-secondary)",fontSize:13},children:e.desc})]})]},e.title))})]}),(0,t.jsxs)("section",{style:{marginBottom:64},children:[(0,t.jsx)("h2",{style:{fontSize:20,fontWeight:600,marginBottom:16},children:"为什么选择 MostBox?"}),(0,t.jsx)("div",{style:{overflowX:"auto"},children:(0,t.jsxs)("table",{style:{width:"100%",borderCollapse:"collapse",fontSize:13,fontFamily:"var(--font-mono)"},children:[(0,t.jsx)("thead",{children:(0,t.jsxs)("tr",{style:{borderBottom:"2px solid var(--border-color)"},children:[(0,t.jsx)("th",{style:{textAlign:"left",padding:"12px 16px",fontWeight:600,fontSize:11,color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.05em"}}),(0,t.jsx)("th",{style:{textAlign:"center",padding:"12px 16px",fontWeight:600,fontSize:11,color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.05em"},children:"微信/QQ"}),(0,t.jsx)("th",{style:{textAlign:"center",padding:"12px 16px",fontWeight:600,fontSize:11,color:"var(--text-muted)",textTransform:"uppercase",letterSpacing:"0.05em"},children:"网盘"}),(0,t.jsx)("th",{style:{textAlign:"center",padding:"12px 16px",fontWeight:600,fontSize:11,color:"var(--accent)",textTransform:"uppercase",letterSpacing:"0.05em"},children:"MostBox"})]})}),(0,t.jsx)("tbody",{children:a.map(e=>(0,t.jsxs)("tr",{style:{borderBottom:"1px solid var(--border-color)"},children:[(0,t.jsx)("td",{style:{padding:"12px 16px"},children:e.feature}),(0,t.jsx)("td",{style:{padding:"12px 16px",textAlign:"center",color:"var(--text-secondary)"},children:e.wechat}),(0,t.jsx)("td",{style:{padding:"12px 16px",textAlign:"center",color:"var(--text-secondary)"},children:e.cloud}),(0,t.jsx)("td",{style:{padding:"12px 16px",textAlign:"center",color:"var(--accent)",fontWeight:600},children:e.mostbox})]},e.feature))})]})})]}),(0,t.jsx)("div",{style:{marginTop:48},children:(0,t.jsx)(l.default,{href:"/changelog/",style:{color:"var(--accent)",fontSize:14},children:"查看更新日志 →"})})]})})})}])}]);
@@ -1 +0,0 @@
1
- (globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,35965,e=>{"use strict";let t=(0,e.i(56420).default)("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"}]]);e.s(["Sun",0,t],35965)},96699,e=>{"use strict";let t=(0,e.i(56420).default)("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"}]]);e.s(["Moon",0,t],96699)},93583,e=>{"use strict";let t=(0,e.i(56420).default)("menu",[["path",{d:"M4 5h16",key:"1tepv9"}],["path",{d:"M4 12h16",key:"1lakjw"}],["path",{d:"M4 19h16",key:"1djgab"}]]);e.s(["Menu",0,t],93583)},59665,5142,e=>{"use strict";var t=e.i(18050),a=e.i(71645),s=e.i(93583);function l(e=!1,t={}){let[s,i]=(0,a.useState)(e),c=(0,a.useCallback)(()=>{i(e=>e||(t.onOpen?.(),!0))},[t.onOpen]),d=(0,a.useCallback)(()=>{i(e=>e?(t.onClose?.(),!1):e)},[t.onClose]);return[s,{open:c,close:d,toggle:(0,a.useCallback)(()=>{s?d():c()},[d,c,s]),set:i}]}e.s(["useDisclosure",0,l],5142);let i=(0,a.createContext)(null);e.s(["default",0,function({sidebar:e,headerTitle:c,headerRight:d,children:n}){let[h,r]=l(!1),[o,u]=(0,a.useState)(!1),p=function(e,{getInitialValueInEffect:t}={getInitialValueInEffect:!0}){let[s,l]=(0,a.useState)(t?void 0:!!("u">typeof window&&"matchMedia"in window)&&window.matchMedia(e).matches);return(0,a.useEffect)(()=>{try{if("matchMedia"in window){let t=window.matchMedia(e);l(t.matches);let a=e=>l(e.matches);return t.addEventListener("change",a),()=>{t.removeEventListener("change",a)}}}catch(e){return}},[e]),s||!1}("(max-width: 768px)");return(0,t.jsx)(i.Provider,{value:{closeSidebar:r.close},children:(0,t.jsxs)("div",{className:"app-layout",children:[(0,t.jsx)("div",{className:`sidebar-overlay ${h?"visible":""}`,onClick:()=>r.close()}),(0,t.jsx)("div",{className:`sidebar ${h?"open":""} ${o?"collapsed":""}`,children:e({closeSidebar:r.close})}),(0,t.jsxs)("div",{className:"main-content",children:[(0,t.jsxs)("header",{className:"app-header",children:[(0,t.jsxs)("div",{className:"header-left",children:[(0,t.jsx)("button",{onClick:()=>{p?r.toggle():u(!o)},className:"btn btn-icon sidebar-toggle-btn","aria-label":p?"打开菜单":o?"展开侧边栏":"收起侧边栏",children:(0,t.jsx)(s.Menu,{size:16})}),c]}),(0,t.jsx)("div",{className:"header-right",children:d})]}),n]})]})})}],59665)},6537,e=>{"use strict";let t=(0,e.i(56420).default)("lock",[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]]);e.s(["Lock",0,t],6537)},8734,e=>{"use strict";let t=(0,e.i(56420).default)("copy",[["rect",{width:"14",height:"14",x:"8",y:"8",rx:"2",ry:"2",key:"17jyea"}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2",key:"zix9uf"}]]);e.s(["Copy",0,t],8734)},82022,e=>{"use strict";let t=(0,e.i(56420).default)("external-link",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);e.s(["ExternalLink",0,t],82022)},70904,e=>{"use strict";let t=(0,e.i(56420).default)("wallet",[["path",{d:"M19 7V4a1 1 0 0 0-1-1H5a2 2 0 0 0 0 4h15a1 1 0 0 1 1 1v4h-3a2 2 0 0 0 0 4h3a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1",key:"18etb6"}],["path",{d:"M3 5v14a2 2 0 0 0 2 2h15a1 1 0 0 0 1-1v-4",key:"xoc0q4"}]]);e.s(["Wallet",0,t],70904)}]);
@@ -1,4 +0,0 @@
1
- .milkdown .milkdown-ai-instruction{z-index:10;position:absolute}.milkdown .milkdown-ai-instruction[data-show=false]{display:none}.milkdown .milkdown-ai-instruction>.ai-instruction{background:var(--crepe-color-surface);width:360px;box-shadow:var(--crepe-shadow-2);font-family:var(--crepe-font-default);color:var(--crepe-color-on-background);border-radius:12px;font-size:14px;overflow:hidden}.milkdown .ai-instruction-input{background:var(--crepe-color-background);border:1px solid color-mix(in srgb, var(--crepe-color-primary) 35%, transparent);border-radius:999px;align-items:center;gap:8px;margin:8px;padding:4px 4px 4px 12px;display:flex}.milkdown .ai-instruction-input-prefix{color:var(--crepe-color-primary);flex-shrink:0;align-items:center;display:inline-flex}.milkdown .ai-instruction-input-prefix svg{width:18px;height:18px;color:var(--crepe-color-primary);fill:var(--crepe-color-primary)}.milkdown .ai-instruction-input-field{min-width:0;color:var(--crepe-color-on-background);background:0 0;border:none;outline:none;flex:1;padding:4px 0;font-family:inherit;font-size:14px;line-height:20px}.milkdown .ai-instruction-input-field::placeholder{color:var(--crepe-color-outline)}.milkdown .ai-instruction-submit{background:var(--crepe-color-primary);width:28px;height:28px;color:var(--crepe-color-on-inverse);cursor:pointer;border:none;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;padding:0;display:inline-flex}.milkdown .ai-instruction-submit svg{width:16px;height:16px;color:var(--crepe-color-on-inverse);fill:var(--crepe-color-on-inverse)}.milkdown .ai-instruction-submit:hover:not(:disabled){background:color-mix(in srgb, var(--crepe-color-primary) 85%, white)}.milkdown .ai-instruction-submit:disabled{opacity:.4;cursor:not-allowed}.milkdown .ai-instruction-list{max-height:320px;padding-bottom:6px;overflow-y:auto}.milkdown .ai-instruction-back{appearance:none;text-align:left;cursor:pointer;width:100%;color:var(--crepe-color-outline);-webkit-user-select:none;user-select:none;background:0 0;border:none;align-items:center;gap:6px;padding:6px 12px 4px;font-family:inherit;font-size:12px;font-weight:500;display:flex}.milkdown .ai-instruction-back:hover{color:var(--crepe-color-on-background)}.milkdown .ai-instruction-back-icon{display:inline-flex}.milkdown .ai-instruction-back-icon svg{stroke:currentColor;width:16px;height:16px}.milkdown .ai-instruction-section{flex-direction:column;display:flex}.milkdown .ai-instruction-section-header{letter-spacing:.08em;color:var(--crepe-color-outline);text-transform:uppercase;-webkit-user-select:none;user-select:none;padding:6px 16px 4px;font-size:11px;font-weight:600}.milkdown .ai-instruction-item{cursor:pointer;-webkit-user-select:none;user-select:none;color:var(--crepe-color-on-background);align-items:center;gap:12px;padding:8px 16px;display:flex}.milkdown .ai-instruction-item.active{background:var(--crepe-color-hover)}.milkdown .ai-instruction-item-icon{flex-shrink:0;justify-content:center;align-items:center;width:20px;height:20px;display:inline-flex}.milkdown .ai-instruction-item-icon svg{width:18px;height:18px;color:var(--crepe-color-on-surface-variant);fill:var(--crepe-color-on-surface-variant);stroke:var(--crepe-color-on-surface-variant)}.milkdown .ai-instruction-item-label{text-overflow:ellipsis;white-space:nowrap;flex:1;font-size:14px;line-height:20px;overflow:hidden}.milkdown .ai-instruction-item-label mark{background:var(--crepe-color-secondary);color:inherit;border-radius:2px;padding:0 1px}.milkdown .ai-instruction-item-arrow{color:var(--crepe-color-outline);flex-shrink:0;display:inline-flex}.milkdown .ai-instruction-item-arrow svg{stroke:currentColor;width:14px;height:14px}.milkdown .ai-instruction-item-prompt .ai-instruction-item-label{color:var(--crepe-color-primary)}.milkdown .ai-instruction-item-prompt .ai-instruction-item-icon svg{color:var(--crepe-color-primary);fill:var(--crepe-color-primary)}.milkdown .ai-instruction-item-quote{font-weight:500}.milkdown .ai-instruction-item-shortcut{background:var(--crepe-color-surface-low);min-width:24px;height:20px;color:var(--crepe-color-outline);border-radius:4px;flex-shrink:0;justify-content:center;align-items:center;padding:0 4px;display:inline-flex}.milkdown .ai-instruction-item-shortcut svg{width:14px;height:14px;color:var(--crepe-color-outline);fill:var(--crepe-color-outline)}.milkdown .milkdown-ai-streaming-indicator{border:1px solid color-mix(in srgb, var(--crepe-color-primary) 20%, transparent);background:var(--crepe-color-surface);vertical-align:middle;white-space:nowrap;-webkit-user-select:none;user-select:none;font-family:var(--crepe-font-default);border-radius:999px;align-items:center;gap:8px;margin:4px 0;padding:4px 6px 4px 12px;display:inline-flex}.milkdown .milkdown-ai-streaming-spinner{border:1.5px solid color-mix(in srgb, var(--crepe-color-primary) 25%, transparent);border-top-color:var(--crepe-color-primary);will-change:transform;border-radius:50%;flex-shrink:0;width:14px;height:14px}.milkdown .milkdown-ai-streaming-label{color:var(--crepe-color-on-background);font-size:13px;line-height:18px}.milkdown .milkdown-ai-streaming-esc{font-family:var(--crepe-font-code,ui-monospace, monospace);background:var(--crepe-color-surface-low);color:var(--crepe-color-outline);border-radius:999px;padding:4px 8px;font-size:11px;line-height:1}.milkdown .milkdown-ai-diff-actions{z-index:11;background:var(--crepe-color-surface);border:1px solid color-mix(in srgb, var(--crepe-color-primary) 18%, transparent);box-shadow:var(--crepe-shadow-2);font-family:var(--crepe-font-default);-webkit-user-select:none;user-select:none;border-radius:999px;align-items:center;gap:4px;padding:6px;display:flex;position:fixed;bottom:24px;left:50%;transform:translate(-50%)}.milkdown .milkdown-ai-diff-actions[data-show=false]{display:none}.milkdown .milkdown-ai-diff-actions-btn{color:var(--crepe-color-on-background);cursor:pointer;white-space:nowrap;background:0 0;border:none;border-radius:999px;align-items:center;gap:6px;padding:8px 14px;font-family:inherit;font-size:13px;font-weight:500;line-height:1;display:inline-flex}.milkdown .milkdown-ai-diff-actions-btn:hover{background:var(--crepe-color-hover)}.milkdown .milkdown-ai-diff-actions-btn:disabled{opacity:.4;cursor:not-allowed}.milkdown .milkdown-ai-diff-actions-btn:disabled:hover{background:0 0}.milkdown .milkdown-ai-diff-actions-icon{justify-content:center;align-items:center;width:18px;height:18px;display:inline-flex}.milkdown .milkdown-ai-diff-actions-icon svg{color:currentColor;fill:currentColor;width:16px;height:16px}.milkdown .milkdown-ai-diff-actions-btn-retry{color:var(--crepe-color-on-surface-variant)}.milkdown .milkdown-ai-diff-actions-btn-reject{color:var(--crepe-color-diff-removed-text,#ba1a1a);background:color-mix(in srgb, var(--crepe-color-diff-removed,#ef4444) 8%, transparent)}.milkdown .milkdown-ai-diff-actions-btn-reject:hover{background:color-mix(in srgb, var(--crepe-color-diff-removed,#ef4444) 16%, transparent)}.milkdown .milkdown-ai-diff-actions-btn-accept{color:var(--crepe-color-diff-added-text,#166534);background:color-mix(in srgb, var(--crepe-color-diff-added,#22c55e) 12%, transparent)}.milkdown .milkdown-ai-diff-actions-btn-accept:hover{background:color-mix(in srgb, var(--crepe-color-diff-added,#22c55e) 22%, transparent)}.milkdown .milkdown-ai-diff-actions-shortcut{background:color-mix(in srgb, var(--crepe-color-diff-added,#22c55e) 14%, transparent);font-family:var(--crepe-font-code,ui-monospace, monospace);color:inherit;border-radius:4px;align-items:center;gap:2px;margin-left:4px;padding:3px 6px;font-size:11px;display:inline-flex}.milkdown .milkdown-ai-diff-actions-shortcut-icon{display:inline-flex}.milkdown .milkdown-ai-diff-actions-shortcut-icon svg{color:currentColor;fill:currentColor;width:12px;height:12px}
2
-
3
- .milkdown{--crepe-color-background:#fff;--crepe-color-on-background:#000;--crepe-color-surface:#f7f7f7;--crepe-color-surface-low:#ededed;--crepe-color-on-surface:#1c1c1c;--crepe-color-on-surface-variant:#4d4d4d;--crepe-color-outline:#a8a8a8;--crepe-color-primary:#333;--crepe-color-secondary:#cfcfcf;--crepe-color-on-secondary:#000;--crepe-color-inverse:#f0f0f0;--crepe-color-on-inverse:#1a1a1a;--crepe-color-inline-code:#ba1a1a;--crepe-color-error:#ba1a1a;--crepe-color-hover:#e0e0e0;--crepe-color-selected:#d5d5d5;--crepe-color-inline-area:#cacaca;--crepe-font-title:"Noto Serif", Cambria, "Times New Roman", Times, serif;--crepe-font-default:"Noto Sans", Arial, Helvetica, sans-serif;--crepe-font-code:"Space Mono", Fira Code, Menlo, Monaco, "Courier New", Courier, monospace;--crepe-shadow-1:0px 1px 3px 1px #00000026, 0px 1px 2px 0px #0000004d;--crepe-shadow-2:0px 2px 6px 2px #00000026, 0px 1px 2px 0px #0000004d}
4
- .note-page{height:calc(100vh - 64px);min-height:0;padding:16px;overflow:hidden}.note-theme-wrap,.note-header-actions{align-items:center;gap:8px;min-width:0;display:flex}.note-header-title{align-items:baseline;gap:10px;min-width:0;display:flex}.note-header-title span{color:var(--text-secondary);white-space:nowrap;font-size:12px}.note-more{flex:none;position:relative}.note-more-trigger{position:relative}.note-more-menu{z-index:50;border:1px solid var(--glass-border);background:var(--glass-bg-solid);width:280px;max-width:calc(100vw - 24px);box-shadow:var(--shadow-lg);border-radius:8px;flex-direction:column;gap:4px;padding:8px;display:flex;position:absolute;top:calc(100% + 8px);right:0}.note-sync-status,.note-more-item{border-radius:8px;align-items:center;gap:10px;min-width:0;display:flex}.note-sync-status{color:var(--text-secondary);background:var(--glass-bg-subtle);padding:10px}.note-sync-status.conflict{color:var(--warning)}.note-sync-status-icon{width:30px;height:30px;color:var(--accent);background:var(--accent-soft);border-radius:8px;flex:none;justify-content:center;align-items:center;display:flex}.note-sync-status.conflict .note-sync-status-icon{color:var(--warning);background:#ff950024}.note-sync-status span:last-child{flex-direction:column;gap:2px;min-width:0;display:flex}.note-sync-status strong,.note-sync-status small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.note-sync-status strong{color:var(--text-primary);font-size:13px}.note-sync-status small{color:inherit;font-size:12px}.note-more-item{width:100%;min-height:36px;color:var(--text-secondary);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;padding:8px 10px;font-size:13px;font-weight:600}.note-more-item:hover:not(:disabled){background:var(--glass-bg-subtle);color:var(--text-primary)}.note-more-item:disabled{cursor:not-allowed;opacity:.45}.note-more-separator{background:var(--glass-border);height:1px;margin:4px 2px}.app-layout:has(.note-browser-page) .sidebar{width:320px;overflow:hidden}.app-layout:has(.note-browser-page) .sidebar.collapsed{width:0}.note-workspace{border:1px solid var(--glass-border);background:var(--glass-bg-heavy);height:100%;box-shadow:var(--shadow-sm);border-radius:8px;display:flex;overflow:hidden}.note-edit-workspace{border:1px solid var(--glass-border);background:var(--glass-bg-heavy);height:100%;min-height:0;box-shadow:var(--shadow-sm);border-radius:8px;overflow:hidden}.note-list-panel,.note-editor-panel{background:var(--glass-bg-solid);min-width:0;min-height:0}.note-list-panel{border-right:1px solid var(--glass-border)}.note-sidebar-list{background:0 0;border-right:0;flex:1;min-height:0;padding:12px 8px}.note-sidebar-list .note-list-header{padding:0 4px}.note-sidebar-list .note-list-header h3{max-width:180px;font-size:16px}.note-sidebar-list .note-search{height:36px}.note-sidebar-list .note-breadcrumbs{min-height:30px;margin:6px 0;padding:0 2px}.note-sidebar-list .note-list{padding-bottom:6px}.note-sidebar-list .note-list-item-main{grid-template-columns:30px minmax(0,1fr) auto;padding:8px 6px}.note-sidebar-list .note-list-icon{width:30px;height:30px}.note-sidebar-list .note-list-date{display:none}.note-sidebar-list .note-list-actions{padding-right:4px}.note-sidebar-list .note-empty-state{min-height:180px;padding:16px 8px}.note-list-header{justify-content:space-between;align-items:center;gap:12px;display:flex}.note-count{color:var(--text-muted);font-size:12px;font-weight:600}.note-list-panel{flex-direction:column;padding:16px 12px;display:flex;overflow:hidden}.note-list-header{margin-bottom:12px}.note-list-header h3{max-width:220px;color:var(--text-primary);text-overflow:ellipsis;white-space:nowrap;font-size:18px;font-weight:700;overflow:hidden}.note-kicker{color:var(--text-muted);letter-spacing:0;margin-bottom:3px;font-size:11px;font-weight:700;display:block}.note-search{border:1px solid var(--glass-border);background:var(--glass-bg-subtle);height:38px;color:var(--text-secondary);border-radius:8px;flex:none;align-items:center;gap:8px;padding:0 10px;display:flex}.note-search .input{background:0 0;border:0;min-width:0;padding-left:0}.note-search .input:focus{box-shadow:none}.note-breadcrumbs{min-height:34px;color:var(--text-muted);flex:none;align-items:center;gap:6px;margin:8px 0;font-size:12px;display:flex;overflow-x:auto}.note-breadcrumbs button{color:var(--text-secondary);cursor:pointer;font:inherit;white-space:nowrap;background:0 0;border:0;flex:none}.note-breadcrumbs button:hover{color:var(--accent)}.note-list{flex-direction:column;gap:4px;min-height:0;display:flex;overflow:auto}.note-list-item{transition:background var(--transition-fast), border-color var(--transition-fast);background:0 0;border:1px solid #0000;border-radius:8px;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:6px;display:grid}.note-list-item:hover,.note-list-item.active{border-color:var(--glass-border);background:var(--glass-bg-subtle)}.note-list-item.active{border-color:var(--accent);background:var(--accent-soft)}.note-list-item-main{min-width:0;color:var(--text-primary);text-align:left;background:0 0;border:0;grid-template-columns:34px minmax(0,1fr) auto;align-items:center;gap:8px;padding:9px 8px;display:grid}.note-list-icon{width:34px;height:34px;color:var(--accent);background:var(--accent-soft);border-radius:8px;justify-content:center;align-items:center;display:flex}.note-list-item-main.folder .note-list-icon{color:var(--warning);background:#ff950024}.note-list-copy{flex-direction:column;gap:2px;min-width:0;display:flex}.note-list-name,.note-list-preview,.note-list-date{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.note-list-name{color:var(--text-primary);font-size:13px;font-weight:700}.note-list-preview,.note-list-date{color:var(--text-secondary);font-size:12px}.note-list-date{text-align:right;max-width:58px}.note-list-actions{opacity:0;transition:opacity var(--transition-fast);align-items:center;gap:4px;padding-right:6px;display:flex}.note-list-item:hover .note-list-actions,.note-list-item:focus-within .note-list-actions,.note-list-item.active .note-list-actions{opacity:1}.note-list-actions .btn-icon{border-radius:8px;width:28px;height:28px}.note-editor-panel{flex-direction:column;flex:1;display:flex;overflow:hidden}.note-editor-panel-standalone{height:100%}.note-editor-panel-header{border-bottom:1px solid var(--glass-border);background:var(--glass-bg-heavy);flex:none;justify-content:space-between;align-items:flex-start;gap:16px;padding:18px 20px 14px;display:flex}.note-editor-title-area{flex:1;min-width:0}.note-editor-title-area h3{color:var(--text-primary);text-overflow:ellipsis;white-space:nowrap;font-size:22px;font-weight:750;line-height:1.25;overflow:hidden}.note-title-input{width:100%;color:var(--text-primary);font-family:var(--font-sans);background:0 0;border:0;outline:none;padding:0;font-size:24px;font-weight:750;line-height:1.25}.note-title-input::placeholder{color:var(--text-muted)}.note-editor-info{color:var(--text-secondary);align-items:center;gap:8px;margin-top:8px;font-size:12px;display:flex;overflow-x:auto}.note-editor-info span{background:var(--glass-bg-subtle);border-radius:8px;flex:none;padding:3px 7px}.note-editor-actions,.note-editor-fields{align-items:center;gap:8px;display:flex}.note-editor-actions{flex-wrap:wrap;justify-content:flex-end}.note-editor-fields{border-bottom:1px solid var(--glass-border);background:var(--glass-bg-solid);flex:none;padding:12px 20px}.note-editor-fields .input{max-width:420px}.note-editor-frame{background:var(--bg-secondary);flex:1;min-height:0;overflow:auto}.note-editor-frame.reading{background:var(--glass-bg-solid)}.milkdown-editor{min-height:100%}.milkdown-editor .milkdown{height:100%;color:var(--text-primary);background:0 0}.milkdown-editor .ProseMirror{width:min(760px,100%);min-height:calc(100vh - 196px);color:var(--text-primary);background:0 0;outline:none;margin:0 auto;padding:42px 36px 72px;font-size:15px;line-height:1.75}.milkdown-editor .ProseMirror h1,.milkdown-editor .ProseMirror h2,.milkdown-editor .ProseMirror h3{line-height:1.25}.milkdown-editor .crepe-placeholder{color:var(--text-muted)}.milkdown-editor .crepe-placeholder:before{color:var(--text-secondary)}.milkdown-editor .link-preview,.milkdown-editor .milkdown-link-preview{background:var(--glass-bg-heavy);color:var(--text-primary)}.note-empty-state,.note-editor-loading,.note-editor-empty{min-height:260px;color:var(--text-secondary);text-align:center;flex-direction:column;justify-content:center;align-items:center;gap:12px;padding:24px;display:flex}.note-editor-empty{background:var(--glass-bg-solid);flex:1}.note-editor-empty h3{color:var(--text-primary);font-size:18px}.note-editor-empty-icon{width:56px;height:56px;color:var(--accent);background:var(--accent-soft);border-radius:8px;justify-content:center;align-items:center;display:flex}.note-empty-state.editor-error{flex:1}.note-rename-modal{flex-direction:column;gap:12px;width:min(420px,92vw);display:flex}@media (max-width:1180px){.note-list-date{display:none}}@media (max-width:900px){.note-page{overflow:auto}.note-workspace,.note-edit-workspace{height:auto;min-height:100%}.note-list-panel{border-right:0;border-bottom:1px solid var(--glass-border)}.note-sidebar-list{border-bottom:0}.note-editor-panel{min-height:70vh}}@media (max-width:768px){.note-page{height:calc(100vh - 56px);padding:10px}.app-layout:has(.note-browser-page) .sidebar{width:min(320px,100vw - 32px)}.note-page.has-editor .note-list-panel{display:none}.note-theme-wrap,.note-header-actions{gap:6px}.note-header-title span{display:none}.note-header-actions .btn{padding:9px 10px}.note-more-menu{right:-4px}.note-editor-panel-header{flex-direction:column;padding:14px}.note-editor-actions{justify-content:flex-start;width:100%}.note-editor-fields{flex-direction:column;align-items:stretch;padding:12px 14px}.note-editor-fields .input{max-width:none}.note-list-item{grid-template-columns:minmax(0,1fr)}.note-list-actions{opacity:1;justify-content:flex-end;padding:0 8px 8px}.milkdown-editor .ProseMirror{min-height:calc(100vh - 280px);padding:28px 18px 56px}}