recappi 0.1.49 → 0.1.50

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/dist/index.js CHANGED
@@ -595,15 +595,18 @@ var init_LiveCaptionsScreen = __esm({
595
595
  import { useEffect as useEffect2, useRef, useState as useState3 } from "react";
596
596
  import { Box as Box2, Text as Text2 } from "ink";
597
597
  import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
598
- function litCount(level) {
598
+ function waveRowsFor(terminalRows) {
599
+ return terminalRows >= 30 ? 5 : 3;
600
+ }
601
+ function litCount(level, rows) {
599
602
  const amp = Math.max(0, Math.min(1, level));
600
603
  if (amp <= 0.028) return 0;
601
- return Math.max(1, Math.min(WAVE_ROWS, Math.ceil(Math.pow(amp, 0.58) * WAVE_ROWS)));
604
+ return Math.max(1, Math.min(rows, Math.ceil(Math.pow(amp, 0.58) * rows)));
602
605
  }
603
- function litCounts(samples, width) {
606
+ function litCounts(samples, width, rows) {
604
607
  if (width <= 0) return [];
605
608
  const tail = samples.slice(-width);
606
- return [...Array(Math.max(0, width - tail.length)).fill(0), ...tail].map(litCount);
609
+ return [...Array(Math.max(0, width - tail.length)).fill(0), ...tail].map((v) => litCount(v, rows));
607
610
  }
608
611
  function levelDb(level) {
609
612
  if (level <= 0.03) return "silent";
@@ -614,18 +617,19 @@ function MeterRow({
614
617
  samples,
615
618
  level,
616
619
  paused,
617
- width
620
+ width,
621
+ rows
618
622
  }) {
619
623
  const silent = level <= 0.03;
620
- const cols = litCounts(samples, width);
624
+ const cols = litCounts(samples, width, rows);
621
625
  const litColor = paused ? "gray" : "cyan";
622
626
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
623
627
  /* @__PURE__ */ jsxs2(Box2, { width: width + 9, children: [
624
628
  /* @__PURE__ */ jsx3(Box2, { width: 9, children: /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: label }) }),
625
629
  /* @__PURE__ */ jsx3(Box2, { flexGrow: 1, justifyContent: "flex-end", children: !paused && silent ? /* @__PURE__ */ jsx3(Text2, { color: "yellow", children: "silent" }) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: paused ? "paused" : levelDb(level) }) })
626
630
  ] }),
627
- Array.from({ length: WAVE_ROWS }, (_, r) => {
628
- const fromBottom = WAVE_ROWS - r;
631
+ Array.from({ length: rows }, (_, r) => {
632
+ const fromBottom = rows - r;
629
633
  return /* @__PURE__ */ jsx3(Text2, { children: cols.map(
630
634
  (c, i) => c >= fromBottom ? /* @__PURE__ */ jsx3(Text2, { color: litColor, children: c === fromBottom ? "\u2022" : "\u25CF" }, i) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: "\xB7" }, i)
631
635
  ) }, r);
@@ -720,7 +724,8 @@ function RecordingHeroScreen({
720
724
  const meterW = Math.max(10, Math.min(72, innerWidth - 20));
721
725
  const sizeStr = telemetry.sizeBytes ? formatBytes2(telemetry.sizeBytes) : "";
722
726
  const context = [telemetry.sourceLabel, telemetry.micEnabled ? "Microphone" : null, sizeStr || null].filter(Boolean).join(" \xB7 ");
723
- const meterBlockRows = (telemetry.micEnabled ? 2 : 1) * (WAVE_ROWS + 1) + (telemetry.micEnabled ? 1 : 0);
727
+ const waveRows = waveRowsFor(size.rows);
728
+ const meterBlockRows = (telemetry.micEnabled ? 2 : 1) * (waveRows + 1) + (telemetry.micEnabled ? 1 : 0);
724
729
  const fixedRows = 8 + meterBlockRows;
725
730
  const captionRows = Math.max(2, size.rows - fixedRows);
726
731
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
@@ -739,13 +744,13 @@ function RecordingHeroScreen({
739
744
  // reads as silence (the elapsed timer above proves it's live).
740
745
  /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: paused ? "Paused" : `Capturing audio${".".repeat(Math.floor(tick / 1e3) % 3 + 1)}` })
741
746
  ) : /* @__PURE__ */ jsxs2(Fragment, { children: [
742
- /* @__PURE__ */ jsx3(MeterRow, { label: "System", samples: waveSys, level: telemetry.level.system ?? 0, paused, width: meterW }),
743
- telemetry.micEnabled ? /* @__PURE__ */ jsx3(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx3(MeterRow, { label: "Mic", samples: waveMic, level: telemetry.level.mic ?? 0, paused, width: meterW }) }) : null
747
+ /* @__PURE__ */ jsx3(MeterRow, { label: "System", samples: waveSys, level: telemetry.level.system ?? 0, paused, width: meterW, rows: waveRows }),
748
+ telemetry.micEnabled ? /* @__PURE__ */ jsx3(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx3(MeterRow, { label: "Mic", samples: waveMic, level: telemetry.level.mic ?? 0, paused, width: meterW, rows: waveRows }) }) : null
744
749
  ] }) }),
745
750
  /* @__PURE__ */ jsx3(Box2, { marginTop: 1, children: /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: context }) }),
746
751
  captions ? /* @__PURE__ */ jsxs2(Box2, { marginTop: 1, flexDirection: "column", children: [
747
752
  /* @__PURE__ */ jsx3(Text2, { bold: true, dimColor: true, children: "LIVE CAPTIONS" }),
748
- /* @__PURE__ */ jsx3(HeroCaptions, { state: captions, maxRows: captionRows })
753
+ /* @__PURE__ */ jsx3(HeroCaptions, { state: captions, maxRows: captionRows, width: innerWidth })
749
754
  ] }) : null
750
755
  ] }),
751
756
  /* @__PURE__ */ jsx3(Box2, { marginTop: 1, children: /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
@@ -754,40 +759,46 @@ function RecordingHeroScreen({
754
759
  ] }) })
755
760
  ] });
756
761
  }
757
- function HeroCaptions({ state, maxRows }) {
762
+ function wrappedRows(text, width) {
763
+ return Math.max(1, Math.ceil(displayWidth(text) / Math.max(1, width)));
764
+ }
765
+ function HeroCaptions({
766
+ state,
767
+ maxRows,
768
+ width
769
+ }) {
758
770
  const hasPartial = Boolean(state.partial && state.partial.length > 0);
759
771
  const captionError = state.status === "error" ? `Captions unavailable: ${state.error ?? "Live captions unavailable."}` : null;
760
772
  if (state.lines.length === 0 && !hasPartial) {
761
- return /* @__PURE__ */ jsx3(Text2, { color: captionError ? "yellow" : void 0, dimColor: !captionError, wrap: "truncate-end", children: captionError ?? (state.status === "live" ? "Listening for speech\u2026" : liveCaptionStatusLabel(state.status)) });
773
+ return /* @__PURE__ */ jsx3(Text2, { color: captionError ? "yellow" : void 0, dimColor: !captionError, children: captionError ?? (state.status === "live" ? "Listening for speech\u2026" : liveCaptionStatusLabel(state.status)) });
762
774
  }
763
- const rows = [];
775
+ const lines = [];
764
776
  for (const line of state.lines) {
765
- rows.push(
766
- /* @__PURE__ */ jsxs2(Text2, { wrap: "truncate-end", children: [
767
- line.speaker ? `${line.speaker}: ` : "",
768
- trimLead(line.text)
769
- ] }, `${line.id}-s`)
770
- );
777
+ lines.push({
778
+ key: `${line.id}-s`,
779
+ text: `${line.speaker ? `${line.speaker}: ` : ""}${trimLead(line.text)}`,
780
+ dim: false
781
+ });
771
782
  if (line.translation) {
772
- rows.push(
773
- /* @__PURE__ */ jsx3(Text2, { dimColor: true, wrap: "truncate-end", children: ` \u21B3 ${trimLead(line.translation)}` }, `${line.id}-t`)
774
- );
783
+ lines.push({ key: `${line.id}-t`, text: ` \u21B3 ${trimLead(line.translation)}`, dim: true });
775
784
  }
776
785
  }
777
- if (hasPartial) {
778
- rows.push(
779
- /* @__PURE__ */ jsx3(Text2, { dimColor: true, wrap: "truncate-end", children: trimLead(state.partial) }, "partial")
780
- );
781
- }
786
+ if (hasPartial) lines.push({ key: "partial", text: trimLead(state.partial), dim: true });
782
787
  if (state.translationPartial) {
783
- rows.push(
784
- /* @__PURE__ */ jsx3(Text2, { dimColor: true, wrap: "truncate-end", children: ` \u21B3 ${trimLead(state.translationPartial)}` }, "tpartial")
785
- );
788
+ lines.push({ key: "tpartial", text: ` \u21B3 ${trimLead(state.translationPartial)}`, dim: true });
789
+ }
790
+ const budget = Math.max(1, maxRows);
791
+ const chosen = [];
792
+ let used = 0;
793
+ for (let i = lines.length - 1; i >= 0; i--) {
794
+ const h = wrappedRows(lines[i].text, width);
795
+ if (used + h > budget && chosen.length > 0) break;
796
+ chosen.unshift(lines[i]);
797
+ used += h;
786
798
  }
787
- const visible = rows.slice(-Math.max(1, maxRows));
788
799
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
789
- visible,
790
- captionError ? /* @__PURE__ */ jsx3(Text2, { color: "yellow", wrap: "truncate-end", children: captionError }) : null
800
+ chosen.map((l) => /* @__PURE__ */ jsx3(Text2, { dimColor: l.dim, wrap: "wrap", children: l.text }, l.key)),
801
+ captionError ? /* @__PURE__ */ jsx3(Text2, { color: "yellow", wrap: "wrap", children: captionError }) : null
791
802
  ] });
792
803
  }
793
804
  function stoppedHandoffCopy(artifact, canTranscribe) {
@@ -808,14 +819,13 @@ function stoppedHandoffCopy(artifact, canTranscribe) {
808
819
  }
809
820
  return { text: "Transcribe now? \u23CE yes \xB7 n not now", tone: "normal" };
810
821
  }
811
- var WAVE_ROWS, WAVE_THROTTLE_MS, trimLead;
822
+ var WAVE_THROTTLE_MS, trimLead;
812
823
  var init_RecordingHeroScreen = __esm({
813
824
  "src/tui/RecordingHeroScreen.tsx"() {
814
825
  "use strict";
815
826
  init_format();
816
827
  init_liveCaptions();
817
828
  init_terminal();
818
- WAVE_ROWS = 5;
819
829
  WAVE_THROTTLE_MS = 220;
820
830
  trimLead = (s) => s.replace(/^\s+/, "");
821
831
  }