mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-11-14 00:01:03 +00:00
196 lines
8.2 KiB
TypeScript
196 lines
8.2 KiB
TypeScript
import { registerPredicate } from './conditions.js';
|
|
import type { SystemNotice } from './types.js';
|
|
|
|
/**
|
|
* Registered at module load, unchanged from before this plan (Plan 3f Task
|
|
* 6/R1's adopted wiring): the closure used to read `app_settings` directly
|
|
* through the raw `db` handle here; now it only reads a value the caller
|
|
* (`SystemNoticesService.getActiveFor`) already resolved into `ctx` before
|
|
* `evaluate()` runs, the same shape `addonEnabled`/`managed` already use.
|
|
* `evaluateOne`'s `case 'custom'` (`conditions.ts`) calls this synchronously
|
|
* inside a `.filter()`, which cannot `await` — moving the DB read into this
|
|
* closure directly would either need to make the closure (and the whole
|
|
* evaluate/evaluateOne chain) async, or read an un-awaited repository
|
|
* result. Reading a pre-resolved value off `ctx` avoids both, stays
|
|
* race-free (the value flows through the per-call `ctx` object, not shared
|
|
* mutable state on a singleton), and needs no Nest lifecycle hook — this
|
|
* registration stays exactly where it always was.
|
|
*/
|
|
registerPredicate('whitespace-collision-detected', (ctx) => ctx.settingFlag('whitespace_migration_collision'));
|
|
|
|
/**
|
|
* SYSTEM NOTICE REGISTRY
|
|
*
|
|
* Rules for authoring:
|
|
* - NEVER reuse a retired `id` — dismissal tracking is keyed by `id`. Retired ids are
|
|
* listed in RETIRED_NOTICE_IDS so they're never accidentally re-used.
|
|
* - `id` must be globally unique and stable across deployments.
|
|
* - Title: ≤40 chars, sentence case, no trailing punctuation.
|
|
* - Body: markdown (modal) or plain text (banner/toast). ≤400/140/80 chars.
|
|
* - CTA label: ≤20 chars.
|
|
* - Never hardcode version numbers/dates in translated strings — use bodyParams.
|
|
*/
|
|
|
|
/**
|
|
* Retired notices. Kept out of the active list but their ids stay reserved so a future
|
|
* notice never reuses one (dismissals are keyed by id). Do not re-add these ids.
|
|
*/
|
|
export const RETIRED_NOTICE_IDS = [
|
|
'v3-thankyou',
|
|
'v3-photos',
|
|
'v3-journey',
|
|
'v3-mcp',
|
|
'v3-features',
|
|
'welcome-v1',
|
|
'release-4-0-0',
|
|
] as const;
|
|
|
|
export const SYSTEM_NOTICES: SystemNotice[] = [
|
|
// ── Release notes: what the current release brought, and a note from the maintainer ──
|
|
// One entry for every release. Each big release swaps the copy (the release_notes
|
|
// keys) and the version below, and keeps this id. `recurring: 'per-version'` brings
|
|
// it back to every user on every upgrade, a patch release included, so nobody is
|
|
// ever left on a version with nothing to show. No upper bound for the same reason.
|
|
{
|
|
id: 'release-notes',
|
|
recurring: 'per-version',
|
|
display: 'modal',
|
|
severity: 'info',
|
|
titleKey: 'system_notice.release_notes.headline',
|
|
bodyKey: 'system_notice.release_notes.intro',
|
|
release: {
|
|
version: '5.1.3',
|
|
eyebrowKey: 'system_notice.release_notes.eyebrow',
|
|
headlineKey: 'system_notice.release_notes.headline',
|
|
introKey: 'system_notice.release_notes.intro',
|
|
featuresLabelKey: 'system_notice.release_notes.features_label',
|
|
featuresAsideKey: 'system_notice.release_notes.features_aside',
|
|
features: [
|
|
{
|
|
iconName: 'Search',
|
|
visual: 'search',
|
|
titleKey: 'system_notice.release_notes.feature_search_title',
|
|
bodyKey: 'system_notice.release_notes.feature_search_body',
|
|
},
|
|
{
|
|
iconName: 'Share2',
|
|
visual: 'share',
|
|
titleKey: 'system_notice.release_notes.feature_share_title',
|
|
bodyKey: 'system_notice.release_notes.feature_share_body',
|
|
},
|
|
{
|
|
iconName: 'Route',
|
|
visual: 'routing',
|
|
titleKey: 'system_notice.release_notes.feature_routing_title',
|
|
bodyKey: 'system_notice.release_notes.feature_routing_body',
|
|
},
|
|
],
|
|
footnoteKey: 'system_notice.release_notes.footnote',
|
|
notes: {
|
|
labelKey: 'system_notice.release_notes.notes_label',
|
|
href: 'https://github.com/liketrek/TREK/releases/tag/v5.1.0',
|
|
},
|
|
note: {
|
|
eyebrowKey: 'system_notice.release_notes.note_eyebrow',
|
|
titleKey: 'system_notice.release_notes.note_title',
|
|
bodyKey: 'system_notice.release_notes.note_body',
|
|
promiseLabelKey: 'system_notice.release_notes.promise_label',
|
|
promiseLeadKey: 'system_notice.release_notes.promise_lead',
|
|
promiseTextKey: 'system_notice.release_notes.promise_text',
|
|
bodyAfterKey: 'system_notice.release_notes.note_body_after',
|
|
closingKey: 'system_notice.release_notes.note_closing',
|
|
},
|
|
supportLabelKey: 'system_notice.release_notes.support_label',
|
|
supportLeadKey: 'system_notice.release_notes.support_lead',
|
|
supportTextKey: 'system_notice.release_notes.support_text',
|
|
},
|
|
cta: {
|
|
kind: 'link',
|
|
labelKey: 'system_notice.release_notes.cta_bmc',
|
|
href: 'https://buymeacoffee.com/mauriceboe',
|
|
},
|
|
secondaryCta: {
|
|
kind: 'link',
|
|
labelKey: 'system_notice.release_notes.cta_kofi',
|
|
href: 'https://ko-fi.com/mauriceboe',
|
|
},
|
|
dismissible: true,
|
|
// Desktop-only: the two-column layout has no phone form, and the phone has its
|
|
// own onboarding.
|
|
desktopOnly: true,
|
|
// It asks the reader to fund the project, and on a managed install they already
|
|
// pay whoever runs it.
|
|
conditions: [{ kind: 'managed', is: false }],
|
|
publishedAt: '2026-09-15T00:00:00Z',
|
|
priority: 110,
|
|
// Where the thank-you notice below hands over; nothing on 3.x ships this copy.
|
|
minVersion: '4.0.0',
|
|
},
|
|
|
|
// ── Thank-you + support the project — shown once per install AND once per upgrade ──
|
|
// `recurring: 'per-version'` re-surfaces it whenever the app version moves up.
|
|
{
|
|
id: 'thank-you-support',
|
|
display: 'modal',
|
|
severity: 'info',
|
|
icon: 'Heart',
|
|
titleKey: 'system_notice.thank_you_support.title',
|
|
bodyKey: 'system_notice.thank_you_support.body',
|
|
highlights: [
|
|
{ labelKey: 'system_notice.thank_you_support.highlight_opensource', iconName: 'Github' },
|
|
{ labelKey: 'system_notice.thank_you_support.highlight_free', iconName: 'Infinity' },
|
|
{ labelKey: 'system_notice.thank_you_support.highlight_community', iconName: 'Users' },
|
|
],
|
|
cta: {
|
|
kind: 'link',
|
|
labelKey: 'system_notice.thank_you_support.cta_bmc',
|
|
href: 'https://buymeacoffee.com/mauriceboe',
|
|
},
|
|
secondaryCta: {
|
|
kind: 'link',
|
|
labelKey: 'system_notice.thank_you_support.cta_kofi',
|
|
href: 'https://ko-fi.com/mauriceboe',
|
|
},
|
|
dismissible: true,
|
|
// Desktop-only: the support modal is suppressed on small/mobile viewports.
|
|
desktopOnly: true,
|
|
// Not on a centrally administered install. The body thanks the reader for
|
|
// installing TREK and asks them to fund it, and there the reader installed
|
|
// nothing and already pays whoever runs it. Gated rather than reworded: the
|
|
// text is right for everyone it was written for.
|
|
conditions: [{ kind: 'managed', is: false }],
|
|
publishedAt: '2026-06-27T00:00:00Z',
|
|
priority: 100,
|
|
recurring: 'per-version',
|
|
// From 4.0.0 on, the release modal carries the same thank-you and the same
|
|
// two support links, so this one would be the second half of a message the
|
|
// reader just read. Retired by version rather than deleted: installs still
|
|
// on 3.x keep it.
|
|
maxVersion: '4.0.0',
|
|
},
|
|
|
|
// ── 3.0.14 admin notice — whitespace migration collision ───────────────────
|
|
// Operational alert (not promo): shown only to admins who upgraded across the
|
|
// 3.0.14 boundary AND only when the migration actually renamed colliding accounts.
|
|
{
|
|
id: 'v3014-whitespace-collision',
|
|
display: 'banner',
|
|
severity: 'warn',
|
|
icon: 'AlertTriangle',
|
|
titleKey: 'system_notice.v3014_whitespace_collision.title',
|
|
bodyKey: 'system_notice.v3014_whitespace_collision.body',
|
|
dismissible: true,
|
|
conditions: [
|
|
{ kind: 'existingUserBeforeVersion', version: '3.0.14' },
|
|
{ kind: 'role', roles: ['admin'] },
|
|
{ kind: 'custom', id: 'whitespace-collision-detected' },
|
|
// The body says to check the server logs. On a managed install the reader
|
|
// has none, and the operator sees the same collision in theirs.
|
|
{ kind: 'managed', is: false },
|
|
],
|
|
publishedAt: '2026-05-03T00:00:00Z',
|
|
priority: 85,
|
|
minVersion: '3.0.14',
|
|
},
|
|
];
|