@@ -20,168 +20,168 @@ import KeyboardTrigger from "@/components/KeyboardTrigger.astro";
2020 </button >
2121 <div id =" voices-options" class =" voices-options" >
2222 <div data-name =" " class =" voice-option" >Choose Voice</div >
23- <div data-name =" mudra" class =" voice-option" >👦 Mudra </div >
24- <div data-name =" rutvi" class =" voice-option" >👧 Rutvi </div >
23+ <div data-name =" mudra" class =" voice-option" >👧 Girl 1 </div >
24+ <div data-name =" rutvi" class =" voice-option" >👧 Girl 2/div> </div >
2525 </div >
26+ <KeyboardTrigger />
27+ <SharePopover />
28+ <Help
29+ title =" Reader"
30+ description =" Press any letter key (A-Z) to display it with a related emoji. Use the Voices dropdown to change voices, and use the audio button to mute/unmute sounds."
31+ />
2632 </div >
27- <KeyboardTrigger />
28- <SharePopover />
29- <Help
30- title =" Reader"
31- description =" Press any letter key (A-Z) to display it with a related emoji. Use the Voices dropdown to change voices, and use the audio button to mute/unmute sounds."
32- />
33+
34+ <article id =" container__reader" class =" container__reader" >a🍎</article >
35+ <section class =" section--audio hide" >
36+ <audio id =" audioPlayer" controlslist =" nodownload" controls autoplay ></audio >
37+ </section >
3338 </Fragment >
3439
35- <article id =" container__reader" class =" container__reader" >a🍎</article >
36- <section class =" section--audio hide" >
37- <audio id =" audioPlayer" controlslist =" nodownload" controls autoplay ></audio >
38- </section >
39- </BaseLayout >
40+ <script >
41+ import { emojiList } from "@/mappers/alphabet";
42+ import { getRandomValue, isAlphabet, isNumber } from "@/utils/index";
4043
41- < script >
42- import { emojiList } from "@/mappers/alphabet" ;
43- import { getRandomValue, isAlphabet, isNumber } from "@/utils/index" ;
44+ const mainBlock = document.querySelector("#container__reader") as HTMLElement;
45+ const muteButton = document.querySelector("#mute") as HTMLButtonElement ;
46+ const audioPlayer = document.querySelector("#audioPlayer") as HTMLAudioElement ;
4447
45- const mainBlock = document.querySelector("#container__reader") as HTMLElement;
46- const muteButton = document.querySelector("#mute") as HTMLButtonElement;
47- const audioPlayer = document.querySelector("#audioPlayer") as HTMLAudioElement;
48+ const voicesButton = document.querySelector("#voices-btn") as HTMLButtonElement;
49+ const selectedVoiceText = document.querySelector("#selected-voice-text") as HTMLSpanElement;
50+ const voicesOptionsContainer = document.querySelector("#voices-options") as HTMLElement;
51+ const voiceOptionElements = Array.from(voicesOptionsContainer.querySelectorAll(".voice-option")) as HTMLElement[];
4852
49- const voicesButton = document.querySelector("#voices-btn") as HTMLButtonElement;
50- const selectedVoiceText = document.querySelector("#selected-voice-text") as HTMLSpanElement;
51- const voicesOptionsContainer = document.querySelector("#voices-options") as HTMLElement;
52- const voiceOptionElements = Array.from(voicesOptionsContainer.querySelectorAll(".voice-option")) as HTMLElement[];
53+ let speakerName: string | null = null;
54+ let isMuted = false;
5355
54- let speakerName: string | null = null;
55- let isMuted = false;
56+ function setSpeaker(name: string | null | undefined, displayText: string) {
57+ speakerName = name ?? null;
58+ selectedVoiceText.textContent = displayText;
5659
57- function setSpeaker(name: string | null | undefined, displayText: string) {
58- speakerName = name ?? null;
59- selectedVoiceText.textContent = displayText;
60+ voiceOptionElements.forEach((opt) => {
61+ opt.classList.toggle("active", opt.dataset.name === name);
62+ });
63+ if (voicesOptionsContainer) {
64+ voicesOptionsContainer.classList.remove("show");
65+ }
66+ }
6067
61- voiceOptionElements.forEach((opt) => {
62- opt.classList.toggle("active", opt.dataset.name === name);
63- } );
64- if (voicesOptionsContainer) {
65- voicesOptionsContainer.classList.remove("show ");
68+ // Initially set the active voice (e.g., the first one)
69+ if (voiceOptionElements.length > 0) {
70+ //setActiveVoice(voiceOptionElements[0].dataset.name );
71+ } else {
72+ setSpeaker(null, "Choose Voice ");
6673 }
67- }
68-
69- // Initially set the active voice (e.g., the first one)
70- if (voiceOptionElements.length > 0) {
71- //setActiveVoice(voiceOptionElements[0].dataset.name);
72- } else {
73- setSpeaker(null, "Choose Voice");
74- }
75-
76- if (voicesButton) {
77- voicesButton.addEventListener("click", (e) => {
78- e.stopPropagation();
79- voicesOptionsContainer?.classList.toggle("show");
80- });
81- }
8274
83- voiceOptionElements.forEach((option) => {
84- option.addEventListener("click", (e) => {
85- e.stopPropagation();
86- const target = e.currentTarget as HTMLElement;
87- setSpeaker(target.dataset.name, target.textContent || "Voice");
88- });
89- });
90-
91- document.addEventListener("click", (e) => {
92- if (
93- voicesButton &&
94- !voicesButton.contains(e.target as Node) &&
95- voicesOptionsContainer &&
96- !voicesOptionsContainer.contains(e.target as Node)
97- ) {
98- voicesOptionsContainer.classList.remove("show");
75+ if (voicesButton) {
76+ voicesButton.addEventListener("click", (e) => {
77+ e.stopPropagation();
78+ voicesOptionsContainer?.classList.toggle("show");
79+ });
9980 }
100- });
101-
102- if (muteButton) {
103- muteButton.addEventListener("click", (e: MouseEvent) => {
104- isMuted = !isMuted;
105- audioPlayer.muted = isMuted;
106- const target = e.target as HTMLButtonElement;
107- target.classList.toggle("mute");
81+
82+ voiceOptionElements.forEach((option) => {
83+ option.addEventListener("click", (e) => {
84+ e.stopPropagation();
85+ const target = e.currentTarget as HTMLElement;
86+ setSpeaker(target.dataset.name, target.textContent || "Voice");
87+ });
10888 });
109- }
110-
111- const getEmoji = (letter: string): string => {
112- type List = { [key: string]: number[] };
113- const upperCase = letter.toUpperCase();
114- const list = (emojiList as List)[upperCase];
115- if (list && list.length) {
116- const codePoint = getRandomValue(list);
117- return String.fromCodePoint(codePoint);
118- }
119- return "";
120- };
12189
122- const attachAudio = (key: string, isNumberSound = false) => {
123- if (!speakerName) {
124- console.warn("No speaker selected. Cannot play audio.");
125- return;
126- }
90+ document.addEventListener("click", (e) => {
91+ if (
92+ voicesButton &&
93+ !voicesButton.contains(e.target as Node) &&
94+ voicesOptionsContainer &&
95+ !voicesOptionsContainer.contains(e.target as Node)
96+ ) {
97+ voicesOptionsContainer.classList.remove("show");
98+ }
99+ });
127100
128- let keyName;
129- let location = "/assets/media/";
130- if (isNumberSound) {
131- keyName = key.replace("Digit", "");
132- location += "numbers";
133- } else {
134- keyName = key.replace("Key", "").toLowerCase();
135- location += "alphabets";
101+ if (muteButton) {
102+ muteButton.addEventListener("click", (e: MouseEvent) => {
103+ isMuted = !isMuted;
104+ audioPlayer.muted = isMuted;
105+ const target = e.target as HTMLButtonElement;
106+ target.classList.toggle("mute");
107+ });
136108 }
137- const source = `${location}/${speakerName}/${keyName}.ogg`;
138-
139- if (audioPlayer) {
140- audioPlayer.src = source;
141- audioPlayer.load();
142- audioPlayer.oncanplaythrough = async () => {
143- if (!isMuted) {
144- try {
145- await audioPlayer.play();
146- } catch (playError: unknown) {
147- if (
148- playError instanceof Error &&
149- (playError.name === "NotAllowedError" || playError.name === "NotSupportedError")
150- ) {
151- console.error(`Audio play error for ${source}: ${playError.name}. User interaction might be required.`);
152- } else {
153- console.error(`Audio play error for ${source}:`, playError);
109+
110+ const getEmoji = (letter: string): string => {
111+ type List = { [key: string]: number[] };
112+ const upperCase = letter.toUpperCase();
113+ const list = (emojiList as List)[upperCase];
114+ if (list && list.length) {
115+ const codePoint = getRandomValue(list);
116+ return String.fromCodePoint(codePoint);
117+ }
118+ return "";
119+ };
120+
121+ const attachAudio = (key: string, isNumberSound = false) => {
122+ if (!speakerName) {
123+ console.warn("No speaker selected. Cannot play audio.");
124+ return;
125+ }
126+
127+ let keyName;
128+ let location = "/assets/media/";
129+ if (isNumberSound) {
130+ keyName = key.replace("Digit", "");
131+ location += "numbers";
132+ } else {
133+ keyName = key.replace("Key", "").toLowerCase();
134+ location += "alphabets";
135+ }
136+ const source = `${location}/${speakerName}/${keyName}.ogg`;
137+
138+ if (audioPlayer) {
139+ audioPlayer.src = source;
140+ audioPlayer.load();
141+ audioPlayer.oncanplaythrough = async () => {
142+ if (!isMuted) {
143+ try {
144+ await audioPlayer.play();
145+ } catch (playError: unknown) {
146+ if (
147+ playError instanceof Error &&
148+ (playError.name === "NotAllowedError" || playError.name === "NotSupportedError")
149+ ) {
150+ console.error(`Audio play error for ${source}: ${playError.name}. User interaction might be required.`);
151+ } else {
152+ console.error(`Audio play error for ${source}:`, playError);
153+ }
154154 }
155155 }
156+ };
157+ audioPlayer.onerror = () => {
158+ console.error(`Error loading audio source: ${source}`, audioPlayer.error);
159+ };
160+ }
161+ };
162+
163+ const isNonPrintingKey = (e: KeyboardEvent): boolean => {
164+ const { altKey, ctrlKey, metaKey, shiftKey } = e;
165+ return metaKey || ctrlKey || shiftKey || altKey;
166+ };
167+
168+ document.addEventListener("keydown", (e: KeyboardEvent) => {
169+ const { key, keyCode, which, code } = e;
170+ if (!mainBlock) return;
171+
172+ if (!isNonPrintingKey(e)) {
173+ if (isAlphabet(which)) {
174+ const emoji = getEmoji(key);
175+ mainBlock.innerHTML = key + emoji;
176+ if (muteButton) attachAudio(code);
177+ } else if (isNumber(keyCode)) {
178+ mainBlock.innerHTML = key;
179+ if (muteButton) attachAudio(code, true);
180+ } else {
181+ const x = String.fromCodePoint(112080);
182+ mainBlock.innerHTML = x;
156183 }
157- };
158- audioPlayer.onerror = () => {
159- console.error(`Error loading audio source: ${source}`, audioPlayer.error);
160- };
161- }
162- };
163-
164- const isNonPrintingKey = (e: KeyboardEvent): boolean => {
165- const { altKey, ctrlKey, metaKey, shiftKey } = e;
166- return metaKey || ctrlKey || shiftKey || altKey;
167- };
168-
169- document.addEventListener("keydown", (e: KeyboardEvent) => {
170- const { key, keyCode, which, code } = e;
171- if (!mainBlock) return;
172-
173- if (!isNonPrintingKey(e)) {
174- if (isAlphabet(which)) {
175- const emoji = getEmoji(key);
176- mainBlock.innerHTML = key + emoji;
177- if (muteButton) attachAudio(code);
178- } else if (isNumber(keyCode)) {
179- mainBlock.innerHTML = key;
180- if (muteButton) attachAudio(code, true);
181- } else {
182- const x = String.fromCodePoint(112080);
183- mainBlock.innerHTML = x;
184184 }
185- }
186- });
187- </script >
185+ });
186+ </ script >
187+ </BaseLayout >
0 commit comments