dsh-tui-theme 0.2.1 → 0.3.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/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  | --- | --- | --- |
7
7
  | **三套粉色主题** | 主题(静态资产) | `pink-night` 夜樱 / `pink-day` 昼樱 / `pink-ansi` 樱·ANSI,启动时自动装进 `~/.dsh-tui/themes/` |
8
8
  | **自动跟随背景** | 启动时序 | 检测终端/系统背景色(OSC 11,与宿主同阈值),在昼樱/夜樱间自动切换——pink 版的 auto |
9
- | **花符状态行** | `tuiStatus` | 输入框上方一行小装饰:✿ · 时钟 · 实时轮数 |
9
+ | **花符状态行** | `tuiStatus` | 输入框上方一行小装饰:✿ · 时钟 · 实时轮数(默认仅粉主题下显示) |
10
10
  | **设置面板** | `tuiSettingsSections` | `/settings` 里一个可编辑区块,改完即时生效 |
11
11
 
12
12
  **明确不做的事**:不注册快捷键、不注册/修改任何命令、不拦截输入、不追加会话事件、不注入 system prompt。卸载即无痕(可选删除主题文件)。
@@ -79,6 +79,7 @@ dsh plugin --profile dsh-tui add -w /path/to/dsh-tui-theme
79
79
  | `showGlyph` | `true` | 花符:开 = ✿ 开头,关 = 不显示 |
80
80
  | `showClock` | `true` | 显示 HH:MM 时钟 |
81
81
  | `showTurns` | `true` | 显示当前会话轮数(`N✦`,自本次启动起计) |
82
+ | `showOnNonPinkThemes` | `false` | 非粉主题下也显示状态行;关 = 仅在樱花粉三主题下显示(推荐保持关闭) |
82
83
 
83
84
  三项装饰全关时状态行整体消失。另有仅 profile 层的开关(`cordis.patch.yml`,不出现在 /settings):`autoInstallThemes`、`statusEnabled`。
84
85
 
package/cordis.patch.yml CHANGED
@@ -13,3 +13,4 @@
13
13
  showGlyph: true
14
14
  showClock: true
15
15
  showTurns: true
16
+ showOnNonPinkThemes: false
@@ -6,9 +6,9 @@
6
6
  * ride it. This module gives pink-day/pink-night the same behavior from the
7
7
  * plugin side:
8
8
  *
9
- * - at apply() (which runs before the React tree mounts and reads
10
- * ~/.dsh-tui/theme.json), the cached detection writes the resolved theme
11
- * name into the pref synchronously always in time for this boot;
9
+ * - the caller wires this from the settings inject callback (see index.ts):
10
+ * that fires before the React tree mounts and reads ~/.dsh-tui/theme.json,
11
+ * so the cached detection still decides this boot;
12
12
  * - a fresh OSC 11 query then refreshes the cache for the next boot. The
13
13
  * very first enabling (or a system flip between boots) lands one boot
14
14
  * late — the same cadence as the host's own "re-select auto or restart".
@@ -1 +1 @@
1
- {"version":3,"file":"autoTheme.d.ts","sourceRoot":"","sources":["../../src/autoTheme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAgBH,UAAU,WAAW;IACnB,KAAK,EAAE,OAAO,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;CACX;AAgCD,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGjE;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAErE;AAED,2CAA2C;AAC3C,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAGxE;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQrE;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,WAA4B,EAC3C,KAAK,GAAE,MAAM,CAAC,UAA0B,EACxC,YAAY,GAAE,OAAO,UAAuB,GAC3C,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAmD9B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAC7B,IAAI,CAYN"}
1
+ {"version":3,"file":"autoTheme.d.ts","sourceRoot":"","sources":["../../src/autoTheme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAeH,UAAU,WAAW;IACnB,KAAK,EAAE,OAAO,CAAA;IACd,EAAE,EAAE,MAAM,CAAA;CACX;AA4BD,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGjE;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAErE;AAED,2CAA2C;AAC3C,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAGxE;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQrE;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,MAAM,CAAC,WAA4B,EAC3C,KAAK,GAAE,MAAM,CAAC,UAA0B,EACxC,YAAY,GAAE,OAAO,UAAuB,GAC3C,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC,CAmD9B;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAC7B,IAAI,CAYN"}
@@ -6,9 +6,9 @@
6
6
  * ride it. This module gives pink-day/pink-night the same behavior from the
7
7
  * plugin side:
8
8
  *
9
- * - at apply() (which runs before the React tree mounts and reads
10
- * ~/.dsh-tui/theme.json), the cached detection writes the resolved theme
11
- * name into the pref synchronously always in time for this boot;
9
+ * - the caller wires this from the settings inject callback (see index.ts):
10
+ * that fires before the React tree mounts and reads ~/.dsh-tui/theme.json,
11
+ * so the cached detection still decides this boot;
12
12
  * - a fresh OSC 11 query then refreshes the cache for the next boot. The
13
13
  * very first enabling (or a system flip between boots) lands one boot
14
14
  * late — the same cadence as the host's own "re-select auto or restart".
@@ -19,7 +19,6 @@
19
19
  * @module dsh-tui-theme/autoTheme
20
20
  */
21
21
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
22
- import { homedir } from 'node:os';
23
22
  import { join } from 'node:path';
24
23
  /** The pair this feature switches between (light terminal → day). */
25
24
  const LIGHT_THEME = 'pink-day';
@@ -29,9 +28,6 @@ const QUERY = '\x1b]11;?\x07';
29
28
  // ST terminated.
30
29
  const REPLY = /\x1b\]11;rgb:([0-9a-fA-F]{1,4})\/([0-9a-fA-F]{1,4})\/([0-9a-fA-F]{1,4})(?:\x07|\x1b\\)/;
31
30
  const DETECT_TIMEOUT_MS = 400;
32
- function homeDir() {
33
- return homedir() || process.env.USERPROFILE || process.env.HOME || '';
34
- }
35
31
  function prefPath(dir) {
36
32
  return join(dir, 'theme.json');
37
33
  }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAKlD,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEjF,eAAO,MAAM,IAAI,kBAAkB,CAAA;AAEnC,wDAAwD;AACxD,MAAM,MAAM,MAAM,GAAG,eAAe,CAAA;AAUpC,eAAO,MAAM,MAAM,EAAE,WAAW,CAAC,MAAM,CAOrC,CAAA;AAiBF;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI,CAsC7D"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAKlD,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEjF,eAAO,MAAM,IAAI,kBAAkB,CAAA;AAEnC,wDAAwD;AACxD,MAAM,MAAM,MAAM,GAAG,eAAe,CAAA;AAUpC,eAAO,MAAM,MAAM,EAAE,WAAW,CAAC,MAAM,CAQrC,CAAA;AAyBF;;;;GAIG;AACH,wBAAgB,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,MAAW,GAAG,IAAI,CAiE7D"}
@@ -35,6 +35,7 @@ export const Config = z.object({
35
35
  showGlyph: z.boolean().default(true),
36
36
  showClock: z.boolean().default(true),
37
37
  showTurns: z.boolean().default(true),
38
+ showOnNonPinkThemes: z.boolean().default(false),
38
39
  });
39
40
  const DEFAULTS = {
40
41
  autoInstallThemes: true,
@@ -43,7 +44,14 @@ const DEFAULTS = {
43
44
  showGlyph: true,
44
45
  showClock: true,
45
46
  showTurns: true,
47
+ showOnNonPinkThemes: false,
46
48
  };
49
+ /**
50
+ * Backstop delay for the cordis-layer follow decision on hosts without a
51
+ * settings service (see apply). Stays under the host's own 300ms pre-mount
52
+ * settings gate so the pref write still lands before first paint.
53
+ */
54
+ const FOLLOW_FALLBACK_MS = 150;
47
55
  /**
48
56
  * Wire the pink theme plugin.
49
57
  * @param ctx - Cordis context (the plugin's own activation).
@@ -59,6 +67,7 @@ export function apply(ctx, config = {}) {
59
67
  showGlyph: config.showGlyph ?? DEFAULTS.showGlyph,
60
68
  showClock: config.showClock ?? DEFAULTS.showClock,
61
69
  showTurns: config.showTurns ?? DEFAULTS.showTurns,
70
+ showOnNonPinkThemes: config.showOnNonPinkThemes ?? DEFAULTS.showOnNonPinkThemes,
62
71
  };
63
72
  if (cordis.autoInstallThemes) {
64
73
  const result = installBundledThemes();
@@ -69,18 +78,45 @@ export function apply(ctx, config = {}) {
69
78
  ctx.logger.warn(`dsh-tui-theme: could not install bundled theme "${file}"`);
70
79
  }
71
80
  }
72
- // Background follow runs before the React tree mounts (which reads the
73
- // theme pref), so the cached detection decides this boot.
74
- if (cordis.followSystem) {
75
- runFollowSystem(join(homeDir(), '.dsh-tui'), message => {
76
- ctx.logger.info(`dsh-tui-theme: ${message}`);
77
- });
78
- }
79
81
  // The /settings user layer (settings.yaml) overrides the cordis layer and
80
82
  // lands live through scope.watch; both override the hardcoded defaults.
81
83
  let effective = cordis;
84
+ // Background follow honors the MERGED knob (cordis layer overlaid by the
85
+ // /settings user layer), so the decision cannot be taken synchronously at
86
+ // apply(): the user layer is only readable once the settings service
87
+ // answers. The settings callback still fires before the host's React tree
88
+ // mounts (the host gates its own mount on the same service, probed
89
+ // against 0.9.0), so the pref write decides this boot exactly like a sync
90
+ // write would, and toggling followSystem in /settings re-decides live.
91
+ let followActive;
92
+ const dataDir = join(homeDir(), '.dsh-tui');
93
+ const startFollow = () => {
94
+ runFollowSystem(dataDir, message => {
95
+ ctx.logger.info(`dsh-tui-theme: ${message}`);
96
+ });
97
+ };
82
98
  registerPinkSettings(ctx, cordis, doc => {
83
99
  effective = { ...cordis, ...doc };
100
+ if (effective.followSystem !== followActive) {
101
+ followActive = effective.followSystem;
102
+ if (followActive) {
103
+ startFollow();
104
+ }
105
+ else {
106
+ ctx.logger.info('dsh-tui-theme: follow: disabled, manual /theme choice preserved');
107
+ }
108
+ }
84
109
  });
110
+ // Degradation backstop for hosts that never provide a settings service:
111
+ // the inject callback never fires there, so the cordis-layer decision
112
+ // applies instead. The delay lets any pending service registration (and
113
+ // its callback) land first — it no-ops once followActive is settled, and
114
+ // stays inside the host's own 300ms pre-mount settings gate either way.
115
+ setTimeout(() => {
116
+ if (followActive === undefined && cordis.followSystem) {
117
+ followActive = true;
118
+ startFollow();
119
+ }
120
+ }, FOLLOW_FALLBACK_MS);
85
121
  startStatusLine(ctx, () => effective);
86
122
  }
@@ -1 +1 @@
1
- {"version":3,"file":"settingsSection.d.ts","sourceRoot":"","sources":["../../src/settingsSection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG;IAC5C,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GACpC,IAAI,CAuCN"}
1
+ {"version":3,"file":"settingsSection.d.ts","sourceRoot":"","sources":["../../src/settingsSection.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAGlD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAEpD,+EAA+E;AAC/E,MAAM,MAAM,eAAe,GAAG,aAAa,GAAG;IAC5C,sEAAsE;IACtE,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAA;AAcD;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,aAAa,EACrB,KAAK,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,GACpC,IAAI,CA4CN"}
@@ -35,6 +35,7 @@ export function registerPinkSettings(ctx, cordis, onDoc) {
35
35
  showGlyph: z.boolean(),
36
36
  showClock: z.boolean(),
37
37
  showTurns: z.boolean(),
38
+ showOnNonPinkThemes: z.boolean(),
38
39
  }));
39
40
  const emit = (doc) => {
40
41
  if (doc === null || typeof doc !== 'object')
@@ -46,8 +47,12 @@ export function registerPinkSettings(ctx, cordis, onDoc) {
46
47
  }
47
48
  onDoc(clean);
48
49
  };
49
- emit(scope.get());
50
- scope.watch(emit);
50
+ // Own the watcher on the inject-scoped ledger so it survives exactly as
51
+ // long as this activation (scope.watch's disposer is otherwise leaked).
52
+ settingsCtx.effect(() => {
53
+ emit(scope.get());
54
+ return scope.watch(emit);
55
+ });
51
56
  });
52
57
  ctx.inject(['tuiSettingsSections'], sectionsCtx => {
53
58
  const sections = sectionsCtx
@@ -106,6 +111,17 @@ function sectionDefinition(cordis) {
106
111
  kind: 'boolean',
107
112
  format: (value) => String(value ?? cordis.showTurns),
108
113
  },
114
+ {
115
+ path: ['showOnNonPinkThemes'],
116
+ label: 'Show on non-pink themes',
117
+ descriptions: { zh: '非粉主题下也显示' },
118
+ hint: 'The blossom line belongs to the pink palettes; off keeps it hidden while another theme is active.',
119
+ hintDescriptions: {
120
+ zh: '状态行属于樱花粉主题;关闭时在其他主题下不显示。',
121
+ },
122
+ kind: 'boolean',
123
+ format: (value) => String(value ?? cordis.showOnNonPinkThemes),
124
+ },
109
125
  ],
110
126
  };
111
127
  }
@@ -5,6 +5,11 @@
5
5
  * live turn count of the current session (seam one, read-only — nothing is
6
6
  * ever appended to the session log). The host owns rendering and
7
7
  * sanitization; text is scalars only.
8
+ *
9
+ * The line belongs to the pink palettes: by default it only renders while a
10
+ * pink theme is active (checked per render with the host's own theme
11
+ * precedence, so a mid-session /theme switch takes effect on the next tick);
12
+ * `showOnNonPinkThemes` opts it into every other theme too.
8
13
  * @module dsh-tui-pink-theme/statusLine
9
14
  */
10
15
  import type { Context } from '@deepseek-ai/cordis';
@@ -17,6 +22,8 @@ export interface StatusOptions {
17
22
  showClock?: boolean;
18
23
  /** Include the live turn count of the current session. */
19
24
  showTurns?: boolean;
25
+ /** Also render while a non-pink theme is active (default: pink only). */
26
+ showOnNonPinkThemes?: boolean;
20
27
  }
21
28
  /** Fully-resolved status knobs. */
22
29
  export type EffectiveStatus = Required<StatusOptions>;
@@ -1 +1 @@
1
- {"version":3,"file":"statusLine.d.ts","sourceRoot":"","sources":["../../src/statusLine.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAKlD,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,sCAAsC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,mCAAmC;AACnC,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAA;AAoBrD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,GAAG,IAAI,CAoDvF"}
1
+ {"version":3,"file":"statusLine.d.ts","sourceRoot":"","sources":["../../src/statusLine.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAOlD,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,sCAAsC;IACtC,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,yEAAyE;IACzE,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B;AAED,mCAAmC;AACnC,MAAM,MAAM,eAAe,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAA;AAwCrD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,GAAG,IAAI,CA2DvF"}
@@ -5,11 +5,37 @@
5
5
  * live turn count of the current session (seam one, read-only — nothing is
6
6
  * ever appended to the session log). The host owns rendering and
7
7
  * sanitization; text is scalars only.
8
+ *
9
+ * The line belongs to the pink palettes: by default it only renders while a
10
+ * pink theme is active (checked per render with the host's own theme
11
+ * precedence, so a mid-session /theme switch takes effect on the next tick);
12
+ * `showOnNonPinkThemes` opts it into every other theme too.
8
13
  * @module dsh-tui-pink-theme/statusLine
9
14
  */
15
+ import { join } from 'node:path';
16
+ import { homeDir } from './themeAssets.js';
17
+ import { readThemePref } from './autoTheme.js';
10
18
  const GLYPH = '✿';
11
19
  const STATUS_KEY = 'dsh-tui-theme';
12
20
  const CLOCK_TICK_MS = 15_000;
21
+ /** The bundled themes this garnish belongs to. */
22
+ const PINK_THEMES = new Set(['pink-night', 'pink-day', 'pink-ansi']);
23
+ /**
24
+ * The active theme name by the host's own precedence: DSH_TUI_THEME first,
25
+ * then the persisted ~/.dsh-tui/theme.json pref. The unforced path (OSC 11
26
+ * auto-detection) only ever resolves to a builtin palette, never a pink one,
27
+ * so "no pref" means non-pink.
28
+ */
29
+ function activeThemeName(dataDir) {
30
+ const env = process.env.DSH_TUI_THEME;
31
+ if (env !== undefined && env !== '')
32
+ return env;
33
+ return readThemePref(dataDir);
34
+ }
35
+ function isPinkThemeActive(dataDir) {
36
+ const name = activeThemeName(dataDir);
37
+ return name !== undefined && PINK_THEMES.has(name);
38
+ }
13
39
  function clockText() {
14
40
  // "HH:MM" from toTimeString()'s "HH:MM:SS GMT…" prefix — locale independent.
15
41
  return new Date().toTimeString().slice(0, 5);
@@ -29,6 +55,7 @@ function clockText() {
29
55
  * edits land live without restarting anything).
30
56
  */
31
57
  export function startStatusLine(ctx, getEffective) {
58
+ const dataDir = join(homeDir(), '.dsh-tui');
32
59
  ctx.inject(['tuiStatus'], statusCtx => {
33
60
  const status = statusCtx.tuiStatus;
34
61
  const turns = new Map();
@@ -38,12 +65,18 @@ export function startStatusLine(ctx, getEffective) {
38
65
  try {
39
66
  const eff = getEffective();
40
67
  const parts = [];
41
- if (eff.showGlyph)
42
- parts.push(GLYPH);
43
- if (eff.showClock)
44
- parts.push(clockText());
45
- if (eff.showTurns && current !== undefined) {
46
- parts.push(`${turns.get(current) ?? 0}✦`);
68
+ // The line is pink garnish: off on other themes unless opted in.
69
+ // The theme check runs here (not once at startup) so a mid-session
70
+ // /theme switch lands on the next tick or session event.
71
+ const themeAllows = eff.showOnNonPinkThemes || isPinkThemeActive(dataDir);
72
+ if (eff.statusEnabled && themeAllows) {
73
+ if (eff.showGlyph)
74
+ parts.push(GLYPH);
75
+ if (eff.showClock)
76
+ parts.push(clockText());
77
+ if (eff.showTurns && current !== undefined) {
78
+ parts.push(`${turns.get(current) ?? 0}✦`);
79
+ }
47
80
  }
48
81
  const text = parts.join(' · ');
49
82
  // The trailing identity must be the inject-scoped context (the same
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-tui-theme",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Sakura-pink themes for dsh-TUI with terminal-background auto-follow (pink-day/pink-night), a blossom status line, and a /settings section. No shortcuts, no commands.",
5
5
  "type": "module",
6
6
  "main": "lib/types/index.js",