Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions src/lib/lexicon/components/EntryView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@
} from '$lib/data/stores/lexicon.svelte';
import type { SqlValue } from 'sql.js';

const clips = import.meta.glob('./*', {
import: 'default',
eager: true,
base: '/src/gen-assets/clips'
}) as Record<string, string>;

interface Props {
wordIds: number[] | null;
onSelectWord: (word: SelectedWord) => void;
Expand All @@ -27,7 +33,6 @@
const dynamicQuery = wordIds.map(() => `id = ?`).join(' OR ');
const dynamicParams = wordIds.map((id) => id);
const results = db.exec(`SELECT xml FROM entries WHERE ${dynamicQuery}`, dynamicParams);
console.log('results:', results[0].values);

return results[0].values;
} catch (error) {
Expand All @@ -42,6 +47,9 @@
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlString, 'text/xml');

// Collect audio elements to add at the end
let audioElements = '';

const parseError = xmlDoc.querySelector('parsererror');
if (parseError) {
console.error('XML parsing error:', parseError.textContent);
Expand Down Expand Up @@ -89,6 +97,17 @@

output += `<span class="clickable cursor-pointer" style="background-color: var(--BackgroundColor);" data-word="${word}" data-index="${index}" data-homonym="${homonymIndex}">${linkText}</span>`;
}
} else if (node.tagName === 'audio-link' && node.hasAttribute('src')) {
// Handle audio-link tag - create audio element and clickable link
const audioFile = node.getAttribute('src');
const src = clips[`./${audioFile}`] ?? 'clips/' + audioFile;
const audioId = 'audio-' + Math.random().toString(36).substr(2, 9); // Generate unique ID

// Collect audio element to add at the very end
audioElements += `<audio id="${audioId}" src="${src}" preload="auto" style="display: none;"></audio>`;

// Add just the inline clickable icon - no audio element here
output += `<button type="button" class="audio-link" data-audio-id="${audioId}" aria-label="Play audio" style="display: inline-block; vertical-align: middle; margin: 0 2px; width: 24px; height: 24px; overflow: visible;"><svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" style="display: block; overflow: visible;"><path d="M14 20.725v-2.05q2.25-.65 3.625-2.5t1.375-4.2q0-2.35-1.375-4.2T14 5.275v-2.05q3.1.7 5.05 3.137Q21 8.8 21 11.975q0 3.175-1.95 5.612-1.95 2.438-5.05 3.138ZM3 15V9h4l5-5v16l-5-5Zm11 1V7.95q1.175.55 1.838 1.65.662 1.1.662 2.4q0 1.275-.662 2.362Q15.175 15.45 14 16Z"/></svg></button>`;
} else {
output += `<${node.tagName}`;
for (let attr of node.attributes) {
Expand Down Expand Up @@ -123,7 +142,7 @@
return output;
}

return processNode(xmlDoc.documentElement);
return processNode(xmlDoc.documentElement) + audioElements;
}

async function updateXmlData() {
Expand Down Expand Up @@ -166,6 +185,17 @@
});
});
});

const audioButtons = document.querySelectorAll('.audio-link');
audioButtons.forEach((button) => {
button.addEventListener('click', () => {
const audioId = button.getAttribute('data-audio-id');
const audioElement = document.getElementById(audioId) as HTMLAudioElement;
if (audioElement) {
audioElement.play();
}
});
});
}

function applyStyles() {
Expand Down