@zaclinley/dsh-mailharbor 0.1.0 → 0.2.0
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 +16 -5
- package/README.md +29 -3
- package/README.zh.md +27 -3
- package/lib/client.js +439 -322
- package/lib/client.js.map +4 -4
- package/lib/index.js +44 -34
- package/lib/index.js.map +3 -3
- package/package.json +3 -1
- 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");
|
|
@@ -201,7 +201,7 @@ function MailIcon() {
|
|
|
201
201
|
}
|
|
202
202
|
|
|
203
203
|
// src/client/panel.tsx
|
|
204
|
-
var
|
|
204
|
+
var import_react7 = require("react");
|
|
205
205
|
|
|
206
206
|
// src/client/account-form.tsx
|
|
207
207
|
var import_react3 = require("react");
|
|
@@ -256,6 +256,15 @@ function Toggle({
|
|
|
256
256
|
label
|
|
257
257
|
);
|
|
258
258
|
}
|
|
259
|
+
function portalRoot() {
|
|
260
|
+
const existing = document.getElementById("mailharbor-portal");
|
|
261
|
+
if (existing !== null) return existing;
|
|
262
|
+
const element = document.createElement("div");
|
|
263
|
+
element.id = "mailharbor-portal";
|
|
264
|
+
element.className = "mailharbor mailharbor-portal";
|
|
265
|
+
document.body.append(element);
|
|
266
|
+
return element;
|
|
267
|
+
}
|
|
259
268
|
function Modal({
|
|
260
269
|
title,
|
|
261
270
|
children,
|
|
@@ -301,7 +310,7 @@ function Modal({
|
|
|
301
310
|
footer === void 0 ? null : (0, import_react2.createElement)("footer", null, footer)
|
|
302
311
|
)
|
|
303
312
|
),
|
|
304
|
-
|
|
313
|
+
portalRoot()
|
|
305
314
|
);
|
|
306
315
|
}
|
|
307
316
|
function ErrorBar({ message, onDismiss }) {
|
|
@@ -837,13 +846,68 @@ function Composer({
|
|
|
837
846
|
);
|
|
838
847
|
}
|
|
839
848
|
|
|
840
|
-
// src/client/
|
|
849
|
+
// src/client/icons.tsx
|
|
841
850
|
var import_react5 = require("react");
|
|
851
|
+
var PATHS = {
|
|
852
|
+
refresh: (0, import_react5.createElement)("path", { d: "M20 11a8 8 0 1 0-2.3 5.7M20 5v6h-6" }),
|
|
853
|
+
plus: (0, import_react5.createElement)("path", { d: "M12 5v14M5 12h14" }),
|
|
854
|
+
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" }),
|
|
855
|
+
archive: (0, import_react5.createElement)(
|
|
856
|
+
"g",
|
|
857
|
+
null,
|
|
858
|
+
(0, import_react5.createElement)("rect", { x: 3, y: 4, width: 18, height: 5, rx: 1.5 }),
|
|
859
|
+
(0, import_react5.createElement)("path", { d: "M5 9v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V9M10 13h4" })
|
|
860
|
+
),
|
|
861
|
+
paperclip: (0, import_react5.createElement)("path", {
|
|
862
|
+
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"
|
|
863
|
+
}),
|
|
864
|
+
mail: (0, import_react5.createElement)(
|
|
865
|
+
"g",
|
|
866
|
+
null,
|
|
867
|
+
(0, import_react5.createElement)("rect", { x: 3, y: 5, width: 18, height: 14, rx: 2.5 }),
|
|
868
|
+
(0, import_react5.createElement)("path", { d: "m4 7 7.1 5a1.6 1.6 0 0 0 1.8 0L20 7" })
|
|
869
|
+
),
|
|
870
|
+
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" }),
|
|
871
|
+
reply: (0, import_react5.createElement)("path", { d: "M9 7 4 12l5 5M4 12h9a6 6 0 0 1 6 6v1" }),
|
|
872
|
+
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" }),
|
|
873
|
+
forward: (0, import_react5.createElement)("path", { d: "m15 7 5 5-5 5M20 12h-9a6 6 0 0 0-6 6v1" }),
|
|
874
|
+
check: (0, import_react5.createElement)("path", { d: "m5 13 4 4L19 7" }),
|
|
875
|
+
image: (0, import_react5.createElement)(
|
|
876
|
+
"g",
|
|
877
|
+
null,
|
|
878
|
+
(0, import_react5.createElement)("rect", { x: 3, y: 4, width: 18, height: 16, rx: 2 }),
|
|
879
|
+
(0, import_react5.createElement)("circle", { cx: 8.5, cy: 9.5, r: 1.5 }),
|
|
880
|
+
(0, import_react5.createElement)("path", { d: "m4 18 5-5 4 4 3-3 4 4" })
|
|
881
|
+
),
|
|
882
|
+
close: (0, import_react5.createElement)("path", { d: "M6 6l12 12M18 6 6 18" }),
|
|
883
|
+
chevronLeft: (0, import_react5.createElement)("path", { d: "m14 6-6 6 6 6" })
|
|
884
|
+
};
|
|
885
|
+
function Icon({ name, size = 16 }) {
|
|
886
|
+
return (0, import_react5.createElement)(
|
|
887
|
+
"svg",
|
|
888
|
+
{
|
|
889
|
+
width: size,
|
|
890
|
+
height: size,
|
|
891
|
+
viewBox: "0 0 24 24",
|
|
892
|
+
fill: "none",
|
|
893
|
+
stroke: "currentColor",
|
|
894
|
+
strokeWidth: 1.7,
|
|
895
|
+
strokeLinecap: "round",
|
|
896
|
+
strokeLinejoin: "round",
|
|
897
|
+
"aria-hidden": "true",
|
|
898
|
+
focusable: "false"
|
|
899
|
+
},
|
|
900
|
+
PATHS[name] ?? null
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
// src/client/reader.tsx
|
|
905
|
+
var import_react6 = require("react");
|
|
842
906
|
var IFRAME_STYLE = `
|
|
843
907
|
html, body { margin: 0; padding: 0; }
|
|
844
908
|
body {
|
|
845
|
-
font: 15px/1.
|
|
846
|
-
color: #171a21; background: #fff; padding:
|
|
909
|
+
font: 15px/1.75 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
910
|
+
color: #171a21; background: #fff; padding: 20px 22px;
|
|
847
911
|
overflow-wrap: anywhere;
|
|
848
912
|
}
|
|
849
913
|
img { max-width: 100%; height: auto; }
|
|
@@ -873,6 +937,9 @@ function escapeHtml(value) {
|
|
|
873
937
|
function hasRemoteImages(detail) {
|
|
874
938
|
return detail.html !== null && /<img[^>]+src=["']https?:/i.test(detail.html);
|
|
875
939
|
}
|
|
940
|
+
function addressLine(list) {
|
|
941
|
+
return list.map((item) => item.name !== "" ? `${item.name} <${item.address}>` : item.address).join("\u3001");
|
|
942
|
+
}
|
|
876
943
|
function Reader({
|
|
877
944
|
detail,
|
|
878
945
|
account,
|
|
@@ -882,11 +949,11 @@ function Reader({
|
|
|
882
949
|
onReply,
|
|
883
950
|
onClose
|
|
884
951
|
}) {
|
|
885
|
-
const [plain, setPlain] = (0,
|
|
886
|
-
const [loadImages, setLoadImages] = (0,
|
|
887
|
-
const [busy, setBusy] = (0,
|
|
888
|
-
const [error, setError] = (0,
|
|
889
|
-
const remoteImages = (0,
|
|
952
|
+
const [plain, setPlain] = (0, import_react6.useState)(false);
|
|
953
|
+
const [loadImages, setLoadImages] = (0, import_react6.useState)(false);
|
|
954
|
+
const [busy, setBusy] = (0, import_react6.useState)(false);
|
|
955
|
+
const [error, setError] = (0, import_react6.useState)("");
|
|
956
|
+
const remoteImages = (0, import_react6.useMemo)(() => hasRemoteImages(detail), [detail]);
|
|
890
957
|
const html = detail.html !== null && detail.html !== "";
|
|
891
958
|
const toggleRead = async () => {
|
|
892
959
|
setBusy(true);
|
|
@@ -906,102 +973,103 @@ function Reader({
|
|
|
906
973
|
setBusy(false);
|
|
907
974
|
}
|
|
908
975
|
};
|
|
909
|
-
return (0,
|
|
976
|
+
return (0, import_react6.createElement)(
|
|
910
977
|
"div",
|
|
911
978
|
{ className: "mailharbor-reader" },
|
|
912
|
-
(0,
|
|
979
|
+
(0, import_react6.createElement)(
|
|
913
980
|
"div",
|
|
914
981
|
{ className: "mailharbor-reader-head" },
|
|
915
|
-
(0,
|
|
982
|
+
(0, import_react6.createElement)(
|
|
916
983
|
"div",
|
|
917
|
-
{
|
|
918
|
-
|
|
919
|
-
|
|
984
|
+
{ className: "mailharbor-reader-title" },
|
|
985
|
+
onClose === void 0 ? null : (0, import_react6.createElement)(
|
|
986
|
+
"button",
|
|
987
|
+
{ className: "ghost icon", onClick: onClose, "aria-label": "\u8FD4\u56DE\u5217\u8868", title: "\u8FD4\u56DE\u5217\u8868" },
|
|
988
|
+
(0, import_react6.createElement)(Icon, { name: "chevronLeft" })
|
|
989
|
+
),
|
|
990
|
+
(0, import_react6.createElement)("h2", { style: { flex: 1 } }, detail.subject),
|
|
991
|
+
(0, import_react6.createElement)(
|
|
992
|
+
"button",
|
|
993
|
+
{
|
|
994
|
+
className: "ghost icon",
|
|
995
|
+
onClick: () => void toggleRead(),
|
|
996
|
+
disabled: busy,
|
|
997
|
+
title: detail.unread ? "\u6807\u4E3A\u5DF2\u8BFB" : "\u6807\u4E3A\u672A\u8BFB",
|
|
998
|
+
"aria-label": detail.unread ? "\u6807\u4E3A\u5DF2\u8BFB" : "\u6807\u4E3A\u672A\u8BFB"
|
|
999
|
+
},
|
|
1000
|
+
(0, import_react6.createElement)(Icon, { name: "check" })
|
|
1001
|
+
)
|
|
920
1002
|
),
|
|
921
|
-
(0,
|
|
1003
|
+
(0, import_react6.createElement)(
|
|
922
1004
|
"div",
|
|
923
1005
|
{ className: "mailharbor-reader-meta" },
|
|
924
|
-
(0,
|
|
1006
|
+
(0, import_react6.createElement)(
|
|
925
1007
|
"span",
|
|
926
|
-
|
|
927
|
-
|
|
1008
|
+
{ className: "who" },
|
|
1009
|
+
(0, import_react6.createElement)(Avatar, { email: detail.from.address, size: 22 }),
|
|
1010
|
+
(0, import_react6.createElement)("strong", null, detail.from.name !== "" ? detail.from.name : detail.from.address),
|
|
1011
|
+
detail.from.name !== "" ? (0, import_react6.createElement)("span", null, `<${detail.from.address}>`) : null
|
|
928
1012
|
),
|
|
929
|
-
(0,
|
|
930
|
-
detail.backedUp === false ? (0,
|
|
1013
|
+
(0, import_react6.createElement)("span", null, longDate(detail.date)),
|
|
1014
|
+
detail.backedUp === false ? (0, import_react6.createElement)("span", { className: "badge warn" }, "\u672A\u5907\u4EFD") : null
|
|
931
1015
|
),
|
|
932
|
-
(0,
|
|
1016
|
+
(0, import_react6.createElement)(
|
|
933
1017
|
"div",
|
|
934
1018
|
{ 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(", ")}`)
|
|
1019
|
+
(0, import_react6.createElement)("span", null, `\u6536\u4EF6\u4EBA: ${addressLine(detail.to) || "\u2014"}`),
|
|
1020
|
+
detail.cc.length === 0 ? null : (0, import_react6.createElement)("span", null, `\u6284\u9001: ${addressLine(detail.cc)}`)
|
|
941
1021
|
),
|
|
942
|
-
(0,
|
|
1022
|
+
(0, import_react6.createElement)(
|
|
943
1023
|
"div",
|
|
944
1024
|
{ className: "mailharbor-reader-actions" },
|
|
945
|
-
(0,
|
|
1025
|
+
(0, import_react6.createElement)(
|
|
946
1026
|
"button",
|
|
947
|
-
{
|
|
948
|
-
|
|
949
|
-
onClick: () => {
|
|
950
|
-
onReply("reply");
|
|
951
|
-
}
|
|
952
|
-
},
|
|
1027
|
+
{ className: "ghost", onClick: () => onReply("reply") },
|
|
1028
|
+
(0, import_react6.createElement)(Icon, { name: "reply" }),
|
|
953
1029
|
"\u56DE\u590D"
|
|
954
1030
|
),
|
|
955
|
-
(0,
|
|
1031
|
+
(0, import_react6.createElement)(
|
|
956
1032
|
"button",
|
|
957
|
-
{
|
|
958
|
-
|
|
959
|
-
onClick: () => {
|
|
960
|
-
onReply("replyAll");
|
|
961
|
-
}
|
|
962
|
-
},
|
|
1033
|
+
{ className: "ghost", onClick: () => onReply("replyAll") },
|
|
1034
|
+
(0, import_react6.createElement)(Icon, { name: "replyAll" }),
|
|
963
1035
|
"\u5168\u90E8\u56DE\u590D"
|
|
964
1036
|
),
|
|
965
|
-
(0,
|
|
1037
|
+
(0, import_react6.createElement)(
|
|
966
1038
|
"button",
|
|
967
|
-
{
|
|
968
|
-
|
|
969
|
-
onClick: () => {
|
|
970
|
-
onReply("forward");
|
|
971
|
-
}
|
|
972
|
-
},
|
|
1039
|
+
{ className: "ghost", onClick: () => onReply("forward") },
|
|
1040
|
+
(0, import_react6.createElement)(Icon, { name: "forward" }),
|
|
973
1041
|
"\u8F6C\u53D1"
|
|
974
1042
|
),
|
|
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)(
|
|
1043
|
+
(0, import_react6.createElement)("span", { className: "spacer" }),
|
|
1044
|
+
html ? (0, import_react6.createElement)(
|
|
982
1045
|
"button",
|
|
983
|
-
{ className: "
|
|
984
|
-
plain ? "\u663E\u793A HTML" : "\
|
|
1046
|
+
{ className: "subtle", onClick: () => setPlain(!plain) },
|
|
1047
|
+
plain ? "\u663E\u793A HTML" : "\u7EAF\u6587\u672C"
|
|
985
1048
|
) : null,
|
|
986
|
-
remoteImages && !loadImages ? (0,
|
|
1049
|
+
remoteImages && !loadImages ? (0, import_react6.createElement)(
|
|
1050
|
+
"button",
|
|
1051
|
+
{ className: "subtle", onClick: () => setLoadImages(true) },
|
|
1052
|
+
(0, import_react6.createElement)(Icon, { name: "image", size: 14 }),
|
|
1053
|
+
"\u663E\u793A\u56FE\u7247"
|
|
1054
|
+
) : null
|
|
987
1055
|
),
|
|
988
|
-
error === "" ? null : (0,
|
|
1056
|
+
error === "" ? null : (0, import_react6.createElement)("div", { className: "small", style: { color: "var(--m-danger)" } }, error)
|
|
989
1057
|
),
|
|
990
|
-
(0,
|
|
1058
|
+
(0, import_react6.createElement)(
|
|
991
1059
|
"div",
|
|
992
1060
|
{ className: "mailharbor-reader-body" },
|
|
993
|
-
html && !plain ? (0,
|
|
1061
|
+
html && !plain ? (0, import_react6.createElement)("iframe", {
|
|
994
1062
|
title: "\u90AE\u4EF6\u6B63\u6587",
|
|
995
1063
|
sandbox: "",
|
|
996
1064
|
srcDoc: srcDoc(detail, loadImages),
|
|
997
1065
|
referrerPolicy: "no-referrer"
|
|
998
|
-
}) : (0,
|
|
1066
|
+
}) : (0, import_react6.createElement)("pre", null, detail.text !== "" ? detail.text : "\uFF08\u65E0\u6B63\u6587\uFF09")
|
|
999
1067
|
),
|
|
1000
|
-
detail.attachments.length === 0 ? null : (0,
|
|
1068
|
+
detail.attachments.length === 0 ? null : (0, import_react6.createElement)(
|
|
1001
1069
|
"div",
|
|
1002
1070
|
{ className: "mailharbor-attachments" },
|
|
1003
1071
|
detail.attachments.map(
|
|
1004
|
-
(file) => (0,
|
|
1072
|
+
(file) => (0, import_react6.createElement)(
|
|
1005
1073
|
"a",
|
|
1006
1074
|
{
|
|
1007
1075
|
className: "mailharbor-attachment",
|
|
@@ -1018,10 +1086,12 @@ function Reader({
|
|
|
1018
1086
|
emailId: detail.id,
|
|
1019
1087
|
attachmentId: file.id
|
|
1020
1088
|
}),
|
|
1021
|
-
download: file.filename
|
|
1089
|
+
download: file.filename,
|
|
1090
|
+
title: file.filename
|
|
1022
1091
|
},
|
|
1023
|
-
(0,
|
|
1024
|
-
(0,
|
|
1092
|
+
(0, import_react6.createElement)(Icon, { name: "paperclip", size: 14 }),
|
|
1093
|
+
(0, import_react6.createElement)("span", { className: "name" }, file.filename),
|
|
1094
|
+
(0, import_react6.createElement)("span", { className: "muted small" }, formatBytes(file.size))
|
|
1025
1095
|
)
|
|
1026
1096
|
)
|
|
1027
1097
|
)
|
|
@@ -1033,44 +1103,50 @@ var EMPTY_PAGE = { items: [], total: 0, offset: 0, limit: 40 };
|
|
|
1033
1103
|
function errorText3(error) {
|
|
1034
1104
|
return error instanceof ApiError || error instanceof Error ? error.message : String(error);
|
|
1035
1105
|
}
|
|
1106
|
+
function matchesNarrow() {
|
|
1107
|
+
return typeof window.matchMedia === "function" ? window.matchMedia("(max-width: 900px)").matches : false;
|
|
1108
|
+
}
|
|
1036
1109
|
function quoteForReply(detail) {
|
|
1037
1110
|
const body = detail.html ?? `<pre>${detail.text.replaceAll("&", "&").replaceAll("<", "<")}</pre>`;
|
|
1038
1111
|
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
1112
|
}
|
|
1040
1113
|
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,
|
|
1114
|
+
const [state, setState] = (0, import_react7.useState)(null);
|
|
1115
|
+
const [error, setError] = (0, import_react7.useState)("");
|
|
1116
|
+
const [source, setSource] = (0, import_react7.useState)("local");
|
|
1117
|
+
const [mailbox, setMailbox] = (0, import_react7.useState)("all");
|
|
1118
|
+
const [folders, setFolders] = (0, import_react7.useState)([]);
|
|
1119
|
+
const [query2, setQuery] = (0, import_react7.useState)("");
|
|
1120
|
+
const [search, setSearch] = (0, import_react7.useState)("");
|
|
1121
|
+
const [page, setPage] = (0, import_react7.useState)(EMPTY_PAGE);
|
|
1122
|
+
const [limit, setLimit] = (0, import_react7.useState)(40);
|
|
1123
|
+
const [loading, setLoading] = (0, import_react7.useState)(false);
|
|
1124
|
+
const [selected, setSelected] = (0, import_react7.useState)(null);
|
|
1125
|
+
const [compose, setCompose] = (0, import_react7.useState)(null);
|
|
1126
|
+
const [showAdd, setShowAdd] = (0, import_react7.useState)(false);
|
|
1127
|
+
const [showBackup, setShowBackup] = (0, import_react7.useState)(false);
|
|
1128
|
+
const [backup, setBackup] = (0, import_react7.useState)(null);
|
|
1129
|
+
const [toast, setToast] = (0, import_react7.useState)("");
|
|
1130
|
+
const [narrow, setNarrow] = (0, import_react7.useState)(() => matchesNarrow());
|
|
1131
|
+
const [tick, setTick] = (0, import_react7.useState)(0);
|
|
1059
1132
|
const account = state?.accounts.find((item) => item.id === state.activeAccountId) ?? null;
|
|
1060
1133
|
const accountId = account?.id ?? null;
|
|
1061
|
-
const refresh = (0,
|
|
1134
|
+
const refresh = (0, import_react7.useCallback)(() => {
|
|
1062
1135
|
setTick((value) => value + 1);
|
|
1063
1136
|
}, []);
|
|
1064
|
-
const notice = (0,
|
|
1137
|
+
const notice = (0, import_react7.useCallback)((message) => {
|
|
1065
1138
|
setToast(message);
|
|
1066
1139
|
window.setTimeout(() => {
|
|
1067
1140
|
setToast("");
|
|
1068
1141
|
}, 3200);
|
|
1069
1142
|
}, []);
|
|
1070
|
-
(0,
|
|
1143
|
+
(0, import_react7.useEffect)(() => {
|
|
1071
1144
|
let cancelled = false;
|
|
1072
1145
|
api.state().then((next) => {
|
|
1073
|
-
if (!cancelled)
|
|
1146
|
+
if (!cancelled) {
|
|
1147
|
+
setState(next);
|
|
1148
|
+
if (next.settings.render.listLimit > 0) setLimit(next.settings.render.listLimit);
|
|
1149
|
+
}
|
|
1074
1150
|
}).catch((caught) => {
|
|
1075
1151
|
if (!cancelled) setError(errorText3(caught));
|
|
1076
1152
|
});
|
|
@@ -1078,12 +1154,12 @@ function MailPanel() {
|
|
|
1078
1154
|
cancelled = true;
|
|
1079
1155
|
};
|
|
1080
1156
|
}, [tick]);
|
|
1081
|
-
(0,
|
|
1157
|
+
(0, import_react7.useEffect)(() => {
|
|
1082
1158
|
if (accountId === null) return;
|
|
1083
1159
|
let cancelled = false;
|
|
1084
1160
|
api.folders({ accountId, source }).then((result) => {
|
|
1085
1161
|
if (cancelled) return;
|
|
1086
|
-
const
|
|
1162
|
+
const items2 = source === "local" ? [
|
|
1087
1163
|
{
|
|
1088
1164
|
name: "all",
|
|
1089
1165
|
label: "\u5168\u90E8\u90AE\u4EF6",
|
|
@@ -1091,7 +1167,7 @@ function MailPanel() {
|
|
|
1091
1167
|
},
|
|
1092
1168
|
...result.items.map((item) => ({ ...item, label: item.label ?? item.name }))
|
|
1093
1169
|
] : result.items.map((item) => ({ ...item, label: item.label ?? item.name }));
|
|
1094
|
-
setFolders(
|
|
1170
|
+
setFolders(items2);
|
|
1095
1171
|
}).catch(() => {
|
|
1096
1172
|
if (!cancelled) setFolders([]);
|
|
1097
1173
|
});
|
|
@@ -1099,12 +1175,11 @@ function MailPanel() {
|
|
|
1099
1175
|
cancelled = true;
|
|
1100
1176
|
};
|
|
1101
1177
|
}, [accountId, source, tick]);
|
|
1102
|
-
(0,
|
|
1178
|
+
(0, import_react7.useEffect)(() => {
|
|
1103
1179
|
setMailbox(source === "local" ? "all" : "INBOX");
|
|
1104
1180
|
setSelected(null);
|
|
1105
|
-
setLimit(state?.settings.render.listLimit ?? 40);
|
|
1106
1181
|
}, [source]);
|
|
1107
|
-
(0,
|
|
1182
|
+
(0, import_react7.useEffect)(() => {
|
|
1108
1183
|
if (accountId === null) return;
|
|
1109
1184
|
let cancelled = false;
|
|
1110
1185
|
setLoading(true);
|
|
@@ -1119,7 +1194,8 @@ function MailPanel() {
|
|
|
1119
1194
|
cancelled = true;
|
|
1120
1195
|
};
|
|
1121
1196
|
}, [accountId, source, mailbox, search, limit, tick]);
|
|
1122
|
-
(0,
|
|
1197
|
+
(0, import_react7.useEffect)(() => {
|
|
1198
|
+
if (typeof window.matchMedia !== "function") return;
|
|
1123
1199
|
const media = window.matchMedia("(max-width: 900px)");
|
|
1124
1200
|
const onChange = () => setNarrow(media.matches);
|
|
1125
1201
|
media.addEventListener("change", onChange);
|
|
@@ -1127,7 +1203,7 @@ function MailPanel() {
|
|
|
1127
1203
|
media.removeEventListener("change", onChange);
|
|
1128
1204
|
};
|
|
1129
1205
|
}, []);
|
|
1130
|
-
(0,
|
|
1206
|
+
(0, import_react7.useEffect)(() => {
|
|
1131
1207
|
if (!showBackup || accountId === null) return;
|
|
1132
1208
|
let cancelled = false;
|
|
1133
1209
|
const poll = async () => {
|
|
@@ -1228,32 +1304,35 @@ function MailPanel() {
|
|
|
1228
1304
|
setError(errorText3(caught));
|
|
1229
1305
|
}
|
|
1230
1306
|
};
|
|
1231
|
-
const folderOptions = (0,
|
|
1307
|
+
const folderOptions = (0, import_react7.useMemo)(
|
|
1232
1308
|
() => folders.map((folder) => ({
|
|
1233
1309
|
value: folder.name,
|
|
1234
1310
|
label: `${folder.label ?? folder.name}${folder.count > 0 ? ` (${String(folder.count)})` : ""}`
|
|
1235
1311
|
})),
|
|
1236
1312
|
[folders]
|
|
1237
1313
|
);
|
|
1238
|
-
const unreadCount = page.items.filter((item) => item.unread).length;
|
|
1239
1314
|
if (state === null) {
|
|
1240
|
-
return (0,
|
|
1315
|
+
return (0, import_react7.createElement)(
|
|
1316
|
+
"div",
|
|
1317
|
+
{ className: "mailharbor" },
|
|
1318
|
+
(0, import_react7.createElement)("div", { className: "mailharbor-empty" }, error === "" ? "\u6B63\u5728\u52A0\u8F7D\u90AE\u7BB1\u2026" : error)
|
|
1319
|
+
);
|
|
1241
1320
|
}
|
|
1242
1321
|
if (account === null) {
|
|
1243
|
-
return (0,
|
|
1322
|
+
return (0, import_react7.createElement)(
|
|
1244
1323
|
"div",
|
|
1245
1324
|
{ className: "mailharbor" },
|
|
1246
|
-
(0,
|
|
1325
|
+
(0, import_react7.createElement)(
|
|
1247
1326
|
"div",
|
|
1248
1327
|
{ className: "mailharbor-settings" },
|
|
1249
|
-
(0,
|
|
1250
|
-
(0,
|
|
1328
|
+
(0, import_react7.createElement)("h2", null, "\u6B22\u8FCE\u4F7F\u7528 MailHarbor"),
|
|
1329
|
+
(0, import_react7.createElement)(
|
|
1251
1330
|
"p",
|
|
1252
1331
|
{ 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\
|
|
1332
|
+
"\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
1333
|
),
|
|
1255
|
-
error === "" ? null : (0,
|
|
1256
|
-
(0,
|
|
1334
|
+
error === "" ? null : (0, import_react7.createElement)("div", { className: "small", style: { color: "var(--m-danger)" } }, error),
|
|
1335
|
+
(0, import_react7.createElement)(AddAccountForm, {
|
|
1257
1336
|
onDone: (next) => {
|
|
1258
1337
|
setState(next);
|
|
1259
1338
|
setSource("local");
|
|
@@ -1263,64 +1342,83 @@ function MailPanel() {
|
|
|
1263
1342
|
);
|
|
1264
1343
|
}
|
|
1265
1344
|
const needsLogin = source === "server" && state.loggedIn === false;
|
|
1266
|
-
|
|
1345
|
+
const items = page.items;
|
|
1346
|
+
return (0, import_react7.createElement)(
|
|
1267
1347
|
"div",
|
|
1268
1348
|
{ className: narrow ? "mailharbor mailharbor-narrow" : "mailharbor" },
|
|
1269
|
-
(0,
|
|
1349
|
+
(0, import_react7.createElement)(
|
|
1270
1350
|
"div",
|
|
1271
1351
|
{ className: "mailharbor-topbar" },
|
|
1272
|
-
(0,
|
|
1273
|
-
|
|
1274
|
-
"
|
|
1275
|
-
{
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1352
|
+
(0, import_react7.createElement)(
|
|
1353
|
+
"div",
|
|
1354
|
+
{ className: "mailharbor-account" },
|
|
1355
|
+
(0, import_react7.createElement)(Avatar, { email: account.email, size: 26 }),
|
|
1356
|
+
state.accounts.length > 1 ? (0, import_react7.createElement)(
|
|
1357
|
+
"select",
|
|
1358
|
+
{
|
|
1359
|
+
value: account.id,
|
|
1360
|
+
onChange: (event) => void switchAccount(event.target.value),
|
|
1361
|
+
"aria-label": "\u8D26\u53F7"
|
|
1362
|
+
},
|
|
1363
|
+
state.accounts.map((item) => (0, import_react7.createElement)("option", { key: item.id, value: item.id }, item.label))
|
|
1364
|
+
) : (0, import_react7.createElement)("span", { className: "name" }, account.label),
|
|
1365
|
+
state.loggedIn === false ? (0, import_react7.createElement)("span", { className: "badge warn" }, "\u672A\u767B\u5F55") : null
|
|
1366
|
+
),
|
|
1367
|
+
(0, import_react7.createElement)(
|
|
1283
1368
|
"div",
|
|
1284
1369
|
{ className: "mailharbor-segment", role: "tablist" },
|
|
1285
|
-
(0,
|
|
1370
|
+
(0, import_react7.createElement)(
|
|
1286
1371
|
"button",
|
|
1287
1372
|
{ className: source === "local" ? "active" : "", onClick: () => setSource("local"), role: "tab" },
|
|
1288
1373
|
"\u672C\u5730\u5907\u4EFD"
|
|
1289
1374
|
),
|
|
1290
|
-
(0,
|
|
1375
|
+
(0, import_react7.createElement)(
|
|
1291
1376
|
"button",
|
|
1292
1377
|
{ className: source === "server" ? "active" : "", onClick: () => setSource("server"), role: "tab" },
|
|
1293
1378
|
"\u670D\u52A1\u5668\u5B9E\u65F6"
|
|
1294
1379
|
)
|
|
1295
1380
|
),
|
|
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)(
|
|
1381
|
+
(0, import_react7.createElement)("span", { className: "spacer" }),
|
|
1382
|
+
(0, import_react7.createElement)(
|
|
1302
1383
|
"button",
|
|
1303
1384
|
{
|
|
1304
|
-
className: "ghost",
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1385
|
+
className: "ghost icon",
|
|
1386
|
+
title: "\u6DFB\u52A0\u8D26\u53F7",
|
|
1387
|
+
"aria-label": "\u6DFB\u52A0\u8D26\u53F7",
|
|
1388
|
+
onClick: () => setShowAdd(true)
|
|
1308
1389
|
},
|
|
1309
|
-
"
|
|
1390
|
+
(0, import_react7.createElement)(Icon, { name: "plus" })
|
|
1391
|
+
),
|
|
1392
|
+
(0, import_react7.createElement)(
|
|
1393
|
+
"button",
|
|
1394
|
+
{ className: "ghost icon", title: "\u5237\u65B0\u5217\u8868", "aria-label": "\u5237\u65B0\u5217\u8868", onClick: refresh },
|
|
1395
|
+
(0, import_react7.createElement)(Icon, { name: "refresh" })
|
|
1396
|
+
),
|
|
1397
|
+
(0, import_react7.createElement)(
|
|
1398
|
+
"button",
|
|
1399
|
+
{ className: "ghost", onClick: () => void startBackup() },
|
|
1400
|
+
(0, import_react7.createElement)(Icon, { name: "archive" }),
|
|
1401
|
+
"\u5907\u4EFD"
|
|
1402
|
+
),
|
|
1403
|
+
(0, import_react7.createElement)(
|
|
1404
|
+
"button",
|
|
1405
|
+
{ className: "primary", onClick: () => startCompose("new") },
|
|
1406
|
+
(0, import_react7.createElement)(Icon, { name: "compose" }),
|
|
1407
|
+
"\u5199\u90AE\u4EF6"
|
|
1310
1408
|
)
|
|
1311
1409
|
),
|
|
1312
|
-
toast === "" ? null : (0,
|
|
1313
|
-
error === "" ? null : (0,
|
|
1314
|
-
needsLogin ? (0,
|
|
1410
|
+
toast === "" ? null : (0, import_react7.createElement)("div", { className: "small", style: { padding: "6px 14px", color: "var(--m-ok)" } }, toast),
|
|
1411
|
+
error === "" ? null : (0, import_react7.createElement)(ErrorBar, { message: error, onDismiss: () => setError("") }),
|
|
1412
|
+
needsLogin ? (0, import_react7.createElement)("div", { className: "mailharbor-settings" }, (0, import_react7.createElement)(LoginForm, { account, onDone: refresh })) : (0, import_react7.createElement)(
|
|
1315
1413
|
"div",
|
|
1316
1414
|
{ className: "mailharbor-body", "data-mode": narrow && selected !== null ? "reader" : "list" },
|
|
1317
|
-
(0,
|
|
1415
|
+
(0, import_react7.createElement)(
|
|
1318
1416
|
"div",
|
|
1319
1417
|
{ className: "mailharbor-list" },
|
|
1320
|
-
(0,
|
|
1418
|
+
(0, import_react7.createElement)(
|
|
1321
1419
|
"div",
|
|
1322
1420
|
{ className: "mailharbor-filters" },
|
|
1323
|
-
(0,
|
|
1421
|
+
(0, import_react7.createElement)(
|
|
1324
1422
|
"select",
|
|
1325
1423
|
{
|
|
1326
1424
|
value: mailbox,
|
|
@@ -1331,12 +1429,13 @@ function MailPanel() {
|
|
|
1331
1429
|
"aria-label": "\u90AE\u7BB1\u6587\u4EF6\u5939"
|
|
1332
1430
|
},
|
|
1333
1431
|
folderOptions.map(
|
|
1334
|
-
(option) => (0,
|
|
1432
|
+
(option) => (0, import_react7.createElement)("option", { key: option.value, value: option.value }, option.label)
|
|
1335
1433
|
)
|
|
1336
1434
|
),
|
|
1337
|
-
(0,
|
|
1435
|
+
(0, import_react7.createElement)("input", {
|
|
1338
1436
|
type: "search",
|
|
1339
1437
|
placeholder: "\u641C\u7D22\u90AE\u4EF6",
|
|
1438
|
+
"aria-label": "\u641C\u7D22\u90AE\u4EF6",
|
|
1340
1439
|
value: query2,
|
|
1341
1440
|
onChange: (event) => setQuery(event.target.value),
|
|
1342
1441
|
onKeyDown: (event) => {
|
|
@@ -1347,78 +1446,96 @@ function MailPanel() {
|
|
|
1347
1446
|
}
|
|
1348
1447
|
}
|
|
1349
1448
|
}),
|
|
1350
|
-
query2 !== search || search !== "" ? (0,
|
|
1449
|
+
query2 !== search || search !== "" ? (0, import_react7.createElement)(
|
|
1351
1450
|
"button",
|
|
1352
1451
|
{
|
|
1353
|
-
className: "subtle
|
|
1452
|
+
className: "subtle",
|
|
1453
|
+
title: "\u6E05\u9664\u641C\u7D22",
|
|
1354
1454
|
onClick: () => {
|
|
1355
1455
|
setQuery("");
|
|
1356
1456
|
setSearch("");
|
|
1357
1457
|
}
|
|
1358
1458
|
},
|
|
1359
|
-
"
|
|
1459
|
+
(0, import_react7.createElement)(Icon, { name: "close", size: 14 })
|
|
1360
1460
|
) : null
|
|
1361
1461
|
),
|
|
1362
|
-
(0,
|
|
1462
|
+
(0, import_react7.createElement)(
|
|
1363
1463
|
"div",
|
|
1364
1464
|
{ className: "mailharbor-rows" },
|
|
1365
|
-
loading &&
|
|
1465
|
+
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
1466
|
"div",
|
|
1367
1467
|
{ className: "mailharbor-empty" },
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
"
|
|
1468
|
+
(0, import_react7.createElement)(Icon, { name: "mail", size: 28 }),
|
|
1469
|
+
(0, import_react7.createElement)(
|
|
1470
|
+
"div",
|
|
1471
|
+
{ className: "title" },
|
|
1472
|
+
source === "local" ? "\u672C\u5730\u5907\u4EFD\u91CC\u8FD8\u6CA1\u6709\u90AE\u4EF6" : "\u670D\u52A1\u5668\u4E0A\u6CA1\u6709\u90AE\u4EF6"
|
|
1473
|
+
),
|
|
1474
|
+
(0, import_react7.createElement)(
|
|
1475
|
+
"div",
|
|
1476
|
+
{ className: "small" },
|
|
1477
|
+
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"
|
|
1478
|
+
)
|
|
1479
|
+
) : items.map(
|
|
1480
|
+
(item) => (0, import_react7.createElement)(
|
|
1481
|
+
"div",
|
|
1372
1482
|
{
|
|
1373
1483
|
key: item.id,
|
|
1374
1484
|
className: `mailharbor-row${item.unread ? " unread" : ""}${selected?.id === item.id ? " selected" : ""}`,
|
|
1375
|
-
|
|
1485
|
+
role: "button",
|
|
1486
|
+
tabIndex: 0,
|
|
1487
|
+
onClick: () => void openMessage(item),
|
|
1488
|
+
onKeyDown: (event) => {
|
|
1489
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1490
|
+
event.preventDefault();
|
|
1491
|
+
void openMessage(item);
|
|
1492
|
+
}
|
|
1493
|
+
}
|
|
1376
1494
|
},
|
|
1377
|
-
(0,
|
|
1495
|
+
(0, import_react7.createElement)(
|
|
1378
1496
|
"span",
|
|
1379
1497
|
{ className: "line-1" },
|
|
1380
|
-
(0,
|
|
1498
|
+
item.unread ? (0, import_react7.createElement)("span", { className: "dot" }) : null,
|
|
1499
|
+
(0, import_react7.createElement)(
|
|
1381
1500
|
"span",
|
|
1382
1501
|
{ className: "from" },
|
|
1383
1502
|
item.from.name !== "" ? item.from.name : item.from.address
|
|
1384
1503
|
),
|
|
1385
|
-
item.
|
|
1386
|
-
(0,
|
|
1504
|
+
item.hasAttachments ? (0, import_react7.createElement)(Icon, { name: "paperclip", size: 13 }) : null,
|
|
1505
|
+
item.backedUp === false ? (0, import_react7.createElement)("span", { className: "badge warn" }, "\u672A\u5907\u4EFD") : null,
|
|
1506
|
+
(0, import_react7.createElement)("span", { className: "date" }, shortDate(item.date))
|
|
1387
1507
|
),
|
|
1388
|
-
(0,
|
|
1389
|
-
item.snippet === "" ? null : (0,
|
|
1508
|
+
(0, import_react7.createElement)("span", { className: "line-2" }, (0, import_react7.createElement)("span", { className: "subject" }, item.subject)),
|
|
1509
|
+
item.snippet === "" ? null : (0, import_react7.createElement)("span", { className: "snippet" }, item.snippet)
|
|
1390
1510
|
)
|
|
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
|
|
1511
|
+
)
|
|
1512
|
+
),
|
|
1513
|
+
items.length > 0 ? (0, import_react7.createElement)(
|
|
1514
|
+
"div",
|
|
1515
|
+
{ className: "mailharbor-list-foot" },
|
|
1516
|
+
(0, import_react7.createElement)("span", null, `${String(items.length)} / ${String(page.total)} \u5C01`),
|
|
1517
|
+
(0, import_react7.createElement)("span", { className: "spacer" }),
|
|
1518
|
+
page.total > items.length ? (0, import_react7.createElement)(
|
|
1519
|
+
"button",
|
|
1520
|
+
{ className: "subtle", onClick: () => setLimit((current) => current + 40) },
|
|
1521
|
+
"\u52A0\u8F7D\u66F4\u591A"
|
|
1406
1522
|
) : null
|
|
1407
|
-
)
|
|
1523
|
+
) : null
|
|
1408
1524
|
),
|
|
1409
|
-
(0,
|
|
1525
|
+
(0, import_react7.createElement)(
|
|
1410
1526
|
"div",
|
|
1411
1527
|
{ className: "mailharbor-reader" },
|
|
1412
|
-
selected === null ? (0,
|
|
1528
|
+
selected === null ? (0, import_react7.createElement)(
|
|
1413
1529
|
"div",
|
|
1414
1530
|
{ className: "mailharbor-empty" },
|
|
1415
|
-
(0,
|
|
1416
|
-
(0,
|
|
1417
|
-
|
|
1531
|
+
(0, import_react7.createElement)(Icon, { name: "mail", size: 34 }),
|
|
1532
|
+
(0, import_react7.createElement)("div", { className: "title" }, "\u9009\u62E9\u4E00\u5C01\u90AE\u4EF6\u5F00\u59CB\u9605\u8BFB"),
|
|
1533
|
+
(0, import_react7.createElement)(
|
|
1534
|
+
"div",
|
|
1418
1535
|
{ className: "small" },
|
|
1419
1536
|
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
1537
|
)
|
|
1421
|
-
) : (0,
|
|
1538
|
+
) : (0, import_react7.createElement)(Reader, {
|
|
1422
1539
|
detail: selected,
|
|
1423
1540
|
account,
|
|
1424
1541
|
source,
|
|
@@ -1429,45 +1546,45 @@ function MailPanel() {
|
|
|
1429
1546
|
})
|
|
1430
1547
|
)
|
|
1431
1548
|
),
|
|
1432
|
-
showBackup && backup !== null ? (0,
|
|
1549
|
+
showBackup && backup !== null ? (0, import_react7.createElement)(
|
|
1433
1550
|
Modal,
|
|
1434
1551
|
{
|
|
1435
1552
|
title: "\u5907\u4EFD",
|
|
1436
1553
|
onClose: () => setShowBackup(false),
|
|
1437
|
-
footer: (0,
|
|
1554
|
+
footer: (0, import_react7.createElement)(
|
|
1438
1555
|
"div",
|
|
1439
1556
|
{ style: { display: "flex", gap: "8px", width: "100%", alignItems: "center" } },
|
|
1440
|
-
(0,
|
|
1441
|
-
(0,
|
|
1442
|
-
backup.running ? (0,
|
|
1443
|
-
(0,
|
|
1557
|
+
(0, import_react7.createElement)("span", { className: "small muted" }, backup.running ? "\u5907\u4EFD\u8FDB\u884C\u4E2D\u2026" : backup.message),
|
|
1558
|
+
(0, import_react7.createElement)("span", { className: "spacer" }),
|
|
1559
|
+
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"),
|
|
1560
|
+
(0, import_react7.createElement)("button", { className: "ghost", onClick: () => setShowBackup(false) }, "\u5173\u95ED")
|
|
1444
1561
|
)
|
|
1445
1562
|
},
|
|
1446
|
-
(0,
|
|
1563
|
+
(0, import_react7.createElement)(
|
|
1447
1564
|
"div",
|
|
1448
1565
|
{ className: "mailharbor-kv" },
|
|
1449
|
-
(0,
|
|
1450
|
-
(0,
|
|
1451
|
-
(0,
|
|
1452
|
-
(0,
|
|
1453
|
-
(0,
|
|
1454
|
-
(0,
|
|
1455
|
-
(0,
|
|
1456
|
-
(0,
|
|
1566
|
+
(0, import_react7.createElement)("dt", null, "\u5F00\u59CB\u65F6\u95F4"),
|
|
1567
|
+
(0, import_react7.createElement)("dd", null, backup.startedAt ?? "\u2014"),
|
|
1568
|
+
(0, import_react7.createElement)("dt", null, "\u4E0A\u6B21\u6210\u529F"),
|
|
1569
|
+
(0, import_react7.createElement)("dd", null, backup.lastSuccessAt ?? "\u2014"),
|
|
1570
|
+
(0, import_react7.createElement)("dt", null, "\u65B0\u589E"),
|
|
1571
|
+
(0, import_react7.createElement)("dd", null, String(backup.added)),
|
|
1572
|
+
(0, import_react7.createElement)("dt", null, "\u603B\u6570"),
|
|
1573
|
+
(0, import_react7.createElement)("dd", null, String(backup.total))
|
|
1457
1574
|
),
|
|
1458
|
-
(0,
|
|
1575
|
+
(0, import_react7.createElement)(
|
|
1459
1576
|
"div",
|
|
1460
1577
|
{ className: "mailharbor-log" },
|
|
1461
1578
|
backup.output.length === 0 ? "\uFF08\u7B49\u5F85\u8F93\u51FA\u2026\uFF09" : backup.output.join("\n")
|
|
1462
1579
|
)
|
|
1463
1580
|
) : null,
|
|
1464
|
-
compose !== null ? (0,
|
|
1581
|
+
compose !== null ? (0, import_react7.createElement)(Composer, {
|
|
1465
1582
|
account,
|
|
1466
1583
|
initial: compose,
|
|
1467
1584
|
onClose: () => setCompose(null),
|
|
1468
1585
|
onSent: (message) => notice(message)
|
|
1469
1586
|
}) : null,
|
|
1470
|
-
showAdd ? (0,
|
|
1587
|
+
showAdd ? (0, import_react7.createElement)(AddAccountModal, {
|
|
1471
1588
|
onClose: () => setShowAdd(false),
|
|
1472
1589
|
onDone: (next) => {
|
|
1473
1590
|
setState(next);
|
|
@@ -1478,27 +1595,27 @@ function MailPanel() {
|
|
|
1478
1595
|
}
|
|
1479
1596
|
|
|
1480
1597
|
// src/client/settings.tsx
|
|
1481
|
-
var
|
|
1598
|
+
var import_react8 = require("react");
|
|
1482
1599
|
function errorText4(error) {
|
|
1483
1600
|
return error instanceof ApiError || error instanceof Error ? error.message : String(error);
|
|
1484
1601
|
}
|
|
1485
1602
|
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,
|
|
1603
|
+
const [state, setState] = (0, import_react8.useState)(null);
|
|
1604
|
+
const [settings, setSettings] = (0, import_react8.useState)(null);
|
|
1605
|
+
const [error, setError] = (0, import_react8.useState)("");
|
|
1606
|
+
const [toast, setToast] = (0, import_react8.useState)("");
|
|
1607
|
+
const [signature, setSignature] = (0, import_react8.useState)("");
|
|
1608
|
+
const [markOnOpen, setMarkOnOpen] = (0, import_react8.useState)(true);
|
|
1609
|
+
const [pollSeconds, setPollSeconds] = (0, import_react8.useState)(60);
|
|
1610
|
+
const [listLimit, setListLimit] = (0, import_react8.useState)(40);
|
|
1611
|
+
const [aiEnabled, setAiEnabled] = (0, import_react8.useState)(true);
|
|
1612
|
+
const [aiProvider, setAiProvider] = (0, import_react8.useState)("deepseek-account");
|
|
1613
|
+
const [aiModel, setAiModel] = (0, import_react8.useState)("deepseek-flash");
|
|
1614
|
+
const [editing, setEditing] = (0, import_react8.useState)(null);
|
|
1615
|
+
const [checkResult, setCheckResult] = (0, import_react8.useState)("");
|
|
1616
|
+
const [adding, setAdding] = (0, import_react8.useState)(false);
|
|
1617
|
+
const [tick, setTick] = (0, import_react8.useState)(0);
|
|
1618
|
+
(0, import_react8.useEffect)(() => {
|
|
1502
1619
|
let cancelled = false;
|
|
1503
1620
|
Promise.all([api.state(), api.settings()]).then(([appState, view]) => {
|
|
1504
1621
|
if (cancelled) return;
|
|
@@ -1536,24 +1653,24 @@ function MailSettings() {
|
|
|
1536
1653
|
};
|
|
1537
1654
|
const account = settings?.accounts.find((item) => item.id === settings.activeAccountId) ?? null;
|
|
1538
1655
|
if (state === null || settings === null) {
|
|
1539
|
-
return (0,
|
|
1656
|
+
return (0, import_react8.createElement)("div", { className: "mailharbor mailharbor-settings" }, error === "" ? "\u6B63\u5728\u52A0\u8F7D\u8BBE\u7F6E\u2026" : error);
|
|
1540
1657
|
}
|
|
1541
|
-
return (0,
|
|
1658
|
+
return (0, import_react8.createElement)(
|
|
1542
1659
|
"div",
|
|
1543
1660
|
{ className: "mailharbor" },
|
|
1544
|
-
(0,
|
|
1661
|
+
(0, import_react8.createElement)(
|
|
1545
1662
|
"div",
|
|
1546
1663
|
{ className: "mailharbor-settings" },
|
|
1547
|
-
(0,
|
|
1548
|
-
(0,
|
|
1549
|
-
toast === "" ? null : (0,
|
|
1550
|
-
error === "" ? null : (0,
|
|
1551
|
-
(0,
|
|
1664
|
+
(0, import_react8.createElement)("h2", null, "MailHarbor"),
|
|
1665
|
+
(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"),
|
|
1666
|
+
toast === "" ? null : (0, import_react8.createElement)("div", { className: "small", style: { color: "var(--m-ok)" } }, toast),
|
|
1667
|
+
error === "" ? null : (0, import_react8.createElement)(ErrorBar, { message: error, onDismiss: () => setError("") }),
|
|
1668
|
+
(0, import_react8.createElement)(
|
|
1552
1669
|
"div",
|
|
1553
1670
|
{ className: "mailharbor-card" },
|
|
1554
|
-
(0,
|
|
1555
|
-
settings.accounts.length === 0 ? (0,
|
|
1556
|
-
(item) => (0,
|
|
1671
|
+
(0, import_react8.createElement)("h3", null, "\u8D26\u53F7"),
|
|
1672
|
+
settings.accounts.length === 0 ? (0, import_react8.createElement)(AddAccountForm, { onDone: () => reload() }) : settings.accounts.map(
|
|
1673
|
+
(item) => (0, import_react8.createElement)(AccountRow, {
|
|
1557
1674
|
key: item.id,
|
|
1558
1675
|
account: item,
|
|
1559
1676
|
active: item.id === settings.activeAccountId,
|
|
@@ -1597,32 +1714,32 @@ function MailSettings() {
|
|
|
1597
1714
|
}
|
|
1598
1715
|
})
|
|
1599
1716
|
),
|
|
1600
|
-
adding ? (0,
|
|
1717
|
+
adding ? (0, import_react8.createElement)(AddAccountForm, {
|
|
1601
1718
|
onDone: () => {
|
|
1602
1719
|
setAdding(false);
|
|
1603
1720
|
reload();
|
|
1604
1721
|
},
|
|
1605
1722
|
onCancel: () => setAdding(false)
|
|
1606
|
-
}) : (0,
|
|
1723
|
+
}) : (0, import_react8.createElement)("button", { className: "ghost", onClick: () => setAdding(true) }, "+ \u6DFB\u52A0\u8D26\u53F7")
|
|
1607
1724
|
),
|
|
1608
|
-
(0,
|
|
1725
|
+
(0, import_react8.createElement)(
|
|
1609
1726
|
"div",
|
|
1610
1727
|
{ className: "mailharbor-card" },
|
|
1611
|
-
(0,
|
|
1612
|
-
(0,
|
|
1728
|
+
(0, import_react8.createElement)("h3", null, "\u5199\u4FE1\u4E0E\u9605\u8BFB"),
|
|
1729
|
+
(0, import_react8.createElement)(
|
|
1613
1730
|
Field,
|
|
1614
1731
|
{ label: "\u7B7E\u540D\uFF08\u7EAF\u6587\u672C\uFF0C\u53D1\u9001\u65F6\u8FFD\u52A0\u5230\u6B63\u6587\u672B\u5C3E\uFF09" },
|
|
1615
|
-
(0,
|
|
1732
|
+
(0, import_react8.createElement)("textarea", {
|
|
1616
1733
|
rows: 4,
|
|
1617
1734
|
value: signature,
|
|
1618
1735
|
onChange: (event) => setSignature(event.target.value)
|
|
1619
1736
|
})
|
|
1620
1737
|
),
|
|
1621
|
-
(0,
|
|
1738
|
+
(0, import_react8.createElement)(
|
|
1622
1739
|
"div",
|
|
1623
1740
|
{ style: { display: "flex", gap: "10px", alignItems: "center", flexWrap: "wrap" } },
|
|
1624
|
-
(0,
|
|
1625
|
-
(0,
|
|
1741
|
+
(0, import_react8.createElement)("button", { className: "ghost", onClick: () => void saveGeneral({ signature }) }, "\u4FDD\u5B58\u7B7E\u540D"),
|
|
1742
|
+
(0, import_react8.createElement)(Toggle, {
|
|
1626
1743
|
checked: markOnOpen,
|
|
1627
1744
|
onChange: (value) => {
|
|
1628
1745
|
setMarkOnOpen(value);
|
|
@@ -1631,13 +1748,13 @@ function MailSettings() {
|
|
|
1631
1748
|
label: "\u6253\u5F00\u90AE\u4EF6\u65F6\u6807\u4E3A\u5DF2\u8BFB"
|
|
1632
1749
|
})
|
|
1633
1750
|
),
|
|
1634
|
-
(0,
|
|
1751
|
+
(0, import_react8.createElement)(
|
|
1635
1752
|
"div",
|
|
1636
1753
|
{ className: "mailharbor-grid" },
|
|
1637
|
-
(0,
|
|
1754
|
+
(0, import_react8.createElement)(
|
|
1638
1755
|
Field,
|
|
1639
1756
|
{ label: "\u5217\u8868\u6BCF\u9875\u6570\u91CF" },
|
|
1640
|
-
(0,
|
|
1757
|
+
(0, import_react8.createElement)("input", {
|
|
1641
1758
|
type: "number",
|
|
1642
1759
|
min: 10,
|
|
1643
1760
|
max: 200,
|
|
@@ -1646,10 +1763,10 @@ function MailSettings() {
|
|
|
1646
1763
|
onBlur: () => void saveGeneral({ render: { listLimit } })
|
|
1647
1764
|
})
|
|
1648
1765
|
),
|
|
1649
|
-
(0,
|
|
1766
|
+
(0, import_react8.createElement)(
|
|
1650
1767
|
Field,
|
|
1651
1768
|
{ label: "\u672A\u8BFB\u89D2\u6807\u8F6E\u8BE2\uFF08\u79D2\uFF09" },
|
|
1652
|
-
(0,
|
|
1769
|
+
(0, import_react8.createElement)("input", {
|
|
1653
1770
|
type: "number",
|
|
1654
1771
|
min: 15,
|
|
1655
1772
|
max: 3600,
|
|
@@ -1660,11 +1777,11 @@ function MailSettings() {
|
|
|
1660
1777
|
)
|
|
1661
1778
|
)
|
|
1662
1779
|
),
|
|
1663
|
-
(0,
|
|
1780
|
+
(0, import_react8.createElement)(
|
|
1664
1781
|
"div",
|
|
1665
1782
|
{ className: "mailharbor-card" },
|
|
1666
|
-
(0,
|
|
1667
|
-
(0,
|
|
1783
|
+
(0, import_react8.createElement)("h3", null, "AI"),
|
|
1784
|
+
(0, import_react8.createElement)(Toggle, {
|
|
1668
1785
|
checked: aiEnabled,
|
|
1669
1786
|
onChange: (value) => {
|
|
1670
1787
|
setAiEnabled(value);
|
|
@@ -1672,54 +1789,54 @@ function MailSettings() {
|
|
|
1672
1789
|
},
|
|
1673
1790
|
label: "\u542F\u7528 AI\uFF08\u6458\u8981\u3001\u8D77\u8349\u3001\u6DA6\u8272\u3001\u81EA\u7136\u8BED\u8A00\u641C\u7D22\uFF09"
|
|
1674
1791
|
}),
|
|
1675
|
-
(0,
|
|
1792
|
+
(0, import_react8.createElement)(
|
|
1676
1793
|
"div",
|
|
1677
1794
|
{ className: "mailharbor-grid" },
|
|
1678
|
-
(0,
|
|
1795
|
+
(0, import_react8.createElement)(
|
|
1679
1796
|
Field,
|
|
1680
1797
|
{ label: "Provider" },
|
|
1681
|
-
(0,
|
|
1798
|
+
(0, import_react8.createElement)("input", {
|
|
1682
1799
|
value: aiProvider,
|
|
1683
1800
|
onChange: (event) => setAiProvider(event.target.value),
|
|
1684
1801
|
onBlur: () => void saveGeneral({ ai: { provider: aiProvider } })
|
|
1685
1802
|
})
|
|
1686
1803
|
),
|
|
1687
|
-
(0,
|
|
1804
|
+
(0, import_react8.createElement)(
|
|
1688
1805
|
Field,
|
|
1689
1806
|
{ label: "\u6A21\u578B" },
|
|
1690
|
-
(0,
|
|
1807
|
+
(0, import_react8.createElement)("input", {
|
|
1691
1808
|
value: aiModel,
|
|
1692
1809
|
onChange: (event) => setAiModel(event.target.value),
|
|
1693
1810
|
onBlur: () => void saveGeneral({ ai: { model: aiModel } })
|
|
1694
1811
|
})
|
|
1695
1812
|
)
|
|
1696
1813
|
),
|
|
1697
|
-
(0,
|
|
1814
|
+
(0, import_react8.createElement)(
|
|
1698
1815
|
"p",
|
|
1699
1816
|
{ className: "small muted" },
|
|
1700
1817
|
"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
1818
|
)
|
|
1702
1819
|
),
|
|
1703
|
-
(0,
|
|
1820
|
+
(0, import_react8.createElement)(
|
|
1704
1821
|
"div",
|
|
1705
1822
|
{ className: "mailharbor-card" },
|
|
1706
|
-
(0,
|
|
1707
|
-
(0,
|
|
1823
|
+
(0, import_react8.createElement)("h3", null, "\u6570\u636E"),
|
|
1824
|
+
(0, import_react8.createElement)(
|
|
1708
1825
|
"dl",
|
|
1709
1826
|
{ className: "mailharbor-kv" },
|
|
1710
|
-
(0,
|
|
1711
|
-
(0,
|
|
1712
|
-
(0,
|
|
1713
|
-
(0,
|
|
1714
|
-
(0,
|
|
1715
|
-
(0,
|
|
1716
|
-
(0,
|
|
1717
|
-
(0,
|
|
1827
|
+
(0, import_react8.createElement)("dt", null, "\u6570\u636E\u76EE\u5F55"),
|
|
1828
|
+
(0, import_react8.createElement)("dd", null, settings.dataDir),
|
|
1829
|
+
(0, import_react8.createElement)("dt", null, "\u914D\u7F6E\u6587\u4EF6"),
|
|
1830
|
+
(0, import_react8.createElement)("dd", null, settings.configFile),
|
|
1831
|
+
(0, import_react8.createElement)("dt", null, "\u5F53\u524D\u8D26\u53F7\u6570\u636E\u5E93"),
|
|
1832
|
+
(0, import_react8.createElement)("dd", null, account === null ? "\u2014" : `${settings.dataDir}/accounts/${account.id}/mail.db`),
|
|
1833
|
+
(0, import_react8.createElement)("dt", null, "\u63D2\u4EF6\u7248\u672C"),
|
|
1834
|
+
(0, import_react8.createElement)("dd", null, state.version)
|
|
1718
1835
|
),
|
|
1719
|
-
(0,
|
|
1836
|
+
(0, import_react8.createElement)(
|
|
1720
1837
|
"div",
|
|
1721
1838
|
{ style: { display: "flex", gap: "8px", flexWrap: "wrap" } },
|
|
1722
|
-
account === null ? null : (0,
|
|
1839
|
+
account === null ? null : (0, import_react8.createElement)(
|
|
1723
1840
|
"button",
|
|
1724
1841
|
{
|
|
1725
1842
|
className: "ghost",
|
|
@@ -1754,19 +1871,19 @@ function AccountRow({
|
|
|
1754
1871
|
onSave,
|
|
1755
1872
|
onRemove
|
|
1756
1873
|
}) {
|
|
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,
|
|
1874
|
+
const [password, setPassword] = (0, import_react8.useState)("");
|
|
1875
|
+
const [remember, setRemember] = (0, import_react8.useState)(true);
|
|
1876
|
+
const [label, setLabel] = (0, import_react8.useState)(account.label);
|
|
1877
|
+
const [username, setUsername] = (0, import_react8.useState)(account.username);
|
|
1878
|
+
const [imapHost, setImapHost] = (0, import_react8.useState)(account.imap.host);
|
|
1879
|
+
const [imapPort, setImapPort] = (0, import_react8.useState)(String(account.imap.port));
|
|
1880
|
+
const [imapSecure, setImapSecure] = (0, import_react8.useState)(account.imap.secure);
|
|
1881
|
+
const [smtpHost, setSmtpHost] = (0, import_react8.useState)(account.smtp.host);
|
|
1882
|
+
const [smtpPort, setSmtpPort] = (0, import_react8.useState)(String(account.smtp.port));
|
|
1883
|
+
const [smtpSecure, setSmtpSecure] = (0, import_react8.useState)(account.smtp.secure);
|
|
1884
|
+
const [fromName, setFromName] = (0, import_react8.useState)(account.smtp.fromName);
|
|
1885
|
+
const [busy, setBusy] = (0, import_react8.useState)(false);
|
|
1886
|
+
(0, import_react8.useEffect)(() => {
|
|
1770
1887
|
setLabel(account.label);
|
|
1771
1888
|
setUsername(account.username);
|
|
1772
1889
|
setImapHost(account.imap.host);
|
|
@@ -1785,103 +1902,103 @@ function AccountRow({
|
|
|
1785
1902
|
setBusy(false);
|
|
1786
1903
|
}
|
|
1787
1904
|
};
|
|
1788
|
-
return (0,
|
|
1905
|
+
return (0, import_react8.createElement)(
|
|
1789
1906
|
"div",
|
|
1790
1907
|
{ className: "mailharbor-card", style: { background: "var(--m-bg-1)" } },
|
|
1791
|
-
(0,
|
|
1908
|
+
(0, import_react8.createElement)(
|
|
1792
1909
|
"div",
|
|
1793
1910
|
{ className: "mailharbor-account-row" },
|
|
1794
|
-
(0,
|
|
1795
|
-
(0,
|
|
1911
|
+
(0, import_react8.createElement)(Avatar, { email: account.email, size: 30 }),
|
|
1912
|
+
(0, import_react8.createElement)(
|
|
1796
1913
|
"div",
|
|
1797
1914
|
{ style: { display: "flex", flexDirection: "column", minWidth: 0 } },
|
|
1798
|
-
(0,
|
|
1799
|
-
(0,
|
|
1915
|
+
(0, import_react8.createElement)("strong", null, account.label),
|
|
1916
|
+
(0, import_react8.createElement)("span", { className: "small muted" }, account.email)
|
|
1800
1917
|
),
|
|
1801
|
-
active ? (0,
|
|
1802
|
-
loggedIn === false ? (0,
|
|
1803
|
-
(0,
|
|
1804
|
-
active ? null : (0,
|
|
1805
|
-
(0,
|
|
1806
|
-
(0,
|
|
1918
|
+
active ? (0, import_react8.createElement)("span", { className: "badge ok" }, "\u5F53\u524D\u8D26\u53F7") : null,
|
|
1919
|
+
loggedIn === false ? (0, import_react8.createElement)("span", { className: "badge warn" }, "\u672A\u767B\u5F55") : null,
|
|
1920
|
+
(0, import_react8.createElement)("span", { className: "spacer" }),
|
|
1921
|
+
active ? null : (0, import_react8.createElement)("button", { className: "ghost small", onClick: () => void wrap(onActivate) }, "\u8BBE\u4E3A\u5F53\u524D"),
|
|
1922
|
+
(0, import_react8.createElement)("button", { className: "ghost small", onClick: () => void wrap(onCheck) }, "\u68C0\u67E5\u8FDE\u63A5"),
|
|
1923
|
+
(0, import_react8.createElement)("button", { className: "ghost small", onClick: onToggleEdit }, editing ? "\u6536\u8D77" : "\u7F16\u8F91")
|
|
1807
1924
|
),
|
|
1808
|
-
editing ? (0,
|
|
1925
|
+
editing ? (0, import_react8.createElement)(
|
|
1809
1926
|
"div",
|
|
1810
1927
|
{ style: { display: "flex", flexDirection: "column", gap: "10px" } },
|
|
1811
|
-
(0,
|
|
1928
|
+
(0, import_react8.createElement)(
|
|
1812
1929
|
"div",
|
|
1813
1930
|
{ className: "mailharbor-grid" },
|
|
1814
|
-
(0,
|
|
1931
|
+
(0, import_react8.createElement)(
|
|
1815
1932
|
Field,
|
|
1816
1933
|
{ label: "\u663E\u793A\u540D\u79F0" },
|
|
1817
|
-
(0,
|
|
1934
|
+
(0, import_react8.createElement)("input", {
|
|
1818
1935
|
value: label,
|
|
1819
1936
|
onChange: (event) => setLabel(event.target.value)
|
|
1820
1937
|
})
|
|
1821
1938
|
),
|
|
1822
|
-
(0,
|
|
1939
|
+
(0, import_react8.createElement)(
|
|
1823
1940
|
Field,
|
|
1824
1941
|
{ label: "\u767B\u5F55\u7528\u6237\u540D" },
|
|
1825
|
-
(0,
|
|
1942
|
+
(0, import_react8.createElement)("input", {
|
|
1826
1943
|
value: username,
|
|
1827
1944
|
onChange: (event) => setUsername(event.target.value)
|
|
1828
1945
|
})
|
|
1829
1946
|
)
|
|
1830
1947
|
),
|
|
1831
|
-
(0,
|
|
1948
|
+
(0, import_react8.createElement)(
|
|
1832
1949
|
"div",
|
|
1833
1950
|
{ className: "mailharbor-grid three" },
|
|
1834
|
-
(0,
|
|
1951
|
+
(0, import_react8.createElement)(
|
|
1835
1952
|
Field,
|
|
1836
1953
|
{ label: "IMAP \u4E3B\u673A" },
|
|
1837
|
-
(0,
|
|
1954
|
+
(0, import_react8.createElement)("input", {
|
|
1838
1955
|
value: imapHost,
|
|
1839
1956
|
onChange: (event) => setImapHost(event.target.value)
|
|
1840
1957
|
})
|
|
1841
1958
|
),
|
|
1842
|
-
(0,
|
|
1959
|
+
(0, import_react8.createElement)(
|
|
1843
1960
|
Field,
|
|
1844
1961
|
{ label: "\u7AEF\u53E3" },
|
|
1845
|
-
(0,
|
|
1962
|
+
(0, import_react8.createElement)("input", {
|
|
1846
1963
|
value: imapPort,
|
|
1847
1964
|
onChange: (event) => setImapPort(event.target.value)
|
|
1848
1965
|
})
|
|
1849
1966
|
),
|
|
1850
|
-
(0,
|
|
1967
|
+
(0, import_react8.createElement)(Toggle, { checked: imapSecure, onChange: setImapSecure, label: "TLS" })
|
|
1851
1968
|
),
|
|
1852
|
-
(0,
|
|
1969
|
+
(0, import_react8.createElement)(
|
|
1853
1970
|
"div",
|
|
1854
1971
|
{ className: "mailharbor-grid three" },
|
|
1855
|
-
(0,
|
|
1972
|
+
(0, import_react8.createElement)(
|
|
1856
1973
|
Field,
|
|
1857
1974
|
{ label: "SMTP \u4E3B\u673A" },
|
|
1858
|
-
(0,
|
|
1975
|
+
(0, import_react8.createElement)("input", {
|
|
1859
1976
|
value: smtpHost,
|
|
1860
1977
|
onChange: (event) => setSmtpHost(event.target.value)
|
|
1861
1978
|
})
|
|
1862
1979
|
),
|
|
1863
|
-
(0,
|
|
1980
|
+
(0, import_react8.createElement)(
|
|
1864
1981
|
Field,
|
|
1865
1982
|
{ label: "\u7AEF\u53E3" },
|
|
1866
|
-
(0,
|
|
1983
|
+
(0, import_react8.createElement)("input", {
|
|
1867
1984
|
value: smtpPort,
|
|
1868
1985
|
onChange: (event) => setSmtpPort(event.target.value)
|
|
1869
1986
|
})
|
|
1870
1987
|
),
|
|
1871
|
-
(0,
|
|
1988
|
+
(0, import_react8.createElement)(Toggle, { checked: smtpSecure, onChange: setSmtpSecure, label: "TLS" })
|
|
1872
1989
|
),
|
|
1873
|
-
(0,
|
|
1990
|
+
(0, import_react8.createElement)(
|
|
1874
1991
|
Field,
|
|
1875
1992
|
{ label: "\u53D1\u4EF6\u4EBA\u540D\u79F0" },
|
|
1876
|
-
(0,
|
|
1993
|
+
(0, import_react8.createElement)("input", {
|
|
1877
1994
|
value: fromName,
|
|
1878
1995
|
onChange: (event) => setFromName(event.target.value)
|
|
1879
1996
|
})
|
|
1880
1997
|
),
|
|
1881
|
-
(0,
|
|
1998
|
+
(0, import_react8.createElement)(
|
|
1882
1999
|
"div",
|
|
1883
2000
|
{ style: { display: "flex", gap: "8px", alignItems: "center", flexWrap: "wrap" } },
|
|
1884
|
-
(0,
|
|
2001
|
+
(0, import_react8.createElement)(
|
|
1885
2002
|
"button",
|
|
1886
2003
|
{
|
|
1887
2004
|
className: "primary small",
|
|
@@ -1897,7 +2014,7 @@ function AccountRow({
|
|
|
1897
2014
|
},
|
|
1898
2015
|
"\u4FDD\u5B58\u8D26\u53F7"
|
|
1899
2016
|
),
|
|
1900
|
-
(0,
|
|
2017
|
+
(0, import_react8.createElement)(
|
|
1901
2018
|
"button",
|
|
1902
2019
|
{
|
|
1903
2020
|
className: "ghost small danger",
|
|
@@ -1906,21 +2023,21 @@ function AccountRow({
|
|
|
1906
2023
|
"\u79FB\u9664\u8D26\u53F7"
|
|
1907
2024
|
)
|
|
1908
2025
|
),
|
|
1909
|
-
(0,
|
|
1910
|
-
(0,
|
|
2026
|
+
(0, import_react8.createElement)("hr", { style: { border: 0, borderTop: "1px solid var(--m-line)", width: "100%" } }),
|
|
2027
|
+
(0, import_react8.createElement)(
|
|
1911
2028
|
Field,
|
|
1912
2029
|
{ label: "\u5BC6\u7801 / \u5E94\u7528\u4E13\u7528\u5BC6\u7801\uFF08\u4E0D\u5199\u5165\u914D\u7F6E\u6587\u4EF6\uFF09" },
|
|
1913
|
-
(0,
|
|
2030
|
+
(0, import_react8.createElement)("input", {
|
|
1914
2031
|
type: "password",
|
|
1915
2032
|
value: password,
|
|
1916
2033
|
onChange: (event) => setPassword(event.target.value)
|
|
1917
2034
|
})
|
|
1918
2035
|
),
|
|
1919
|
-
(0,
|
|
2036
|
+
(0, import_react8.createElement)(
|
|
1920
2037
|
"div",
|
|
1921
2038
|
{ style: { display: "flex", gap: "8px", alignItems: "center" } },
|
|
1922
|
-
(0,
|
|
1923
|
-
(0,
|
|
2039
|
+
(0, import_react8.createElement)(Toggle, { checked: remember, onChange: setRemember, label: "\u8BB0\u4F4F\u5BC6\u7801" }),
|
|
2040
|
+
(0, import_react8.createElement)(
|
|
1924
2041
|
"button",
|
|
1925
2042
|
{
|
|
1926
2043
|
className: "primary small",
|
|
@@ -1932,15 +2049,15 @@ function AccountRow({
|
|
|
1932
2049
|
},
|
|
1933
2050
|
"\u767B\u5F55"
|
|
1934
2051
|
),
|
|
1935
|
-
(0,
|
|
2052
|
+
(0, import_react8.createElement)("button", { className: "ghost small", onClick: () => void wrap(onLogout) }, "\u9000\u51FA\u767B\u5F55")
|
|
1936
2053
|
),
|
|
1937
|
-
checkResult === "" ? null : (0,
|
|
2054
|
+
checkResult === "" ? null : (0, import_react8.createElement)("div", { className: "small muted" }, checkResult)
|
|
1938
2055
|
) : null
|
|
1939
2056
|
);
|
|
1940
2057
|
}
|
|
1941
2058
|
|
|
1942
2059
|
// src/client/index.tsx
|
|
1943
|
-
var VERSION = "0.
|
|
2060
|
+
var VERSION = "0.2.0";
|
|
1944
2061
|
var inject = ["slots"];
|
|
1945
2062
|
var PANEL_ID = "mailharbor";
|
|
1946
2063
|
var STYLE_ID = "mailharbor-style";
|