Skip to content

Commit dad6e40

Browse files
committed
feat: improve transcript readability with compact layout and speaker colors
- More compact layout: removed Cards, reduced spacing - Speaker names only show when speaker changes (not repeated) - Consistent color-coding for each speaker - Alternating row backgrounds for better scanning - Timestamp inline with text for better use of space - 100px fixed-width speaker column for alignment
1 parent 6f42e14 commit dad6e40

File tree

1 file changed

+61
-18
lines changed

1 file changed

+61
-18
lines changed

src/renderer/features/notetaker/components/LiveTranscriptView.tsx

Lines changed: 61 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,29 +120,53 @@ export function LiveTranscriptView({
120120
ref={scrollRef as never}
121121
onScroll={handleScroll}
122122
>
123-
<Flex direction="column" gap="2">
124-
{segments.map((segment, idx) => (
125-
<Card
126-
key={`${segment.timestamp}-${idx}`}
127-
style={{
128-
opacity: 1,
129-
}}
130-
>
131-
<Flex direction="column" gap="1">
132-
<Flex align="center" gap="2">
133-
{segment.speaker && (
134-
<Text size="1" weight="bold" color="gray">
123+
<Flex direction="column" gap="1">
124+
{segments.map((segment, idx) => {
125+
const prevSegment = idx > 0 ? segments[idx - 1] : null;
126+
const isSameSpeaker = prevSegment?.speaker === segment.speaker;
127+
128+
return (
129+
<Flex
130+
key={`${segment.timestamp}-${idx}`}
131+
gap="2"
132+
py="1"
133+
px="2"
134+
style={{
135+
backgroundColor:
136+
idx % 2 === 0 ? "var(--gray-2)" : "transparent",
137+
}}
138+
>
139+
{/* Speaker name (only show if different from previous) */}
140+
<Box style={{ minWidth: "100px", flexShrink: 0 }}>
141+
{!isSameSpeaker && segment.speaker && (
142+
<Text
143+
size="1"
144+
weight="bold"
145+
style={{ color: getSpeakerColor(segment.speaker) }}
146+
>
135147
{segment.speaker}
136148
</Text>
137149
)}
138-
<Text size="1" color="gray">
139-
{formatTimestamp(segment.timestamp)}
140-
</Text>
150+
</Box>
151+
152+
{/* Timestamp + Text */}
153+
<Flex direction="column" gap="1" style={{ flex: 1 }}>
154+
<Flex align="baseline" gap="2">
155+
<Text
156+
size="1"
157+
color="gray"
158+
style={{ fontVariantNumeric: "tabular-nums" }}
159+
>
160+
{formatTimestamp(segment.timestamp)}
161+
</Text>
162+
<Text size="2" style={{ lineHeight: "1.5" }}>
163+
{segment.text}
164+
</Text>
165+
</Flex>
141166
</Flex>
142-
<Text size="2">{segment.text}</Text>
143167
</Flex>
144-
</Card>
145-
))}
168+
);
169+
})}
146170
</Flex>
147171
</ScrollArea>
148172

@@ -168,3 +192,22 @@ function formatTimestamp(milliseconds: number): string {
168192
}
169193
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
170194
}
195+
196+
// Consistent color assignment for speakers
197+
function getSpeakerColor(speaker: string): string {
198+
const colors = [
199+
"var(--blue-11)",
200+
"var(--green-11)",
201+
"var(--orange-11)",
202+
"var(--purple-11)",
203+
"var(--pink-11)",
204+
"var(--cyan-11)",
205+
];
206+
207+
// Simple hash function to consistently map speaker to color
208+
let hash = 0;
209+
for (let i = 0; i < speaker.length; i++) {
210+
hash = speaker.charCodeAt(i) + ((hash << 5) - hash);
211+
}
212+
return colors[Math.abs(hash) % colors.length];
213+
}

0 commit comments

Comments
 (0)