changeset 52:27758f3b2d69

add hide_ruby
author Franklin Schmidt <fschmidt@gmail.com>
date Sat, 16 Aug 2025 09:56:10 +0900
parents 4581a20b8124
children 6c78fd83518f
files src/chat.css src/chat.html.luan src/chat.js src/edit_course.html.luan src/lib/Chat.luan src/lib/Course.luan src/lib/ai/claude/Ai_chat.luan src/new_chat.red.luan src/save_chat.js.luan src/save_course.js.luan src/view_course.html.luan
diffstat 11 files changed, 65 insertions(+), 33 deletions(-) [+]
line wrap: on
line diff
--- a/src/chat.css	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/chat.css	Sat Aug 16 09:56:10 2025 +0900
@@ -39,9 +39,9 @@
 	width: 100%;
 }
 
-div[role=assistant] div[message] {
+div[role=assistant]:has(option[hide_text]:checked) div[message] {
 	filter: blur(5px);
 }
-div[role=assistant]:has([name=show_text]:checked) div[message] {
-	filter: none;
+div[role=assistant]:has(option[hide_ruby]:checked) div[message] rt {
+	filter: blur(5px);
 }
--- a/src/chat.html.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/chat.html.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -91,7 +91,13 @@
 					<label clickable><input type=checkbox name=autoplay>Autoplay</label>
 				</p>
 				<p>
-					<label clickable><input type=checkbox name=show_text>Show text</label>
+					<select name=show_text>
+						<option value=show_text>Show text</option>
+<%	if chat.has_ruby then %>
+						<option value=hide_ruby>Hide pronunciation</option>
+<%	end %>
+						<option value=hide_text>Hide text</option>
+					</select>
 				</p>
 				<p>
 					<label clickable><input type=checkbox name=is_private>Private chat</label>
--- a/src/chat.js	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/chat.js	Sat Aug 16 09:56:10 2025 +0900
@@ -22,7 +22,8 @@
 	let dialog = document.querySelector('dialog[edit]');
 	dialog.querySelector('input[name=name]').value = chat.name;
 	dialog.querySelector('select[name=voice]').value = chat.voice;
-	dialog.querySelector('input[name=show_text]').checked = chat.show_text;
+	if( chat.show_text )
+		dialog.querySelector('select[name=show_text]').value = chat.show_text;
 	dialog.querySelector('input[name=autoplay]').checked = chat.autoplay;
 	dialog.querySelector('input[name=is_private]').checked = chat.is_private;
 	dialog.showModal();
--- a/src/edit_course.html.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/edit_course.html.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -26,6 +26,9 @@
 			language = Http.request.parameters.language or error()
 			name = ""
 			ai_system_prompt = ""
+			ai_first_message = ""
+			tts_instructions = ""
+			has_ruby = false
 		}
 	end
 	Io.stdout = Http.response.text_writer()
@@ -35,12 +38,9 @@
 	<head>
 <%		head() %>
 		<style>
-			input,
+			input[type=text],
 			textarea {
 				display: block;
-			}
-			input[type=text],
-			textarea {
 				width: 100%;
 			}
 			h4 {
@@ -66,14 +66,16 @@
 			<h4>Course name</h4>
 			<input type=text required name=name value="<%=html_encode(course.name)%>">
 
+			<p><label clickable><input type=checkbox name=has_ruby <%= course.has_ruby and "checked" or "" %> > Has pronunciation like {japanese|romaji}</label></p>
+
 			<h4>AI system prompt</h4>
 			<textarea required name=ai_system_prompt oninput="fixTextarea(event.target)"><%=html_encode(course.ai_system_prompt)%></textarea>
 
 			<h4>AI first message (optional)</h4>
-			<textarea name=ai_first_message oninput="fixTextarea(event.target)"><%=html_encode(course.ai_first_message or "")%></textarea>
+			<textarea name=ai_first_message oninput="fixTextarea(event.target)"><%=html_encode(course.ai_first_message)%></textarea>
 
 			<h4>Text to speech instructions</h4>
-			<textarea name=tts_instructions oninput="fixTextarea(event.target)"><%=html_encode(course.tts_instructions or "")%></textarea>
+			<textarea name=tts_instructions oninput="fixTextarea(event.target)"><%=html_encode(course.tts_instructions)%></textarea>
 
 			<input type=submit>
 
--- a/src/lib/Chat.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/lib/Chat.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -31,9 +31,10 @@
 		language = doc.language
 		tts_instructions = doc.tts_instructions
 		voice = doc.voice
-		show_text = doc.show_text == "true"
+		show_text = doc.show_text
 		autoplay = doc.autoplay == "true"
 		is_private = doc.is_private == "true"
+		has_ruby = doc.has_ruby == "true"
 	}
 end
 
@@ -49,16 +50,16 @@
 		language = chat.language or error()
 		tts_instructions = chat.tts_instructions -- or error()
 		voice = chat.voice or error()
-		show_text = chat.show_text and "true" or "false"
+		show_text = chat.show_text
 		autoplay = chat.autoplay and "true" or "false"
 		is_private = chat.is_private and "true" or nil
+		has_ruby = chat.has_ruby and "true" or nil
 	}
 end
 
 function Chat.new(chat)
 	chat.updated = chat.updated or time_now()
 	chat.voice = chat.voice or voices[1]
-	if chat.show_text==nil then chat.show_text = true end
 	if chat.autoplay==nil then chat.autoplay = true end
 
 	function chat.save()
@@ -103,8 +104,32 @@
 		Ai_chat.output_system_prompt(chat.ai_thread)
 	end
 
+	local function option(name,text)
+		local selected = name==chat.show_text and " selected" or ""
+%>
+						<option <%=name%><%=selected%>><%=text%></option>
+<%
+	end
+
+	local function assistant_controls()
+		return `%>
+				<div controls>
+					<audio controls preload=none></audio>
+					<select>
+<%
+						option("show_text","Show text")
+			if chat.has_ruby then
+						option("hide_ruby","Hide pronunciation")
+			end
+						option("hide_text","Hide text")
+%>
+					</select>
+				</div>
+<%		`
+	end
+
 	function chat.output_messages_html()
-		Ai_chat.output_messages_html(chat.show_text,chat.ai_thread)
+		Ai_chat.output_messages_html(assistant_controls(),chat.ai_thread)
 	end
 
 	function chat.ask(input)
@@ -115,7 +140,7 @@
 			chat.ai_thread = ai_thread
 			chat.save()
 		end )
-		return `Ai_chat.output_messages_html(chat.show_text,ai_thread,old_thread)`
+		return `Ai_chat.output_messages_html(assistant_controls(),ai_thread,old_thread)`
 	end
 
 	function chat.language_name()
--- a/src/lib/Course.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/lib/Course.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -23,6 +23,7 @@
 		ai_system_prompt = doc.ai_system_prompt
 		ai_first_message = doc.ai_first_message
 		tts_instructions = doc.tts_instructions
+		has_ruby = doc.has_ruby == "true"
 	}
 end
 
@@ -37,6 +38,7 @@
 		ai_system_prompt = course.ai_system_prompt or error()
 		ai_first_message = course.ai_first_message
 		tts_instructions = course.tts_instructions
+		has_ruby = course.has_ruby and "true" or nil
 	}
 end
 
--- a/src/lib/ai/claude/Ai_chat.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/lib/ai/claude/Ai_chat.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -25,7 +25,7 @@
 	%><%=system_prompt%><%
 end
 
-function Ai_chat.output_messages_html(show_text,thread,old_thread)
+function Ai_chat.output_messages_html(assistant_controls,thread,old_thread)
 	thread = json_parse(thread)
 	local messages = thread.messages or error
 	local n = 0
@@ -34,7 +34,6 @@
 		local old_messages = old_thread.messages or error
 		n = #old_messages
 	end
-	local checked = show_text and "checked" or ""
 	for i, message in ipairs(messages) do
 		if i <= n then
 			continue
@@ -55,10 +54,7 @@
 			<div role="<%=role%>">
 				<div message markdown><%=text%></div>
 <%			if role=="assistant" then %>
-				<div controls>
-					<audio controls preload=none></audio>
-					<label clickable><input type=checkbox name=show_text <%=checked%> >Show text</label>
-				</div>
+<%=				assistant_controls %>
 <%			end %>
 			</div>
 <%
--- a/src/new_chat.red.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/new_chat.red.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -21,6 +21,7 @@
 		name = course.name
 		language = course.language
 		tts_instructions = course.tts_instructions
+		has_ruby = course.has_ruby
 		ai_thread = ai_init(course.ai_system_prompt)
 	}
 	chat.save()
--- a/src/save_chat.js.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/save_chat.js.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -15,20 +15,16 @@
 
 
 return function()
-	local chat = Http.request.parameters.chat or error()
-	local name = Http.request.parameters.name or error()
-	local voice = Http.request.parameters.voice or error()
-	local show_text = Http.request.parameters.show_text
-	local autoplay = Http.request.parameters.autoplay
-	local is_private = Http.request.parameters.is_private
+	local parameters = Http.request.parameters
+	local chat = parameters.chat or error()
 	run_in_transaction( function()
 		chat = get_chat_by_id(chat) or error()
 		chat.user_id == current_user().id or error()
-		chat.name = name
-		chat.voice = voice
-		chat.show_text = show_text ~= nil
-		chat.autoplay = autoplay ~= nil
-		chat.is_private = is_private ~= nil
+		chat.name = parameters.name or error()
+		chat.voice = parameters.voice or error()
+		chat.show_text = parameters.show_text or error()
+		chat.autoplay = parameters.autoplay ~= nil
+		chat.is_private = parameters.is_private ~= nil
 		chat.save()
 	end )
 	Io.stdout = Http.response.text_writer()
--- a/src/save_course.js.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/save_course.js.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -31,6 +31,7 @@
 		course.ai_system_prompt = parameters.ai_system_prompt or error()
 		course.ai_first_message = parameters.ai_first_message or error()
 		course.tts_instructions = parameters.tts_instructions or error()
+		course.has_ruby = parameters.has_ruby ~= nil
 		course.updated = time_now()
 		course.save()
 	end )
--- a/src/view_course.html.luan	Fri Aug 15 23:24:38 2025 +0900
+++ b/src/view_course.html.luan	Sat Aug 16 09:56:10 2025 +0900
@@ -51,6 +51,8 @@
 <%	end %>
 			</p>
 
+			<p><input type=checkbox name=has_ruby <%= course.has_ruby and "checked" or "" %> disabled> Has pronunciation like {japanese|romaji}</p>
+
 			<h4>AI system prompt</h4>
 			<pre><%=html_encode(course.ai_system_prompt)%></pre>