@zaclinley/dsh-mailharbor 0.1.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -5
- package/README.md +29 -3
- package/README.zh.md +27 -3
- package/lib/client.js +467 -334
- package/lib/client.js.map +4 -4
- package/lib/index.js +44 -34
- package/lib/index.js.map +3 -3
- package/package.json +4 -2
- package/scripts/migrate-legacy.mjs +318 -0
package/lib/client.js
CHANGED
|
@@ -34,7 +34,7 @@ __export(index_exports, {
|
|
|
34
34
|
module.exports = __toCommonJS(index_exports);
|
|
35
35
|
|
|
36
36
|
// src/client/styles.css
|
|
37
|
-
var styles_default = "/* MailHarbor panel + settings. Colors come from the DSH shell tokens with\n light-mode fallbacks so the plugin also renders in a bare host page. */\n\n.mailharbor {\n --m-bg: var(--dsw-alias-bg-base, #ffffff);\n --m-bg-1: var(--dsw-alias-bg-layer-1, #f6f7f9);\n --m-bg-2: var(--dsw-alias-bg-layer-2, #eceef2);\n --m-bg-3: var(--dsw-alias-bg-layer-3, #e4e7ec);\n --m-line: var(--dsw-alias-border-l2, rgba(15, 23, 42, 0.1));\n --m-line-soft: var(--dsw-alias-border-l1, rgba(15, 23, 42, 0.06));\n --m-text: var(--dsw-alias-label-primary, #171a21);\n --m-text-2: var(--dsw-alias-label-secondary, #565c67);\n --m-text-3: var(--dsw-alias-label-tertiary, #8a909c);\n --m-brand: var(--dsw-alias-brand-primary, #4d6bfe);\n --m-brand-soft: color-mix(in srgb, var(--m-brand) 12%, transparent);\n --m-hover: var(--dsw-alias-interactive-bg-hover, rgba(15, 23, 42, 0.05));\n --m-danger: var(--dsw-alias-label-error, #d93025);\n --m-ok: var(--dsw-alias-state-success-primary, #1a9e5c);\n --m-warn: var(--dsw-alias-state-warn-primary, #d88a2a);\n\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n background: var(--m-bg);\n color: var(--m-text);\n font-size: 13px;\n line-height: 1.5;\n}\n\n.mailharbor *,\n.mailharbor *::before,\n.mailharbor *::after {\n box-sizing: border-box;\n}\n\n/* ---------- shell ---------- */\n\n.mailharbor-topbar {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-body {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n\n.mailharbor-list {\n display: flex;\n flex-direction: column;\n width: 340px;\n flex: none;\n border-right: 1px solid var(--m-line-soft);\n min-height: 0;\n}\n\n.mailharbor-reader {\n flex: 1;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n@media (max-width: 900px) {\n .mailharbor-list {\n width: 280px;\n }\n}\n\n.mailharbor-narrow .mailharbor-body[data-mode='reader'] .mailharbor-list {\n display: none;\n}\n\n.mailharbor-narrow .mailharbor-body[data-mode='list'] .mailharbor-reader {\n display: none;\n}\n\n/* ---------- controls ---------- */\n\n.mailharbor button {\n font: inherit;\n color: inherit;\n background: transparent;\n border: 1px solid transparent;\n border-radius: 7px;\n padding: 5px 9px;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n white-space: nowrap;\n}\n\n.mailharbor button:hover:not(:disabled) {\n background: var(--m-hover);\n}\n\n.mailharbor button:disabled {\n opacity: 0.5;\n cursor: default;\n}\n\n.mailharbor button.primary {\n background: var(--m-brand);\n color: #fff;\n}\n\n.mailharbor button.primary:hover:not(:disabled) {\n filter: brightness(1.05);\n background: var(--m-brand);\n}\n\n.mailharbor button.ghost {\n border-color: var(--m-line);\n}\n\n.mailharbor button.subtle {\n color: var(--m-text-2);\n}\n\n.mailharbor button.danger {\n color: var(--m-danger);\n}\n\n.mailharbor input,\n.mailharbor select,\n.mailharbor textarea {\n font: inherit;\n color: inherit;\n background: var(--m-bg-1);\n border: 1px solid var(--m-line);\n border-radius: 7px;\n padding: 6px 8px;\n min-width: 0;\n}\n\n.mailharbor input:focus,\n.mailharbor select:focus,\n.mailharbor textarea:focus,\n.mailharbor [contenteditable='true']:focus {\n outline: 2px solid color-mix(in srgb, var(--m-brand) 45%, transparent);\n outline-offset: -1px;\n}\n\n.mailharbor .spacer {\n flex: 1;\n}\n\n.mailharbor .muted {\n color: var(--m-text-3);\n}\n\n.mailharbor .small {\n font-size: 12px;\n}\n\n.mailharbor .badge {\n font-size: 11px;\n padding: 1px 6px;\n border-radius: 999px;\n background: var(--m-bg-2);\n color: var(--m-text-2);\n}\n\n.mailharbor .badge.ok {\n background: color-mix(in srgb, var(--m-ok) 15%, transparent);\n color: var(--m-ok);\n}\n\n.mailharbor .badge.warn {\n background: color-mix(in srgb, var(--m-warn) 16%, transparent);\n color: var(--m-warn);\n}\n\n.mailharbor .error {\n color: var(--m-danger);\n padding: 8px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n background: color-mix(in srgb, var(--m-danger) 7%, transparent);\n}\n\n/* ---------- list ---------- */\n\n.mailharbor-filters {\n display: flex;\n gap: 8px;\n align-items: center;\n padding: 8px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-filters input[type='search'] {\n flex: 1;\n}\n\n.mailharbor-segment {\n display: inline-flex;\n background: var(--m-bg-2);\n border-radius: 8px;\n padding: 2px;\n gap: 2px;\n}\n\n.mailharbor-segment button {\n padding: 3px 10px;\n border-radius: 6px;\n color: var(--m-text-2);\n}\n\n.mailharbor-segment button.active {\n background: var(--m-bg);\n color: var(--m-text);\n box-shadow: 0 1px 2px rgba(15, 23, 42, 0.12);\n}\n\n.mailharbor-rows {\n flex: 1;\n overflow: auto;\n min-height: 0;\n}\n\n.mailharbor-row {\n display: flex;\n flex-direction: column;\n gap: 2px;\n padding: 9px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n cursor: pointer;\n text-align: left;\n width: 100%;\n border-radius: 0;\n border-left: 2px solid transparent;\n}\n\n.mailharbor-row:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-row.selected {\n background: var(--m-brand-soft);\n border-left-color: var(--m-brand);\n}\n\n.mailharbor-row .line-1,\n.mailharbor-row .line-2 {\n display: flex;\n gap: 8px;\n align-items: baseline;\n min-width: 0;\n}\n\n.mailharbor-row .from {\n font-weight: 600;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-row .date {\n margin-left: auto;\n color: var(--m-text-3);\n font-size: 11px;\n flex: none;\n}\n\n.mailharbor-row .subject {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--m-text-2);\n}\n\n.mailharbor-row.unread .subject,\n.mailharbor-row.unread .from {\n color: var(--m-text);\n}\n\n.mailharbor-row.unread .from::before {\n content: '';\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--m-brand);\n margin-right: 6px;\n vertical-align: middle;\n}\n\n.mailharbor-row .snippet {\n color: var(--m-text-3);\n font-size: 12px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-empty {\n padding: 40px 20px;\n text-align: center;\n color: var(--m-text-3);\n}\n\n/* ---------- reader ---------- */\n\n.mailharbor-reader-head {\n padding: 10px 14px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n display: flex;\n flex-direction: column;\n gap: 6px;\n}\n\n.mailharbor-reader-head h2 {\n margin: 0;\n font-size: 15px;\n line-height: 1.35;\n word-break: break-word;\n}\n\n.mailharbor-reader-meta {\n color: var(--m-text-2);\n font-size: 12px;\n display: flex;\n flex-wrap: wrap;\n gap: 4px 12px;\n}\n\n.mailharbor-reader-actions {\n display: flex;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.mailharbor-reader-body {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n background: var(--m-bg-1);\n}\n\n.mailharbor-reader-body iframe {\n flex: 1;\n width: 100%;\n border: 0;\n background: #fff;\n}\n\n.mailharbor-reader-body pre {\n flex: 1;\n overflow: auto;\n margin: 0;\n padding: 16px 18px;\n white-space: pre-wrap;\n word-break: break-word;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12px;\n line-height: 1.6;\n}\n\n.mailharbor-attachments {\n padding: 8px 14px;\n border-top: 1px solid var(--m-line-soft);\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n flex: none;\n background: var(--m-bg);\n}\n\n.mailharbor-attachment {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n border: 1px solid var(--m-line);\n border-radius: 8px;\n padding: 4px 8px;\n font-size: 12px;\n text-decoration: none;\n color: var(--m-text);\n max-width: 260px;\n}\n\n.mailharbor-attachment:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-attachment span.name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* ---------- modal / form ---------- */\n\n.mailharbor-modal-mask {\n position: fixed;\n inset: 0;\n background: rgba(15, 23, 42, 0.35);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 60;\n padding: 24px;\n}\n\n.mailharbor-modal {\n background: var(--m-bg);\n color: var(--m-text);\n border-radius: 12px;\n box-shadow: 0 18px 60px rgba(15, 23, 42, 0.28);\n width: min(760px, 100%);\n max-height: 100%;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.mailharbor-modal header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 16px;\n border-bottom: 1px solid var(--m-line-soft);\n font-weight: 600;\n}\n\n.mailharbor-modal .content {\n padding: 16px;\n overflow: auto;\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n.mailharbor-modal footer {\n display: flex;\n gap: 8px;\n justify-content: flex-end;\n padding: 12px 16px;\n border-top: 1px solid var(--m-line-soft);\n}\n\n.mailharbor-field {\n display: flex;\n flex-direction: column;\n gap: 4px;\n min-width: 0;\n}\n\n.mailharbor-field > label {\n font-size: 12px;\n color: var(--m-text-2);\n}\n\n.mailharbor-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 10px;\n}\n\n.mailharbor-grid.three {\n grid-template-columns: 2fr 1fr auto;\n}\n\n.mailharbor-toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n color: var(--m-text-2);\n cursor: pointer;\n}\n\n/* ---------- composer ---------- */\n\n.mailharbor-editor {\n min-height: 220px;\n max-height: 46vh;\n overflow: auto;\n padding: 10px 12px;\n border: 1px solid var(--m-line);\n border-radius: 8px;\n background: var(--m-bg);\n outline: none;\n}\n\n.mailharbor-editor:empty::before {\n content: attr(data-placeholder);\n color: var(--m-text-3);\n}\n\n.mailharbor-toolbar {\n display: flex;\n gap: 2px;\n flex-wrap: wrap;\n}\n\n.mailharbor-toolbar button {\n padding: 3px 8px;\n font-size: 12px;\n border: 1px solid transparent;\n}\n\n.mailharbor-toolbar button:hover {\n border-color: var(--m-line);\n}\n\n/* ---------- settings ---------- */\n\n.mailharbor-settings {\n padding: 16px 20px 40px;\n display: flex;\n flex-direction: column;\n gap: 18px;\n max-width: 860px;\n}\n\n.mailharbor-settings h2 {\n margin: 0 0 4px;\n font-size: 15px;\n}\n\n.mailharbor-settings h3 {\n margin: 0 0 8px;\n font-size: 13px;\n color: var(--m-text-2);\n font-weight: 600;\n}\n\n.mailharbor-card {\n border: 1px solid var(--m-line-soft);\n border-radius: 10px;\n padding: 14px;\n display: flex;\n flex-direction: column;\n gap: 10px;\n background: var(--m-bg);\n}\n\n.mailharbor-account-row {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.mailharbor-account-row .avatar {\n width: 30px;\n height: 30px;\n border-radius: 50%;\n background: var(--m-brand-soft);\n color: var(--m-brand);\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 600;\n flex: none;\n}\n\n.mailharbor-log {\n background: var(--m-bg-1);\n border-radius: 8px;\n padding: 8px 10px;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n line-height: 1.5;\n max-height: 220px;\n overflow: auto;\n white-space: pre-wrap;\n}\n\n.mailharbor-kv {\n display: grid;\n grid-template-columns: minmax(120px, 180px) 1fr;\n gap: 4px 12px;\n font-size: 12px;\n}\n\n.mailharbor-kv dt {\n color: var(--m-text-3);\n}\n\n.mailharbor-kv dd {\n margin: 0;\n word-break: break-all;\n}\n";
|
|
37
|
+
var styles_default = "/* MailHarbor panel + settings.\n Tokens come from the DSH shell (dark by default); fallbacks match the\n default dark theme so the panel also renders in a bare host page.\n Component rules are all scoped under `.mailharbor` and the generic element\n reset lives in `:where()` so it cannot outrank a component class. */\n\n.mailharbor {\n --m-bg: var(--dsw-alias-bg-base, #151517);\n --m-bg-1: var(--dsw-alias-bg-layer-1, #232324);\n --m-bg-2: var(--dsw-alias-bg-layer-2, #2c2c2e);\n --m-bg-3: var(--dsw-alias-bg-layer-3, #353638);\n --m-line: var(--dsw-alias-border-l2, #ffffff1f);\n --m-line-soft: var(--dsw-alias-border-l1, #ffffff0f);\n --m-line-strong: var(--dsw-alias-border-l3, #ffffff29);\n --m-text: var(--dsw-alias-label-primary, #f9fafb);\n --m-text-2: var(--dsw-alias-label-secondary, #cfd3d6);\n --m-text-3: var(--dsw-alias-label-tertiary, #adb2b8);\n --m-caption: var(--dsw-alias-label-caption, #81858c);\n --m-accent: #5686fe;\n --m-accent-soft: rgba(86, 134, 254, 0.14);\n --m-primary-bg: var(--dsw-alias-brand-primary, #f9fafb);\n --m-primary-fg: var(--dsw-alias-label-primary-foreground, #0f1115);\n --m-hover: var(--dsw-alias-interactive-bg-hover, #ffffff14);\n --m-danger: #f25a5a;\n --m-ok: #3fbf7f;\n --m-warn: var(--dsw-alias-state-warn-label, #dd8629);\n --m-radius: 8px;\n --m-shadow: 0 18px 60px rgba(0, 0, 0, 0.5);\n\n display: flex;\n flex-direction: column;\n height: 100%;\n min-height: 0;\n background: var(--m-bg);\n color: var(--m-text);\n font-size: 13px;\n line-height: 1.5;\n -webkit-font-smoothing: antialiased;\n}\n\n.mailharbor *,\n.mailharbor *::before,\n.mailharbor *::after {\n box-sizing: border-box;\n}\n\n/* ---------- base controls ---------- */\n\n.mailharbor :where(button) {\n font: inherit;\n color: inherit;\n background: transparent;\n border: 0;\n margin: 0;\n cursor: pointer;\n}\n\n.mailharbor button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 30px;\n padding: 0 12px;\n border-radius: var(--m-radius);\n border: 1px solid transparent;\n color: var(--m-text-2);\n font-size: 12.5px;\n font-weight: 500;\n white-space: nowrap;\n transition:\n background 120ms ease,\n color 120ms ease,\n border-color 120ms ease;\n}\n\n.mailharbor button:hover:not(:disabled) {\n background: var(--m-hover);\n color: var(--m-text);\n}\n\n.mailharbor button:disabled {\n opacity: 0.45;\n cursor: default;\n}\n\n.mailharbor button.primary {\n background: var(--m-primary-bg);\n color: var(--m-primary-fg);\n border-color: transparent;\n}\n\n.mailharbor button.primary:hover:not(:disabled) {\n background: var(--m-primary-bg);\n filter: brightness(0.94);\n color: var(--m-primary-fg);\n}\n\n.mailharbor button.ghost {\n border-color: var(--m-line);\n color: var(--m-text-2);\n}\n\n.mailharbor button.ghost:hover:not(:disabled) {\n border-color: var(--m-line-strong);\n color: var(--m-text);\n}\n\n.mailharbor button.subtle {\n color: var(--m-text-3);\n padding: 0 8px;\n}\n\n.mailharbor button.icon {\n width: 30px;\n padding: 0;\n}\n\n.mailharbor button.danger {\n color: var(--m-danger);\n}\n\n.mailharbor input,\n.mailharbor select,\n.mailharbor textarea {\n font: inherit;\n color: var(--m-text);\n background: var(--m-bg-1);\n border: 1px solid var(--m-line);\n border-radius: var(--m-radius);\n padding: 0 10px;\n height: 32px;\n min-width: 0;\n}\n\n.mailharbor textarea {\n height: auto;\n padding: 8px 10px;\n resize: vertical;\n line-height: 1.6;\n}\n\n.mailharbor select {\n padding-right: 26px;\n appearance: none;\n background-image:\n linear-gradient(45deg, transparent 50%, var(--m-text-3) 50%),\n linear-gradient(135deg, var(--m-text-3) 50%, transparent 50%);\n background-position:\n calc(100% - 15px) 14px,\n calc(100% - 10px) 14px;\n background-size:\n 5px 5px,\n 5px 5px;\n background-repeat: no-repeat;\n}\n\n.mailharbor ::placeholder {\n color: var(--m-caption);\n}\n\n.mailharbor input:focus-visible,\n.mailharbor select:focus-visible,\n.mailharbor textarea:focus-visible,\n.mailharbor button:focus-visible,\n.mailharbor [contenteditable='true']:focus-visible {\n outline: 2px solid rgba(86, 134, 254, 0.55);\n outline-offset: -1px;\n}\n\n.mailharbor .spacer {\n flex: 1;\n}\n\n.mailharbor .muted {\n color: var(--m-text-3);\n}\n\n.mailharbor .small {\n font-size: 12px;\n}\n\n.mailharbor .badge {\n display: inline-flex;\n align-items: center;\n height: 18px;\n padding: 0 6px;\n border-radius: 999px;\n font-size: 10.5px;\n font-weight: 500;\n background: var(--m-bg-3);\n color: var(--m-text-2);\n}\n\n.mailharbor .badge.ok {\n background: rgba(63, 191, 127, 0.16);\n color: var(--m-ok);\n}\n\n.mailharbor .badge.warn {\n background: rgba(221, 134, 41, 0.16);\n color: var(--m-warn);\n}\n\n.mailharbor .error {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 14px;\n color: var(--m-danger);\n background: rgba(242, 90, 90, 0.1);\n border-bottom: 1px solid rgba(242, 90, 90, 0.2);\n font-size: 12.5px;\n}\n\n/* ---------- shell ---------- */\n\n.mailharbor-topbar {\n display: flex;\n align-items: center;\n gap: 10px;\n height: 52px;\n padding: 0 14px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-account {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n max-width: 220px;\n padding: 4px 8px 4px 4px;\n border-radius: 999px;\n border: 1px solid transparent;\n cursor: default;\n}\n\n.mailharbor-account:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-account .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-weight: 500;\n}\n\n.mailharbor-account select {\n height: 26px;\n background: transparent;\n border-color: transparent;\n font-weight: 500;\n}\n\n.mailharbor-body {\n display: flex;\n flex: 1;\n min-height: 0;\n}\n\n.mailharbor-list {\n display: flex;\n flex-direction: column;\n width: 360px;\n flex: none;\n border-right: 1px solid var(--m-line-soft);\n min-height: 0;\n}\n\n.mailharbor-reader {\n flex: 1;\n min-width: 0;\n min-height: 0;\n display: flex;\n flex-direction: column;\n}\n\n@media (max-width: 1000px) {\n .mailharbor-list {\n width: 300px;\n }\n}\n\n.mailharbor-narrow .mailharbor-body[data-mode='reader'] .mailharbor-list {\n display: none;\n}\n\n.mailharbor-narrow .mailharbor-body[data-mode='list'] .mailharbor-reader {\n display: none;\n}\n\n/* ---------- segmented control ---------- */\n\n.mailharbor-segment {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n padding: 2px;\n border-radius: 9px;\n background: var(--m-bg-2);\n}\n\n.mailharbor-segment button {\n height: 26px;\n padding: 0 12px;\n border-radius: 7px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.mailharbor-segment button:hover:not(.active) {\n color: var(--m-text-2);\n background: transparent;\n}\n\n.mailharbor-segment button.active {\n background: var(--m-bg-3);\n color: var(--m-text);\n}\n\n/* ---------- list ---------- */\n\n.mailharbor-filters {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 10px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n}\n\n.mailharbor-filters select {\n width: 128px;\n flex: none;\n font-size: 12px;\n}\n\n.mailharbor-filters input[type='search'] {\n flex: 1;\n height: 30px;\n font-size: 12.5px;\n}\n\n.mailharbor-rows {\n flex: 1;\n overflow: auto;\n min-height: 0;\n}\n\n.mailharbor-row {\n display: flex;\n flex-direction: column;\n gap: 3px;\n width: 100%;\n padding: 10px 14px;\n border: 0;\n border-bottom: 1px solid var(--m-line-soft);\n border-left: 2px solid transparent;\n border-radius: 0;\n background: transparent;\n color: inherit;\n text-align: left;\n cursor: pointer;\n user-select: none;\n}\n\n.mailharbor-row:hover {\n background: var(--m-hover);\n}\n\n.mailharbor-row.selected {\n background: var(--m-accent-soft);\n border-left-color: var(--m-accent);\n}\n\n.mailharbor-row .line-1,\n.mailharbor-row .line-2 {\n display: flex;\n align-items: center;\n gap: 8px;\n min-width: 0;\n width: 100%;\n}\n\n.mailharbor-row .from {\n font-weight: 600;\n font-size: 12.5px;\n color: var(--m-text-2);\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.mailharbor-row .date {\n margin-left: auto;\n color: var(--m-caption);\n font-size: 11px;\n flex: none;\n}\n\n.mailharbor-row .subject {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n color: var(--m-text-2);\n font-size: 12.5px;\n}\n\n.mailharbor-row .snippet {\n color: var(--m-caption);\n font-size: 11.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n width: 100%;\n}\n\n.mailharbor-row.unread .from,\n.mailharbor-row.unread .subject {\n color: var(--m-text);\n}\n\n.mailharbor-row .dot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: var(--m-accent);\n flex: none;\n}\n\n.mailharbor-row .paperclip {\n color: var(--m-caption);\n flex: none;\n display: inline-flex;\n}\n\n.mailharbor-list-foot {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 8px 12px;\n border-top: 1px solid var(--m-line-soft);\n color: var(--m-text-3);\n font-size: 11.5px;\n flex: none;\n}\n\n.mailharbor-empty {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 10px;\n padding: 48px 24px;\n color: var(--m-text-3);\n text-align: center;\n}\n\n.mailharbor-empty svg {\n opacity: 0.5;\n}\n\n.mailharbor-empty .title {\n color: var(--m-text-2);\n font-size: 13px;\n font-weight: 500;\n}\n\n/* ---------- reader ---------- */\n\n.mailharbor-reader-head {\n padding: 16px 20px 12px;\n border-bottom: 1px solid var(--m-line-soft);\n flex: none;\n display: flex;\n flex-direction: column;\n gap: 10px;\n}\n\n.mailharbor-reader-title {\n display: flex;\n align-items: flex-start;\n gap: 10px;\n}\n\n.mailharbor-reader-title h2 {\n margin: 0;\n font-size: 17px;\n line-height: 1.35;\n font-weight: 600;\n letter-spacing: -0.01em;\n word-break: break-word;\n}\n\n.mailharbor-reader-meta {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 4px 10px;\n color: var(--m-text-3);\n font-size: 12px;\n}\n\n.mailharbor-reader-meta .who {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n color: var(--m-text-2);\n}\n\n.mailharbor-reader-meta .who strong {\n color: var(--m-text);\n font-weight: 600;\n}\n\n.mailharbor-reader-actions {\n display: flex;\n align-items: center;\n gap: 6px;\n flex-wrap: wrap;\n}\n\n.mailharbor-reader-body {\n flex: 1;\n min-height: 0;\n display: flex;\n flex-direction: column;\n padding: 14px 18px 18px;\n background: var(--m-bg-2);\n}\n\n.mailharbor-reader-body iframe {\n flex: 1;\n width: 100%;\n border: 0;\n border-radius: 10px;\n background: #fff;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n}\n\n.mailharbor-reader-body pre {\n flex: 1;\n overflow: auto;\n margin: 0;\n padding: 20px 22px;\n white-space: pre-wrap;\n word-break: break-word;\n background: #fff;\n border-radius: 10px;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25);\n color: #171a21;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 12.5px;\n line-height: 1.7;\n}\n\n.mailharbor-attachments {\n padding: 10px 18px;\n border-top: 1px solid var(--m-line-soft);\n display: flex;\n flex-wrap: wrap;\n gap: 8px;\n flex: none;\n background: var(--m-bg);\n}\n\n.mailharbor-attachment {\n display: inline-flex;\n align-items: center;\n gap: 8px;\n height: 30px;\n padding: 0 10px;\n border: 1px solid var(--m-line);\n border-radius: var(--m-radius);\n font-size: 12px;\n text-decoration: none;\n color: var(--m-text-2);\n max-width: 260px;\n background: var(--m-bg-1);\n}\n\n.mailharbor-attachment:hover {\n border-color: var(--m-line-strong);\n color: var(--m-text);\n}\n\n.mailharbor-attachment .name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* ---------- modal / forms ---------- */\n\n.mailharbor-portal {\n position: fixed;\n inset: 0;\n z-index: 80;\n height: auto;\n background: transparent;\n pointer-events: none;\n}\n\n.mailharbor-portal .mailharbor-modal-mask {\n pointer-events: auto;\n}\n\n.mailharbor-modal-mask {\n position: fixed;\n inset: 0;\n z-index: 60;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 24px;\n background: rgba(0, 0, 0, 0.55);\n backdrop-filter: blur(2px);\n}\n\n.mailharbor-modal {\n display: flex;\n flex-direction: column;\n width: min(720px, 100%);\n max-height: 86vh;\n overflow: hidden;\n border: 1px solid var(--m-line);\n border-radius: 14px;\n background: var(--m-bg-1);\n color: var(--m-text);\n box-shadow: var(--m-shadow);\n}\n\n.mailharbor-modal > header {\n display: flex;\n align-items: center;\n gap: 8px;\n height: 52px;\n padding: 0 14px 0 18px;\n border-bottom: 1px solid var(--m-line-soft);\n font-size: 14px;\n font-weight: 600;\n}\n\n.mailharbor-modal .content {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 18px;\n overflow: auto;\n}\n\n.mailharbor-modal > footer {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 12px 18px;\n border-top: 1px solid var(--m-line-soft);\n}\n\n.mailharbor-field {\n display: flex;\n flex-direction: column;\n gap: 5px;\n min-width: 0;\n}\n\n.mailharbor-field > label {\n font-size: 11.5px;\n color: var(--m-text-3);\n}\n\n.mailharbor-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 10px;\n}\n\n.mailharbor-grid.three {\n grid-template-columns: 2fr 90px auto;\n align-items: end;\n}\n\n.mailharbor-toggle {\n display: inline-flex;\n align-items: center;\n gap: 7px;\n color: var(--m-text-2);\n font-size: 12.5px;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.mailharbor-toggle input[type='checkbox'] {\n width: 14px;\n height: 14px;\n accent-color: var(--m-accent);\n}\n\n/* ---------- composer ---------- */\n\n.mailharbor-toolbar {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-wrap: wrap;\n padding: 6px;\n border: 1px solid var(--m-line-soft);\n border-bottom: 0;\n border-radius: 10px 10px 0 0;\n background: var(--m-bg-2);\n}\n\n.mailharbor-toolbar button {\n height: 26px;\n padding: 0 9px;\n border-radius: 6px;\n color: var(--m-text-2);\n font-size: 12px;\n}\n\n.mailharbor-toolbar button:hover {\n background: var(--m-bg-3);\n color: var(--m-text);\n}\n\n.mailharbor-editor {\n min-height: 240px;\n max-height: 44vh;\n overflow: auto;\n padding: 14px 16px;\n border: 1px solid var(--m-line-soft);\n border-radius: 0 0 10px 10px;\n background: #fff;\n color: #171a21;\n outline: none;\n font-size: 13.5px;\n line-height: 1.7;\n}\n\n.mailharbor-editor:empty::before {\n content: attr(data-placeholder);\n color: #9aa0ab;\n}\n\n/* ---------- settings ---------- */\n\n.mailharbor-settings {\n padding: 20px 24px 48px;\n display: flex;\n flex-direction: column;\n gap: 16px;\n max-width: 880px;\n}\n\n.mailharbor-settings h2 {\n margin: 0;\n font-size: 18px;\n font-weight: 600;\n letter-spacing: -0.01em;\n}\n\n.mailharbor-settings h3 {\n margin: 0;\n font-size: 12px;\n font-weight: 600;\n color: var(--m-text-3);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.mailharbor-card {\n display: flex;\n flex-direction: column;\n gap: 12px;\n padding: 16px;\n border: 1px solid var(--m-line-soft);\n border-radius: 12px;\n background: var(--m-bg-1);\n}\n\n.mailharbor-account-row {\n display: flex;\n align-items: center;\n gap: 10px;\n}\n\n.mailharbor-account-row .meta {\n display: flex;\n flex-direction: column;\n min-width: 0;\n}\n\n.mailharbor-account-row .meta strong {\n font-weight: 600;\n}\n\n.mailharbor-account-row .meta span {\n color: var(--m-text-3);\n font-size: 11.5px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.mailharbor .avatar {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex: none;\n border-radius: 50%;\n background: var(--m-accent-soft);\n color: var(--m-accent);\n font-weight: 600;\n}\n\n.mailharbor-log {\n padding: 10px 12px;\n border-radius: 8px;\n background: var(--m-bg);\n border: 1px solid var(--m-line-soft);\n color: var(--m-text-2);\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: 11px;\n line-height: 1.6;\n max-height: 220px;\n overflow: auto;\n white-space: pre-wrap;\n}\n\n.mailharbor-kv {\n display: grid;\n grid-template-columns: minmax(120px, 170px) 1fr;\n gap: 6px 14px;\n font-size: 12px;\n margin: 0;\n}\n\n.mailharbor-kv dt {\n color: var(--m-text-3);\n}\n\n.mailharbor-kv dd {\n margin: 0;\n color: var(--m-text-2);\n word-break: break-all;\n}\n\n.mailharbor hr {\n border: 0;\n border-top: 1px solid var(--m-line-soft);\n margin: 2px 0;\n}\n";
|
|
38
38
|
|
|
39
39
|
// src/client/icon.tsx
|
|
40
40
|
var import_react = require("react");
|
|
@@ -163,16 +163,24 @@ function MailIcon() {
|
|
|
163
163
|
return (0, import_react.createElement)(
|
|
164
164
|
"span",
|
|
165
165
|
{
|
|
166
|
-
style: {
|
|
166
|
+
style: {
|
|
167
|
+
position: "relative",
|
|
168
|
+
display: "inline-flex",
|
|
169
|
+
alignItems: "center",
|
|
170
|
+
justifyContent: "center",
|
|
171
|
+
width: "18px",
|
|
172
|
+
height: "18px",
|
|
173
|
+
boxSizing: "border-box"
|
|
174
|
+
}
|
|
167
175
|
},
|
|
168
176
|
(0, import_react.createElement)(
|
|
169
177
|
"svg",
|
|
170
|
-
{ width:
|
|
171
|
-
(0, import_react.createElement)("rect", { x: 2.5, y: 5, width: 19, height: 14, rx: 2.5, stroke: "currentColor", strokeWidth: 1.
|
|
178
|
+
{ width: 16, height: 16, viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true" },
|
|
179
|
+
(0, import_react.createElement)("rect", { x: 2.5, y: 5, width: 19, height: 14, rx: 2.5, stroke: "currentColor", strokeWidth: 1.7 }),
|
|
172
180
|
(0, import_react.createElement)("path", {
|
|
173
181
|
d: "M3.5 7l7.6 5.4a1.6 1.6 0 0 0 1.8 0L20.5 7",
|
|
174
182
|
stroke: "currentColor",
|
|
175
|
-
strokeWidth: 1.
|
|
183
|
+
strokeWidth: 1.7,
|
|
176
184
|
strokeLinecap: "round"
|
|
177
185
|
})
|
|
178
186
|
),
|
|
@@ -181,18 +189,26 @@ function MailIcon() {
|
|
|
181
189
|
{
|
|
182
190
|
style: {
|
|
183
191
|
position: "absolute",
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
192
|
+
right: "-5px",
|
|
193
|
+
bottom: "-3px",
|
|
194
|
+
display: "flex",
|
|
195
|
+
alignItems: "center",
|
|
196
|
+
justifyContent: "center",
|
|
197
|
+
boxSizing: "border-box",
|
|
198
|
+
minWidth: "13px",
|
|
199
|
+
height: "13px",
|
|
188
200
|
padding: "0 3px",
|
|
189
201
|
borderRadius: "999px",
|
|
190
|
-
background: "
|
|
202
|
+
background: "#5686fe",
|
|
191
203
|
color: "#fff",
|
|
192
204
|
fontSize: "9px",
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
205
|
+
fontWeight: 600,
|
|
206
|
+
lineHeight: "13px",
|
|
207
|
+
zIndex: 1,
|
|
208
|
+
letterSpacing: "-0.01em",
|
|
209
|
+
fontVariantNumeric: "tabular-nums",
|
|
210
|
+
boxShadow: "0 0 0 2px var(--dsw-alias-bg-base, #151517)",
|
|
211
|
+
pointerEvents: "none"
|
|
196
212
|
}
|
|
197
213
|
},
|
|
198
214
|
unread > 99 ? "99+" : String(unread)
|
|
@@ -201,7 +217,7 @@ function MailIcon() {
|
|
|
201
217
|
}
|
|
202
218
|
|
|
203
219
|
// src/client/panel.tsx
|
|
204
|
-
var
|
|
220
|
+
var import_react7 = require("react");
|
|
205
221
|
|
|
206
222
|
// src/client/account-form.tsx
|
|
207
223
|
var import_react3 = require("react");
|
|
@@ -256,6 +272,15 @@ function Toggle({
|
|
|
256
272
|
label
|
|
257
273
|
);
|
|
258
274
|
}
|
|
275
|
+
function portalRoot() {
|
|
276
|
+
const existing = document.getElementById("mailharbor-portal");
|
|
277
|
+
if (existing !== null) return existing;
|
|
278
|
+
const element = document.createElement("div");
|
|
279
|
+
element.id = "mailharbor-portal";
|
|
280
|
+
element.className = "mailharbor mailharbor-portal";
|
|
281
|
+
document.body.append(element);
|
|
282
|
+
return element;
|
|
283
|
+
}
|
|
259
284
|
function Modal({
|
|
260
285
|
title,
|
|
261
286
|
children,
|
|
@@ -301,7 +326,7 @@ function Modal({
|
|
|
301
326
|
footer === void 0 ? null : (0, import_react2.createElement)("footer", null, footer)
|
|
302
327
|
)
|
|
303
328
|
),
|
|
304
|
-
|
|
329
|
+
portalRoot()
|
|
305
330
|
);
|
|
306
331
|
}
|
|
307
332
|
function ErrorBar({ message, onDismiss }) {
|
|
@@ -837,13 +862,68 @@ function Composer({
|
|
|
837
862
|
);
|
|
838
863
|
}
|
|
839
864
|
|
|
840
|
-
// src/client/
|
|
865
|
+
// src/client/icons.tsx
|
|
841
866
|
var import_react5 = require("react");
|
|
867
|
+
var PATHS = {
|
|
868
|
+
refresh: (0, import_react5.createElement)("path", { d: "M20 11a8 8 0 1 0-2.3 5.7M20 5v6h-6" }),
|
|
869
|
+
plus: (0, import_react5.createElement)("path", { d: "M12 5v14M5 12h14" }),
|
|
870
|
+
compose: (0, import_react5.createElement)("path", { d: "M4 20h4l10.5-10.5a2.1 2.1 0 0 0-3-3L5 17v3zM13.5 6.5l3 3" }),
|
|
871
|
+
archive: (0, import_react5.createElement)(
|
|
872
|
+
"g",
|
|
873
|
+
null,
|
|
874
|
+
(0, import_react5.createElement)("rect", { x: 3, y: 4, width: 18, height: 5, rx: 1.5 }),
|
|
875
|
+
(0, import_react5.createElement)("path", { d: "M5 9v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V9M10 13h4" })
|
|
876
|
+
),
|
|
877
|
+
paperclip: (0, import_react5.createElement)("path", {
|
|
878
|
+
d: "M20 11.5 12 19.5a5 5 0 0 1-7-7l8-8a3.3 3.3 0 0 1 4.7 4.7l-8 8a1.7 1.7 0 0 1-2.4-2.4l7.3-7.3"
|
|
879
|
+
}),
|
|
880
|
+
mail: (0, import_react5.createElement)(
|
|
881
|
+
"g",
|
|
882
|
+
null,
|
|
883
|
+
(0, import_react5.createElement)("rect", { x: 3, y: 5, width: 18, height: 14, rx: 2.5 }),
|
|
884
|
+
(0, import_react5.createElement)("path", { d: "m4 7 7.1 5a1.6 1.6 0 0 0 1.8 0L20 7" })
|
|
885
|
+
),
|
|
886
|
+
search: (0, import_react5.createElement)("path", { d: "M11 18a7 7 0 1 0 0-14 7 7 0 0 0 0 14zM20 20l-4-4" }),
|
|
887
|
+
reply: (0, import_react5.createElement)("path", { d: "M9 7 4 12l5 5M4 12h9a6 6 0 0 1 6 6v1" }),
|
|
888
|
+
replyAll: (0, import_react5.createElement)("path", { d: "m9 7-5 5 5 5M14 7l-5 5 5 5M13 12h5a5 5 0 0 1 5 5" }),
|
|
889
|
+
forward: (0, import_react5.createElement)("path", { d: "m15 7 5 5-5 5M20 12h-9a6 6 0 0 0-6 6v1" }),
|
|
890
|
+
check: (0, import_react5.createElement)("path", { d: "m5 13 4 4L19 7" }),
|
|
891
|
+
image: (0, import_react5.createElement)(
|
|
892
|
+
"g",
|
|
893
|
+
null,
|
|
894
|
+
(0, import_react5.createElement)("rect", { x: 3, y: 4, width: 18, height: 16, rx: 2 }),
|
|
895
|
+
(0, import_react5.createElement)("circle", { cx: 8.5, cy: 9.5, r: 1.5 }),
|
|
896
|
+
(0, import_react5.createElement)("path", { d: "m4 18 5-5 4 4 3-3 4 4" })
|
|
897
|
+
),
|
|
898
|
+
close: (0, import_react5.createElement)("path", { d: "M6 6l12 12M18 6 6 18" }),
|
|
899
|
+
chevronLeft: (0, import_react5.createElement)("path", { d: "m14 6-6 6 6 6" })
|
|
900
|
+
};
|
|
901
|
+
function Icon({ name, size = 16 }) {
|
|
902
|
+
return (0, import_react5.createElement)(
|
|
903
|
+
"svg",
|
|
904
|
+
{
|
|
905
|
+
width: size,
|
|
906
|
+
height: size,
|
|
907
|
+
viewBox: "0 0 24 24",
|
|
908
|
+
fill: "none",
|
|
909
|
+
stroke: "currentColor",
|
|
910
|
+
strokeWidth: 1.7,
|
|
911
|
+
strokeLinecap: "round",
|
|
912
|
+
strokeLinejoin: "round",
|
|
913
|
+
"aria-hidden": "true",
|
|
914
|
+
focusable: "false"
|
|
915
|
+
},
|
|
916
|
+
PATHS[name] ?? null
|
|
917
|
+
);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// src/client/reader.tsx
|
|
921
|
+
var import_react6 = require("react");
|
|
842
922
|
var IFRAME_STYLE = `
|
|
843
923
|
html, body { margin: 0; padding: 0; }
|
|
844
924
|
body {
|
|
845
|
-
font: 15px/1.
|
|
846
|
-
color: #171a21; background: #fff; padding:
|
|
925
|
+
font: 15px/1.75 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
926
|
+
color: #171a21; background: #fff; padding: 20px 22px;
|
|
847
927
|
overflow-wrap: anywhere;
|
|
848
928
|
}
|
|
849
929
|
img { max-width: 100%; height: auto; }
|
|
@@ -873,6 +953,9 @@ function escapeHtml(value) {
|
|
|
873
953
|
function hasRemoteImages(detail) {
|
|
874
954
|
return detail.html !== null && /<img[^>]+src=["']https?:/i.test(detail.html);
|
|
875
955
|
}
|
|
956
|
+
function addressLine(list) {
|
|
957
|
+
return list.map((item) => item.name !== "" ? `${item.name} <${item.address}>` : item.address).join("\u3001");
|
|
958
|
+
}
|
|
876
959
|
function Reader({
|
|
877
960
|
detail,
|
|
878
961
|
account,
|
|
@@ -882,11 +965,11 @@ function Reader({
|
|
|
882
965
|
onReply,
|
|
883
966
|
onClose
|
|
884
967
|
}) {
|
|
885
|
-
const [plain, setPlain] = (0,
|
|
886
|
-
const [loadImages, setLoadImages] = (0,
|
|
887
|
-
const [busy, setBusy] = (0,
|
|
888
|
-
const [error, setError] = (0,
|
|
889
|
-
const remoteImages = (0,
|
|
968
|
+
const [plain, setPlain] = (0, import_react6.useState)(false);
|
|
969
|
+
const [loadImages, setLoadImages] = (0, import_react6.useState)(false);
|
|
970
|
+
const [busy, setBusy] = (0, import_react6.useState)(false);
|
|
971
|
+
const [error, setError] = (0, import_react6.useState)("");
|
|
972
|
+
const remoteImages = (0, import_react6.useMemo)(() => hasRemoteImages(detail), [detail]);
|
|
890
973
|
const html = detail.html !== null && detail.html !== "";
|
|
891
974
|
const toggleRead = async () => {
|
|
892
975
|
setBusy(true);
|
|
@@ -906,102 +989,103 @@ function Reader({
|
|
|
906
989
|
setBusy(false);
|
|
907
990
|
}
|
|
908
991
|
};
|
|
909
|
-
return (0,
|
|
992
|
+
return (0, import_react6.createElement)(
|
|
910
993
|
"div",
|
|
911
994
|
{ className: "mailharbor-reader" },
|
|
912
|
-
(0,
|
|
995
|
+
(0, import_react6.createElement)(
|
|
913
996
|
"div",
|
|
914
997
|
{ className: "mailharbor-reader-head" },
|
|
915
|
-
(0,
|
|
998
|
+
(0, import_react6.createElement)(
|
|
916
999
|
"div",
|
|
917
|
-
{
|
|
918
|
-
|
|
919
|
-
|
|
1000
|
+
{ className: "mailharbor-reader-title" },
|
|
1001
|
+
onClose === void 0 ? null : (0, import_react6.createElement)(
|
|
1002
|
+
"button",
|
|
1003
|
+
{ className: "ghost icon", onClick: onClose, "aria-label": "\u8FD4\u56DE\u5217\u8868", title: "\u8FD4\u56DE\u5217\u8868" },
|
|
1004
|
+
(0, import_react6.createElement)(Icon, { name: "chevronLeft" })
|
|
1005
|
+
),
|
|
1006
|
+
(0, import_react6.createElement)("h2", { style: { flex: 1 } }, detail.subject),
|
|
1007
|
+
(0, import_react6.createElement)(
|
|
1008
|
+
"button",
|
|
1009
|
+
{
|
|
1010
|
+
className: "ghost icon",
|
|
1011
|
+
onClick: () => void toggleRead(),
|
|
1012
|
+
disabled: busy,
|
|
1013
|
+
title: detail.unread ? "\u6807\u4E3A\u5DF2\u8BFB" : "\u6807\u4E3A\u672A\u8BFB",
|
|
1014
|
+
"aria-label": detail.unread ? "\u6807\u4E3A\u5DF2\u8BFB" : "\u6807\u4E3A\u672A\u8BFB"
|
|
1015
|
+
},
|
|
1016
|
+
(0, import_react6.createElement)(Icon, { name: "check" })
|
|
1017
|
+
)
|
|
920
1018
|
),
|
|
921
|
-
(0,
|
|
1019
|
+
(0, import_react6.createElement)(
|
|
922
1020
|
"div",
|
|
923
1021
|
{ className: "mailharbor-reader-meta" },
|
|
924
|
-
(0,
|
|
1022
|
+
(0, import_react6.createElement)(
|
|
925
1023
|
"span",
|
|
926
|
-
|
|
927
|
-
|
|
1024
|
+
{ className: "who" },
|
|
1025
|
+
(0, import_react6.createElement)(Avatar, { email: detail.from.address, size: 22 }),
|
|
1026
|
+
(0, import_react6.createElement)("strong", null, detail.from.name !== "" ? detail.from.name : detail.from.address),
|
|
1027
|
+
detail.from.name !== "" ? (0, import_react6.createElement)("span", null, `<${detail.from.address}>`) : null
|
|
928
1028
|
),
|
|
929
|
-
(0,
|
|
930
|
-
detail.backedUp === false ? (0,
|
|
1029
|
+
(0, import_react6.createElement)("span", null, longDate(detail.date)),
|
|
1030
|
+
detail.backedUp === false ? (0, import_react6.createElement)("span", { className: "badge warn" }, "\u672A\u5907\u4EFD") : null
|
|
931
1031
|
),
|
|
932
|
-
(0,
|
|
1032
|
+
(0, import_react6.createElement)(
|
|
933
1033
|
"div",
|
|
934
1034
|
{ className: "mailharbor-reader-meta" },
|
|
935
|
-
(0,
|
|
936
|
-
|
|
937
|
-
null,
|
|
938
|
-
`\u6536\u4EF6\u4EBA: ${detail.to.map((item) => item.name !== "" ? `${item.name} <${item.address}>` : item.address).join(", ") || "\u2014"}`
|
|
939
|
-
),
|
|
940
|
-
detail.cc.length === 0 ? null : (0, import_react5.createElement)("span", null, `\u6284\u9001: ${detail.cc.map((item) => item.address).join(", ")}`)
|
|
1035
|
+
(0, import_react6.createElement)("span", null, `\u6536\u4EF6\u4EBA: ${addressLine(detail.to) || "\u2014"}`),
|
|
1036
|
+
detail.cc.length === 0 ? null : (0, import_react6.createElement)("span", null, `\u6284\u9001: ${addressLine(detail.cc)}`)
|
|
941
1037
|
),
|
|
942
|
-
(0,
|
|
1038
|
+
(0, import_react6.createElement)(
|
|
943
1039
|
"div",
|
|
944
1040
|
{ className: "mailharbor-reader-actions" },
|
|
945
|
-
(0,
|
|
1041
|
+
(0, import_react6.createElement)(
|
|
946
1042
|
"button",
|
|
947
|
-
{
|
|
948
|
-
|
|
949
|
-
onClick: () => {
|
|
950
|
-
onReply("reply");
|
|
951
|
-
}
|
|
952
|
-
},
|
|
1043
|
+
{ className: "ghost", onClick: () => onReply("reply") },
|
|
1044
|
+
(0, import_react6.createElement)(Icon, { name: "reply" }),
|
|
953
1045
|
"\u56DE\u590D"
|
|
954
1046
|
),
|
|
955
|
-
(0,
|
|
1047
|
+
(0, import_react6.createElement)(
|
|
956
1048
|
"button",
|
|
957
|
-
{
|
|
958
|
-
|
|
959
|
-
onClick: () => {
|
|
960
|
-
onReply("replyAll");
|
|
961
|
-
}
|
|
962
|
-
},
|
|
1049
|
+
{ className: "ghost", onClick: () => onReply("replyAll") },
|
|
1050
|
+
(0, import_react6.createElement)(Icon, { name: "replyAll" }),
|
|
963
1051
|
"\u5168\u90E8\u56DE\u590D"
|
|
964
1052
|
),
|
|
965
|
-
(0,
|
|
1053
|
+
(0, import_react6.createElement)(
|
|
966
1054
|
"button",
|
|
967
|
-
{
|
|
968
|
-
|
|
969
|
-
onClick: () => {
|
|
970
|
-
onReply("forward");
|
|
971
|
-
}
|
|
972
|
-
},
|
|
1055
|
+
{ className: "ghost", onClick: () => onReply("forward") },
|
|
1056
|
+
(0, import_react6.createElement)(Icon, { name: "forward" }),
|
|
973
1057
|
"\u8F6C\u53D1"
|
|
974
1058
|
),
|
|
975
|
-
(0,
|
|
976
|
-
(0,
|
|
977
|
-
"button",
|
|
978
|
-
{ className: "ghost", onClick: () => void toggleRead(), disabled: busy },
|
|
979
|
-
detail.unread ? "\u6807\u4E3A\u5DF2\u8BFB" : "\u6807\u4E3A\u672A\u8BFB"
|
|
980
|
-
),
|
|
981
|
-
html ? (0, import_react5.createElement)(
|
|
1059
|
+
(0, import_react6.createElement)("span", { className: "spacer" }),
|
|
1060
|
+
html ? (0, import_react6.createElement)(
|
|
982
1061
|
"button",
|
|
983
|
-
{ className: "
|
|
984
|
-
plain ? "\u663E\u793A HTML" : "\
|
|
1062
|
+
{ className: "subtle", onClick: () => setPlain(!plain) },
|
|
1063
|
+
plain ? "\u663E\u793A HTML" : "\u7EAF\u6587\u672C"
|
|
985
1064
|
) : null,
|
|
986
|
-
remoteImages && !loadImages ? (0,
|
|
1065
|
+
remoteImages && !loadImages ? (0, import_react6.createElement)(
|
|
1066
|
+
"button",
|
|
1067
|
+
{ className: "subtle", onClick: () => setLoadImages(true) },
|
|
1068
|
+
(0, import_react6.createElement)(Icon, { name: "image", size: 14 }),
|
|
1069
|
+
"\u663E\u793A\u56FE\u7247"
|
|
1070
|
+
) : null
|
|
987
1071
|
),
|
|
988
|
-
error === "" ? null : (0,
|
|
1072
|
+
error === "" ? null : (0, import_react6.createElement)("div", { className: "small", style: { color: "var(--m-danger)" } }, error)
|
|
989
1073
|
),
|
|
990
|
-
(0,
|
|
1074
|
+
(0, import_react6.createElement)(
|
|
991
1075
|
"div",
|
|
992
1076
|
{ className: "mailharbor-reader-body" },
|
|
993
|
-
html && !plain ? (0,
|
|
1077
|
+
html && !plain ? (0, import_react6.createElement)("iframe", {
|
|
994
1078
|
title: "\u90AE\u4EF6\u6B63\u6587",
|
|
995
1079
|
sandbox: "",
|
|
996
1080
|
srcDoc: srcDoc(detail, loadImages),
|
|
997
1081
|
referrerPolicy: "no-referrer"
|
|
998
|
-
}) : (0,
|
|
1082
|
+
}) : (0, import_react6.createElement)("pre", null, detail.text !== "" ? detail.text : "\uFF08\u65E0\u6B63\u6587\uFF09")
|
|
999
1083
|
),
|
|
1000
|
-
detail.attachments.length === 0 ? null : (0,
|
|
1084
|
+
detail.attachments.length === 0 ? null : (0, import_react6.createElement)(
|
|
1001
1085
|
"div",
|
|
1002
1086
|
{ className: "mailharbor-attachments" },
|
|
1003
1087
|
detail.attachments.map(
|
|
1004
|
-
(file) => (0,
|
|
1088
|
+
(file) => (0, import_react6.createElement)(
|
|
1005
1089
|
"a",
|
|
1006
1090
|
{
|
|
1007
1091
|
className: "mailharbor-attachment",
|
|
@@ -1018,10 +1102,12 @@ function Reader({
|
|
|
1018
1102
|
emailId: detail.id,
|
|
1019
1103
|
attachmentId: file.id
|
|
1020
1104
|
}),
|
|
1021
|
-
download: file.filename
|
|
1105
|
+
download: file.filename,
|
|
1106
|
+
title: file.filename
|
|
1022
1107
|
},
|
|
1023
|
-
(0,
|
|
1024
|
-
(0,
|
|
1108
|
+
(0, import_react6.createElement)(Icon, { name: "paperclip", size: 14 }),
|
|
1109
|
+
(0, import_react6.createElement)("span", { className: "name" }, file.filename),
|
|
1110
|
+
(0, import_react6.createElement)("span", { className: "muted small" }, formatBytes(file.size))
|
|
1025
1111
|
)
|
|
1026
1112
|
)
|
|
1027
1113
|
)
|
|
@@ -1033,44 +1119,50 @@ var EMPTY_PAGE = { items: [], total: 0, offset: 0, limit: 40 };
|
|
|
1033
1119
|
function errorText3(error) {
|
|
1034
1120
|
return error instanceof ApiError || error instanceof Error ? error.message : String(error);
|
|
1035
1121
|
}
|
|
1122
|
+
function matchesNarrow() {
|
|
1123
|
+
return typeof window.matchMedia === "function" ? window.matchMedia("(max-width: 900px)").matches : false;
|
|
1124
|
+
}
|
|
1036
1125
|
function quoteForReply(detail) {
|
|
1037
1126
|
const body = detail.html ?? `<pre>${detail.text.replaceAll("&", "&").replaceAll("<", "<")}</pre>`;
|
|
1038
1127
|
return `<p><br></p><p>------------------ \u539F\u59CB\u90AE\u4EF6 ------------------</p><blockquote style="margin:0 0 0 12px;padding-left:12px;border-left:2px solid #d7dbe3;color:#565c67">${body}</blockquote>`;
|
|
1039
1128
|
}
|
|
1040
1129
|
function MailPanel() {
|
|
1041
|
-
const [state, setState] = (0,
|
|
1042
|
-
const [error, setError] = (0,
|
|
1043
|
-
const [source, setSource] = (0,
|
|
1044
|
-
const [mailbox, setMailbox] = (0,
|
|
1045
|
-
const [folders, setFolders] = (0,
|
|
1046
|
-
const [query2, setQuery] = (0,
|
|
1047
|
-
const [search, setSearch] = (0,
|
|
1048
|
-
const [page, setPage] = (0,
|
|
1049
|
-
const [limit, setLimit] = (0,
|
|
1050
|
-
const [loading, setLoading] = (0,
|
|
1051
|
-
const [selected, setSelected] = (0,
|
|
1052
|
-
const [compose, setCompose] = (0,
|
|
1053
|
-
const [showAdd, setShowAdd] = (0,
|
|
1054
|
-
const [showBackup, setShowBackup] = (0,
|
|
1055
|
-
const [backup, setBackup] = (0,
|
|
1056
|
-
const [toast, setToast] = (0,
|
|
1057
|
-
const [narrow, setNarrow] = (0,
|
|
1058
|
-
const [tick, setTick] = (0,
|
|
1130
|
+
const [state, setState] = (0, import_react7.useState)(null);
|
|
1131
|
+
const [error, setError] = (0, import_react7.useState)("");
|
|
1132
|
+
const [source, setSource] = (0, import_react7.useState)("local");
|
|
1133
|
+
const [mailbox, setMailbox] = (0, import_react7.useState)("all");
|
|
1134
|
+
const [folders, setFolders] = (0, import_react7.useState)([]);
|
|
1135
|
+
const [query2, setQuery] = (0, import_react7.useState)("");
|
|
1136
|
+
const [search, setSearch] = (0, import_react7.useState)("");
|
|
1137
|
+
const [page, setPage] = (0, import_react7.useState)(EMPTY_PAGE);
|
|
1138
|
+
const [limit, setLimit] = (0, import_react7.useState)(40);
|
|
1139
|
+
const [loading, setLoading] = (0, import_react7.useState)(false);
|
|
1140
|
+
const [selected, setSelected] = (0, import_react7.useState)(null);
|
|
1141
|
+
const [compose, setCompose] = (0, import_react7.useState)(null);
|
|
1142
|
+
const [showAdd, setShowAdd] = (0, import_react7.useState)(false);
|
|
1143
|
+
const [showBackup, setShowBackup] = (0, import_react7.useState)(false);
|
|
1144
|
+
const [backup, setBackup] = (0, import_react7.useState)(null);
|
|
1145
|
+
const [toast, setToast] = (0, import_react7.useState)("");
|
|
1146
|
+
const [narrow, setNarrow] = (0, import_react7.useState)(() => matchesNarrow());
|
|
1147
|
+
const [tick, setTick] = (0, import_react7.useState)(0);
|
|
1059
1148
|
const account = state?.accounts.find((item) => item.id === state.activeAccountId) ?? null;
|
|
1060
1149
|
const accountId = account?.id ?? null;
|
|
1061
|
-
const refresh = (0,
|
|
1150
|
+
const refresh = (0, import_react7.useCallback)(() => {
|
|
1062
1151
|
setTick((value) => value + 1);
|
|
1063
1152
|
}, []);
|
|
1064
|
-
const notice = (0,
|
|
1153
|
+
const notice = (0, import_react7.useCallback)((message) => {
|
|
1065
1154
|
setToast(message);
|
|
1066
1155
|
window.setTimeout(() => {
|
|
1067
1156
|
setToast("");
|
|
1068
1157
|
}, 3200);
|
|
1069
1158
|
}, []);
|
|
1070
|
-
(0,
|
|
1159
|
+
(0, import_react7.useEffect)(() => {
|
|
1071
1160
|
let cancelled = false;
|
|
1072
1161
|
api.state().then((next) => {
|
|
1073
|
-
if (!cancelled)
|
|
1162
|
+
if (!cancelled) {
|
|
1163
|
+
setState(next);
|
|
1164
|
+
if (next.settings.render.listLimit > 0) setLimit(next.settings.render.listLimit);
|
|
1165
|
+
}
|
|
1074
1166
|
}).catch((caught) => {
|
|
1075
1167
|
if (!cancelled) setError(errorText3(caught));
|
|
1076
1168
|
});
|
|
@@ -1078,12 +1170,12 @@ function MailPanel() {
|
|
|
1078
1170
|
cancelled = true;
|
|
1079
1171
|
};
|
|
1080
1172
|
}, [tick]);
|
|
1081
|
-
(0,
|
|
1173
|
+
(0, import_react7.useEffect)(() => {
|
|
1082
1174
|
if (accountId === null) return;
|
|
1083
1175
|
let cancelled = false;
|
|
1084
1176
|
api.folders({ accountId, source }).then((result) => {
|
|
1085
1177
|
if (cancelled) return;
|
|
1086
|
-
const
|
|
1178
|
+
const items2 = source === "local" ? [
|
|
1087
1179
|
{
|
|
1088
1180
|
name: "all",
|
|
1089
1181
|
label: "\u5168\u90E8\u90AE\u4EF6",
|
|
@@ -1091,7 +1183,7 @@ function MailPanel() {
|
|
|
1091
1183
|
},
|
|
1092
1184
|
...result.items.map((item) => ({ ...item, label: item.label ?? item.name }))
|
|
1093
1185
|
] : result.items.map((item) => ({ ...item, label: item.label ?? item.name }));
|
|
1094
|
-
setFolders(
|
|
1186
|
+
setFolders(items2);
|
|
1095
1187
|
}).catch(() => {
|
|
1096
1188
|
if (!cancelled) setFolders([]);
|
|
1097
1189
|
});
|
|
@@ -1099,12 +1191,11 @@ function MailPanel() {
|
|
|
1099
1191
|
cancelled = true;
|
|
1100
1192
|
};
|
|
1101
1193
|
}, [accountId, source, tick]);
|
|
1102
|
-
(0,
|
|
1194
|
+
(0, import_react7.useEffect)(() => {
|
|
1103
1195
|
setMailbox(source === "local" ? "all" : "INBOX");
|
|
1104
1196
|
setSelected(null);
|
|
1105
|
-
setLimit(state?.settings.render.listLimit ?? 40);
|
|
1106
1197
|
}, [source]);
|
|
1107
|
-
(0,
|
|
1198
|
+
(0, import_react7.useEffect)(() => {
|
|
1108
1199
|
if (accountId === null) return;
|
|
1109
1200
|
let cancelled = false;
|
|
1110
1201
|
setLoading(true);
|
|
@@ -1119,7 +1210,8 @@ function MailPanel() {
|
|
|
1119
1210
|
cancelled = true;
|
|
1120
1211
|
};
|
|
1121
1212
|
}, [accountId, source, mailbox, search, limit, tick]);
|
|
1122
|
-
(0,
|
|
1213
|
+
(0, import_react7.useEffect)(() => {
|
|
1214
|
+
if (typeof window.matchMedia !== "function") return;
|
|
1123
1215
|
const media = window.matchMedia("(max-width: 900px)");
|
|
1124
1216
|
const onChange = () => setNarrow(media.matches);
|
|
1125
1217
|
media.addEventListener("change", onChange);
|
|
@@ -1127,7 +1219,7 @@ function MailPanel() {
|
|
|
1127
1219
|
media.removeEventListener("change", onChange);
|
|
1128
1220
|
};
|
|
1129
1221
|
}, []);
|
|
1130
|
-
(0,
|
|
1222
|
+
(0, import_react7.useEffect)(() => {
|
|
1131
1223
|
if (!showBackup || accountId === null) return;
|
|
1132
1224
|
let cancelled = false;
|
|
1133
1225
|
const poll = async () => {
|
|
@@ -1228,32 +1320,35 @@ function MailPanel() {
|
|
|
1228
1320
|
setError(errorText3(caught));
|
|
1229
1321
|
}
|
|
1230
1322
|
};
|
|
1231
|
-
const folderOptions = (0,
|
|
1323
|
+
const folderOptions = (0, import_react7.useMemo)(
|
|
1232
1324
|
() => folders.map((folder) => ({
|
|
1233
1325
|
value: folder.name,
|
|
1234
1326
|
label: `${folder.label ?? folder.name}${folder.count > 0 ? ` (${String(folder.count)})` : ""}`
|
|
1235
1327
|
})),
|
|
1236
1328
|
[folders]
|
|
1237
1329
|
);
|
|
1238
|
-
const unreadCount = page.items.filter((item) => item.unread).length;
|
|
1239
1330
|
if (state === null) {
|
|
1240
|
-
return (0,
|
|
1331
|
+
return (0, import_react7.createElement)(
|
|
1332
|
+
"div",
|
|
1333
|
+
{ className: "mailharbor" },
|
|
1334
|
+
(0, import_react7.createElement)("div", { className: "mailharbor-empty" }, error === "" ? "\u6B63\u5728\u52A0\u8F7D\u90AE\u7BB1\u2026" : error)
|
|
1335
|
+
);
|
|
1241
1336
|
}
|
|
1242
1337
|
if (account === null) {
|
|
1243
|
-
return (0,
|
|
1338
|
+
return (0, import_react7.createElement)(
|
|
1244
1339
|
"div",
|
|
1245
1340
|
{ className: "mailharbor" },
|
|
1246
|
-
(0,
|
|
1341
|
+
(0, import_react7.createElement)(
|
|
1247
1342
|
"div",
|
|
1248
1343
|
{ className: "mailharbor-settings" },
|
|
1249
|
-
(0,
|
|
1250
|
-
(0,
|
|
1344
|
+
(0, import_react7.createElement)("h2", null, "\u6B22\u8FCE\u4F7F\u7528 MailHarbor"),
|
|
1345
|
+
(0, import_react7.createElement)(
|
|
1251
1346
|
"p",
|
|
1252
1347
|
{ className: "muted small" },
|
|
1253
|
-
"\u628A\u4EFB\u610F IMAP/SMTP \u90AE\u7BB1\u63A5\u8FDB DeepSeek Harness\uFF1A\u672C\u5730\u5907\u4EFD\u3001\u5B9E\u65F6\u8BFB\u4FE1\u3001\u5199\u90AE\u4EF6\
|
|
1348
|
+
"\u628A\u4EFB\u610F IMAP/SMTP \u90AE\u7BB1\u63A5\u8FDB DeepSeek Harness\uFF1A\u672C\u5730\u5907\u4EFD\u3001\u5B9E\u65F6\u8BFB\u4FE1\u3001\u5199\u90AE\u4EF6\u4E0E Agent \u5DE5\u5177\u3002"
|
|
1254
1349
|
),
|
|
1255
|
-
error === "" ? null : (0,
|
|
1256
|
-
(0,
|
|
1350
|
+
error === "" ? null : (0, import_react7.createElement)("div", { className: "small", style: { color: "var(--m-danger)" } }, error),
|
|
1351
|
+
(0, import_react7.createElement)(AddAccountForm, {
|
|
1257
1352
|
onDone: (next) => {
|
|
1258
1353
|
setState(next);
|
|
1259
1354
|
setSource("local");
|
|
@@ -1263,64 +1358,83 @@ function MailPanel() {
|
|
|
1263
1358
|
);
|
|
1264
1359
|
}
|
|
1265
1360
|
const needsLogin = source === "server" && state.loggedIn === false;
|
|
1266
|
-
|
|
1361
|
+
const items = page.items;
|
|
1362
|
+
return (0, import_react7.createElement)(
|
|
1267
1363
|
"div",
|
|
1268
1364
|
{ className: narrow ? "mailharbor mailharbor-narrow" : "mailharbor" },
|
|
1269
|
-
(0,
|
|
1365
|
+
(0, import_react7.createElement)(
|
|
1270
1366
|
"div",
|
|
1271
1367
|
{ className: "mailharbor-topbar" },
|
|
1272
|
-
(0,
|
|
1273
|
-
|
|
1274
|
-
"
|
|
1275
|
-
{
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1368
|
+
(0, import_react7.createElement)(
|
|
1369
|
+
"div",
|
|
1370
|
+
{ className: "mailharbor-account" },
|
|
1371
|
+
(0, import_react7.createElement)(Avatar, { email: account.email, size: 26 }),
|
|
1372
|
+
state.accounts.length > 1 ? (0, import_react7.createElement)(
|
|
1373
|
+
"select",
|
|
1374
|
+
{
|
|
1375
|
+
value: account.id,
|
|
1376
|
+
onChange: (event) => void switchAccount(event.target.value),
|
|
1377
|
+
"aria-label": "\u8D26\u53F7"
|
|
1378
|
+
},
|
|
1379
|
+
state.accounts.map((item) => (0, import_react7.createElement)("option", { key: item.id, value: item.id }, item.label))
|
|
1380
|
+
) : (0, import_react7.createElement)("span", { className: "name" }, account.label),
|
|
1381
|
+
state.loggedIn === false ? (0, import_react7.createElement)("span", { className: "badge warn" }, "\u672A\u767B\u5F55") : null
|
|
1382
|
+
),
|
|
1383
|
+
(0, import_react7.createElement)(
|
|
1283
1384
|
"div",
|
|
1284
1385
|
{ className: "mailharbor-segment", role: "tablist" },
|
|
1285
|
-
(0,
|
|
1386
|
+
(0, import_react7.createElement)(
|
|
1286
1387
|
"button",
|
|
1287
1388
|
{ className: source === "local" ? "active" : "", onClick: () => setSource("local"), role: "tab" },
|
|
1288
1389
|
"\u672C\u5730\u5907\u4EFD"
|
|
1289
1390
|
),
|
|
1290
|
-
(0,
|
|
1391
|
+
(0, import_react7.createElement)(
|
|
1291
1392
|
"button",
|
|
1292
1393
|
{ className: source === "server" ? "active" : "", onClick: () => setSource("server"), role: "tab" },
|
|
1293
1394
|
"\u670D\u52A1\u5668\u5B9E\u65F6"
|
|
1294
1395
|
)
|
|
1295
1396
|
),
|
|
1296
|
-
(0,
|
|
1297
|
-
|
|
1298
|
-
(0, import_react6.createElement)("button", { className: "ghost", onClick: () => setShowAdd(true), title: "\u6DFB\u52A0\u8D26\u53F7" }, "+ \u8D26\u53F7"),
|
|
1299
|
-
(0, import_react6.createElement)("button", { className: "primary", onClick: () => startCompose("new") }, "\u5199\u90AE\u4EF6"),
|
|
1300
|
-
(0, import_react6.createElement)("button", { className: "ghost", onClick: () => void startBackup() }, "\u5907\u4EFD"),
|
|
1301
|
-
(0, import_react6.createElement)(
|
|
1397
|
+
(0, import_react7.createElement)("span", { className: "spacer" }),
|
|
1398
|
+
(0, import_react7.createElement)(
|
|
1302
1399
|
"button",
|
|
1303
1400
|
{
|
|
1304
|
-
className: "ghost",
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1401
|
+
className: "ghost icon",
|
|
1402
|
+
title: "\u6DFB\u52A0\u8D26\u53F7",
|
|
1403
|
+
"aria-label": "\u6DFB\u52A0\u8D26\u53F7",
|
|
1404
|
+
onClick: () => setShowAdd(true)
|
|
1308
1405
|
},
|
|
1309
|
-
"
|
|
1406
|
+
(0, import_react7.createElement)(Icon, { name: "plus" })
|
|
1407
|
+
),
|
|
1408
|
+
(0, import_react7.createElement)(
|
|
1409
|
+
"button",
|
|
1410
|
+
{ className: "ghost icon", title: "\u5237\u65B0\u5217\u8868", "aria-label": "\u5237\u65B0\u5217\u8868", onClick: refresh },
|
|
1411
|
+
(0, import_react7.createElement)(Icon, { name: "refresh" })
|
|
1412
|
+
),
|
|
1413
|
+
(0, import_react7.createElement)(
|
|
1414
|
+
"button",
|
|
1415
|
+
{ className: "ghost", onClick: () => void startBackup() },
|
|
1416
|
+
(0, import_react7.createElement)(Icon, { name: "archive" }),
|
|
1417
|
+
"\u5907\u4EFD"
|
|
1418
|
+
),
|
|
1419
|
+
(0, import_react7.createElement)(
|
|
1420
|
+
"button",
|
|
1421
|
+
{ className: "primary", onClick: () => startCompose("new") },
|
|
1422
|
+
(0, import_react7.createElement)(Icon, { name: "compose" }),
|
|
1423
|
+
"\u5199\u90AE\u4EF6"
|
|
1310
1424
|
)
|
|
1311
1425
|
),
|
|
1312
|
-
toast === "" ? null : (0,
|
|
1313
|
-
error === "" ? null : (0,
|
|
1314
|
-
needsLogin ? (0,
|
|
1426
|
+
toast === "" ? null : (0, import_react7.createElement)("div", { className: "small", style: { padding: "6px 14px", color: "var(--m-ok)" } }, toast),
|
|
1427
|
+
error === "" ? null : (0, import_react7.createElement)(ErrorBar, { message: error, onDismiss: () => setError("") }),
|
|
1428
|
+
needsLogin ? (0, import_react7.createElement)("div", { className: "mailharbor-settings" }, (0, import_react7.createElement)(LoginForm, { account, onDone: refresh })) : (0, import_react7.createElement)(
|
|
1315
1429
|
"div",
|
|
1316
1430
|
{ className: "mailharbor-body", "data-mode": narrow && selected !== null ? "reader" : "list" },
|
|
1317
|
-
(0,
|
|
1431
|
+
(0, import_react7.createElement)(
|
|
1318
1432
|
"div",
|
|
1319
1433
|
{ className: "mailharbor-list" },
|
|
1320
|
-
(0,
|
|
1434
|
+
(0, import_react7.createElement)(
|
|
1321
1435
|
"div",
|
|
1322
1436
|
{ className: "mailharbor-filters" },
|
|
1323
|
-
(0,
|
|
1437
|
+
(0, import_react7.createElement)(
|
|
1324
1438
|
"select",
|
|
1325
1439
|
{
|
|
1326
1440
|
value: mailbox,
|
|
@@ -1331,12 +1445,13 @@ function MailPanel() {
|
|
|
1331
1445
|
"aria-label": "\u90AE\u7BB1\u6587\u4EF6\u5939"
|
|
1332
1446
|
},
|
|
1333
1447
|
folderOptions.map(
|
|
1334
|
-
(option) => (0,
|
|
1448
|
+
(option) => (0, import_react7.createElement)("option", { key: option.value, value: option.value }, option.label)
|
|
1335
1449
|
)
|
|
1336
1450
|
),
|
|
1337
|
-
(0,
|
|
1451
|
+
(0, import_react7.createElement)("input", {
|
|
1338
1452
|
type: "search",
|
|
1339
1453
|
placeholder: "\u641C\u7D22\u90AE\u4EF6",
|
|
1454
|
+
"aria-label": "\u641C\u7D22\u90AE\u4EF6",
|
|
1340
1455
|
value: query2,
|
|
1341
1456
|
onChange: (event) => setQuery(event.target.value),
|
|
1342
1457
|
onKeyDown: (event) => {
|
|
@@ -1347,78 +1462,96 @@ function MailPanel() {
|
|
|
1347
1462
|
}
|
|
1348
1463
|
}
|
|
1349
1464
|
}),
|
|
1350
|
-
query2 !== search || search !== "" ? (0,
|
|
1465
|
+
query2 !== search || search !== "" ? (0, import_react7.createElement)(
|
|
1351
1466
|
"button",
|
|
1352
1467
|
{
|
|
1353
|
-
className: "subtle
|
|
1468
|
+
className: "subtle",
|
|
1469
|
+
title: "\u6E05\u9664\u641C\u7D22",
|
|
1354
1470
|
onClick: () => {
|
|
1355
1471
|
setQuery("");
|
|
1356
1472
|
setSearch("");
|
|
1357
1473
|
}
|
|
1358
1474
|
},
|
|
1359
|
-
"
|
|
1475
|
+
(0, import_react7.createElement)(Icon, { name: "close", size: 14 })
|
|
1360
1476
|
) : null
|
|
1361
1477
|
),
|
|
1362
|
-
(0,
|
|
1478
|
+
(0, import_react7.createElement)(
|
|
1363
1479
|
"div",
|
|
1364
1480
|
{ className: "mailharbor-rows" },
|
|
1365
|
-
loading &&
|
|
1481
|
+
loading && items.length === 0 ? (0, import_react7.createElement)("div", { className: "mailharbor-empty" }, "\u6B63\u5728\u8BFB\u53D6\u2026") : items.length === 0 ? (0, import_react7.createElement)(
|
|
1366
1482
|
"div",
|
|
1367
1483
|
{ className: "mailharbor-empty" },
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
"
|
|
1484
|
+
(0, import_react7.createElement)(Icon, { name: "mail", size: 28 }),
|
|
1485
|
+
(0, import_react7.createElement)(
|
|
1486
|
+
"div",
|
|
1487
|
+
{ className: "title" },
|
|
1488
|
+
source === "local" ? "\u672C\u5730\u5907\u4EFD\u91CC\u8FD8\u6CA1\u6709\u90AE\u4EF6" : "\u670D\u52A1\u5668\u4E0A\u6CA1\u6709\u90AE\u4EF6"
|
|
1489
|
+
),
|
|
1490
|
+
(0, import_react7.createElement)(
|
|
1491
|
+
"div",
|
|
1492
|
+
{ className: "small" },
|
|
1493
|
+
source === "local" ? "\u70B9\u9876\u90E8\u300C\u5907\u4EFD\u300D\u628A\u670D\u52A1\u5668\u90AE\u4EF6\u540C\u6B65\u4E0B\u6765\u3002" : "\u6362\u4E00\u4E2A\u6587\u4EF6\u5939\u6216\u7A0D\u540E\u5237\u65B0\u3002"
|
|
1494
|
+
)
|
|
1495
|
+
) : items.map(
|
|
1496
|
+
(item) => (0, import_react7.createElement)(
|
|
1497
|
+
"div",
|
|
1372
1498
|
{
|
|
1373
1499
|
key: item.id,
|
|
1374
1500
|
className: `mailharbor-row${item.unread ? " unread" : ""}${selected?.id === item.id ? " selected" : ""}`,
|
|
1375
|
-
|
|
1501
|
+
role: "button",
|
|
1502
|
+
tabIndex: 0,
|
|
1503
|
+
onClick: () => void openMessage(item),
|
|
1504
|
+
onKeyDown: (event) => {
|
|
1505
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1506
|
+
event.preventDefault();
|
|
1507
|
+
void openMessage(item);
|
|
1508
|
+
}
|
|
1509
|
+
}
|
|
1376
1510
|
},
|
|
1377
|
-
(0,
|
|
1511
|
+
(0, import_react7.createElement)(
|
|
1378
1512
|
"span",
|
|
1379
1513
|
{ className: "line-1" },
|
|
1380
|
-
(0,
|
|
1514
|
+
item.unread ? (0, import_react7.createElement)("span", { className: "dot" }) : null,
|
|
1515
|
+
(0, import_react7.createElement)(
|
|
1381
1516
|
"span",
|
|
1382
1517
|
{ className: "from" },
|
|
1383
1518
|
item.from.name !== "" ? item.from.name : item.from.address
|
|
1384
1519
|
),
|
|
1385
|
-
item.
|
|
1386
|
-
(0,
|
|
1520
|
+
item.hasAttachments ? (0, import_react7.createElement)(Icon, { name: "paperclip", size: 13 }) : null,
|
|
1521
|
+
item.backedUp === false ? (0, import_react7.createElement)("span", { className: "badge warn" }, "\u672A\u5907\u4EFD") : null,
|
|
1522
|
+
(0, import_react7.createElement)("span", { className: "date" }, shortDate(item.date))
|
|
1387
1523
|
),
|
|
1388
|
-
(0,
|
|
1389
|
-
item.snippet === "" ? null : (0,
|
|
1524
|
+
(0, import_react7.createElement)("span", { className: "line-2" }, (0, import_react7.createElement)("span", { className: "subject" }, item.subject)),
|
|
1525
|
+
item.snippet === "" ? null : (0, import_react7.createElement)("span", { className: "snippet" }, item.snippet)
|
|
1390
1526
|
)
|
|
1391
|
-
)
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
"button",
|
|
1403
|
-
{ className: "subtle small", onClick: () => setLimit((current) => current + 40) },
|
|
1404
|
-
"\u52A0\u8F7D\u66F4\u591A"
|
|
1405
|
-
) : null
|
|
1527
|
+
)
|
|
1528
|
+
),
|
|
1529
|
+
items.length > 0 ? (0, import_react7.createElement)(
|
|
1530
|
+
"div",
|
|
1531
|
+
{ className: "mailharbor-list-foot" },
|
|
1532
|
+
(0, import_react7.createElement)("span", null, `${String(items.length)} / ${String(page.total)} \u5C01`),
|
|
1533
|
+
(0, import_react7.createElement)("span", { className: "spacer" }),
|
|
1534
|
+
page.total > items.length ? (0, import_react7.createElement)(
|
|
1535
|
+
"button",
|
|
1536
|
+
{ className: "subtle", onClick: () => setLimit((current) => current + 40) },
|
|
1537
|
+
"\u52A0\u8F7D\u66F4\u591A"
|
|
1406
1538
|
) : null
|
|
1407
|
-
)
|
|
1539
|
+
) : null
|
|
1408
1540
|
),
|
|
1409
|
-
(0,
|
|
1541
|
+
(0, import_react7.createElement)(
|
|
1410
1542
|
"div",
|
|
1411
1543
|
{ className: "mailharbor-reader" },
|
|
1412
|
-
selected === null ? (0,
|
|
1544
|
+
selected === null ? (0, import_react7.createElement)(
|
|
1413
1545
|
"div",
|
|
1414
1546
|
{ className: "mailharbor-empty" },
|
|
1415
|
-
(0,
|
|
1416
|
-
(0,
|
|
1417
|
-
|
|
1547
|
+
(0, import_react7.createElement)(Icon, { name: "mail", size: 34 }),
|
|
1548
|
+
(0, import_react7.createElement)("div", { className: "title" }, "\u9009\u62E9\u4E00\u5C01\u90AE\u4EF6\u5F00\u59CB\u9605\u8BFB"),
|
|
1549
|
+
(0, import_react7.createElement)(
|
|
1550
|
+
"div",
|
|
1418
1551
|
{ className: "small" },
|
|
1419
1552
|
state.loggedIn ? "\u5DF2\u767B\u5F55\uFF0C\u53EF\u5207\u6362\u300C\u670D\u52A1\u5668\u5B9E\u65F6\u300D\u67E5\u770B\u6700\u65B0\u90AE\u4EF6\u3002" : "\u6D4F\u89C8\u672C\u5730\u5907\u4EFD\u4E0D\u9700\u8981\u767B\u5F55\u3002"
|
|
1420
1553
|
)
|
|
1421
|
-
) : (0,
|
|
1554
|
+
) : (0, import_react7.createElement)(Reader, {
|
|
1422
1555
|
detail: selected,
|
|
1423
1556
|
account,
|
|
1424
1557
|
source,
|
|
@@ -1429,45 +1562,45 @@ function MailPanel() {
|
|
|
1429
1562
|
})
|
|
1430
1563
|
)
|
|
1431
1564
|
),
|
|
1432
|
-
showBackup && backup !== null ? (0,
|
|
1565
|
+
showBackup && backup !== null ? (0, import_react7.createElement)(
|
|
1433
1566
|
Modal,
|
|
1434
1567
|
{
|
|
1435
1568
|
title: "\u5907\u4EFD",
|
|
1436
1569
|
onClose: () => setShowBackup(false),
|
|
1437
|
-
footer: (0,
|
|
1570
|
+
footer: (0, import_react7.createElement)(
|
|
1438
1571
|
"div",
|
|
1439
1572
|
{ style: { display: "flex", gap: "8px", width: "100%", alignItems: "center" } },
|
|
1440
|
-
(0,
|
|
1441
|
-
(0,
|
|
1442
|
-
backup.running ? (0,
|
|
1443
|
-
(0,
|
|
1573
|
+
(0, import_react7.createElement)("span", { className: "small muted" }, backup.running ? "\u5907\u4EFD\u8FDB\u884C\u4E2D\u2026" : backup.message),
|
|
1574
|
+
(0, import_react7.createElement)("span", { className: "spacer" }),
|
|
1575
|
+
backup.running ? (0, import_react7.createElement)("button", { className: "ghost danger", onClick: () => void stopBackup() }, "\u505C\u6B62\u5907\u4EFD") : (0, import_react7.createElement)("button", { className: "primary", onClick: () => void startBackup() }, "\u5F00\u59CB\u5907\u4EFD"),
|
|
1576
|
+
(0, import_react7.createElement)("button", { className: "ghost", onClick: () => setShowBackup(false) }, "\u5173\u95ED")
|
|
1444
1577
|
)
|
|
1445
1578
|
},
|
|
1446
|
-
(0,
|
|
1579
|
+
(0, import_react7.createElement)(
|
|
1447
1580
|
"div",
|
|
1448
1581
|
{ className: "mailharbor-kv" },
|
|
1449
|
-
(0,
|
|
1450
|
-
(0,
|
|
1451
|
-
(0,
|
|
1452
|
-
(0,
|
|
1453
|
-
(0,
|
|
1454
|
-
(0,
|
|
1455
|
-
(0,
|
|
1456
|
-
(0,
|
|
1582
|
+
(0, import_react7.createElement)("dt", null, "\u5F00\u59CB\u65F6\u95F4"),
|
|
1583
|
+
(0, import_react7.createElement)("dd", null, backup.startedAt ?? "\u2014"),
|
|
1584
|
+
(0, import_react7.createElement)("dt", null, "\u4E0A\u6B21\u6210\u529F"),
|
|
1585
|
+
(0, import_react7.createElement)("dd", null, backup.lastSuccessAt ?? "\u2014"),
|
|
1586
|
+
(0, import_react7.createElement)("dt", null, "\u65B0\u589E"),
|
|
1587
|
+
(0, import_react7.createElement)("dd", null, String(backup.added)),
|
|
1588
|
+
(0, import_react7.createElement)("dt", null, "\u603B\u6570"),
|
|
1589
|
+
(0, import_react7.createElement)("dd", null, String(backup.total))
|
|
1457
1590
|
),
|
|
1458
|
-
(0,
|
|
1591
|
+
(0, import_react7.createElement)(
|
|
1459
1592
|
"div",
|
|
1460
1593
|
{ className: "mailharbor-log" },
|
|
1461
1594
|
backup.output.length === 0 ? "\uFF08\u7B49\u5F85\u8F93\u51FA\u2026\uFF09" : backup.output.join("\n")
|
|
1462
1595
|
)
|
|
1463
1596
|
) : null,
|
|
1464
|
-
compose !== null ? (0,
|
|
1597
|
+
compose !== null ? (0, import_react7.createElement)(Composer, {
|
|
1465
1598
|
account,
|
|
1466
1599
|
initial: compose,
|
|
1467
1600
|
onClose: () => setCompose(null),
|
|
1468
1601
|
onSent: (message) => notice(message)
|
|
1469
1602
|
}) : null,
|
|
1470
|
-
showAdd ? (0,
|
|
1603
|
+
showAdd ? (0, import_react7.createElement)(AddAccountModal, {
|
|
1471
1604
|
onClose: () => setShowAdd(false),
|
|
1472
1605
|
onDone: (next) => {
|
|
1473
1606
|
setState(next);
|
|
@@ -1478,27 +1611,27 @@ function MailPanel() {
|
|
|
1478
1611
|
}
|
|
1479
1612
|
|
|
1480
1613
|
// src/client/settings.tsx
|
|
1481
|
-
var
|
|
1614
|
+
var import_react8 = require("react");
|
|
1482
1615
|
function errorText4(error) {
|
|
1483
1616
|
return error instanceof ApiError || error instanceof Error ? error.message : String(error);
|
|
1484
1617
|
}
|
|
1485
1618
|
function MailSettings() {
|
|
1486
|
-
const [state, setState] = (0,
|
|
1487
|
-
const [settings, setSettings] = (0,
|
|
1488
|
-
const [error, setError] = (0,
|
|
1489
|
-
const [toast, setToast] = (0,
|
|
1490
|
-
const [signature, setSignature] = (0,
|
|
1491
|
-
const [markOnOpen, setMarkOnOpen] = (0,
|
|
1492
|
-
const [pollSeconds, setPollSeconds] = (0,
|
|
1493
|
-
const [listLimit, setListLimit] = (0,
|
|
1494
|
-
const [aiEnabled, setAiEnabled] = (0,
|
|
1495
|
-
const [aiProvider, setAiProvider] = (0,
|
|
1496
|
-
const [aiModel, setAiModel] = (0,
|
|
1497
|
-
const [editing, setEditing] = (0,
|
|
1498
|
-
const [checkResult, setCheckResult] = (0,
|
|
1499
|
-
const [adding, setAdding] = (0,
|
|
1500
|
-
const [tick, setTick] = (0,
|
|
1501
|
-
(0,
|
|
1619
|
+
const [state, setState] = (0, import_react8.useState)(null);
|
|
1620
|
+
const [settings, setSettings] = (0, import_react8.useState)(null);
|
|
1621
|
+
const [error, setError] = (0, import_react8.useState)("");
|
|
1622
|
+
const [toast, setToast] = (0, import_react8.useState)("");
|
|
1623
|
+
const [signature, setSignature] = (0, import_react8.useState)("");
|
|
1624
|
+
const [markOnOpen, setMarkOnOpen] = (0, import_react8.useState)(true);
|
|
1625
|
+
const [pollSeconds, setPollSeconds] = (0, import_react8.useState)(60);
|
|
1626
|
+
const [listLimit, setListLimit] = (0, import_react8.useState)(40);
|
|
1627
|
+
const [aiEnabled, setAiEnabled] = (0, import_react8.useState)(true);
|
|
1628
|
+
const [aiProvider, setAiProvider] = (0, import_react8.useState)("deepseek-account");
|
|
1629
|
+
const [aiModel, setAiModel] = (0, import_react8.useState)("deepseek-flash");
|
|
1630
|
+
const [editing, setEditing] = (0, import_react8.useState)(null);
|
|
1631
|
+
const [checkResult, setCheckResult] = (0, import_react8.useState)("");
|
|
1632
|
+
const [adding, setAdding] = (0, import_react8.useState)(false);
|
|
1633
|
+
const [tick, setTick] = (0, import_react8.useState)(0);
|
|
1634
|
+
(0, import_react8.useEffect)(() => {
|
|
1502
1635
|
let cancelled = false;
|
|
1503
1636
|
Promise.all([api.state(), api.settings()]).then(([appState, view]) => {
|
|
1504
1637
|
if (cancelled) return;
|
|
@@ -1536,24 +1669,24 @@ function MailSettings() {
|
|
|
1536
1669
|
};
|
|
1537
1670
|
const account = settings?.accounts.find((item) => item.id === settings.activeAccountId) ?? null;
|
|
1538
1671
|
if (state === null || settings === null) {
|
|
1539
|
-
return (0,
|
|
1672
|
+
return (0, import_react8.createElement)("div", { className: "mailharbor mailharbor-settings" }, error === "" ? "\u6B63\u5728\u52A0\u8F7D\u8BBE\u7F6E\u2026" : error);
|
|
1540
1673
|
}
|
|
1541
|
-
return (0,
|
|
1674
|
+
return (0, import_react8.createElement)(
|
|
1542
1675
|
"div",
|
|
1543
1676
|
{ className: "mailharbor" },
|
|
1544
|
-
(0,
|
|
1677
|
+
(0, import_react8.createElement)(
|
|
1545
1678
|
"div",
|
|
1546
1679
|
{ className: "mailharbor-settings" },
|
|
1547
|
-
(0,
|
|
1548
|
-
(0,
|
|
1549
|
-
toast === "" ? null : (0,
|
|
1550
|
-
error === "" ? null : (0,
|
|
1551
|
-
(0,
|
|
1680
|
+
(0, import_react8.createElement)("h2", null, "MailHarbor"),
|
|
1681
|
+
(0, import_react8.createElement)("p", { className: "small muted" }, "\u591A\u8D26\u53F7 IMAP/SMTP \u90AE\u7BB1\u3001\u672C\u5730\u5907\u4EFD\u3001AI \u4E0E\u4EFB\u52A1\u3002\u8BBE\u7F6E\u4F1A\u7ACB\u5373\u751F\u6548\u3002"),
|
|
1682
|
+
toast === "" ? null : (0, import_react8.createElement)("div", { className: "small", style: { color: "var(--m-ok)" } }, toast),
|
|
1683
|
+
error === "" ? null : (0, import_react8.createElement)(ErrorBar, { message: error, onDismiss: () => setError("") }),
|
|
1684
|
+
(0, import_react8.createElement)(
|
|
1552
1685
|
"div",
|
|
1553
1686
|
{ className: "mailharbor-card" },
|
|
1554
|
-
(0,
|
|
1555
|
-
settings.accounts.length === 0 ? (0,
|
|
1556
|
-
(item) => (0,
|
|
1687
|
+
(0, import_react8.createElement)("h3", null, "\u8D26\u53F7"),
|
|
1688
|
+
settings.accounts.length === 0 ? (0, import_react8.createElement)(AddAccountForm, { onDone: () => reload() }) : settings.accounts.map(
|
|
1689
|
+
(item) => (0, import_react8.createElement)(AccountRow, {
|
|
1557
1690
|
key: item.id,
|
|
1558
1691
|
account: item,
|
|
1559
1692
|
active: item.id === settings.activeAccountId,
|
|
@@ -1597,32 +1730,32 @@ function MailSettings() {
|
|
|
1597
1730
|
}
|
|
1598
1731
|
})
|
|
1599
1732
|
),
|
|
1600
|
-
adding ? (0,
|
|
1733
|
+
adding ? (0, import_react8.createElement)(AddAccountForm, {
|
|
1601
1734
|
onDone: () => {
|
|
1602
1735
|
setAdding(false);
|
|
1603
1736
|
reload();
|
|
1604
1737
|
},
|
|
1605
1738
|
onCancel: () => setAdding(false)
|
|
1606
|
-
}) : (0,
|
|
1739
|
+
}) : (0, import_react8.createElement)("button", { className: "ghost", onClick: () => setAdding(true) }, "+ \u6DFB\u52A0\u8D26\u53F7")
|
|
1607
1740
|
),
|
|
1608
|
-
(0,
|
|
1741
|
+
(0, import_react8.createElement)(
|
|
1609
1742
|
"div",
|
|
1610
1743
|
{ className: "mailharbor-card" },
|
|
1611
|
-
(0,
|
|
1612
|
-
(0,
|
|
1744
|
+
(0, import_react8.createElement)("h3", null, "\u5199\u4FE1\u4E0E\u9605\u8BFB"),
|
|
1745
|
+
(0, import_react8.createElement)(
|
|
1613
1746
|
Field,
|
|
1614
1747
|
{ label: "\u7B7E\u540D\uFF08\u7EAF\u6587\u672C\uFF0C\u53D1\u9001\u65F6\u8FFD\u52A0\u5230\u6B63\u6587\u672B\u5C3E\uFF09" },
|
|
1615
|
-
(0,
|
|
1748
|
+
(0, import_react8.createElement)("textarea", {
|
|
1616
1749
|
rows: 4,
|
|
1617
1750
|
value: signature,
|
|
1618
1751
|
onChange: (event) => setSignature(event.target.value)
|
|
1619
1752
|
})
|
|
1620
1753
|
),
|
|
1621
|
-
(0,
|
|
1754
|
+
(0, import_react8.createElement)(
|
|
1622
1755
|
"div",
|
|
1623
1756
|
{ style: { display: "flex", gap: "10px", alignItems: "center", flexWrap: "wrap" } },
|
|
1624
|
-
(0,
|
|
1625
|
-
(0,
|
|
1757
|
+
(0, import_react8.createElement)("button", { className: "ghost", onClick: () => void saveGeneral({ signature }) }, "\u4FDD\u5B58\u7B7E\u540D"),
|
|
1758
|
+
(0, import_react8.createElement)(Toggle, {
|
|
1626
1759
|
checked: markOnOpen,
|
|
1627
1760
|
onChange: (value) => {
|
|
1628
1761
|
setMarkOnOpen(value);
|
|
@@ -1631,13 +1764,13 @@ function MailSettings() {
|
|
|
1631
1764
|
label: "\u6253\u5F00\u90AE\u4EF6\u65F6\u6807\u4E3A\u5DF2\u8BFB"
|
|
1632
1765
|
})
|
|
1633
1766
|
),
|
|
1634
|
-
(0,
|
|
1767
|
+
(0, import_react8.createElement)(
|
|
1635
1768
|
"div",
|
|
1636
1769
|
{ className: "mailharbor-grid" },
|
|
1637
|
-
(0,
|
|
1770
|
+
(0, import_react8.createElement)(
|
|
1638
1771
|
Field,
|
|
1639
1772
|
{ label: "\u5217\u8868\u6BCF\u9875\u6570\u91CF" },
|
|
1640
|
-
(0,
|
|
1773
|
+
(0, import_react8.createElement)("input", {
|
|
1641
1774
|
type: "number",
|
|
1642
1775
|
min: 10,
|
|
1643
1776
|
max: 200,
|
|
@@ -1646,10 +1779,10 @@ function MailSettings() {
|
|
|
1646
1779
|
onBlur: () => void saveGeneral({ render: { listLimit } })
|
|
1647
1780
|
})
|
|
1648
1781
|
),
|
|
1649
|
-
(0,
|
|
1782
|
+
(0, import_react8.createElement)(
|
|
1650
1783
|
Field,
|
|
1651
1784
|
{ label: "\u672A\u8BFB\u89D2\u6807\u8F6E\u8BE2\uFF08\u79D2\uFF09" },
|
|
1652
|
-
(0,
|
|
1785
|
+
(0, import_react8.createElement)("input", {
|
|
1653
1786
|
type: "number",
|
|
1654
1787
|
min: 15,
|
|
1655
1788
|
max: 3600,
|
|
@@ -1660,11 +1793,11 @@ function MailSettings() {
|
|
|
1660
1793
|
)
|
|
1661
1794
|
)
|
|
1662
1795
|
),
|
|
1663
|
-
(0,
|
|
1796
|
+
(0, import_react8.createElement)(
|
|
1664
1797
|
"div",
|
|
1665
1798
|
{ className: "mailharbor-card" },
|
|
1666
|
-
(0,
|
|
1667
|
-
(0,
|
|
1799
|
+
(0, import_react8.createElement)("h3", null, "AI"),
|
|
1800
|
+
(0, import_react8.createElement)(Toggle, {
|
|
1668
1801
|
checked: aiEnabled,
|
|
1669
1802
|
onChange: (value) => {
|
|
1670
1803
|
setAiEnabled(value);
|
|
@@ -1672,54 +1805,54 @@ function MailSettings() {
|
|
|
1672
1805
|
},
|
|
1673
1806
|
label: "\u542F\u7528 AI\uFF08\u6458\u8981\u3001\u8D77\u8349\u3001\u6DA6\u8272\u3001\u81EA\u7136\u8BED\u8A00\u641C\u7D22\uFF09"
|
|
1674
1807
|
}),
|
|
1675
|
-
(0,
|
|
1808
|
+
(0, import_react8.createElement)(
|
|
1676
1809
|
"div",
|
|
1677
1810
|
{ className: "mailharbor-grid" },
|
|
1678
|
-
(0,
|
|
1811
|
+
(0, import_react8.createElement)(
|
|
1679
1812
|
Field,
|
|
1680
1813
|
{ label: "Provider" },
|
|
1681
|
-
(0,
|
|
1814
|
+
(0, import_react8.createElement)("input", {
|
|
1682
1815
|
value: aiProvider,
|
|
1683
1816
|
onChange: (event) => setAiProvider(event.target.value),
|
|
1684
1817
|
onBlur: () => void saveGeneral({ ai: { provider: aiProvider } })
|
|
1685
1818
|
})
|
|
1686
1819
|
),
|
|
1687
|
-
(0,
|
|
1820
|
+
(0, import_react8.createElement)(
|
|
1688
1821
|
Field,
|
|
1689
1822
|
{ label: "\u6A21\u578B" },
|
|
1690
|
-
(0,
|
|
1823
|
+
(0, import_react8.createElement)("input", {
|
|
1691
1824
|
value: aiModel,
|
|
1692
1825
|
onChange: (event) => setAiModel(event.target.value),
|
|
1693
1826
|
onBlur: () => void saveGeneral({ ai: { model: aiModel } })
|
|
1694
1827
|
})
|
|
1695
1828
|
)
|
|
1696
1829
|
),
|
|
1697
|
-
(0,
|
|
1830
|
+
(0, import_react8.createElement)(
|
|
1698
1831
|
"p",
|
|
1699
1832
|
{ className: "small muted" },
|
|
1700
1833
|
"AI \u8C03\u7528\u8D70 DSH \u81EA\u5DF1\u7684\u6A21\u578B\u670D\u52A1\uFF0C\u4E0D\u989D\u5916\u4FDD\u5B58\u5BC6\u94A5\u3002AI \u9762\u677F\u529F\u80FD\u5C06\u5728 v0.2 \u63D0\u4F9B\u3002"
|
|
1701
1834
|
)
|
|
1702
1835
|
),
|
|
1703
|
-
(0,
|
|
1836
|
+
(0, import_react8.createElement)(
|
|
1704
1837
|
"div",
|
|
1705
1838
|
{ className: "mailharbor-card" },
|
|
1706
|
-
(0,
|
|
1707
|
-
(0,
|
|
1839
|
+
(0, import_react8.createElement)("h3", null, "\u6570\u636E"),
|
|
1840
|
+
(0, import_react8.createElement)(
|
|
1708
1841
|
"dl",
|
|
1709
1842
|
{ className: "mailharbor-kv" },
|
|
1710
|
-
(0,
|
|
1711
|
-
(0,
|
|
1712
|
-
(0,
|
|
1713
|
-
(0,
|
|
1714
|
-
(0,
|
|
1715
|
-
(0,
|
|
1716
|
-
(0,
|
|
1717
|
-
(0,
|
|
1843
|
+
(0, import_react8.createElement)("dt", null, "\u6570\u636E\u76EE\u5F55"),
|
|
1844
|
+
(0, import_react8.createElement)("dd", null, settings.dataDir),
|
|
1845
|
+
(0, import_react8.createElement)("dt", null, "\u914D\u7F6E\u6587\u4EF6"),
|
|
1846
|
+
(0, import_react8.createElement)("dd", null, settings.configFile),
|
|
1847
|
+
(0, import_react8.createElement)("dt", null, "\u5F53\u524D\u8D26\u53F7\u6570\u636E\u5E93"),
|
|
1848
|
+
(0, import_react8.createElement)("dd", null, account === null ? "\u2014" : `${settings.dataDir}/accounts/${account.id}/mail.db`),
|
|
1849
|
+
(0, import_react8.createElement)("dt", null, "\u63D2\u4EF6\u7248\u672C"),
|
|
1850
|
+
(0, import_react8.createElement)("dd", null, state.version)
|
|
1718
1851
|
),
|
|
1719
|
-
(0,
|
|
1852
|
+
(0, import_react8.createElement)(
|
|
1720
1853
|
"div",
|
|
1721
1854
|
{ style: { display: "flex", gap: "8px", flexWrap: "wrap" } },
|
|
1722
|
-
account === null ? null : (0,
|
|
1855
|
+
account === null ? null : (0, import_react8.createElement)(
|
|
1723
1856
|
"button",
|
|
1724
1857
|
{
|
|
1725
1858
|
className: "ghost",
|
|
@@ -1754,19 +1887,19 @@ function AccountRow({
|
|
|
1754
1887
|
onSave,
|
|
1755
1888
|
onRemove
|
|
1756
1889
|
}) {
|
|
1757
|
-
const [password, setPassword] = (0,
|
|
1758
|
-
const [remember, setRemember] = (0,
|
|
1759
|
-
const [label, setLabel] = (0,
|
|
1760
|
-
const [username, setUsername] = (0,
|
|
1761
|
-
const [imapHost, setImapHost] = (0,
|
|
1762
|
-
const [imapPort, setImapPort] = (0,
|
|
1763
|
-
const [imapSecure, setImapSecure] = (0,
|
|
1764
|
-
const [smtpHost, setSmtpHost] = (0,
|
|
1765
|
-
const [smtpPort, setSmtpPort] = (0,
|
|
1766
|
-
const [smtpSecure, setSmtpSecure] = (0,
|
|
1767
|
-
const [fromName, setFromName] = (0,
|
|
1768
|
-
const [busy, setBusy] = (0,
|
|
1769
|
-
(0,
|
|
1890
|
+
const [password, setPassword] = (0, import_react8.useState)("");
|
|
1891
|
+
const [remember, setRemember] = (0, import_react8.useState)(true);
|
|
1892
|
+
const [label, setLabel] = (0, import_react8.useState)(account.label);
|
|
1893
|
+
const [username, setUsername] = (0, import_react8.useState)(account.username);
|
|
1894
|
+
const [imapHost, setImapHost] = (0, import_react8.useState)(account.imap.host);
|
|
1895
|
+
const [imapPort, setImapPort] = (0, import_react8.useState)(String(account.imap.port));
|
|
1896
|
+
const [imapSecure, setImapSecure] = (0, import_react8.useState)(account.imap.secure);
|
|
1897
|
+
const [smtpHost, setSmtpHost] = (0, import_react8.useState)(account.smtp.host);
|
|
1898
|
+
const [smtpPort, setSmtpPort] = (0, import_react8.useState)(String(account.smtp.port));
|
|
1899
|
+
const [smtpSecure, setSmtpSecure] = (0, import_react8.useState)(account.smtp.secure);
|
|
1900
|
+
const [fromName, setFromName] = (0, import_react8.useState)(account.smtp.fromName);
|
|
1901
|
+
const [busy, setBusy] = (0, import_react8.useState)(false);
|
|
1902
|
+
(0, import_react8.useEffect)(() => {
|
|
1770
1903
|
setLabel(account.label);
|
|
1771
1904
|
setUsername(account.username);
|
|
1772
1905
|
setImapHost(account.imap.host);
|
|
@@ -1785,103 +1918,103 @@ function AccountRow({
|
|
|
1785
1918
|
setBusy(false);
|
|
1786
1919
|
}
|
|
1787
1920
|
};
|
|
1788
|
-
return (0,
|
|
1921
|
+
return (0, import_react8.createElement)(
|
|
1789
1922
|
"div",
|
|
1790
1923
|
{ className: "mailharbor-card", style: { background: "var(--m-bg-1)" } },
|
|
1791
|
-
(0,
|
|
1924
|
+
(0, import_react8.createElement)(
|
|
1792
1925
|
"div",
|
|
1793
1926
|
{ className: "mailharbor-account-row" },
|
|
1794
|
-
(0,
|
|
1795
|
-
(0,
|
|
1927
|
+
(0, import_react8.createElement)(Avatar, { email: account.email, size: 30 }),
|
|
1928
|
+
(0, import_react8.createElement)(
|
|
1796
1929
|
"div",
|
|
1797
1930
|
{ style: { display: "flex", flexDirection: "column", minWidth: 0 } },
|
|
1798
|
-
(0,
|
|
1799
|
-
(0,
|
|
1931
|
+
(0, import_react8.createElement)("strong", null, account.label),
|
|
1932
|
+
(0, import_react8.createElement)("span", { className: "small muted" }, account.email)
|
|
1800
1933
|
),
|
|
1801
|
-
active ? (0,
|
|
1802
|
-
loggedIn === false ? (0,
|
|
1803
|
-
(0,
|
|
1804
|
-
active ? null : (0,
|
|
1805
|
-
(0,
|
|
1806
|
-
(0,
|
|
1934
|
+
active ? (0, import_react8.createElement)("span", { className: "badge ok" }, "\u5F53\u524D\u8D26\u53F7") : null,
|
|
1935
|
+
loggedIn === false ? (0, import_react8.createElement)("span", { className: "badge warn" }, "\u672A\u767B\u5F55") : null,
|
|
1936
|
+
(0, import_react8.createElement)("span", { className: "spacer" }),
|
|
1937
|
+
active ? null : (0, import_react8.createElement)("button", { className: "ghost small", onClick: () => void wrap(onActivate) }, "\u8BBE\u4E3A\u5F53\u524D"),
|
|
1938
|
+
(0, import_react8.createElement)("button", { className: "ghost small", onClick: () => void wrap(onCheck) }, "\u68C0\u67E5\u8FDE\u63A5"),
|
|
1939
|
+
(0, import_react8.createElement)("button", { className: "ghost small", onClick: onToggleEdit }, editing ? "\u6536\u8D77" : "\u7F16\u8F91")
|
|
1807
1940
|
),
|
|
1808
|
-
editing ? (0,
|
|
1941
|
+
editing ? (0, import_react8.createElement)(
|
|
1809
1942
|
"div",
|
|
1810
1943
|
{ style: { display: "flex", flexDirection: "column", gap: "10px" } },
|
|
1811
|
-
(0,
|
|
1944
|
+
(0, import_react8.createElement)(
|
|
1812
1945
|
"div",
|
|
1813
1946
|
{ className: "mailharbor-grid" },
|
|
1814
|
-
(0,
|
|
1947
|
+
(0, import_react8.createElement)(
|
|
1815
1948
|
Field,
|
|
1816
1949
|
{ label: "\u663E\u793A\u540D\u79F0" },
|
|
1817
|
-
(0,
|
|
1950
|
+
(0, import_react8.createElement)("input", {
|
|
1818
1951
|
value: label,
|
|
1819
1952
|
onChange: (event) => setLabel(event.target.value)
|
|
1820
1953
|
})
|
|
1821
1954
|
),
|
|
1822
|
-
(0,
|
|
1955
|
+
(0, import_react8.createElement)(
|
|
1823
1956
|
Field,
|
|
1824
1957
|
{ label: "\u767B\u5F55\u7528\u6237\u540D" },
|
|
1825
|
-
(0,
|
|
1958
|
+
(0, import_react8.createElement)("input", {
|
|
1826
1959
|
value: username,
|
|
1827
1960
|
onChange: (event) => setUsername(event.target.value)
|
|
1828
1961
|
})
|
|
1829
1962
|
)
|
|
1830
1963
|
),
|
|
1831
|
-
(0,
|
|
1964
|
+
(0, import_react8.createElement)(
|
|
1832
1965
|
"div",
|
|
1833
1966
|
{ className: "mailharbor-grid three" },
|
|
1834
|
-
(0,
|
|
1967
|
+
(0, import_react8.createElement)(
|
|
1835
1968
|
Field,
|
|
1836
1969
|
{ label: "IMAP \u4E3B\u673A" },
|
|
1837
|
-
(0,
|
|
1970
|
+
(0, import_react8.createElement)("input", {
|
|
1838
1971
|
value: imapHost,
|
|
1839
1972
|
onChange: (event) => setImapHost(event.target.value)
|
|
1840
1973
|
})
|
|
1841
1974
|
),
|
|
1842
|
-
(0,
|
|
1975
|
+
(0, import_react8.createElement)(
|
|
1843
1976
|
Field,
|
|
1844
1977
|
{ label: "\u7AEF\u53E3" },
|
|
1845
|
-
(0,
|
|
1978
|
+
(0, import_react8.createElement)("input", {
|
|
1846
1979
|
value: imapPort,
|
|
1847
1980
|
onChange: (event) => setImapPort(event.target.value)
|
|
1848
1981
|
})
|
|
1849
1982
|
),
|
|
1850
|
-
(0,
|
|
1983
|
+
(0, import_react8.createElement)(Toggle, { checked: imapSecure, onChange: setImapSecure, label: "TLS" })
|
|
1851
1984
|
),
|
|
1852
|
-
(0,
|
|
1985
|
+
(0, import_react8.createElement)(
|
|
1853
1986
|
"div",
|
|
1854
1987
|
{ className: "mailharbor-grid three" },
|
|
1855
|
-
(0,
|
|
1988
|
+
(0, import_react8.createElement)(
|
|
1856
1989
|
Field,
|
|
1857
1990
|
{ label: "SMTP \u4E3B\u673A" },
|
|
1858
|
-
(0,
|
|
1991
|
+
(0, import_react8.createElement)("input", {
|
|
1859
1992
|
value: smtpHost,
|
|
1860
1993
|
onChange: (event) => setSmtpHost(event.target.value)
|
|
1861
1994
|
})
|
|
1862
1995
|
),
|
|
1863
|
-
(0,
|
|
1996
|
+
(0, import_react8.createElement)(
|
|
1864
1997
|
Field,
|
|
1865
1998
|
{ label: "\u7AEF\u53E3" },
|
|
1866
|
-
(0,
|
|
1999
|
+
(0, import_react8.createElement)("input", {
|
|
1867
2000
|
value: smtpPort,
|
|
1868
2001
|
onChange: (event) => setSmtpPort(event.target.value)
|
|
1869
2002
|
})
|
|
1870
2003
|
),
|
|
1871
|
-
(0,
|
|
2004
|
+
(0, import_react8.createElement)(Toggle, { checked: smtpSecure, onChange: setSmtpSecure, label: "TLS" })
|
|
1872
2005
|
),
|
|
1873
|
-
(0,
|
|
2006
|
+
(0, import_react8.createElement)(
|
|
1874
2007
|
Field,
|
|
1875
2008
|
{ label: "\u53D1\u4EF6\u4EBA\u540D\u79F0" },
|
|
1876
|
-
(0,
|
|
2009
|
+
(0, import_react8.createElement)("input", {
|
|
1877
2010
|
value: fromName,
|
|
1878
2011
|
onChange: (event) => setFromName(event.target.value)
|
|
1879
2012
|
})
|
|
1880
2013
|
),
|
|
1881
|
-
(0,
|
|
2014
|
+
(0, import_react8.createElement)(
|
|
1882
2015
|
"div",
|
|
1883
2016
|
{ style: { display: "flex", gap: "8px", alignItems: "center", flexWrap: "wrap" } },
|
|
1884
|
-
(0,
|
|
2017
|
+
(0, import_react8.createElement)(
|
|
1885
2018
|
"button",
|
|
1886
2019
|
{
|
|
1887
2020
|
className: "primary small",
|
|
@@ -1897,7 +2030,7 @@ function AccountRow({
|
|
|
1897
2030
|
},
|
|
1898
2031
|
"\u4FDD\u5B58\u8D26\u53F7"
|
|
1899
2032
|
),
|
|
1900
|
-
(0,
|
|
2033
|
+
(0, import_react8.createElement)(
|
|
1901
2034
|
"button",
|
|
1902
2035
|
{
|
|
1903
2036
|
className: "ghost small danger",
|
|
@@ -1906,21 +2039,21 @@ function AccountRow({
|
|
|
1906
2039
|
"\u79FB\u9664\u8D26\u53F7"
|
|
1907
2040
|
)
|
|
1908
2041
|
),
|
|
1909
|
-
(0,
|
|
1910
|
-
(0,
|
|
2042
|
+
(0, import_react8.createElement)("hr", { style: { border: 0, borderTop: "1px solid var(--m-line)", width: "100%" } }),
|
|
2043
|
+
(0, import_react8.createElement)(
|
|
1911
2044
|
Field,
|
|
1912
2045
|
{ label: "\u5BC6\u7801 / \u5E94\u7528\u4E13\u7528\u5BC6\u7801\uFF08\u4E0D\u5199\u5165\u914D\u7F6E\u6587\u4EF6\uFF09" },
|
|
1913
|
-
(0,
|
|
2046
|
+
(0, import_react8.createElement)("input", {
|
|
1914
2047
|
type: "password",
|
|
1915
2048
|
value: password,
|
|
1916
2049
|
onChange: (event) => setPassword(event.target.value)
|
|
1917
2050
|
})
|
|
1918
2051
|
),
|
|
1919
|
-
(0,
|
|
2052
|
+
(0, import_react8.createElement)(
|
|
1920
2053
|
"div",
|
|
1921
2054
|
{ style: { display: "flex", gap: "8px", alignItems: "center" } },
|
|
1922
|
-
(0,
|
|
1923
|
-
(0,
|
|
2055
|
+
(0, import_react8.createElement)(Toggle, { checked: remember, onChange: setRemember, label: "\u8BB0\u4F4F\u5BC6\u7801" }),
|
|
2056
|
+
(0, import_react8.createElement)(
|
|
1924
2057
|
"button",
|
|
1925
2058
|
{
|
|
1926
2059
|
className: "primary small",
|
|
@@ -1932,15 +2065,15 @@ function AccountRow({
|
|
|
1932
2065
|
},
|
|
1933
2066
|
"\u767B\u5F55"
|
|
1934
2067
|
),
|
|
1935
|
-
(0,
|
|
2068
|
+
(0, import_react8.createElement)("button", { className: "ghost small", onClick: () => void wrap(onLogout) }, "\u9000\u51FA\u767B\u5F55")
|
|
1936
2069
|
),
|
|
1937
|
-
checkResult === "" ? null : (0,
|
|
2070
|
+
checkResult === "" ? null : (0, import_react8.createElement)("div", { className: "small muted" }, checkResult)
|
|
1938
2071
|
) : null
|
|
1939
2072
|
);
|
|
1940
2073
|
}
|
|
1941
2074
|
|
|
1942
2075
|
// src/client/index.tsx
|
|
1943
|
-
var VERSION = "0.1
|
|
2076
|
+
var VERSION = "0.2.1";
|
|
1944
2077
|
var inject = ["slots"];
|
|
1945
2078
|
var PANEL_ID = "mailharbor";
|
|
1946
2079
|
var STYLE_ID = "mailharbor-style";
|