@@ -9,19 +9,30 @@ document.addEventListener("DOMContentLoaded", () => {
99 const voiceToggleBtn = document . getElementById ( "voice-toggle" ) ;
1010 const modelSelect = document . getElementById ( "model-select" ) ;
1111
12+ // Initialize current session from storage (or create a new one if none exists)
13+ let currentSession = Storage . getCurrentSession ( ) ;
14+ if ( ! currentSession ) {
15+ currentSession = Storage . createSession ( "New Chat" ) ;
16+ localStorage . setItem ( "currentSessionId" , currentSession . id ) ;
17+ }
18+
1219 const synth = window . speechSynthesis ;
1320 let voices = [ ] ;
1421 let selectedVoice = null ;
1522 let isSpeaking = false ;
1623 let autoSpeakEnabled = localStorage . getItem ( "autoSpeakEnabled" ) === "true" ;
1724 let currentlySpeakingMessage = null ;
25+
26+ // Combined variable declarations from both branches
1827 let activeUtterance = null ;
1928 let recognition = null ;
2029 let isListening = false ;
2130 let voiceInputBtn = null ;
31+ let slideshowInterval = null ;
2232
23- // Voice Chat Modal Elements
24- const voiceChatModal = document . getElementById ( "voice-chat-modal" ) || createVoiceChatModal ( ) ;
33+ // Voice Chat Modal Elements (from develop branch)
34+ const voiceChatModal =
35+ document . getElementById ( "voice-chat-modal" ) || createVoiceChatModal ( ) ;
2536 const voiceChatBtn = document . getElementById ( "open-voice-chat-modal" ) ;
2637 const voiceChatClose = document . getElementById ( "voice-chat-modal-close" ) ;
2738 const voiceChatListen = document . getElementById ( "voice-chat-listen" ) ;
@@ -66,8 +77,30 @@ document.addEventListener("DOMContentLoaded", () => {
6677 voices = synth . getVoices ( ) ;
6778 if ( voices . length > 0 ) {
6879 voicesLoaded = true ;
80+ // First try to restore a previously selected voice
6981 const savedVoiceIndex = localStorage . getItem ( "selectedVoiceIndex" ) ;
70- selectedVoice = savedVoiceIndex && voices [ savedVoiceIndex ] ? voices [ savedVoiceIndex ] : voices . find ( v => v . name . toLowerCase ( ) . includes ( "female" ) ) || voices [ 0 ] ;
82+ if ( savedVoiceIndex && voices [ savedVoiceIndex ] ) {
83+ selectedVoice = voices [ savedVoiceIndex ] ;
84+ } else {
85+ // Otherwise, use a list of preferred voices
86+ const preferredVoices = [
87+ "Google UK English Female" ,
88+ "Microsoft Zira" ,
89+ "Samantha" ,
90+ "Victoria"
91+ ] ;
92+ for ( const name of preferredVoices ) {
93+ const voice = voices . find ( ( v ) => v . name === name ) ;
94+ if ( voice ) {
95+ selectedVoice = voice ;
96+ break ;
97+ }
98+ }
99+ if ( ! selectedVoice ) {
100+ selectedVoice = voices . find ( ( v ) => v . name . toLowerCase ( ) . includes ( "female" ) ) || voices [ 0 ] ;
101+ }
102+ }
103+ console . log ( "Selected voice:" , selectedVoice ? selectedVoice . name : "None" ) ;
71104 resolve ( selectedVoice ) ;
72105 }
73106 }
@@ -78,9 +111,10 @@ document.addEventListener("DOMContentLoaded", () => {
78111 } ) ;
79112 }
80113
81- loadVoices ( ) . then ( ( ) => updateVoiceToggleUI ( ) ) ;
114+ loadVoices ( ) . then ( ( ) => {
115+ updateVoiceToggleUI ( ) ;
116+ } ) ;
82117
83- // Toggle auto-speak
84118 function toggleAutoSpeak ( ) {
85119 autoSpeakEnabled = ! autoSpeakEnabled ;
86120 localStorage . setItem ( "autoSpeakEnabled" , autoSpeakEnabled . toString ( ) ) ;
@@ -90,24 +124,41 @@ document.addEventListener("DOMContentLoaded", () => {
90124
91125 function updateVoiceToggleUI ( ) {
92126 if ( voiceToggleBtn ) {
93- voiceToggleBtn . innerHTML = autoSpeakEnabled ? '<i class="fas fa-volume-up"></i> Voice On' : '<i class="fas fa-volume-mute"></i> Voice Off' ;
127+ voiceToggleBtn . innerHTML = autoSpeakEnabled
128+ ? '<i class="fas fa-volume-up"></i> Voice On'
129+ : '<i class="fas fa-volume-mute"></i> Voice Off' ;
94130 voiceToggleBtn . style . backgroundColor = autoSpeakEnabled ? "#4CAF50" : "" ;
95131 }
96132 }
97133
98- // Speak message with completion callback
99134 function speakMessage ( text , onEnd = null ) {
100135 if ( ! synth || ! window . SpeechSynthesisUtterance ) {
101136 showToast ( "Speech synthesis not supported" ) ;
102137 return ;
103138 }
104- if ( isSpeaking ) synth . cancel ( ) ;
139+ if ( isSpeaking ) {
140+ synth . cancel ( ) ;
141+ }
142+
143+ let cleanText = text
144+ . replace ( / ` ` ` [ \s \S ] * ?` ` ` / g, "code block omitted." )
145+ . replace ( / ` [ \s \S ] * ?` / g, "inline code omitted." )
146+ . replace ( / h t t p s ? : \/ \/ [ ^ \s ] + / g, "URL link." ) ;
105147
106- const cleanText = text . replace ( / ` ` ` [ \s \S ] * ?` ` ` / g, "code block omitted." ) . replace ( / ` [ \s \S ] * ?` / g, "inline code omitted." ) ;
107148 const utterance = new SpeechSynthesisUtterance ( cleanText ) ;
108149 activeUtterance = utterance ;
109- if ( selectedVoice ) utterance . voice = selectedVoice ;
110- utterance . rate = 0.9 ;
150+ if ( selectedVoice ) {
151+ utterance . voice = selectedVoice ;
152+ } else {
153+ loadVoices ( ) . then ( ( voice ) => {
154+ if ( voice ) {
155+ utterance . voice = voice ;
156+ synth . speak ( utterance ) ;
157+ }
158+ } ) ;
159+ return ;
160+ }
161+ utterance . rate = 1.0 ;
111162 utterance . pitch = 1.0 ;
112163 utterance . volume = 1.0 ;
113164
@@ -155,7 +206,6 @@ document.addEventListener("DOMContentLoaded", () => {
155206 }
156207 }
157208
158- // Initialize speech recognition
159209 function initSpeechRecognition ( ) {
160210 if ( "webkitSpeechRecognition" in window ) {
161211 recognition = new webkitSpeechRecognition ( ) ;
@@ -218,36 +268,43 @@ document.addEventListener("DOMContentLoaded", () => {
218268
219269 // Send voice chat message to API and handle response
220270 function sendVoiceChatMessage ( message ) {
221- const currentSession = Storage . getCurrentSession ( ) ;
222- currentSession . messages . push ( { role : "user" , content : message } ) ;
223- Storage . updateSessionMessages ( currentSession . id , currentSession . messages ) ;
271+ // Use the global currentSession, but refresh it from Storage if needed
272+ const session = Storage . getCurrentSession ( ) ;
273+ session . messages . push ( { role : "user" , content : message } ) ;
274+ Storage . updateSessionMessages ( session . id , session . messages ) ;
224275 window . addNewMessage ( { role : "user" , content : message } ) ; // Display in chat
225276 statusText . textContent = "Waiting for AI response..." ;
226277
227278 const messages = [
228279 { role : "system" , content : "You are a helpful AI assistant. Respond concisely." } ,
229- ...currentSession . messages . slice ( - 10 ) . map ( msg => ( { role : msg . role === "ai" ? "assistant" : "user" , content : msg . content } ) )
280+ ...session . messages . slice ( - 10 ) . map ( ( msg ) => ( {
281+ role : msg . role === "ai" ? "assistant" : "user" ,
282+ content : msg . content
283+ } ) )
230284 ] ;
231285
232- const safeParam = window . _pollinationsAPIConfig ? `safe=${ window . _pollinationsAPIConfig . safe } ` : "safe=false" ;
286+ const safeParam = window . _pollinationsAPIConfig
287+ ? `safe=${ window . _pollinationsAPIConfig . safe } `
288+ : "safe=false" ;
233289 fetch ( `https://text.pollinations.ai/openai?${ safeParam } ` , {
234290 method : "POST" ,
235291 headers : { "Content-Type" : "application/json" } ,
236292 body : JSON . stringify ( { messages, model : modelSelect . value || "unity" , stream : false } )
237293 } )
238- . then ( res => {
294+ . then ( ( res ) => {
239295 if ( ! res . ok ) throw new Error ( `Pollinations error: ${ res . status } ` ) ;
240296 return res . json ( ) ;
241297 } )
242- . then ( data => {
298+ . then ( ( data ) => {
243299 let aiContent = data . choices ?. [ 0 ] ?. message ?. content || "Error: No response" ;
244300
245301 // Check for image generation request
246302 const lastUserMsg = message . toLowerCase ( ) ;
247- const isImageRequest = lastUserMsg . includes ( "image" ) ||
248- lastUserMsg . includes ( "picture" ) ||
249- lastUserMsg . includes ( "show me" ) ||
250- lastUserMsg . includes ( "generate an image" ) ;
303+ const isImageRequest =
304+ lastUserMsg . includes ( "image" ) ||
305+ lastUserMsg . includes ( "picture" ) ||
306+ lastUserMsg . includes ( "show me" ) ||
307+ lastUserMsg . includes ( "generate an image" ) ;
251308 if ( isImageRequest && ! aiContent . includes ( "https://image.pollinations.ai" ) ) {
252309 let imagePrompt = lastUserMsg . replace ( / s h o w m e | g e n e r a t e | i m a g e o f | p i c t u r e o f | i m a g e | p i c t u r e / gi, "" ) . trim ( ) ;
253310 if ( imagePrompt . length < 5 && aiContent . toLowerCase ( ) . includes ( "image" ) ) {
@@ -256,20 +313,22 @@ document.addEventListener("DOMContentLoaded", () => {
256313 if ( imagePrompt . length > 100 ) imagePrompt = imagePrompt . substring ( 0 , 100 ) ;
257314 imagePrompt += ", photographic" ;
258315 const seed = Math . floor ( Math . random ( ) * 1000000 ) ;
259- const imageUrl = `https://image.pollinations.ai/prompt/${ encodeURIComponent ( imagePrompt ) } ?width=512&height=512&seed=${ seed } &${ safeParam } &nolog=true` ;
316+ const imageUrl = `https://image.pollinations.ai/prompt/${ encodeURIComponent (
317+ imagePrompt
318+ ) } ?width=512&height=512&seed=${ seed } &${ safeParam } &nolog=true`;
260319 aiContent += `\n\n**Generated Image:**\n${ imageUrl } ` ;
261320 }
262321
263- currentSession . messages . push ( { role : "ai" , content : aiContent } ) ;
264- Storage . updateSessionMessages ( currentSession . id , currentSession . messages ) ;
322+ session . messages . push ( { role : "ai" , content : aiContent } ) ;
323+ Storage . updateSessionMessages ( session . id , session . messages ) ;
265324 window . addNewMessage ( { role : "ai" , content : aiContent } ) ; // Display in chat
266325 voiceChatTranscript . value = aiContent ;
267326 statusText . textContent = "Speaking response..." ;
268327 speakMessage ( aiContent , ( ) => {
269328 statusText . textContent = "Press 'Listen' to start" ;
270329 } ) ;
271330 } )
272- . catch ( err => {
331+ . catch ( ( err ) => {
273332 showToast ( "Failed to get AI response" ) ;
274333 statusText . textContent = "Error: Try again" ;
275334 } ) ;
@@ -328,7 +387,7 @@ document.addEventListener("DOMContentLoaded", () => {
328387 toast . textContent = message ;
329388 toast . style . opacity = "1" ;
330389 clearTimeout ( toast . timeout ) ;
331- toast . timeout = setTimeout ( ( ) => toast . style . opacity = "0" , duration ) ;
390+ toast . timeout = setTimeout ( ( ) => ( toast . style . opacity = "0" ) , duration ) ;
332391 }
333392
334393 window . _chatInternals = {
@@ -338,6 +397,7 @@ document.addEventListener("DOMContentLoaded", () => {
338397 clearChatBtn,
339398 voiceToggleBtn,
340399 modelSelect,
400+ currentSession,
341401 synth,
342402 voices,
343403 selectedVoice,
@@ -347,11 +407,12 @@ document.addEventListener("DOMContentLoaded", () => {
347407 recognition,
348408 isListening,
349409 voiceInputBtn,
410+ slideshowInterval,
350411 toggleAutoSpeak,
351412 updateVoiceToggleUI,
352413 speakMessage,
353414 stopSpeaking,
354415 initSpeechRecognition,
355416 showToast
356417 } ;
357- } ) ;
418+ } ) ;
0 commit comments