klaudio 0.11.0 → 0.11.2

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/cli.js +33 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "klaudio",
3
- "version": "0.11.0",
3
+ "version": "0.11.2",
4
4
  "description": "Add sound effects to your coding sessions — play sounds when tasks complete, notifications arrive, and more",
5
5
  "type": "module",
6
6
  "bin": {
package/src/cli.js CHANGED
@@ -137,15 +137,16 @@ const NavHint = ({ back = true, extra = "" }) =>
137
137
  );
138
138
 
139
139
  // ── Screen: Scope ───────────────────────────────────────────────
140
- const ScopeScreen = ({ onNext, onMusic, tts, onToggleTts }) => {
140
+ const ScopeScreen = ({ onNext, onMusic, onUpdate, tts, onToggleTts, outdatedReasons }) => {
141
+ const isOutdated = outdatedReasons && outdatedReasons.length > 0;
141
142
  const items = [
143
+ ...(isOutdated ? [{ label: "⬆ Apply updates", value: "_update" }] : []),
142
144
  { label: "Global — Claude Code + Copilot (all projects)", value: "global" },
143
145
  { label: "This project — Claude Code + Copilot (this project only)", value: "project" },
144
- // index 2 = music
145
146
  { label: "🎵 Play game music while you code", value: "_music" },
146
147
  ];
147
148
  const [sel, setSel] = useState(0);
148
- const GAP_AT = 2; // visual gap before this index
149
+ const GAP_AT = (isOutdated ? 1 : 0) + 2; // visual gap before music
149
150
 
150
151
  useInput((input, key) => {
151
152
  if (input === "k" || key.upArrow) {
@@ -156,12 +157,21 @@ const ScopeScreen = ({ onNext, onMusic, tts, onToggleTts }) => {
156
157
  onToggleTts();
157
158
  } else if (key.return) {
158
159
  const v = items[sel].value;
159
- if (v === "_music") onMusic();
160
+ if (v === "_update") onUpdate();
161
+ else if (v === "_music") onMusic();
160
162
  else onNext(v);
161
163
  }
162
164
  });
163
165
 
164
166
  return h(Box, { flexDirection: "column" },
167
+ isOutdated
168
+ ? h(Box, { flexDirection: "column", marginLeft: 2, marginBottom: 1 },
169
+ h(Text, { color: "yellow", bold: true }, " Updates available:"),
170
+ ...outdatedReasons.map((r, i) =>
171
+ h(Text, { key: i, color: "yellow", dimColor: true, marginLeft: 4 }, `+ ${r}`),
172
+ ),
173
+ )
174
+ : null,
165
175
  h(Text, { bold: true }, " Where should sounds be installed?"),
166
176
  h(Box, { flexDirection: "column", marginLeft: 2 },
167
177
  ...items.map((item, i) => h(React.Fragment, { key: item.value },
@@ -1560,6 +1570,18 @@ const InstallApp = () => {
1560
1570
 
1561
1571
  useEffect(() => {
1562
1572
  isKokoroAvailable().then(setHasKokoro).catch(() => {});
1573
+ // Check both scopes for outdated hooks on startup
1574
+ Promise.all([
1575
+ checkHooksOutdated("global"),
1576
+ checkHooksOutdated("project"),
1577
+ ]).then(([g, p]) => {
1578
+ const combined = [...new Set([...g, ...p])];
1579
+ setOutdatedReasons(combined);
1580
+ }).catch(() => {});
1581
+ // Also pre-load existing sounds from global (most common)
1582
+ getExistingSounds("global").then((existing) => {
1583
+ if (Object.keys(existing).length > 0) setSounds(existing);
1584
+ }).catch(() => {});
1563
1585
  }, []);
1564
1586
 
1565
1587
  const initSoundsFromPreset = useCallback((pid) => {
@@ -1572,15 +1594,22 @@ const InstallApp = () => {
1572
1594
  case SCREEN.SCOPE:
1573
1595
  return h(ScopeScreen, {
1574
1596
  tts,
1597
+ outdatedReasons,
1575
1598
  onToggleTts: () => setTts((v) => !v),
1576
1599
  onNext: (s) => {
1577
1600
  setScope(s);
1601
+ // Refresh sounds/outdated for the selected scope
1578
1602
  getExistingSounds(s).then((existing) => {
1579
1603
  if (Object.keys(existing).length > 0) setSounds(existing);
1580
1604
  });
1581
1605
  checkHooksOutdated(s).then(setOutdatedReasons).catch(() => {});
1582
1606
  setScreen(SCREEN.PRESET);
1583
1607
  },
1608
+ onUpdate: () => {
1609
+ // Quick-apply: use global scope with existing sounds, skip to install
1610
+ setScope("global");
1611
+ setScreen(SCREEN.INSTALLING);
1612
+ },
1584
1613
  onMusic: () => setScreen(SCREEN.MUSIC_MODE),
1585
1614
  });
1586
1615