♻️ refactor(client): 浏览器半拆成 src 模块,client.js 改由构建产出

This commit is contained in:
pyh
2026-10-04 19:01:22 +08:00
parent 3986aac863
commit 68ab60273e
30 changed files with 3506 additions and 1394 deletions
+68
View File
@@ -0,0 +1,68 @@
/**
* The delivered copy: what a candidate becomes once it is on screen, plus the
* two diagnoses the settings page prints about past deliveries.
*
* @module @dsh-plugin/session-notify/client/core/copy
*/
/**
* Build the copy table for one translate function.
* @param t - the translate function every string here goes through.
* @returns `copyFor` (candidate → notice) and the two diagnosis renderers.
*/
export function createCopy(t) {
/** Build the delivered copy for one candidate. */
const copyFor = (candidate) => {
const title = candidate.title === '' ? t('body.untitled') : candidate.title
if (candidate.kind === 'completion') {
return { kind: 'completion', title: t('notification.completion'), body: t('body.completion', { title }) }
}
if (candidate.kind === 'question') {
const question = candidate.detail
return {
kind: 'question',
title: t('notification.question'),
body: question === '' ? t('body.question', { title }) : `${title} · ${question}`,
}
}
// Kept in v1.0.6's order, which makes this branch unreachable today: the
// observer queues a plan review as `kind: 'question'`, so the branch above
// already answered with the plan's own text. Restoring the documented copy
// (`body.planReview`, "计划正在等待你确认") means testing `pendingKind`
// before `kind` — a user-visible behavior change, so it is deliberately NOT
// part of this refactor. `tests/unit/copy.test.js` pins today's output.
if (candidate.pendingKind === 'plan-review') {
return { kind: 'question', title: t('notification.question'), body: t('body.planReview', { title }) }
}
const tool = candidate.detail
return {
kind: 'approval',
title: t('notification.approval'),
body: tool === '' ? t('body.approvalPlain', { title }) : t('body.approval', { title, tool }),
}
}
/** Describe the newest alert's fate in one line. */
const describeDelivery = (last, tr) => {
if (last === null || last === undefined) return tr('config.diag.none')
const outcome = last.outcome.startsWith('system-refused')
? tr('config.diag.refused')
: last.outcome === 'system'
? last.shown === true
? tr('config.diag.systemShown')
: last.shown === false
? tr('config.diag.systemFailed')
: tr('config.diag.systemUnconfirmed')
: last.outcome === 'replay'
? tr('config.diag.replayDelivery')
: tr('config.diag.popup')
return `${tr('config.diag.last')}: ${last.at} · ${outcome} · ${last.title}`
}
/** Say how many away-channel alerts are still waiting to be replayed in-app. */
const describeReplay = (count, tr) => (
count === 0 ? tr('config.diag.replayNone') : tr('config.diag.replay', { count })
)
return { copyFor, describeDelivery, describeReplay }
}