@awiki/dsh-plugin 0.3.5 → 0.3.6

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 (64) hide show
  1. package/README.md +29 -14
  2. package/README.zh.md +24 -13
  3. package/cordis.patch.yml +7 -4
  4. package/lib/client.js +569 -95
  5. package/lib/client.js.map +1 -1
  6. package/lib/index.js +402 -98
  7. package/lib/provider.js +1 -1
  8. package/lib/{sdk-adapter-CDLTgHJA.mjs → sdk-adapter--trNlr-T.mjs} +34 -1
  9. package/lib/typert.host.js +97 -42
  10. package/lib/typert.remote-client.d.ts +3 -1
  11. package/lib/typert.remote-client.d.ts.map +1 -1
  12. package/lib/typert.remote-client.js +97 -42
  13. package/lib/types/client/AwikiMail.d.ts +1 -1
  14. package/lib/types/client/AwikiMail.d.ts.map +1 -1
  15. package/lib/types/client/AwikiMail.js +130 -6
  16. package/lib/types/client/AwikiMail.js.map +1 -1
  17. package/lib/types/client/AwikiOverlay.d.ts.map +1 -1
  18. package/lib/types/client/AwikiOverlay.js +1 -1
  19. package/lib/types/client/AwikiOverlay.js.map +1 -1
  20. package/lib/types/client/controller.d.ts +7 -1
  21. package/lib/types/client/controller.d.ts.map +1 -1
  22. package/lib/types/client/controller.js +41 -15
  23. package/lib/types/client/controller.js.map +1 -1
  24. package/lib/types/client/index.d.ts.map +1 -1
  25. package/lib/types/client/index.js +2 -0
  26. package/lib/types/client/index.js.map +1 -1
  27. package/lib/types/client/mail-attachment.d.ts +40 -0
  28. package/lib/types/client/mail-attachment.d.ts.map +1 -0
  29. package/lib/types/client/mail-attachment.js +186 -0
  30. package/lib/types/client/mail-attachment.js.map +1 -0
  31. package/lib/types/client/settings-locales.js +8 -8
  32. package/lib/types/client/settings-locales.js.map +1 -1
  33. package/lib/types/client/slots.d.ts +5 -1
  34. package/lib/types/client/slots.d.ts.map +1 -1
  35. package/lib/types/index.d.ts +18 -6
  36. package/lib/types/index.d.ts.map +1 -1
  37. package/lib/types/index.js +244 -68
  38. package/lib/types/index.js.map +1 -1
  39. package/lib/types/mail.d.ts +28 -2
  40. package/lib/types/mail.d.ts.map +1 -1
  41. package/lib/types/mail.js +78 -2
  42. package/lib/types/mail.js.map +1 -1
  43. package/lib/types/profile-state.d.ts +6 -0
  44. package/lib/types/profile-state.d.ts.map +1 -1
  45. package/lib/types/profile-state.js +10 -0
  46. package/lib/types/profile-state.js.map +1 -1
  47. package/lib/types/provider-api.d.ts +32 -4
  48. package/lib/types/provider-api.d.ts.map +1 -1
  49. package/lib/types/sdk-adapter.d.ts +4 -3
  50. package/lib/types/sdk-adapter.d.ts.map +1 -1
  51. package/lib/types/sdk-adapter.js +45 -1
  52. package/lib/types/sdk-adapter.js.map +1 -1
  53. package/lib/types/sent-mail-store.d.ts +7 -2
  54. package/lib/types/sent-mail-store.d.ts.map +1 -1
  55. package/lib/types/sent-mail-store.js +125 -23
  56. package/lib/types/sent-mail-store.js.map +1 -1
  57. package/lib/types/tools.d.ts +1 -1
  58. package/lib/types/tools.d.ts.map +1 -1
  59. package/lib/types/tools.js +20 -4
  60. package/lib/types/tools.js.map +1 -1
  61. package/lib/types/types.d.ts +39 -1
  62. package/lib/types/types.d.ts.map +1 -1
  63. package/lib/types/types.js.map +1 -1
  64. package/package.json +15 -17
package/lib/client.js CHANGED
@@ -589,7 +589,7 @@ window.__ModuleLoader__.load({
589
589
  const ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;
590
590
  const cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/;
591
591
  const cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;
592
- const base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
592
+ const base64$1 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;
593
593
  const base64url = /^[A-Za-z0-9_-]*$/;
594
594
  const httpProtocol = /^https?$/;
595
595
  const e164 = /^\+[1-9]\d{6,14}$/;
@@ -1326,7 +1326,7 @@ window.__ModuleLoader__.load({
1326
1326
  }
1327
1327
  }
1328
1328
  const $ZodBase64 = /*@__PURE__*/ $constructor("$ZodBase64", (inst, def) => {
1329
- def.pattern ?? (def.pattern = base64);
1329
+ def.pattern ?? (def.pattern = base64$1);
1330
1330
  $ZodStringFormat.init(inst, def);
1331
1331
  inst._zod.bag.contentEncoding = "base64";
1332
1332
  inst._zod.check = (payload) => {
@@ -4400,6 +4400,51 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4400
4400
  "bytesBase64": string().readonly()
4401
4401
  }).readonly()
4402
4402
  })]);
4403
+ const _awiki_dsh_plugin_awiki_downloadMailAttachment_parameter_0$schema = object({
4404
+ "localMessageId": intersection(string(), unknown()).readonly(),
4405
+ "attachmentIndex": number().readonly()
4406
+ });
4407
+ const _awiki_dsh_plugin_awiki_downloadMailAttachment_result$schema = union([object({
4408
+ "ok": literal(false).readonly(),
4409
+ "error": object({
4410
+ "code": union([
4411
+ literal("not-registered"),
4412
+ literal("signed-out"),
4413
+ literal("already-registered"),
4414
+ literal("invalid-request"),
4415
+ literal("invalid-otp"),
4416
+ literal("challenge-expired"),
4417
+ literal("handle-unavailable"),
4418
+ literal("not-found"),
4419
+ literal("forbidden"),
4420
+ literal("identity-recovery-required"),
4421
+ literal("conflict"),
4422
+ literal("state-in-use"),
4423
+ literal("rate-limited"),
4424
+ literal("group-membership-required"),
4425
+ literal("group-identity-stale"),
4426
+ literal("attachment-too-large"),
4427
+ literal("summary-unavailable"),
4428
+ literal("summary-timeout"),
4429
+ literal("summary-cancelled"),
4430
+ literal("summary-invalid-output"),
4431
+ literal("summary-failed"),
4432
+ literal("delivery-unknown"),
4433
+ literal("network"),
4434
+ literal("remote")
4435
+ ]).readonly(),
4436
+ "message": string().readonly()
4437
+ }).readonly()
4438
+ }), object({
4439
+ "ok": literal(true).readonly(),
4440
+ "value": object({
4441
+ "fileName": string().readonly(),
4442
+ "contentType": string().readonly(),
4443
+ "sizeBytes": number().readonly(),
4444
+ "sha256": string().readonly(),
4445
+ "bytesBase64": string().readonly()
4446
+ }).readonly()
4447
+ })]);
4403
4448
  const _awiki_dsh_plugin_awiki_getConfig_result$schema = union([object({
4404
4449
  "ok": literal(false).readonly(),
4405
4450
  "error": object({
@@ -4434,8 +4479,12 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
4434
4479
  }), object({
4435
4480
  "ok": literal(true).readonly(),
4436
4481
  "value": object({
4482
+ "tenantDomain": string().readonly(),
4437
4483
  "pollIntervalMs": number().readonly(),
4438
4484
  "attachmentMaxBytes": number().readonly(),
4485
+ "mailAttachmentMaxCount": number().readonly(),
4486
+ "mailAttachmentMaxBytes": number().readonly(),
4487
+ "mailAttachmentTotalMaxBytes": number().readonly(),
4439
4488
  "profileName": string().readonly().optional(),
4440
4489
  "legacySharedStateDetected": boolean().readonly().optional()
4441
4490
  }).readonly()
@@ -5814,7 +5863,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
5814
5863
  "to": array(string()).readonly(),
5815
5864
  "cc": array(string()).readonly().optional(),
5816
5865
  "subject": string().readonly(),
5817
- "bodyText": string().readonly()
5866
+ "bodyText": string().readonly(),
5867
+ "attachments": array(object({
5868
+ "fileName": string().readonly(),
5869
+ "contentType": string().readonly(),
5870
+ "sizeBytes": number().readonly(),
5871
+ "bytesBase64": string().readonly()
5872
+ })).readonly().optional()
5818
5873
  });
5819
5874
  const _awiki_dsh_plugin_awiki_sendMail_result$schema = union([object({
5820
5875
  "ok": literal(false).readonly(),
@@ -6284,7 +6339,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6284
6339
  },
6285
6340
  sourceLocation: {
6286
6341
  "file": "packages/dsh-awiki/src/index.ts",
6287
- "line": 117,
6342
+ "line": 119,
6288
6343
  "column": 9
6289
6344
  }
6290
6345
  },
@@ -6311,7 +6366,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6311
6366
  },
6312
6367
  sourceLocation: {
6313
6368
  "file": "packages/dsh-awiki/src/index.ts",
6314
- "line": 147,
6369
+ "line": 149,
6315
6370
  "column": 3
6316
6371
  }
6317
6372
  },
@@ -6338,7 +6393,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6338
6393
  },
6339
6394
  sourceLocation: {
6340
6395
  "file": "packages/dsh-awiki/src/index.ts",
6341
- "line": 205,
6396
+ "line": 212,
6342
6397
  "column": 3
6343
6398
  }
6344
6399
  },
@@ -6365,7 +6420,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6365
6420
  },
6366
6421
  sourceLocation: {
6367
6422
  "file": "packages/dsh-awiki/src/index.ts",
6368
- "line": 132,
6423
+ "line": 134,
6369
6424
  "column": 9
6370
6425
  }
6371
6426
  },
@@ -6392,7 +6447,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6392
6447
  },
6393
6448
  sourceLocation: {
6394
6449
  "file": "packages/dsh-awiki/src/index.ts",
6395
- "line": 126,
6450
+ "line": 128,
6396
6451
  "column": 9
6397
6452
  }
6398
6453
  },
@@ -6419,7 +6474,34 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6419
6474
  },
6420
6475
  sourceLocation: {
6421
6476
  "file": "packages/dsh-awiki/src/index.ts",
6422
- "line": 187,
6477
+ "line": 189,
6478
+ "column": 9
6479
+ }
6480
+ },
6481
+ {
6482
+ id: "@awiki/dsh-plugin#awiki/downloadMailAttachment",
6483
+ service: "awiki",
6484
+ namespace: "awiki",
6485
+ method: "downloadMailAttachment",
6486
+ invocation: { kind: "direct" },
6487
+ parameters: [{
6488
+ name: "request",
6489
+ wire: "request",
6490
+ source: "json",
6491
+ codec: {
6492
+ mode: "strict",
6493
+ typeSymbol: "@awiki/dsh-plugin/types#AwikiMailAttachmentDownloadRequest",
6494
+ schema: _awiki_dsh_plugin_awiki_downloadMailAttachment_parameter_0$schema
6495
+ }
6496
+ }],
6497
+ result: {
6498
+ mode: "strict",
6499
+ typeSymbol: "@awiki/dsh-plugin/types#AwikiResult",
6500
+ schema: _awiki_dsh_plugin_awiki_downloadMailAttachment_result$schema
6501
+ },
6502
+ sourceLocation: {
6503
+ "file": "packages/dsh-awiki/src/index.ts",
6504
+ "line": 207,
6423
6505
  "column": 9
6424
6506
  }
6425
6507
  },
@@ -6437,7 +6519,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6437
6519
  },
6438
6520
  sourceLocation: {
6439
6521
  "file": "packages/dsh-awiki/src/index.ts",
6440
- "line": 76,
6522
+ "line": 78,
6441
6523
  "column": 3
6442
6524
  }
6443
6525
  },
@@ -6455,7 +6537,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6455
6537
  },
6456
6538
  sourceLocation: {
6457
6539
  "file": "packages/dsh-awiki/src/index.ts",
6458
- "line": 156,
6540
+ "line": 158,
6459
6541
  "column": 3
6460
6542
  }
6461
6543
  },
@@ -6482,7 +6564,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6482
6564
  },
6483
6565
  sourceLocation: {
6484
6566
  "file": "packages/dsh-awiki/src/index.ts",
6485
- "line": 135,
6567
+ "line": 137,
6486
6568
  "column": 3
6487
6569
  }
6488
6570
  },
@@ -6509,7 +6591,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6509
6591
  },
6510
6592
  sourceLocation: {
6511
6593
  "file": "packages/dsh-awiki/src/index.ts",
6512
- "line": 167,
6594
+ "line": 169,
6513
6595
  "column": 3
6514
6596
  }
6515
6597
  },
@@ -6527,7 +6609,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6527
6609
  },
6528
6610
  sourceLocation: {
6529
6611
  "file": "packages/dsh-awiki/src/index.ts",
6530
- "line": 79,
6612
+ "line": 81,
6531
6613
  "column": 9
6532
6614
  }
6533
6615
  },
@@ -6554,7 +6636,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6554
6636
  },
6555
6637
  sourceLocation: {
6556
6638
  "file": "packages/dsh-awiki/src/index.ts",
6557
- "line": 170,
6639
+ "line": 172,
6558
6640
  "column": 3
6559
6641
  }
6560
6642
  },
@@ -6572,7 +6654,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6572
6654
  },
6573
6655
  sourceLocation: {
6574
6656
  "file": "packages/dsh-awiki/src/index.ts",
6575
- "line": 190,
6657
+ "line": 192,
6576
6658
  "column": 3
6577
6659
  }
6578
6660
  },
@@ -6590,7 +6672,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6590
6672
  },
6591
6673
  sourceLocation: {
6592
6674
  "file": "packages/dsh-awiki/src/index.ts",
6593
- "line": 105,
6675
+ "line": 107,
6594
6676
  "column": 3
6595
6677
  }
6596
6678
  },
@@ -6617,7 +6699,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6617
6699
  },
6618
6700
  sourceLocation: {
6619
6701
  "file": "packages/dsh-awiki/src/index.ts",
6620
- "line": 120,
6702
+ "line": 122,
6621
6703
  "column": 9
6622
6704
  }
6623
6705
  },
@@ -6635,7 +6717,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6635
6717
  },
6636
6718
  sourceLocation: {
6637
6719
  "file": "packages/dsh-awiki/src/index.ts",
6638
- "line": 82,
6720
+ "line": 84,
6639
6721
  "column": 9
6640
6722
  }
6641
6723
  },
@@ -6662,7 +6744,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6662
6744
  },
6663
6745
  sourceLocation: {
6664
6746
  "file": "packages/dsh-awiki/src/index.ts",
6665
- "line": 91,
6747
+ "line": 93,
6666
6748
  "column": 9
6667
6749
  }
6668
6750
  },
@@ -6689,7 +6771,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6689
6771
  },
6690
6772
  sourceLocation: {
6691
6773
  "file": "packages/dsh-awiki/src/index.ts",
6692
- "line": 138,
6774
+ "line": 140,
6693
6775
  "column": 3
6694
6776
  }
6695
6777
  },
@@ -6716,7 +6798,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6716
6798
  },
6717
6799
  sourceLocation: {
6718
6800
  "file": "packages/dsh-awiki/src/index.ts",
6719
- "line": 141,
6801
+ "line": 143,
6720
6802
  "column": 9
6721
6803
  }
6722
6804
  },
@@ -6744,7 +6826,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6744
6826
  },
6745
6827
  sourceLocation: {
6746
6828
  "file": "packages/dsh-awiki/src/index.ts",
6747
- "line": 164,
6829
+ "line": 166,
6748
6830
  "column": 3
6749
6831
  }
6750
6832
  },
@@ -6771,7 +6853,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6771
6853
  },
6772
6854
  sourceLocation: {
6773
6855
  "file": "packages/dsh-awiki/src/index.ts",
6774
- "line": 144,
6856
+ "line": 146,
6775
6857
  "column": 3
6776
6858
  }
6777
6859
  },
@@ -6799,7 +6881,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6799
6881
  },
6800
6882
  sourceLocation: {
6801
6883
  "file": "packages/dsh-awiki/src/index.ts",
6802
- "line": 193,
6884
+ "line": 195,
6803
6885
  "column": 9
6804
6886
  }
6805
6887
  },
@@ -6817,7 +6899,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6817
6899
  },
6818
6900
  sourceLocation: {
6819
6901
  "file": "packages/dsh-awiki/src/index.ts",
6820
- "line": 88,
6902
+ "line": 90,
6821
6903
  "column": 3
6822
6904
  }
6823
6905
  },
@@ -6844,7 +6926,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6844
6926
  },
6845
6927
  sourceLocation: {
6846
6928
  "file": "packages/dsh-awiki/src/index.ts",
6847
- "line": 85,
6929
+ "line": 87,
6848
6930
  "column": 3
6849
6931
  }
6850
6932
  },
@@ -6871,7 +6953,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6871
6953
  },
6872
6954
  sourceLocation: {
6873
6955
  "file": "packages/dsh-awiki/src/index.ts",
6874
- "line": 178,
6956
+ "line": 180,
6875
6957
  "column": 3
6876
6958
  }
6877
6959
  },
@@ -6898,7 +6980,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6898
6980
  },
6899
6981
  sourceLocation: {
6900
6982
  "file": "packages/dsh-awiki/src/index.ts",
6901
- "line": 199,
6983
+ "line": 201,
6902
6984
  "column": 3
6903
6985
  }
6904
6986
  },
@@ -6925,7 +7007,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6925
7007
  },
6926
7008
  sourceLocation: {
6927
7009
  "file": "packages/dsh-awiki/src/index.ts",
6928
- "line": 114,
7010
+ "line": 116,
6929
7011
  "column": 3
6930
7012
  }
6931
7013
  },
@@ -6952,7 +7034,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6952
7034
  },
6953
7035
  sourceLocation: {
6954
7036
  "file": "packages/dsh-awiki/src/index.ts",
6955
- "line": 196,
7037
+ "line": 198,
6956
7038
  "column": 9
6957
7039
  }
6958
7040
  },
@@ -6979,7 +7061,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
6979
7061
  },
6980
7062
  sourceLocation: {
6981
7063
  "file": "packages/dsh-awiki/src/index.ts",
6982
- "line": 99,
7064
+ "line": 101,
6983
7065
  "column": 9
6984
7066
  }
6985
7067
  },
@@ -7006,7 +7088,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7006
7088
  },
7007
7089
  sourceLocation: {
7008
7090
  "file": "packages/dsh-awiki/src/index.ts",
7009
- "line": 150,
7091
+ "line": 152,
7010
7092
  "column": 3
7011
7093
  }
7012
7094
  },
@@ -7033,7 +7115,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7033
7115
  },
7034
7116
  sourceLocation: {
7035
7117
  "file": "packages/dsh-awiki/src/index.ts",
7036
- "line": 129,
7118
+ "line": 131,
7037
7119
  "column": 3
7038
7120
  }
7039
7121
  },
@@ -7051,7 +7133,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7051
7133
  },
7052
7134
  sourceLocation: {
7053
7135
  "file": "packages/dsh-awiki/src/index.ts",
7054
- "line": 153,
7136
+ "line": 155,
7055
7137
  "column": 9
7056
7138
  }
7057
7139
  },
@@ -7078,7 +7160,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7078
7160
  },
7079
7161
  sourceLocation: {
7080
7162
  "file": "packages/dsh-awiki/src/index.ts",
7081
- "line": 123,
7163
+ "line": 125,
7082
7164
  "column": 9
7083
7165
  }
7084
7166
  },
@@ -7105,7 +7187,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7105
7187
  },
7106
7188
  sourceLocation: {
7107
7189
  "file": "packages/dsh-awiki/src/index.ts",
7108
- "line": 184,
7190
+ "line": 186,
7109
7191
  "column": 9
7110
7192
  }
7111
7193
  },
@@ -7132,7 +7214,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7132
7214
  },
7133
7215
  sourceLocation: {
7134
7216
  "file": "packages/dsh-awiki/src/index.ts",
7135
- "line": 202,
7217
+ "line": 204,
7136
7218
  "column": 9
7137
7219
  }
7138
7220
  },
@@ -7159,7 +7241,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7159
7241
  },
7160
7242
  sourceLocation: {
7161
7243
  "file": "packages/dsh-awiki/src/index.ts",
7162
- "line": 111,
7244
+ "line": 113,
7163
7245
  "column": 3
7164
7246
  }
7165
7247
  },
@@ -7186,7 +7268,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7186
7268
  },
7187
7269
  sourceLocation: {
7188
7270
  "file": "packages/dsh-awiki/src/index.ts",
7189
- "line": 96,
7271
+ "line": 98,
7190
7272
  "column": 3
7191
7273
  }
7192
7274
  },
@@ -7213,7 +7295,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7213
7295
  },
7214
7296
  sourceLocation: {
7215
7297
  "file": "packages/dsh-awiki/src/index.ts",
7216
- "line": 181,
7298
+ "line": 183,
7217
7299
  "column": 3
7218
7300
  }
7219
7301
  },
@@ -7240,7 +7322,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7240
7322
  },
7241
7323
  sourceLocation: {
7242
7324
  "file": "packages/dsh-awiki/src/index.ts",
7243
- "line": 173,
7325
+ "line": 175,
7244
7326
  "column": 9
7245
7327
  }
7246
7328
  },
@@ -7267,7 +7349,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7267
7349
  },
7268
7350
  sourceLocation: {
7269
7351
  "file": "packages/dsh-awiki/src/index.ts",
7270
- "line": 159,
7352
+ "line": 161,
7271
7353
  "column": 3
7272
7354
  }
7273
7355
  },
@@ -7294,7 +7376,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7294
7376
  },
7295
7377
  sourceLocation: {
7296
7378
  "file": "packages/dsh-awiki/src/index.ts",
7297
- "line": 102,
7379
+ "line": 104,
7298
7380
  "column": 9
7299
7381
  }
7300
7382
  },
@@ -7321,7 +7403,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
7321
7403
  },
7322
7404
  sourceLocation: {
7323
7405
  "file": "packages/dsh-awiki/src/index.ts",
7324
- "line": 108,
7406
+ "line": 110,
7325
7407
  "column": 3
7326
7408
  }
7327
7409
  }
@@ -8822,18 +8904,23 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8822
8904
  ];
8823
8905
  /** Runtime-only decoded-byte budget that prevents repeat Host calls while browsing. */
8824
8906
  const BROWSER_IMAGE_ATTACHMENT_CACHE_MAX_BYTES = 33554432;
8825
- const RECOVERY_OPERATION_STORAGE_KEY = "awiki.handle-recovery.operation.v1";
8826
- function storedRecoveryOperation() {
8907
+ const RECOVERY_OPERATION_STORAGE_PREFIX = "awiki.handle-recovery.operation.v2:";
8908
+ function recoveryOperationStorageKey(tenantDomain) {
8909
+ return `${RECOVERY_OPERATION_STORAGE_PREFIX}${encodeURIComponent(tenantDomain)}`;
8910
+ }
8911
+ function storedRecoveryOperation(tenantDomain) {
8827
8912
  try {
8828
- return globalThis.localStorage?.getItem(RECOVERY_OPERATION_STORAGE_KEY) ?? null;
8913
+ return globalThis.localStorage?.getItem(recoveryOperationStorageKey(tenantDomain)) ?? null;
8829
8914
  } catch {
8830
8915
  return null;
8831
8916
  }
8832
8917
  }
8833
- function storeRecoveryOperation(operationId) {
8918
+ function storeRecoveryOperation(tenantDomain, operationId) {
8919
+ if (tenantDomain === void 0) return;
8834
8920
  try {
8835
- if (operationId === null) globalThis.localStorage?.removeItem(RECOVERY_OPERATION_STORAGE_KEY);
8836
- else globalThis.localStorage?.setItem(RECOVERY_OPERATION_STORAGE_KEY, operationId);
8921
+ const key = recoveryOperationStorageKey(tenantDomain);
8922
+ if (operationId === null) globalThis.localStorage?.removeItem(key);
8923
+ else globalThis.localStorage?.setItem(key, operationId);
8837
8924
  } catch {}
8838
8925
  }
8839
8926
  /** Wait between group-history readiness probes without retaining controller state. */
@@ -8969,9 +9056,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8969
9056
  attachmentMaxBytes: config.value.attachmentMaxBytes,
8970
9057
  profileName: config.value.profileName ?? null,
8971
9058
  legacySharedStateDetected: config.value.legacySharedStateDetected ?? false,
8972
- recoveryOperationId: storedRecoveryOperation()
9059
+ recoveryOperationId: storedRecoveryOperation(config.value.tenantDomain)
8973
9060
  });
8974
- const operationId = storedRecoveryOperation();
9061
+ const operationId = storedRecoveryOperation(config.value.tenantDomain);
8975
9062
  if (operationId !== null) {
8976
9063
  const recovery = await call(() => this.remote.getRecoveryStatus({ operationId }));
8977
9064
  if (this.current(generation) && recovery.ok) {
@@ -8981,7 +9068,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
8981
9068
  recoveryProgress: recovery.value
8982
9069
  });
8983
9070
  if (recovery.value.phase === "applied") {
8984
- storeRecoveryOperation(null);
9071
+ storeRecoveryOperation(config.value.tenantDomain, null);
8985
9072
  this.publish({
8986
9073
  ...this.view,
8987
9074
  recoveryOperationId: null,
@@ -9156,7 +9243,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9156
9243
  async sendRecoveryOtp(request) {
9157
9244
  const result = await this.withPending("发送恢复验证码", () => call(() => this.remote.sendRecoveryOtp(request), registrationOtpFailureMessage), { publishFailure: false });
9158
9245
  if (!result.ok) return result;
9159
- storeRecoveryOperation(result.value.operationId);
9246
+ storeRecoveryOperation(this.config?.tenantDomain, result.value.operationId);
9160
9247
  this.publish({
9161
9248
  ...this.view,
9162
9249
  recoveryOperationId: result.value.operationId,
@@ -9191,7 +9278,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9191
9278
  recoveryProgress: result.value
9192
9279
  });
9193
9280
  if (result.value.phase === "applied") {
9194
- storeRecoveryOperation(null);
9281
+ storeRecoveryOperation(this.config?.tenantDomain, null);
9195
9282
  this.publish({
9196
9283
  ...this.view,
9197
9284
  recoveryOperationId: null,
@@ -9212,7 +9299,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9212
9299
  recoveryProgress: result.value
9213
9300
  });
9214
9301
  if (result.value.phase === "applied") {
9215
- storeRecoveryOperation(null);
9302
+ storeRecoveryOperation(this.config?.tenantDomain, null);
9216
9303
  this.publish({
9217
9304
  ...this.view,
9218
9305
  recoveryOperationId: null,
@@ -9239,7 +9326,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9239
9326
  recoveryProgress: result.value
9240
9327
  });
9241
9328
  if (result.value.phase === "applied") {
9242
- storeRecoveryOperation(null);
9329
+ storeRecoveryOperation(this.config?.tenantDomain, null);
9243
9330
  this.publish({
9244
9331
  ...this.view,
9245
9332
  recoveryOperationId: null,
@@ -9260,7 +9347,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9260
9347
  if (phase !== void 0 && phase !== "awaiting_factor" && phase !== "ready_to_commit") return this.fail("当前恢复状态不能取消");
9261
9348
  const result = await this.withPending("取消身份恢复", () => call(() => this.remote.discardRecovery({ operationId })), { publishFailure: false });
9262
9349
  if (!result.ok) return result;
9263
- storeRecoveryOperation(null);
9350
+ storeRecoveryOperation(this.config?.tenantDomain, null);
9264
9351
  this.publish({
9265
9352
  ...this.view,
9266
9353
  recoveryOperationId: null,
@@ -9271,6 +9358,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9271
9358
  value: void 0
9272
9359
  };
9273
9360
  }
9361
+ /** Return cached browser-safe runtime policy, or load it once on demand. */
9362
+ async getConfig() {
9363
+ if (this.config !== null) return {
9364
+ ok: true,
9365
+ value: this.config
9366
+ };
9367
+ const result = await call(() => this.remote.getConfig(), mailFailureMessage);
9368
+ if (result.ok) this.config = result.value;
9369
+ return result;
9370
+ }
9274
9371
  /** Read the active deployment identity's public mailbox state. */
9275
9372
  getMailAccount() {
9276
9373
  return call(() => this.remote.getMailAccount(), mailFailureMessage);
@@ -9291,6 +9388,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
9291
9388
  sendMail(request) {
9292
9389
  return call(() => this.remote.sendMail(request), mailFailureMessage);
9293
9390
  }
9391
+ /** Download one explicitly selected mail attachment without retaining its bytes. */
9392
+ async downloadMailAttachment(request) {
9393
+ if (this.disposed) return {
9394
+ ok: false,
9395
+ error: "AWiki 插件已卸载"
9396
+ };
9397
+ const generation = this.generation;
9398
+ const result = await call(() => this.remote.downloadMailAttachment(request), mailFailureMessage);
9399
+ if (!this.current(generation)) return {
9400
+ ok: false,
9401
+ error: "AWiki 已关闭"
9402
+ };
9403
+ return result;
9404
+ }
9294
9405
  /**
9295
9406
  * Load another page of the conversation roster.
9296
9407
  * @returns successful pagination or one display-safe failure.
@@ -10126,13 +10237,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10126
10237
  if (!result.ok) return result;
10127
10238
  await this.persistentImageCache.clear().catch(() => void 0);
10128
10239
  this.close();
10240
+ const tenantDomain = this.config?.tenantDomain;
10129
10241
  this.config = null;
10130
10242
  this.conversationsCursor = void 0;
10131
10243
  this.historyCursor = void 0;
10132
10244
  this.unreadAtOpen.clear();
10133
10245
  this.summaryBaselines.clear();
10134
10246
  this.clearPresentationCache();
10135
- storeRecoveryOperation(null);
10247
+ storeRecoveryOperation(tenantDomain, null);
10136
10248
  this.publish({
10137
10249
  ...INITIAL_VIEW,
10138
10250
  status: "ready"
@@ -10862,8 +10974,141 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10862
10974
  } catch {}
10863
10975
  }
10864
10976
  //#endregion
10977
+ //#region lib/types/client/mail-attachment.js
10978
+ /** Browser-only mail attachment selection, encoding, integrity, and download helpers. */
10979
+ function invalid(message) {
10980
+ throw new TypeError(message);
10981
+ }
10982
+ function fileName(value) {
10983
+ if (value.length === 0 || value.trim() !== value || value.replace(/[. ]+$/u, "") !== value || value === "." || value === ".." || new TextEncoder().encode(value).byteLength > 255 || /[\\/\p{C}]/u.test(value)) invalid("附件文件名无效。");
10984
+ return value;
10985
+ }
10986
+ function contentType(value) {
10987
+ if (value === "") return "application/octet-stream";
10988
+ if (!/^[A-Za-z0-9!#$&^_.+-]+\/[A-Za-z0-9!#$&^_.+-]+$/u.test(value)) invalid("附件 MIME 类型无效。");
10989
+ return value;
10990
+ }
10991
+ function assertLimits(limits) {
10992
+ if (!Number.isSafeInteger(limits.maxCount) || limits.maxCount < 0 || !Number.isSafeInteger(limits.maxBytes) || limits.maxBytes < 1 || !Number.isSafeInteger(limits.totalMaxBytes) || limits.totalMaxBytes < limits.maxBytes) invalid("邮件附件限制暂不可用。");
10993
+ }
10994
+ function base64(bytes) {
10995
+ let binary = "";
10996
+ const chunkSize = 32768;
10997
+ for (let offset = 0; offset < bytes.length; offset += chunkSize) binary += String.fromCharCode(...bytes.subarray(offset, offset + chunkSize));
10998
+ return btoa(binary);
10999
+ }
11000
+ /** Append browser File references after enforcing the exact Host-owned limits. */
11001
+ function selectMailAttachments(current, selected, limits, createId) {
11002
+ assertLimits(limits);
11003
+ const additions = Array.from(selected, (file) => ({
11004
+ id: createId(),
11005
+ file,
11006
+ fileName: fileName(file.name),
11007
+ contentType: contentType(file.type),
11008
+ sizeBytes: file.size,
11009
+ lastModified: file.lastModified
11010
+ }));
11011
+ const combined = [...current, ...additions];
11012
+ if (combined.length > limits.maxCount) invalid(`邮件最多选择 ${limits.maxCount} 个附件。`);
11013
+ for (const attachment of combined) {
11014
+ if (!Number.isSafeInteger(attachment.sizeBytes) || attachment.sizeBytes < 0) invalid("附件大小无效。");
11015
+ if (attachment.sizeBytes > limits.maxBytes) invalid(`单个附件不能超过 ${limits.maxBytes} bytes。`);
11016
+ }
11017
+ const total = combined.reduce((sum, attachment) => sum + attachment.sizeBytes, 0);
11018
+ if (!Number.isSafeInteger(total) || total > limits.totalMaxBytes) invalid(`附件总大小不能超过 ${limits.totalMaxBytes} bytes。`);
11019
+ return combined;
11020
+ }
11021
+ /** Re-read the same approved File objects and return JSON-safe Remote attachments. */
11022
+ async function encodeMailAttachments(attachments, limits) {
11023
+ selectMailAttachments([], attachments.map((value) => value.file), limits, () => "validation-only");
11024
+ const encoded = [];
11025
+ for (const attachment of attachments) {
11026
+ if (attachment.file.name !== attachment.fileName || contentType(attachment.file.type) !== attachment.contentType || attachment.file.size !== attachment.sizeBytes || attachment.file.lastModified !== attachment.lastModified) invalid(`附件 ${attachment.fileName} 已发生变化,请重新选择。`);
11027
+ let buffer;
11028
+ try {
11029
+ buffer = await attachment.file.arrayBuffer();
11030
+ } catch {
11031
+ invalid(`无法读取附件 ${attachment.fileName},请重新选择。`);
11032
+ }
11033
+ const bytes = new Uint8Array(buffer);
11034
+ if (bytes.byteLength !== attachment.sizeBytes) invalid(`附件 ${attachment.fileName} 的大小已发生变化,请重新选择。`);
11035
+ encoded.push({
11036
+ fileName: attachment.fileName,
11037
+ contentType: attachment.contentType,
11038
+ sizeBytes: bytes.byteLength,
11039
+ bytesBase64: base64(bytes)
11040
+ });
11041
+ }
11042
+ return encoded;
11043
+ }
11044
+ /** Return canonical download metadata only when the service supplied every required field. */
11045
+ function downloadableMailAttachment(value, maxBytes) {
11046
+ if (!Number.isSafeInteger(value.index) || value.index < 0 || value.index > 4294967295) return void 0;
11047
+ if (value.fileName === void 0 || value.contentType === void 0 || value.sizeBytes === void 0) return void 0;
11048
+ if (!/^(?:0|[1-9][0-9]*)$/u.test(value.sizeBytes)) return void 0;
11049
+ const sizeBytes = Number(value.sizeBytes);
11050
+ if (!Number.isSafeInteger(sizeBytes) || sizeBytes < 0 || sizeBytes > maxBytes) return void 0;
11051
+ try {
11052
+ return {
11053
+ index: value.index,
11054
+ fileName: fileName(value.fileName),
11055
+ contentType: contentType(value.contentType),
11056
+ sizeBytes
11057
+ };
11058
+ } catch {
11059
+ return;
11060
+ }
11061
+ }
11062
+ /** Validate exact metadata, canonical Base64, byte length, and SHA-256 before download. */
11063
+ async function prepareMailAttachmentDownload(value, expected, maxBytes) {
11064
+ if (fileName(value.fileName) !== expected.fileName || contentType(value.contentType) !== expected.contentType || value.sizeBytes !== expected.sizeBytes || value.sizeBytes > maxBytes) invalid("下载附件与邮件元数据不一致。");
11065
+ if (!/^[a-f0-9]{64}$/u.test(value.sha256)) invalid("下载附件完整性信息无效。");
11066
+ const expectedEncodedLength = Math.ceil(value.sizeBytes / 3) * 4;
11067
+ if (value.bytesBase64.length !== expectedEncodedLength || value.bytesBase64.length % 4 !== 0 || !/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value.bytesBase64)) invalid("下载附件编码无效。");
11068
+ let binary;
11069
+ try {
11070
+ binary = atob(value.bytesBase64);
11071
+ } catch {
11072
+ invalid("下载附件编码无效。");
11073
+ }
11074
+ const bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
11075
+ if (bytes.byteLength !== value.sizeBytes || base64(bytes) !== value.bytesBase64) invalid("下载附件大小或编码不一致。");
11076
+ const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", bytes));
11077
+ if (Array.from(digest, (byte) => byte.toString(16).padStart(2, "0")).join("") !== value.sha256) invalid("下载附件完整性校验失败。");
11078
+ return {
11079
+ fileName: expected.fileName,
11080
+ contentType: expected.contentType,
11081
+ bytes
11082
+ };
11083
+ }
11084
+ /** Trigger one download and always revoke the temporary object URL immediately. */
11085
+ function savePreparedMailAttachment(value) {
11086
+ const url = URL.createObjectURL(new Blob([value.bytes], { type: value.contentType }));
11087
+ const anchor = document.createElement("a");
11088
+ try {
11089
+ anchor.href = url;
11090
+ anchor.download = value.fileName;
11091
+ anchor.hidden = true;
11092
+ document.body.append(anchor);
11093
+ anchor.click();
11094
+ } finally {
11095
+ anchor.remove();
11096
+ URL.revokeObjectURL(url);
11097
+ }
11098
+ }
11099
+ /** Execute the exact Browser UI download path: Remote, integrity check, Blob, and save click. */
11100
+ async function downloadAndSaveMailAttachment(download, request, expected, maxBytes, active = () => true) {
11101
+ const result = await download(request);
11102
+ if (!active()) return false;
11103
+ if (!result.ok) invalid(result.error);
11104
+ const prepared = await prepareMailAttachmentDownload(result.value, expected, maxBytes);
11105
+ if (!active()) return false;
11106
+ savePreparedMailAttachment(prepared);
11107
+ return true;
11108
+ }
11109
+ //#endregion
10865
11110
  //#region \0dsh-awiki-css:AwikiMail.module.css.mjs
10866
- const css$1 = ".eMUW5a_mail{background:var(--dsw-alias-bg-layer-1);flex:1;grid-template-columns:240px 320px minmax(420px,1fr);min-height:0;display:grid;position:relative}.eMUW5a_sidebar,.eMUW5a_mailList,.eMUW5a_mailDetail{min-width:0;min-height:0}.eMUW5a_sidebar{border-right:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);flex-direction:column;display:flex}.eMUW5a_accountCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:10px;gap:3px;margin:0 14px 12px;padding:10px 12px;display:grid}.eMUW5a_accountCard small,.eMUW5a_accountCard span{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_accountCard strong{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.eMUW5a_accountCard .eMUW5a_accountStatus{color:var(--dsw-alias-state-success-primary)}.eMUW5a_folderNav{gap:4px;padding:0 10px;display:grid}.eMUW5a_folderNav button{min-height:38px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:9px;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:9px;padding:0 10px;display:grid}.eMUW5a_folderNav button:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_folderNav button[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.eMUW5a_folderNav small{min-width:20px;color:var(--dsw-alias-brand-primary);text-align:right}.eMUW5a_folderRow{color:var(--dsw-alias-label-secondary);border-radius:9px;grid-template-columns:minmax(0,1fr) 38px;display:grid}.eMUW5a_folderRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_folderRow[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.eMUW5a_folderRow>button{color:inherit;background:0 0;border-radius:0}.eMUW5a_folderRow>button:hover{background:0 0}.eMUW5a_folderRow>.eMUW5a_composeIconButton{border-radius:8px;grid-template-columns:1fr;place-items:center;gap:0;width:38px;padding:0}.eMUW5a_folderRow>.eMUW5a_composeIconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailList{border-right:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);flex-direction:column;display:flex;position:relative}.eMUW5a_listHeader,.eMUW5a_detailHeader{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:9px;min-height:56px;padding:0 12px;display:flex}.eMUW5a_listHeader>div,.eMUW5a_detailHeader>div{flex-direction:column;flex:1;min-width:0;display:flex}.eMUW5a_listHeader strong,.eMUW5a_detailHeader strong,.eMUW5a_listHeader small,.eMUW5a_detailHeader small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.eMUW5a_listHeader strong,.eMUW5a_detailHeader strong{font-size:13px;line-height:20px}.eMUW5a_listHeader small,.eMUW5a_detailHeader small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_listHeader>button,.eMUW5a_detailBack{width:30px;height:30px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:8px;flex:none;place-items:center;padding:0;display:grid}.eMUW5a_listHeader>button:hover,.eMUW5a_detailBack:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.eMUW5a_listHeader>button:disabled{opacity:.5;cursor:default}.eMUW5a_detailBack{display:none}.eMUW5a_listHeader svg,.eMUW5a_loadingState svg{animation:none}.eMUW5a_listHeader button:disabled svg,.eMUW5a_loadingState svg{animation:1s linear infinite eMUW5a_mail-spin}@keyframes eMUW5a_mail-spin{to{transform:rotate(360deg)}}.eMUW5a_rows{flex:1;min-height:0;padding:6px;overflow:auto}.eMUW5a_mailRow{width:100%;min-height:82px;color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:10px;grid-template-columns:7px minmax(0,1fr) auto;gap:7px;padding:10px 9px;display:grid;position:relative}.eMUW5a_mailRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailRow[data-active]{background:var(--dsw-alias-interactive-bg-active)}.eMUW5a_unreadDot{background:0 0;border-radius:50%;align-self:start;width:6px;height:6px;margin-top:7px}.eMUW5a_mailRow[data-unread] .eMUW5a_unreadDot{background:var(--dsw-alias-brand-primary)}.eMUW5a_rowContent{flex-direction:column;gap:2px;min-width:0;display:flex}.eMUW5a_rowTop{align-items:center;gap:8px;display:flex}.eMUW5a_rowTop strong{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12px;line-height:18px;overflow:hidden}.eMUW5a_mailRow[data-unread] .eMUW5a_rowTop strong,.eMUW5a_mailRow[data-unread] .eMUW5a_rowSubject{font-weight:600}.eMUW5a_rowTop time{color:var(--dsw-alias-label-tertiary);flex:none;font-size:10px;line-height:15px}.eMUW5a_rowSubject,.eMUW5a_rowPreview{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.eMUW5a_rowSubject{color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px}.eMUW5a_rowPreview{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_rowAttachment{color:var(--dsw-alias-label-tertiary);align-self:end;align-items:center;gap:2px;display:flex}.eMUW5a_rowAttachment small{font-size:10px}.eMUW5a_inlineError,.eMUW5a_detailError{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:8px;padding:8px 12px;font-size:11px;line-height:16px;display:flex}.eMUW5a_inlineError button{color:inherit;cursor:pointer;background:0 0;border:0;flex:none;text-decoration:underline}.eMUW5a_loadingState,.eMUW5a_emptyState,.eMUW5a_detailEmpty{color:var(--dsw-alias-label-tertiary);justify-content:center;align-items:center;gap:8px;font-size:12px;display:flex}.eMUW5a_loadingState{pointer-events:none;position:absolute;inset:56px 0 0}.eMUW5a_emptyState{flex-direction:column;min-height:180px}.eMUW5a_emptyState p,.eMUW5a_detailEmpty p{margin:0}.eMUW5a_loadMore{background:var(--dsw-alias-button-elevated-fill);min-height:34px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;border:0;border-radius:9px;margin:7px}.eMUW5a_loadMore:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailDetail{background:var(--dsw-alias-bg-layer-1);flex-direction:column;display:flex;position:relative}.eMUW5a_detailEmpty{flex-direction:column;flex:1}.eMUW5a_detailEmpty button{background:var(--dsw-alias-button-primary-fill);min-height:34px;color:var(--dsw-alias-label-primary-inverted);cursor:pointer;border:0;border-radius:9px;padding:0 14px}.eMUW5a_markReadButton{border:1px solid var(--dsw-alias-border-l2);min-height:30px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;background:0 0;border-radius:8px;flex:none;padding:0 9px;font-size:11px}.eMUW5a_markReadButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_markReadButton:disabled{opacity:.5;cursor:default}.eMUW5a_messageBody{flex:1;min-height:0;padding:22px 24px;overflow:auto}.eMUW5a_messageMeta{border-bottom:1px solid var(--dsw-alias-border-l1);padding-bottom:18px}.eMUW5a_messageMeta h3{overflow-wrap:anywhere;margin:0 0 5px;font-size:18px;line-height:27px}.eMUW5a_messageMeta>time{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_messageMeta dl{gap:3px;margin:14px 0 0;display:grid}.eMUW5a_messageMeta dl>div{grid-template-columns:48px minmax(0,1fr);gap:8px;font-size:11px;line-height:17px;display:grid}.eMUW5a_messageMeta dt{color:var(--dsw-alias-label-tertiary)}.eMUW5a_messageMeta dd{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0}.eMUW5a_untrustedNotice{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);border-radius:8px;align-items:center;gap:7px;margin:16px 0;padding:8px 10px;font-size:11px;line-height:16px;display:flex}.eMUW5a_plainBody{min-height:120px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;font-size:13px;line-height:22px}.eMUW5a_truncatedNotice{color:var(--dsw-alias-state-warn-label);margin:14px 0 0;font-size:11px}.eMUW5a_attachments{border-top:1px solid var(--dsw-alias-border-l1);gap:8px;margin-top:22px;padding-top:16px;display:grid}.eMUW5a_attachments h4{margin:0;font-size:12px;line-height:18px}.eMUW5a_attachments>div{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:9px;align-items:center;gap:9px;padding:9px 10px;display:flex}.eMUW5a_attachments>div>span{flex-direction:column;min-width:0;display:flex}.eMUW5a_attachments strong{text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_attachments small{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.eMUW5a_notice{z-index:6;box-sizing:border-box;background:var(--dsw-alias-button-primary-fill);max-width:min(360px,100% - 32px);color:var(--dsw-alias-label-primary-inverted);box-shadow:var(--dsw-shadow-lv2);overflow-wrap:anywhere;pointer-events:none;text-align:center;border-radius:9px;padding:10px 14px;font-size:12px;line-height:18px;animation:2.4s both eMUW5a_mail-notice;position:absolute;top:16px;left:50%;transform:translate(-50%)}@keyframes eMUW5a_mail-notice{0%{opacity:0;transform:translate(-50%,-6px)}8%,88%{opacity:1;transform:translate(-50%)}to{opacity:0;transform:translate(-50%,-4px)}}.eMUW5a_composer{flex-direction:column;flex:1;min-height:0;display:flex}.eMUW5a_composeFields{flex-direction:column;flex:1;gap:11px;min-height:0;padding:18px 20px;display:flex;overflow:auto}.eMUW5a_composeFields label{color:var(--dsw-alias-label-secondary);grid-template-rows:max-content max-content;gap:5px;font-size:11px;line-height:16px;display:grid}.eMUW5a_composeFields input,.eMUW5a_composeFields textarea{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);width:100%;color:var(--dsw-alias-label-primary);font:inherit;resize:vertical;border-radius:9px;padding:8px 10px}.eMUW5a_composeFields input{height:38px}.eMUW5a_composeFields .eMUW5a_bodyField{flex:1;grid-template-rows:max-content minmax(160px,1fr);min-height:160px}.eMUW5a_bodyField textarea{resize:none;min-height:160px}.eMUW5a_composeError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:11px;line-height:16px}.eMUW5a_composeFooter{border-top:1px solid var(--dsw-alias-border-l1);flex:none;justify-content:flex-end;gap:8px;padding:10px 14px;display:flex}.eMUW5a_cancelButton,.eMUW5a_sendButton{cursor:pointer;min-height:34px;font:inherit;border-radius:9px;justify-content:center;align-items:center;gap:6px;padding:0 13px;display:flex}.eMUW5a_cancelButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.eMUW5a_sendButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-inverted);border:0}.eMUW5a_cancelButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_sendButton:hover{background:var(--dsw-alias-button-primary-hover)}.eMUW5a_confirmSummary{color:var(--dsw-alias-label-secondary);gap:6px;display:grid}.eMUW5a_confirmSummary p,.eMUW5a_discardText{overflow-wrap:anywhere;margin:0}@media (width<=1119px){.eMUW5a_mail{grid-template-columns:220px minmax(0,1fr)}.eMUW5a_mailList,.eMUW5a_mailDetail{grid-area:1/2}.eMUW5a_mailDetail,.eMUW5a_mail[data-detail-active] .eMUW5a_mailList{display:none}.eMUW5a_mail[data-detail-active] .eMUW5a_mailDetail{display:flex}.eMUW5a_detailBack{display:grid}}@media (width<=719px){.eMUW5a_mail{grid-template-columns:1fr}.eMUW5a_sidebar,.eMUW5a_mailList,.eMUW5a_mailDetail{grid-area:1/1}.eMUW5a_mailList,.eMUW5a_mailDetail,.eMUW5a_mail[data-pane=list] .eMUW5a_sidebar,.eMUW5a_mail[data-pane=detail] .eMUW5a_sidebar{display:none}.eMUW5a_mail[data-pane=list] .eMUW5a_mailList,.eMUW5a_mail[data-pane=detail] .eMUW5a_mailDetail{display:flex}.eMUW5a_messageBody{padding:18px}}@media (prefers-reduced-motion:reduce){.eMUW5a_listHeader button:disabled svg,.eMUW5a_loadingState svg,.eMUW5a_notice{animation:none}}";
11111
+ const css$1 = ".eMUW5a_mail{background:var(--dsw-alias-bg-layer-1);flex:1;grid-template-columns:240px 320px minmax(420px,1fr);min-height:0;display:grid;position:relative}.eMUW5a_sidebar,.eMUW5a_mailList,.eMUW5a_mailDetail{min-width:0;min-height:0}.eMUW5a_sidebar{border-right:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);flex-direction:column;display:flex}.eMUW5a_accountCard{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:10px;gap:3px;margin:0 14px 12px;padding:10px 12px;display:grid}.eMUW5a_accountCard small,.eMUW5a_accountCard span{color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_accountCard strong{text-overflow:ellipsis;white-space:nowrap;font-size:12px;line-height:18px;overflow:hidden}.eMUW5a_accountCard .eMUW5a_accountStatus{color:var(--dsw-alias-state-success-primary)}.eMUW5a_folderNav{gap:4px;padding:0 10px;display:grid}.eMUW5a_folderNav button{min-height:38px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:9px;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:9px;padding:0 10px;display:grid}.eMUW5a_folderNav button:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_folderNav button[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.eMUW5a_folderNav small{min-width:20px;color:var(--dsw-alias-brand-primary);text-align:right}.eMUW5a_folderRow{color:var(--dsw-alias-label-secondary);border-radius:9px;grid-template-columns:minmax(0,1fr) 38px;display:grid}.eMUW5a_folderRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_folderRow[data-active]{background:var(--dsw-alias-interactive-bg-active);color:var(--dsw-alias-label-primary)}.eMUW5a_folderRow>button{color:inherit;background:0 0;border-radius:0}.eMUW5a_folderRow>button:hover{background:0 0}.eMUW5a_folderRow>.eMUW5a_composeIconButton{border-radius:8px;grid-template-columns:1fr;place-items:center;gap:0;width:38px;padding:0}.eMUW5a_folderRow>.eMUW5a_composeIconButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailList{border-right:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);flex-direction:column;display:flex;position:relative}.eMUW5a_listHeader,.eMUW5a_detailHeader{border-bottom:1px solid var(--dsw-alias-border-l1);flex:none;align-items:center;gap:9px;min-height:56px;padding:0 12px;display:flex}.eMUW5a_listHeader>div,.eMUW5a_detailHeader>div{flex-direction:column;flex:1;min-width:0;display:flex}.eMUW5a_listHeader strong,.eMUW5a_detailHeader strong,.eMUW5a_listHeader small,.eMUW5a_detailHeader small{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.eMUW5a_listHeader strong,.eMUW5a_detailHeader strong{font-size:13px;line-height:20px}.eMUW5a_listHeader small,.eMUW5a_detailHeader small{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_listHeader>button,.eMUW5a_detailBack{width:30px;height:30px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:0;border-radius:8px;flex:none;place-items:center;padding:0;display:grid}.eMUW5a_listHeader>button:hover,.eMUW5a_detailBack:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary)}.eMUW5a_listHeader>button:disabled{opacity:.5;cursor:default}.eMUW5a_detailBack{display:none}.eMUW5a_listHeader svg,.eMUW5a_loadingState svg{animation:none}.eMUW5a_listHeader button:disabled svg,.eMUW5a_loadingState svg{animation:1s linear infinite eMUW5a_mail-spin}.eMUW5a_listHeader>.eMUW5a_listBack{display:none}@keyframes eMUW5a_mail-spin{to{transform:rotate(360deg)}}.eMUW5a_rows{flex:1;min-height:0;padding:6px;overflow:auto}.eMUW5a_mailRow{width:100%;min-height:82px;color:inherit;cursor:pointer;font:inherit;text-align:left;background:0 0;border:0;border-radius:10px;grid-template-columns:7px minmax(0,1fr) auto;gap:7px;padding:10px 9px;display:grid;position:relative}.eMUW5a_mailRow:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailRow[data-active]{background:var(--dsw-alias-interactive-bg-active)}.eMUW5a_unreadDot{background:0 0;border-radius:50%;align-self:start;width:6px;height:6px;margin-top:7px}.eMUW5a_mailRow[data-unread] .eMUW5a_unreadDot{background:var(--dsw-alias-brand-primary)}.eMUW5a_rowContent{flex-direction:column;gap:2px;min-width:0;display:flex}.eMUW5a_rowTop{align-items:center;gap:8px;display:flex}.eMUW5a_rowTop strong{text-overflow:ellipsis;white-space:nowrap;flex:1;min-width:0;font-size:12px;line-height:18px;overflow:hidden}.eMUW5a_mailRow[data-unread] .eMUW5a_rowTop strong,.eMUW5a_mailRow[data-unread] .eMUW5a_rowSubject{font-weight:600}.eMUW5a_rowTop time{color:var(--dsw-alias-label-tertiary);flex:none;font-size:10px;line-height:15px}.eMUW5a_rowSubject,.eMUW5a_rowPreview{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.eMUW5a_rowSubject{color:var(--dsw-alias-label-primary);font-size:12px;line-height:18px}.eMUW5a_rowPreview{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_rowAttachment{color:var(--dsw-alias-label-tertiary);align-self:end;align-items:center;gap:2px;display:flex}.eMUW5a_rowAttachment small{font-size:10px}.eMUW5a_inlineError,.eMUW5a_detailError{background:var(--dsw-alias-interactive-bg-hover-danger);color:var(--dsw-alias-state-error-primary);justify-content:space-between;align-items:center;gap:8px;padding:8px 12px;font-size:11px;line-height:16px;display:flex}.eMUW5a_inlineError button{color:inherit;cursor:pointer;background:0 0;border:0;flex:none;text-decoration:underline}.eMUW5a_loadingState,.eMUW5a_emptyState,.eMUW5a_detailEmpty{color:var(--dsw-alias-label-tertiary);justify-content:center;align-items:center;gap:8px;font-size:12px;display:flex}.eMUW5a_loadingState{pointer-events:none;position:absolute;inset:56px 0 0}.eMUW5a_emptyState{flex-direction:column;min-height:180px}.eMUW5a_emptyState p,.eMUW5a_detailEmpty p{margin:0}.eMUW5a_loadMore{background:var(--dsw-alias-button-elevated-fill);min-height:34px;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;border:0;border-radius:9px;margin:7px}.eMUW5a_loadMore:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_mailDetail{background:var(--dsw-alias-bg-layer-1);flex-direction:column;display:flex;position:relative}.eMUW5a_detailEmpty{flex-direction:column;flex:1}.eMUW5a_detailEmpty button{background:var(--dsw-alias-button-primary-fill);min-height:34px;color:var(--dsw-alias-label-primary-inverted);cursor:pointer;border:0;border-radius:9px;padding:0 14px}.eMUW5a_markReadButton{border:1px solid var(--dsw-alias-border-l2);min-height:30px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;background:0 0;border-radius:8px;flex:none;padding:0 9px;font-size:11px}.eMUW5a_markReadButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_markReadButton:disabled{opacity:.5;cursor:default}.eMUW5a_messageBody{flex:1;min-height:0;padding:22px 24px;overflow:auto}.eMUW5a_messageMeta{border-bottom:1px solid var(--dsw-alias-border-l1);padding-bottom:18px}.eMUW5a_messageMeta h3{overflow-wrap:anywhere;margin:0 0 5px;font-size:18px;line-height:27px}.eMUW5a_messageMeta>time{color:var(--dsw-alias-label-tertiary);font-size:11px;line-height:16px}.eMUW5a_messageMeta dl{gap:3px;margin:14px 0 0;display:grid}.eMUW5a_messageMeta dl>div{grid-template-columns:48px minmax(0,1fr);gap:8px;font-size:11px;line-height:17px;display:grid}.eMUW5a_messageMeta dt{color:var(--dsw-alias-label-tertiary)}.eMUW5a_messageMeta dd{color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere;margin:0}.eMUW5a_untrustedNotice{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-tertiary);border-radius:8px;align-items:center;gap:7px;margin:16px 0;padding:8px 10px;font-size:11px;line-height:16px;display:flex}.eMUW5a_plainBody{min-height:120px;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere;font-size:13px;line-height:22px}.eMUW5a_truncatedNotice{color:var(--dsw-alias-state-warn-label);margin:14px 0 0;font-size:11px}.eMUW5a_attachments{border-top:1px solid var(--dsw-alias-border-l1);gap:8px;min-width:0;margin-top:22px;padding-top:16px;display:grid}.eMUW5a_attachments h4{margin:0;font-size:12px;line-height:18px}.eMUW5a_attachments>div{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:9px;align-items:center;gap:9px;min-width:0;max-width:100%;padding:9px 10px;display:flex}.eMUW5a_attachments>div>span{flex-direction:column;flex:1;min-width:0;display:flex}.eMUW5a_attachments strong{text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_attachments small{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.eMUW5a_attachments button,.eMUW5a_selectedAttachments button{border:1px solid var(--dsw-alias-border-l2);min-height:30px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;background:0 0;border-radius:8px;flex:none;padding:0 10px;font-size:11px}.eMUW5a_attachments button:hover,.eMUW5a_selectedAttachments button:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_attachments button:disabled,.eMUW5a_selectedAttachments button:disabled{opacity:.5;cursor:default}.eMUW5a_attachments .eMUW5a_attachmentDownloadError{color:var(--dsw-alias-state-error-primary);overflow-wrap:anywhere}.eMUW5a_notice{z-index:6;box-sizing:border-box;background:var(--dsw-alias-button-primary-fill);max-width:min(360px,100% - 32px);color:var(--dsw-alias-label-primary-inverted);box-shadow:var(--dsw-shadow-lv2);overflow-wrap:anywhere;pointer-events:none;text-align:center;border-radius:9px;padding:10px 14px;font-size:12px;line-height:18px;animation:2.4s both eMUW5a_mail-notice;position:absolute;top:16px;left:50%;transform:translate(-50%)}@keyframes eMUW5a_mail-notice{0%{opacity:0;transform:translate(-50%,-6px)}8%,88%{opacity:1;transform:translate(-50%)}to{opacity:0;transform:translate(-50%,-4px)}}.eMUW5a_composer{flex-direction:column;flex:1;min-height:0;display:flex}.eMUW5a_composeFields{flex-direction:column;flex:1;gap:11px;min-height:0;padding:18px 20px;display:flex;overflow:auto}.eMUW5a_composeFields label{color:var(--dsw-alias-label-secondary);grid-template-rows:max-content max-content;gap:5px;font-size:11px;line-height:16px;display:grid}.eMUW5a_composeFields input,.eMUW5a_composeFields textarea{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);width:100%;color:var(--dsw-alias-label-primary);font:inherit;resize:vertical;border-radius:9px;padding:8px 10px}.eMUW5a_composeFields input{height:38px}.eMUW5a_composeFields .eMUW5a_bodyField{flex:1;grid-template-rows:max-content minmax(160px,1fr);min-height:160px}.eMUW5a_bodyField textarea{resize:none;min-height:160px}.eMUW5a_composeAttachments{gap:9px;display:grid}.eMUW5a_attachmentPickerRow{align-items:center;gap:10px;display:flex}.eMUW5a_attachmentPickerRow>small{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.eMUW5a_attachmentPicker{box-sizing:border-box;border:1px solid var(--dsw-alias-border-l2);appearance:none;background:var(--dsw-alias-bg-layer-1);height:30px;color:var(--dsw-alias-label-primary);cursor:pointer;font:inherit;white-space:nowrap;border-radius:7px;flex:none;justify-content:center;align-items:center;gap:5px;padding:0 10px;font-size:11px;font-weight:500;line-height:16px;display:inline-flex}.eMUW5a_attachmentPicker:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_attachmentPicker:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.eMUW5a_attachmentPicker:disabled{opacity:.5;cursor:default}.eMUW5a_attachmentInput{display:none}.eMUW5a_selectedAttachments{gap:7px;display:grid}.eMUW5a_selectedAttachments>div{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-2);border-radius:9px;align-items:center;gap:9px;padding:8px 9px;display:flex}.eMUW5a_selectedAttachments>div>span{flex-direction:column;flex:1;min-width:0;display:flex}.eMUW5a_selectedAttachments strong{text-overflow:ellipsis;white-space:nowrap;font-size:11px;line-height:16px;overflow:hidden}.eMUW5a_selectedAttachments small{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px}.eMUW5a_selectedAttachments>p{color:var(--dsw-alias-label-tertiary);margin:0;font-size:10px;line-height:15px}.eMUW5a_composeError{color:var(--dsw-alias-state-error-primary);margin:0;font-size:11px;line-height:16px}.eMUW5a_composeFooter{border-top:1px solid var(--dsw-alias-border-l1);flex:none;justify-content:flex-end;gap:8px;padding:10px 14px;display:flex}.eMUW5a_cancelButton,.eMUW5a_sendButton{cursor:pointer;min-height:34px;font:inherit;border-radius:9px;justify-content:center;align-items:center;gap:6px;padding:0 13px;display:flex}.eMUW5a_cancelButton{border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);background:0 0}.eMUW5a_sendButton{background:var(--dsw-alias-button-primary-fill);color:var(--dsw-alias-label-primary-inverted);border:0}.eMUW5a_cancelButton:hover{background:var(--dsw-alias-interactive-bg-hover)}.eMUW5a_sendButton:hover{background:var(--dsw-alias-button-primary-hover)}.eMUW5a_confirmSummary{color:var(--dsw-alias-label-secondary);gap:6px;display:grid}.eMUW5a_confirmSummary p,.eMUW5a_discardText{overflow-wrap:anywhere;margin:0}@media (width<=1119px){.eMUW5a_mail{grid-template-columns:220px minmax(0,1fr)}.eMUW5a_mailList,.eMUW5a_mailDetail{grid-area:1/2}.eMUW5a_mailDetail,.eMUW5a_mail[data-detail-active] .eMUW5a_mailList{display:none}.eMUW5a_mail[data-detail-active] .eMUW5a_mailDetail{display:flex}.eMUW5a_detailBack{display:grid}}@media (width<=719px){.eMUW5a_mail{grid-template-columns:1fr}.eMUW5a_sidebar,.eMUW5a_mailList,.eMUW5a_mailDetail{grid-area:1/1}.eMUW5a_mailList,.eMUW5a_mailDetail,.eMUW5a_mail[data-pane=list] .eMUW5a_sidebar,.eMUW5a_mail[data-pane=detail] .eMUW5a_sidebar{display:none}.eMUW5a_mail[data-pane=list] .eMUW5a_mailList,.eMUW5a_mail[data-pane=detail] .eMUW5a_mailDetail{display:flex}.eMUW5a_listHeader>.eMUW5a_listBack{display:grid}.eMUW5a_messageBody{padding:18px}}@media (prefers-reduced-motion:reduce){.eMUW5a_listHeader button:disabled svg,.eMUW5a_loadingState svg,.eMUW5a_notice{animation:none}}";
10867
11112
  const tagId$1 = "@awiki/dsh-plugin/AwikiMail.module.css";
10868
11113
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$1) + "]") === null) {
10869
11114
  const tag = document.createElement("style");
@@ -10875,9 +11120,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10875
11120
  var _dsh_awiki_css_AwikiMail_module_css_default = {
10876
11121
  "accountCard": "eMUW5a_accountCard",
10877
11122
  "accountStatus": "eMUW5a_accountStatus",
11123
+ "attachmentDownloadError": "eMUW5a_attachmentDownloadError",
11124
+ "attachmentInput": "eMUW5a_attachmentInput",
11125
+ "attachmentPicker": "eMUW5a_attachmentPicker",
11126
+ "attachmentPickerRow": "eMUW5a_attachmentPickerRow",
10878
11127
  "attachments": "eMUW5a_attachments",
10879
11128
  "bodyField": "eMUW5a_bodyField",
10880
11129
  "cancelButton": "eMUW5a_cancelButton",
11130
+ "composeAttachments": "eMUW5a_composeAttachments",
10881
11131
  "composeError": "eMUW5a_composeError",
10882
11132
  "composeFields": "eMUW5a_composeFields",
10883
11133
  "composeFooter": "eMUW5a_composeFooter",
@@ -10893,6 +11143,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10893
11143
  "folderNav": "eMUW5a_folderNav",
10894
11144
  "folderRow": "eMUW5a_folderRow",
10895
11145
  "inlineError": "eMUW5a_inlineError",
11146
+ "listBack": "eMUW5a_listBack",
10896
11147
  "listHeader": "eMUW5a_listHeader",
10897
11148
  "loadingState": "eMUW5a_loadingState",
10898
11149
  "loadMore": "eMUW5a_loadMore",
@@ -10913,6 +11164,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10913
11164
  "rows": "eMUW5a_rows",
10914
11165
  "rowSubject": "eMUW5a_rowSubject",
10915
11166
  "rowTop": "eMUW5a_rowTop",
11167
+ "selectedAttachments": "eMUW5a_selectedAttachments",
10916
11168
  "sendButton": "eMUW5a_sendButton",
10917
11169
  "sidebar": "eMUW5a_sidebar",
10918
11170
  "truncatedNotice": "eMUW5a_truncatedNotice",
@@ -10958,6 +11210,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
10958
11210
  function utf8Bytes(value) {
10959
11211
  return new TextEncoder().encode(value).byteLength;
10960
11212
  }
11213
+ function displayBytes(value) {
11214
+ if (value < 1024) return `${value} bytes`;
11215
+ if (value < 1048576) return `${(value / 1024).toFixed(value < 10240 ? 1 : 0)} KiB`;
11216
+ return `${(value / 1048576).toFixed(value < 10485760 ? 1 : 0)} MiB`;
11217
+ }
10961
11218
  function browserLocalStorage() {
10962
11219
  try {
10963
11220
  return window.localStorage;
@@ -11094,6 +11351,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11094
11351
  const [cc, setCc] = (0, react.useState)("");
11095
11352
  const [subject, setSubject] = (0, react.useState)("");
11096
11353
  const [bodyText, setBodyText] = (0, react.useState)("");
11354
+ const [attachmentLimits, setAttachmentLimits] = (0, react.useState)(null);
11355
+ const [attachments, setAttachments] = (0, react.useState)([]);
11356
+ const [attachmentError, setAttachmentError] = (0, react.useState)(null);
11357
+ const [downloadStates, setDownloadStates] = (0, react.useState)({});
11097
11358
  const [composeError, setComposeError] = (0, react.useState)(null);
11098
11359
  const [confirmOpen, setConfirmOpen] = (0, react.useState)(false);
11099
11360
  const [discardOpen, setDiscardOpen] = (0, react.useState)(false);
@@ -11104,6 +11365,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11104
11365
  const loadGeneration = (0, react.useRef)(0);
11105
11366
  const detailGeneration = (0, react.useRef)(0);
11106
11367
  const noticeRevision = (0, react.useRef)(0);
11368
+ const attachmentRevision = (0, react.useRef)(0);
11369
+ const fileInput = (0, react.useRef)(null);
11107
11370
  const visibleUnreadCount = (0, react.useMemo)(() => items.reduce((total, item) => total + (item.unread ? 1 : 0), 0), [items]);
11108
11371
  (0, react.useEffect)(() => {
11109
11372
  props.onUnreadCountChange(inboxUnreadCount);
@@ -11152,6 +11415,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11152
11415
  setListError(null);
11153
11416
  setNotice(null);
11154
11417
  const cacheVisible = hydrateListCache(requestedFolder);
11418
+ const configRequest = props.getConfig();
11155
11419
  const accountRequest = props.getMailAccount();
11156
11420
  const inboxRequest = props.listMailInbox({
11157
11421
  folder: requestedFolder,
@@ -11159,6 +11423,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11159
11423
  limit: 20,
11160
11424
  offset: 0
11161
11425
  });
11426
+ const configResult = await configRequest;
11427
+ if (generation !== loadGeneration.current) return;
11428
+ setAttachmentLimits(configResult.ok ? {
11429
+ maxCount: configResult.value.mailAttachmentMaxCount,
11430
+ maxBytes: configResult.value.mailAttachmentMaxBytes,
11431
+ totalMaxBytes: configResult.value.mailAttachmentTotalMaxBytes
11432
+ } : null);
11162
11433
  const accountResult = await accountRequest;
11163
11434
  if (generation !== loadGeneration.current) return;
11164
11435
  if (accountResult.ok) setAccount(accountResult.value);
@@ -11204,6 +11475,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11204
11475
  setSelectedId(null);
11205
11476
  setMessage(null);
11206
11477
  setDetailError(null);
11478
+ setDownloadStates({});
11207
11479
  if (!hydrateListCache(nextFolder)) applyListPage(nextFolder, {
11208
11480
  items: [],
11209
11481
  hasMore: false
@@ -11216,6 +11488,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11216
11488
  setCompose(false);
11217
11489
  setSelectedId(summary.id);
11218
11490
  setMessage(null);
11491
+ setDownloadStates({});
11219
11492
  setDetailLoading(true);
11220
11493
  setDetailError(null);
11221
11494
  setNotice(null);
@@ -11295,6 +11568,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11295
11568
  showNotice(result.value.updated > 0 ? "已标为已读。" : "该邮件已经是已读状态。");
11296
11569
  };
11297
11570
  const requestSend = () => {
11571
+ if (attachmentError !== null) {
11572
+ setComposeError(attachmentError);
11573
+ return;
11574
+ }
11575
+ if (attachments.length > 0 && attachmentLimits === null) {
11576
+ setComposeError("邮件附件限制暂不可用,请稍后刷新邮箱再试。");
11577
+ return;
11578
+ }
11298
11579
  const validated = validateDraft$1(to, cc, subject, bodyText);
11299
11580
  if (!validated.ok) {
11300
11581
  setComposeError(validated.error);
@@ -11308,6 +11589,32 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11308
11589
  setCc("");
11309
11590
  setSubject("");
11310
11591
  setBodyText("");
11592
+ setAttachments([]);
11593
+ setAttachmentError(null);
11594
+ if (fileInput.current !== null) fileInput.current.value = "";
11595
+ setComposeError(null);
11596
+ };
11597
+ const chooseAttachments = (files) => {
11598
+ if (files === null || files.length === 0) return;
11599
+ if (attachmentLimits === null) {
11600
+ setAttachmentError("邮件附件限制暂不可用,请稍后刷新邮箱再试。");
11601
+ return;
11602
+ }
11603
+ try {
11604
+ const next = selectMailAttachments(attachments, files, attachmentLimits, () => {
11605
+ attachmentRevision.current += 1;
11606
+ return `mail-attachment-${attachmentRevision.current}`;
11607
+ });
11608
+ setAttachments(next);
11609
+ setAttachmentError(null);
11610
+ setComposeError(null);
11611
+ } catch (error) {
11612
+ setAttachmentError(error instanceof TypeError ? error.message : "无法选择这些附件。");
11613
+ }
11614
+ };
11615
+ const removeAttachment = (id) => {
11616
+ setAttachments((current) => current.filter((attachment) => attachment.id !== id));
11617
+ setAttachmentError(null);
11311
11618
  setComposeError(null);
11312
11619
  };
11313
11620
  const confirmSend = async () => {
@@ -11317,12 +11624,27 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11317
11624
  setComposeError(validated.error);
11318
11625
  return;
11319
11626
  }
11627
+ if (attachmentError !== null || attachments.length > 0 && attachmentLimits === null) {
11628
+ setConfirmOpen(false);
11629
+ setComposeError(attachmentError ?? "邮件附件限制暂不可用,请稍后刷新邮箱再试。");
11630
+ return;
11631
+ }
11320
11632
  setSending(true);
11633
+ let encodedAttachments = [];
11634
+ try {
11635
+ if (attachments.length > 0) encodedAttachments = await encodeMailAttachments(attachments, attachmentLimits);
11636
+ } catch (error) {
11637
+ setSending(false);
11638
+ setConfirmOpen(false);
11639
+ setComposeError(error instanceof TypeError ? error.message : "无法读取附件,请重新选择后再试。");
11640
+ return;
11641
+ }
11321
11642
  const request = {
11322
11643
  to: validated.value.to,
11323
11644
  cc: validated.value.cc,
11324
11645
  subject: validated.value.subject,
11325
- bodyText: validated.value.bodyText
11646
+ bodyText: validated.value.bodyText,
11647
+ ...encodedAttachments.length === 0 ? {} : { attachments: encodedAttachments }
11326
11648
  };
11327
11649
  const result = await props.sendMail(request);
11328
11650
  setSending(false);
@@ -11335,7 +11657,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11335
11657
  setComposeError("邮件服务没有接受本次发送,请检查内容后重试。");
11336
11658
  return;
11337
11659
  }
11338
- const warningText = result.value.warnings.length === 0 ? "" : `,服务返回 ${result.value.warnings.length} 条提示`;
11660
+ const acceptedWithWarning = result.value.warnings.length > 0;
11339
11661
  clearDraft();
11340
11662
  setFolder("sent");
11341
11663
  const storage = browserLocalStorage();
@@ -11348,9 +11670,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11348
11670
  setCompose(false);
11349
11671
  setPane("list");
11350
11672
  refresh("sent");
11351
- showNotice(`邮件已发送${warningText}。`);
11673
+ showNotice(acceptedWithWarning ? `邮件已被服务接受,但返回 ${result.value.warnings.length} 条本地记录提示,请勿立即重复发送。` : "邮件已发送。");
11352
11674
  };
11353
- const dirty = to.trim() !== "" || cc.trim() !== "" || subject.trim() !== "" || bodyText.trim() !== "";
11675
+ const dirty = to.trim() !== "" || cc.trim() !== "" || subject.trim() !== "" || bodyText.trim() !== "" || attachments.length > 0;
11354
11676
  const cancelCompose = () => {
11355
11677
  if (dirty) {
11356
11678
  setDiscardOpen(true);
@@ -11360,6 +11682,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11360
11682
  setPane("list");
11361
11683
  };
11362
11684
  const selectedSummary = items.find((item) => item.id === selectedId);
11685
+ const attachmentTotalBytes = attachments.reduce((sum, attachment) => sum + attachment.sizeBytes, 0);
11686
+ const downloadAttachment = async (attachment) => {
11687
+ if (message === null || attachmentLimits === null) return;
11688
+ const expected = downloadableMailAttachment(attachment, attachmentLimits.maxBytes);
11689
+ if (expected === void 0 || downloadStates[attachment.index]?.status === "loading") return;
11690
+ const generation = detailGeneration.current;
11691
+ const localMessageId = message.summary.id;
11692
+ setDownloadStates((current) => ({
11693
+ ...current,
11694
+ [attachment.index]: { status: "loading" }
11695
+ }));
11696
+ try {
11697
+ if (!await downloadAndSaveMailAttachment(props.downloadMailAttachment, {
11698
+ localMessageId,
11699
+ attachmentIndex: attachment.index
11700
+ }, expected, attachmentLimits.maxBytes, () => generation === detailGeneration.current && message.summary.id === localMessageId)) return;
11701
+ setDownloadStates((current) => {
11702
+ const next = { ...current };
11703
+ delete next[attachment.index];
11704
+ return next;
11705
+ });
11706
+ showNotice(`已开始下载 ${expected.fileName}。`);
11707
+ } catch (error) {
11708
+ if (generation !== detailGeneration.current || message.summary.id !== localMessageId) return;
11709
+ setDownloadStates((current) => ({
11710
+ ...current,
11711
+ [attachment.index]: {
11712
+ status: "error",
11713
+ error: error instanceof TypeError ? error.message : "无法保存附件,请重试。"
11714
+ }
11715
+ }));
11716
+ }
11717
+ };
11363
11718
  return (0, react_jsx_runtime.jsxs)("div", {
11364
11719
  className: _dsh_awiki_css_AwikiMail_module_css_default.mail,
11365
11720
  "data-pane": pane,
@@ -11425,19 +11780,31 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11425
11780
  children: [
11426
11781
  (0, react_jsx_runtime.jsxs)("header", {
11427
11782
  className: _dsh_awiki_css_AwikiMail_module_css_default.listHeader,
11428
- children: [(0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("strong", { children: MAIL_FOLDER_COPY[folder].title }), (0, react_jsx_runtime.jsxs)("small", { children: [
11429
- items.length,
11430
- " 封邮件",
11431
- folder === "inbox" && visibleUnreadCount > 0 ? ` · ${visibleUnreadCount} 封未读` : ""
11432
- ] })] }), (0, react_jsx_runtime.jsx)("button", {
11433
- type: "button",
11434
- "aria-label": `刷新${MAIL_FOLDER_COPY[folder].title}`,
11435
- disabled: listLoading,
11436
- onClick: () => {
11437
- refresh();
11438
- },
11439
- children: listLoading ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLoadingOutline16, { size: 15 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline14, { size: 15 })
11440
- })]
11783
+ children: [
11784
+ (0, react_jsx_runtime.jsx)("button", {
11785
+ type: "button",
11786
+ className: _dsh_awiki_css_AwikiMail_module_css_default.listBack,
11787
+ "aria-label": "返回邮箱导航",
11788
+ onClick: () => {
11789
+ setPane("folders");
11790
+ },
11791
+ children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutline14, { size: 14 })
11792
+ }),
11793
+ (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("strong", { children: MAIL_FOLDER_COPY[folder].title }), (0, react_jsx_runtime.jsxs)("small", { children: [
11794
+ items.length,
11795
+ " 封邮件",
11796
+ folder === "inbox" && visibleUnreadCount > 0 ? ` · ${visibleUnreadCount} 封未读` : ""
11797
+ ] })] }),
11798
+ (0, react_jsx_runtime.jsx)("button", {
11799
+ type: "button",
11800
+ "aria-label": `刷新${MAIL_FOLDER_COPY[folder].title}`,
11801
+ disabled: listLoading,
11802
+ onClick: () => {
11803
+ refresh();
11804
+ },
11805
+ children: listLoading ? (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconLoadingOutline16, { size: 15 }) : (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconRefreshOutline14, { size: 15 })
11806
+ })
11807
+ ]
11441
11808
  }),
11442
11809
  listError !== null && (0, react_jsx_runtime.jsxs)("div", {
11443
11810
  className: _dsh_awiki_css_AwikiMail_module_css_default.inlineError,
@@ -11498,7 +11865,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11498
11865
  "aria-label": `返回${MAIL_FOLDER_COPY[folder].title}`,
11499
11866
  onClick: cancelCompose,
11500
11867
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutline14, { size: 14 })
11501
- }), (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("strong", { children: "写邮件" }), (0, react_jsx_runtime.jsx)("small", { children: "发送纯文本邮件" })] })]
11868
+ }), (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)("strong", { children: "写邮件" }), (0, react_jsx_runtime.jsx)("small", { children: "发送纯文本邮件,可添加附件" })] })]
11502
11869
  }),
11503
11870
  (0, react_jsx_runtime.jsxs)("div", {
11504
11871
  className: _dsh_awiki_css_AwikiMail_module_css_default.composeFields,
@@ -11506,6 +11873,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11506
11873
  (0, react_jsx_runtime.jsxs)("label", { children: ["收件人", (0, react_jsx_runtime.jsx)("textarea", {
11507
11874
  value: to,
11508
11875
  rows: 1,
11876
+ disabled: sending,
11509
11877
  autoFocus: true,
11510
11878
  placeholder: "alice@example.com,可用逗号或换行分隔",
11511
11879
  onChange: (event) => {
@@ -11516,6 +11884,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11516
11884
  (0, react_jsx_runtime.jsxs)("label", { children: ["抄送", (0, react_jsx_runtime.jsx)("textarea", {
11517
11885
  value: cc,
11518
11886
  rows: 1,
11887
+ disabled: sending,
11519
11888
  placeholder: "选填",
11520
11889
  onChange: (event) => {
11521
11890
  setCc(event.target.value);
@@ -11524,6 +11893,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11524
11893
  })] }),
11525
11894
  (0, react_jsx_runtime.jsxs)("label", { children: ["主题", (0, react_jsx_runtime.jsx)("input", {
11526
11895
  value: subject,
11896
+ disabled: sending,
11527
11897
  placeholder: "邮件主题",
11528
11898
  onChange: (event) => {
11529
11899
  setSubject(event.target.value);
@@ -11534,6 +11904,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11534
11904
  className: _dsh_awiki_css_AwikiMail_module_css_default.bodyField,
11535
11905
  children: ["正文", (0, react_jsx_runtime.jsx)("textarea", {
11536
11906
  value: bodyText,
11907
+ disabled: sending,
11537
11908
  placeholder: "输入纯文本邮件正文",
11538
11909
  onChange: (event) => {
11539
11910
  setBodyText(event.target.value);
@@ -11541,6 +11912,65 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11541
11912
  }
11542
11913
  })]
11543
11914
  }),
11915
+ (0, react_jsx_runtime.jsxs)("section", {
11916
+ className: _dsh_awiki_css_AwikiMail_module_css_default.composeAttachments,
11917
+ "aria-label": "邮件附件",
11918
+ children: [(0, react_jsx_runtime.jsxs)("div", {
11919
+ className: _dsh_awiki_css_AwikiMail_module_css_default.attachmentPickerRow,
11920
+ children: [
11921
+ (0, react_jsx_runtime.jsxs)("button", {
11922
+ type: "button",
11923
+ className: _dsh_awiki_css_AwikiMail_module_css_default.attachmentPicker,
11924
+ disabled: sending || attachmentLimits === null || attachmentLimits.maxCount === 0,
11925
+ onClick: () => {
11926
+ fileInput.current?.click();
11927
+ },
11928
+ children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, { size: 14 }), "添加附件"]
11929
+ }),
11930
+ (0, react_jsx_runtime.jsx)("input", {
11931
+ ref: fileInput,
11932
+ className: _dsh_awiki_css_AwikiMail_module_css_default.attachmentInput,
11933
+ type: "file",
11934
+ multiple: true,
11935
+ "aria-label": "选择邮件附件",
11936
+ disabled: sending || attachmentLimits === null || attachmentLimits.maxCount === 0,
11937
+ onChange: (event) => {
11938
+ chooseAttachments(event.currentTarget.files);
11939
+ event.currentTarget.value = "";
11940
+ }
11941
+ }),
11942
+ (0, react_jsx_runtime.jsx)("small", { children: attachmentLimits === null ? "附件限制暂不可用" : `最多 ${attachmentLimits.maxCount} 个 · 单个 ${displayBytes(attachmentLimits.maxBytes)} · 总计 ${displayBytes(attachmentLimits.totalMaxBytes)}` })
11943
+ ]
11944
+ }), attachments.length > 0 && (0, react_jsx_runtime.jsxs)("div", {
11945
+ className: _dsh_awiki_css_AwikiMail_module_css_default.selectedAttachments,
11946
+ children: [attachments.map((attachment) => (0, react_jsx_runtime.jsxs)("div", { children: [
11947
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, { size: 15 }),
11948
+ (0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("strong", { children: attachment.fileName }), (0, react_jsx_runtime.jsxs)("small", { children: [
11949
+ attachment.contentType,
11950
+ " · ",
11951
+ displayBytes(attachment.sizeBytes)
11952
+ ] })] }),
11953
+ (0, react_jsx_runtime.jsx)("button", {
11954
+ type: "button",
11955
+ disabled: sending,
11956
+ "aria-label": `移除附件 ${attachment.fileName}`,
11957
+ onClick: () => {
11958
+ removeAttachment(attachment.id);
11959
+ },
11960
+ children: "移除"
11961
+ })
11962
+ ] }, attachment.id)), (0, react_jsx_runtime.jsxs)("p", { children: [
11963
+ attachments.length,
11964
+ " 个附件 · 共 ",
11965
+ displayBytes(attachmentTotalBytes)
11966
+ ] })]
11967
+ })]
11968
+ }),
11969
+ attachmentError !== null && (0, react_jsx_runtime.jsx)("p", {
11970
+ className: _dsh_awiki_css_AwikiMail_module_css_default.composeError,
11971
+ role: "alert",
11972
+ children: attachmentError
11973
+ }),
11544
11974
  composeError !== null && (0, react_jsx_runtime.jsx)("p", {
11545
11975
  className: _dsh_awiki_css_AwikiMail_module_css_default.composeError,
11546
11976
  role: "alert",
@@ -11559,7 +11989,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11559
11989
  }), (0, react_jsx_runtime.jsxs)("button", {
11560
11990
  type: "submit",
11561
11991
  className: _dsh_awiki_css_AwikiMail_module_css_default.sendButton,
11562
- disabled: sending,
11992
+ disabled: sending || attachmentError !== null,
11563
11993
  children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconSendOutline16, { size: 15 }), "发送"]
11564
11994
  })]
11565
11995
  })
@@ -11584,8 +12014,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11584
12014
  className: _dsh_awiki_css_AwikiMail_module_css_default.detailBack,
11585
12015
  "aria-label": `返回${MAIL_FOLDER_COPY[folder].title}`,
11586
12016
  onClick: () => {
12017
+ detailGeneration.current += 1;
11587
12018
  setSelectedId(null);
11588
12019
  setMessage(null);
12020
+ setDownloadStates({});
11589
12021
  setPane("list");
11590
12022
  },
11591
12023
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronLeftOutline14, { size: 14 })
@@ -11641,8 +12073,33 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11641
12073
  }),
11642
12074
  message.attachments.length > 0 && (0, react_jsx_runtime.jsxs)("section", {
11643
12075
  className: _dsh_awiki_css_AwikiMail_module_css_default.attachments,
11644
- "aria-label": "附件元数据",
11645
- children: [(0, react_jsx_runtime.jsx)("h4", { children: "附件(仅元数据)" }), message.attachments.map((attachment) => (0, react_jsx_runtime.jsxs)("div", { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, { size: 15 }), (0, react_jsx_runtime.jsxs)("span", { children: [(0, react_jsx_runtime.jsx)("strong", { children: attachment.fileName ?? `附件 ${attachment.index + 1}` }), (0, react_jsx_runtime.jsx)("small", { children: [attachment.contentType, attachment.sizeBytes === void 0 ? void 0 : `${attachment.sizeBytes} bytes`].filter(Boolean).join(" · ") || "暂无更多信息" })] })] }, attachment.index))]
12076
+ "aria-label": "邮件附件",
12077
+ children: [(0, react_jsx_runtime.jsx)("h4", { children: "附件" }), message.attachments.map((attachment) => {
12078
+ const downloadable = attachmentLimits === null ? void 0 : downloadableMailAttachment(attachment, attachmentLimits.maxBytes);
12079
+ const state = downloadStates[attachment.index];
12080
+ return (0, react_jsx_runtime.jsxs)("div", { children: [
12081
+ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconPaperclipOutline16, { size: 15 }),
12082
+ (0, react_jsx_runtime.jsxs)("span", { children: [
12083
+ (0, react_jsx_runtime.jsx)("strong", { children: attachment.fileName ?? `附件 ${attachment.index + 1}` }),
12084
+ (0, react_jsx_runtime.jsx)("small", { children: [attachment.contentType, attachment.sizeBytes === void 0 ? void 0 : `${attachment.sizeBytes} bytes`].filter(Boolean).join(" · ") || "暂无更多信息" }),
12085
+ downloadable === void 0 && (0, react_jsx_runtime.jsx)("small", { children: "当前记录缺少完整、可验证的下载元数据。" }),
12086
+ state?.status === "error" && (0, react_jsx_runtime.jsx)("small", {
12087
+ className: _dsh_awiki_css_AwikiMail_module_css_default.attachmentDownloadError,
12088
+ role: "alert",
12089
+ children: state.error
12090
+ })
12091
+ ] }),
12092
+ downloadable !== void 0 && (0, react_jsx_runtime.jsx)("button", {
12093
+ type: "button",
12094
+ disabled: state?.status === "loading",
12095
+ "aria-label": `${state?.status === "error" ? "重试下载" : "下载附件"} ${downloadable.fileName}`,
12096
+ onClick: () => {
12097
+ downloadAttachment(attachment);
12098
+ },
12099
+ children: state?.status === "loading" ? "下载中…" : state?.status === "error" ? "重试" : "下载"
12100
+ })
12101
+ ] }, attachment.index);
12102
+ })]
11646
12103
  })
11647
12104
  ]
11648
12105
  })
@@ -11695,7 +12152,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11695
12152
  splitAddresses(cc).length,
11696
12153
  " 人"
11697
12154
  ] }),
11698
- (0, react_jsx_runtime.jsxs)("p", { children: ["主题:", subject.trim()] })
12155
+ (0, react_jsx_runtime.jsxs)("p", { children: ["主题:", subject.trim()] }),
12156
+ (0, react_jsx_runtime.jsxs)("p", { children: [
12157
+ "附件:",
12158
+ attachments.length,
12159
+ " 个 · 共 ",
12160
+ displayBytes(attachmentTotalBytes)
12161
+ ] }),
12162
+ attachments.map((attachment) => (0, react_jsx_runtime.jsxs)("p", { children: [
12163
+ attachment.fileName,
12164
+ " · ",
12165
+ attachment.contentType,
12166
+ " · ",
12167
+ displayBytes(attachment.sizeBytes)
12168
+ ] }, attachment.id))
11699
12169
  ]
11700
12170
  })
11701
12171
  }),
@@ -11706,7 +12176,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11706
12176
  },
11707
12177
  title: "放弃这封邮件?",
11708
12178
  closeLabel: "继续编辑",
11709
- description: "首版不会保存草稿,放弃后当前内容将被清空。",
12179
+ description: "当前不会保存草稿,放弃后文字和附件选择都会被清空。",
11710
12180
  footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
11711
12181
  type: "button",
11712
12182
  variant: "outline",
@@ -11727,7 +12197,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
11727
12197
  })] }),
11728
12198
  children: (0, react_jsx_runtime.jsx)("p", {
11729
12199
  className: _dsh_awiki_css_AwikiMail_module_css_default.discardText,
11730
- children: "收件人、主题和正文中的未发送内容都会丢失。"
12200
+ children: "收件人、主题、正文和已选择的附件都会丢失。"
11731
12201
  })
11732
12202
  })
11733
12203
  ]
@@ -14652,11 +15122,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
14652
15122
  onChange: setMode
14653
15123
  }),
14654
15124
  onUnreadCountChange: setMailUnreadCount,
15125
+ getConfig: props.getConfig,
14655
15126
  getMailAccount: props.getMailAccount,
14656
15127
  listMailInbox: props.listMailInbox,
14657
15128
  readMail: props.readMail,
14658
15129
  markMailRead: props.markMailRead,
14659
- sendMail: props.sendMail
15130
+ sendMail: props.sendMail,
15131
+ downloadMailAttachment: props.downloadMailAttachment
14660
15132
  }, view.identity.did)
14661
15133
  })] }),
14662
15134
  composeDirect && (0, react_jsx_runtime.jsx)("div", {
@@ -15246,16 +15718,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15246
15718
  /** Bilingual copy for the AWiki identity and installation settings page. */
15247
15719
  const zh = {
15248
15720
  nav: "AWiki",
15249
- intro: "管理 AWiki 身份、域名与本地数据设置。",
15250
- domainLabel: "默认域名",
15251
- domainDescription: "输入纯域名,不要包含协议、路径或端口。",
15721
+ intro: "管理 AWiki 租户、身份与本地数据设置。",
15722
+ domainLabel: "租户域名",
15723
+ domainDescription: "输入纯域名;重启后 User、Message、Mail 与附件服务都会切换到该域名。",
15252
15724
  defaultValue: "默认值:{domain}",
15253
15725
  save: "保存",
15254
15726
  saving: "保存中…",
15255
15727
  reset: "恢复默认值",
15256
15728
  saved: "已保存。",
15257
15729
  restartNotice: "重启 DeepSeek Harness 后生效。",
15258
- identityNotice: "此设置仅影响后续注册和短 Handle 的域名补全,不会改写已经注册的 DID 或 Handle。",
15730
+ identityNotice: "不同域名使用相互隔离的本地身份、消息与身份恢复进度。切回原域名时会恢复该域名原有的本地状态。",
15259
15731
  invalidDomain: "请输入有效的域名,例如 awiki.ai。",
15260
15732
  saveFailed: "未能保存设置,请刷新后重试。",
15261
15733
  loading: "正在读取 AWiki 设置…",
@@ -15278,16 +15750,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15278
15750
  };
15279
15751
  const en = {
15280
15752
  nav: "AWiki",
15281
- intro: "Manage AWiki identity, domain, and local data settings.",
15282
- domainLabel: "Default domain",
15283
- domainDescription: "Enter a bare domain without a protocol, path, or port.",
15753
+ intro: "Manage the AWiki tenant, identity, and local data settings.",
15754
+ domainLabel: "Tenant domain",
15755
+ domainDescription: "Enter a bare domain. After restart, User, Message, Mail, and attachment services all switch to it.",
15284
15756
  defaultValue: "Default: {domain}",
15285
15757
  save: "Save",
15286
15758
  saving: "Saving…",
15287
15759
  reset: "Restore default",
15288
15760
  saved: "Saved.",
15289
15761
  restartNotice: "Restart DeepSeek Harness for the change to take effect.",
15290
- identityNotice: "This affects future registrations and short-Handle completion. It does not rewrite an existing DID or Handle.",
15762
+ identityNotice: "Each domain uses isolated local identity, message, and identity-recovery state. Switching back restores that domain’s previous local state.",
15291
15763
  invalidDomain: "Enter a valid domain, such as awiki.ai.",
15292
15764
  saveFailed: "The setting could not be saved. Refresh and try again.",
15293
15765
  loading: "Loading AWiki settings…",
@@ -15576,11 +16048,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
15576
16048
  value: void 0
15577
16049
  } : result;
15578
16050
  },
16051
+ getConfig: () => awiki.getConfig(),
15579
16052
  getMailAccount: () => awiki.getMailAccount(),
15580
16053
  listMailInbox: (request) => awiki.listMailInbox(request),
15581
16054
  readMail: (request) => awiki.readMail(request),
15582
16055
  markMailRead: (request) => awiki.markMailRead(request),
15583
- sendMail: (request) => awiki.sendMail(request)
16056
+ sendMail: (request) => awiki.sendMail(request),
16057
+ downloadMailAttachment: (request) => awiki.downloadMailAttachment(request)
15584
16058
  })
15585
16059
  }, AwikiOverlay);
15586
16060
  });