Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 89991a5

Browse files
pibulusclaude
andcommitted
🔧 Simplify transcript display with fixed width and consistent behavior
• Remove dynamic responsive font sizing - use fixed text-base for consistency • Lock transcript container to 600px max-width to match lyrics collection • Simplify selection back to line-by-line only (removed complex chunk detection) • Remove responsive padding that was causing width fluctuations • Clean up unused responsiveFontSize props and calculation logic • Improve mobile responsiveness while maintaining consistent sizing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 2c2e8e3 commit 89991a5

3 files changed

Lines changed: 8 additions & 249 deletions

File tree

‎src/lib/components/mainPage/audio-transcript/AudioToText.svelte‎

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -377,65 +377,6 @@
377377
}
378378
}
379379
380-
// Function to calculate responsive font size based on transcript length, word count, and device
381-
function getResponsiveFontSize(text) {
382-
if (!text) return 'text-base'; // Default size
383-
384-
// Get viewport width for more responsive sizing
385-
let viewportWidth = 0;
386-
if (typeof window !== 'undefined') {
387-
viewportWidth = window.innerWidth;
388-
}
389-
390-
// Smaller base sizes for mobile
391-
const isMobile = viewportWidth > 0 && viewportWidth < 640;
392-
const isDesktop = viewportWidth >= 1024;
393-
394-
// Calculate both character length and word count
395-
const charLength = text.length;
396-
const wordCount = text.trim().split(/\s+/).length;
397-
398-
// Typography best practices suggest that readability is impacted by both
399-
// total length and average word length
400-
const avgWordLength = charLength / (wordCount || 1); // Avoid division by zero
401-
402-
403-
// Extremely short text (5 words or less): Use larger font, especially on desktop
404-
if (wordCount <= 5) {
405-
return isMobile
406-
? 'text-xl sm:text-2xl md:text-3xl'
407-
: isDesktop
408-
? 'text-2xl md:text-3xl lg:text-4xl'
409-
: 'text-2xl md:text-3xl';
410-
}
411-
412-
// Very short text: 6-10 words or under 50 chars
413-
if (wordCount < 10 || charLength < 50) {
414-
return isMobile ? 'text-lg sm:text-xl md:text-2xl' : 'text-xl md:text-2xl';
415-
}
416-
417-
// Short text: 11-25 words or under 150 chars with normal word length
418-
if ((wordCount < 25 || charLength < 150) && avgWordLength < 8) {
419-
return isMobile ? 'text-base sm:text-lg md:text-xl' : 'text-lg md:text-xl';
420-
}
421-
422-
// Medium text: 26-50 words or under 300 chars
423-
if (wordCount < 50 || charLength < 300) {
424-
return isMobile ? 'text-sm sm:text-base md:text-lg' : 'text-base md:text-lg';
425-
}
426-
427-
// Medium-long text: 51-100 words or under 500 chars
428-
if (wordCount < 100 || charLength < 500) {
429-
return isMobile ? 'text-xs sm:text-sm md:text-base' : 'text-sm md:text-base';
430-
}
431-
432-
// Long text: Over 100 words or 500+ chars
433-
// Use smaller text for better readability on longer content
434-
return isMobile ? 'text-xs sm:text-sm' : 'text-sm md:text-base';
435-
}
436-
437-
// Reactive font size based on transcript length
438-
$: responsiveFontSize = getResponsiveFontSize($transcriptionText);
439380
440381
// CTA rotation
441382
let currentCtaIndex = 0;
@@ -597,7 +538,6 @@
597538
<TranscriptDisplay
598539
transcript={$transcriptionText || ''}
599540
{showCopyTooltip}
600-
{responsiveFontSize}
601541
{parentContainer}
602542
on:copy={handleTranscriptEvent}
603543
on:reroll={handleReroll}

‎src/lib/components/mainPage/audio-transcript/TranscriptDisplay.svelte‎

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
// Create local props from store values
5353
export let transcript;
5454
export let showCopyTooltip;
55-
export let responsiveFontSize;
5655
export let parentContainer;
5756
5857
// DOM references that need binding
@@ -75,18 +74,12 @@
7574
// Debug log for monitoring transcript updates
7675
$: if (transcript) console.log('[DEBUG] TranscriptDisplay has transcript:', transcript.substring(0, 30));
7776
78-
// Mark chunk lines when transcript changes
79-
$: if (transcript && editableTranscript) {
80-
setTimeout(() => markChunkLines(), 100); // Small delay to ensure DOM is updated
81-
}
82-
8377
// Set the dispatch in the store for other modules to use
8478
dispatchStore.set(dispatch);
8579
8680
// Subscribe to stores for local use - FIXED: Removed the transcript subscription that was causing feedback loop
8781
// The transcriptStore is now updated directly from TranscriptDisplay_Core.js
8882
showCopyTooltipStore.subscribe(value => (showCopyTooltip = value));
89-
responsiveFontSizeStore.subscribe(value => (responsiveFontSize = value));
9083
parentContainerStore.subscribe(value => (parentContainer = value));
9184
notificationStore.subscribe(value => (notification = value));
9285
selectionActiveStore.subscribe(value => (selectionActive = value));
@@ -98,7 +91,6 @@
9891
// Set the store values when props change - FIXED: Removed bidirectional binding for transcript
9992
// We now only allow one-way updates from global transcriptionText to local transcriptStore
10093
$: showCopyTooltipStore.set(showCopyTooltip);
101-
$: responsiveFontSizeStore.set(responsiveFontSize);
10294
$: parentContainerStore.set(parentContainer);
10395
10496
// Sync DOM refs with stores when they update
@@ -108,8 +100,7 @@
108100
109101
import {
110102
handleTextSelection,
111-
hideSelectionButton,
112-
markChunkLines
103+
hideSelectionButton
113104
} from './TranscriptDisplay_Selection.js';
114105
115106
import {
@@ -177,7 +168,7 @@
177168

178169
<div class="wrapper-container flex w-full justify-center">
179170
<div
180-
class="transcript-box-container relative mx-auto w-[95%] max-w-[600px] px-0 sm:w-full"
171+
class="transcript-box-container relative mx-auto w-full max-w-[600px] px-4"
181172
>
182173
<!-- Toast Notification for Lyrics Collection positioned relative to this container -->
183174
{#if notification}
@@ -222,16 +213,16 @@
222213
class="transcript-box animate-shadow-appear relative mx-auto mb-4 box-border
223214
rounded-[2rem] border border-purple-100/70 bg-white/95
224215
shadow-sm transition-all duration-500 ease-in-out contain-layout
225-
w-full min-w-[300px]"
216+
w-full"
226217
>
227218

228219
<!-- Content Area - scrollable with increased height and smooth transitions -->
229220
<div
230-
class="transcript-content-area w-full max-h-[600px] overflow-y-auto overflow-x-hidden px-7 pt-6 pb-8 sm:px-10 sm:pt-7 sm:pb-10 relative z-5 transition-all duration-500 ease-in-out"
221+
class="transcript-content-area w-full max-h-[600px] overflow-y-auto overflow-x-hidden px-8 pt-6 pb-8 relative z-5 transition-all duration-500 ease-in-out"
231222
bind:this={transcriptBoxRef}
232223
>
233224
<div
234-
class={`transcript-text ${responsiveFontSize} text-left custom-transcript-text animate-text-appear font-mono mb-3 lyric-display font-medium max-w-full break-words`}
225+
class="transcript-text text-base text-left custom-transcript-text animate-text-appear font-mono mb-3 lyric-display font-medium max-w-full break-words"
235226
contenteditable="true"
236227
role="textbox"
237228
aria-label="Transcript editor"
@@ -486,17 +477,6 @@
486477
transform: none; /* Prevent transforms on hover */
487478
}
488479
489-
/* Chunk hover effect - show subtle chunk boundaries when hovering */
490-
.lyric-line:hover.part-of-chunk {
491-
box-shadow: 0 0 0 1px rgba(197, 163, 255, 0.4);
492-
}
493-
494-
/* Visual indicator for chunk boundaries */
495-
.lyric-line.part-of-chunk {
496-
border-left: 2px solid rgba(197, 163, 255, 0.15);
497-
padding-left: calc(0.5rem - 2px);
498-
}
499-
500480
/* Line focus/selection effect - solid chunk highlight */
501481
.lyric-line:focus, .lyric-line.selected, .lyric-line-grabbed {
502482
background-color: #C5A3FF; /* Solid purple highlight color */

‎src/lib/components/mainPage/audio-transcript/TranscriptDisplay_Selection.js‎

Lines changed: 3 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515

1616
import { get } from 'svelte/store';
1717

18-
// Smart selection system - automatically detects chunks vs individual lines
18+
// Simple line-by-line selection system
1919

2020
// Export selection-related functions
2121
export function handleTextSelection(event) {
@@ -33,17 +33,8 @@ export function handleTextSelection(event) {
3333
// Check if we have a click (rather than a drag selection)
3434
// We can determine this by checking if the selection is empty
3535
if (selectionText.length === 0 && event.type === 'mouseup' && event.target.nodeName !== 'BUTTON') {
36-
// Smart selection: check if the clicked line is part of a chunk (paragraph)
37-
// If it is, select the whole chunk; otherwise, select just the line
38-
const shouldSelectChunk = isPartOfChunk(event.target);
39-
40-
if (shouldSelectChunk) {
41-
// Select the entire chunk/paragraph
42-
selectEntireParagraph(event.target);
43-
} else {
44-
// Select just the single line
45-
selectEntireLine(event.target);
46-
}
36+
// Simple line selection - just select the clicked line
37+
selectEntireLine(event.target);
4738

4839
// After selecting the line, get the new selection
4940
const newSelection = window.getSelection();
@@ -311,158 +302,6 @@ export function selectEntireLine(node) {
311302
selection.addRange(range);
312303
}
313304

314-
export function markChunkLines() {
315-
const editableTranscript = get(editableTranscriptStore);
316-
if (!editableTranscript) return;
317-
318-
const allLines = editableTranscript.querySelectorAll('.lyric-line');
319-
320-
allLines.forEach((line, index) => {
321-
const allLinesArray = Array.from(allLines);
322-
let isPartOfChunk = false;
323-
324-
// Check if there are adjacent non-empty lines
325-
// Check previous line
326-
if (index > 0) {
327-
const prevText = allLinesArray[index - 1].textContent.trim();
328-
if (prevText !== '' && prevText !== ' ') {
329-
isPartOfChunk = true;
330-
}
331-
}
332-
333-
// Check next line
334-
if (index < allLinesArray.length - 1) {
335-
const nextText = allLinesArray[index + 1].textContent.trim();
336-
if (nextText !== '' && nextText !== ' ') {
337-
isPartOfChunk = true;
338-
}
339-
}
340-
341-
// Apply or remove the class
342-
if (isPartOfChunk) {
343-
line.classList.add('part-of-chunk');
344-
} else {
345-
line.classList.remove('part-of-chunk');
346-
}
347-
});
348-
}
349-
350-
export function isPartOfChunk(node) {
351-
const editableTranscript = get(editableTranscriptStore);
352-
353-
// Find the lyric-line element containing this node
354-
let lineElement = node;
355-
while (lineElement && !lineElement.classList?.contains('lyric-line') && lineElement !== editableTranscript) {
356-
lineElement = lineElement.parentNode;
357-
}
358-
359-
if (!lineElement || !lineElement.classList?.contains('lyric-line')) {
360-
return false;
361-
}
362-
363-
// Get all lines
364-
const allLines = Array.from(editableTranscript.querySelectorAll('.lyric-line'));
365-
const currentIndex = allLines.indexOf(lineElement);
366-
367-
if (currentIndex === -1) {
368-
return false;
369-
}
370-
371-
// Check if there are adjacent non-empty lines (indicating this line is part of a chunk)
372-
let hasAdjacentLines = false;
373-
374-
// Check previous line
375-
if (currentIndex > 0) {
376-
const prevLine = allLines[currentIndex - 1];
377-
const prevText = prevLine.textContent.trim();
378-
if (prevText !== '' && prevText !== ' ') {
379-
hasAdjacentLines = true;
380-
}
381-
}
382-
383-
// Check next line
384-
if (currentIndex < allLines.length - 1) {
385-
const nextLine = allLines[currentIndex + 1];
386-
const nextText = nextLine.textContent.trim();
387-
if (nextText !== '' && nextText !== ' ') {
388-
hasAdjacentLines = true;
389-
}
390-
}
391-
392-
return hasAdjacentLines;
393-
}
394-
395-
export function selectEntireParagraph(node) {
396-
const editableTranscript = get(editableTranscriptStore);
397-
398-
// Remove selected class from all lines first
399-
if (editableTranscript) {
400-
const allLines = editableTranscript.querySelectorAll('.lyric-line');
401-
allLines.forEach(line => line.classList.remove('selected'));
402-
}
403-
404-
// Find the lyric-line element containing this node
405-
let lineElement = node;
406-
while (lineElement && !lineElement.classList?.contains('lyric-line') && lineElement !== editableTranscript) {
407-
lineElement = lineElement.parentNode;
408-
}
409-
410-
if (!lineElement || !lineElement.classList?.contains('lyric-line')) {
411-
// Fallback to single line selection
412-
selectEntireLine(node);
413-
return;
414-
}
415-
416-
// Find the paragraph boundaries (consecutive non-empty lines)
417-
const allLines = Array.from(editableTranscript.querySelectorAll('.lyric-line'));
418-
const currentIndex = allLines.indexOf(lineElement);
419-
420-
if (currentIndex === -1) {
421-
selectEntireLine(node);
422-
return;
423-
}
424-
425-
// Find paragraph start - go backwards until we hit an empty line or start
426-
let paragraphStart = currentIndex;
427-
while (paragraphStart > 0) {
428-
const prevLine = allLines[paragraphStart - 1];
429-
const prevText = prevLine.textContent.trim();
430-
431-
// If previous line is empty or just whitespace, stop here
432-
if (prevText === '' || prevText === ' ') {
433-
break;
434-
}
435-
paragraphStart--;
436-
}
437-
438-
// Find paragraph end - go forwards until we hit an empty line or end
439-
let paragraphEnd = currentIndex;
440-
while (paragraphEnd < allLines.length - 1) {
441-
const nextLine = allLines[paragraphEnd + 1];
442-
const nextText = nextLine.textContent.trim();
443-
444-
// If next line is empty or just whitespace, stop here
445-
if (nextText === '' || nextText === ' ') {
446-
break;
447-
}
448-
paragraphEnd++;
449-
}
450-
451-
// Select all lines in the paragraph
452-
const paragraphLines = allLines.slice(paragraphStart, paragraphEnd + 1);
453-
paragraphLines.forEach(line => line.classList.add('selected'));
454-
455-
// Create a range that encompasses all paragraph lines
456-
if (paragraphLines.length > 0) {
457-
const range = document.createRange();
458-
range.setStartBefore(paragraphLines[0]);
459-
range.setEndAfter(paragraphLines[paragraphLines.length - 1]);
460-
461-
const selection = window.getSelection();
462-
selection.removeAllRanges();
463-
selection.addRange(range);
464-
}
465-
}
466305

467306
export function selectElementContents(element) {
468307
if (!element) return;

0 commit comments

Comments
 (0)