Compare commits
2 commits
fb6bc981d1
...
44ff82a66d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44ff82a66d | ||
|
|
1899f2cff1 |
4 changed files with 48 additions and 8 deletions
|
|
@ -489,6 +489,8 @@ fun MessageRow(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isVoiceOnly = hasAttachments && message.content.isBlank() && message.attachments.all { it.kind == "audio" }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
Modifier
|
Modifier
|
||||||
.widthIn(max = 300.dp)
|
.widthIn(max = 300.dp)
|
||||||
|
|
@ -499,12 +501,28 @@ fun MessageRow(
|
||||||
.border(1.2.dp, borderBrush, shape),
|
.border(1.2.dp, borderBrush, shape),
|
||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
if (hasAttachments) AttachmentGrid(message.attachments, Modifier.padding(6.dp))
|
if (isVoiceOnly) {
|
||||||
if (message.content.isNotBlank()) {
|
Row(
|
||||||
Text(
|
Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
|
||||||
message.content, color = cs.onBackground, fontSize = 16.sp, lineHeight = 26.sp,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = if (hasAttachments) 4.dp else 13.dp, bottom = 13.dp),
|
) {
|
||||||
)
|
Icon(KaizenIcons.Mic, null, tint = accent.primary.copy(alpha = 0.7f), modifier = Modifier.size(18.dp))
|
||||||
|
Spacer(Modifier.width(8.dp))
|
||||||
|
Text(
|
||||||
|
stringResource(R.string.chat_voice_message),
|
||||||
|
color = cs.onBackground.copy(alpha = 0.70f),
|
||||||
|
fontSize = 14.sp,
|
||||||
|
fontWeight = FontWeight.Medium,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (hasAttachments) AttachmentGrid(message.attachments, Modifier.padding(6.dp))
|
||||||
|
if (message.content.isNotBlank()) {
|
||||||
|
Text(
|
||||||
|
message.content, color = cs.onBackground, fontSize = 16.sp, lineHeight = 26.sp,
|
||||||
|
modifier = Modifier.padding(start = 16.dp, end = 16.dp, top = if (hasAttachments) 4.dp else 13.dp, bottom = 13.dp),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -283,9 +283,29 @@ fun ChatScreen(
|
||||||
val cid = convIdDeferred?.await() ?: conversationId ?: return@launch
|
val cid = convIdDeferred?.await() ?: conversationId ?: return@launch
|
||||||
if (conversationId == null) conversationId = cid
|
if (conversationId == null) conversationId = cid
|
||||||
val assistantMsg = messages.lastOrNull { it.id == assistantId } ?: return@launch
|
val assistantMsg = messages.lastOrNull { it.id == assistantId } ?: return@launch
|
||||||
|
val finalContent = assistantMsg.content
|
||||||
|
val finalReasoning = assistantMsg.reasoning.takeIf { it.isNotBlank() }
|
||||||
|
val finalSources = assistantMsg.sources.takeIf { it.isNotEmpty() }
|
||||||
val userSave = SaveMessage(id = userMsg.wireId, parentId = userParentId, role = "user", content = "", attachments = listOf(att))
|
val userSave = SaveMessage(id = userMsg.wireId, parentId = userParentId, role = "user", content = "", attachments = listOf(att))
|
||||||
val assistantSave = SaveMessage(id = assistantMsg.wireId, parentId = userMsg.wireId, role = "assistant", content = assistantMsg.content, model = cfg.model, reasoning = assistantMsg.reasoning.takeIf { it.isNotBlank() }, sources = assistantMsg.sources.takeIf { it.isNotEmpty() }?.map { dev.kaizen.app.net.SearchSource(it.title, it.url, it.snippet) })
|
val assistantSave = SaveMessage(id = assistantWireId, parentId = userMsg.wireId, role = "assistant", content = finalContent, model = cfg.model, reasoning = finalReasoning, sources = finalSources?.map { dev.kaizen.app.net.SearchSource(it.title, it.url, it.snippet) })
|
||||||
KaizenApi.saveMessages(cfg.baseUrl, cfg.token, cid, listOf(userSave, assistantSave))
|
val saved = KaizenApi.saveMessages(cfg.baseUrl, cfg.token, cid, listOf(userSave, assistantSave))
|
||||||
|
if (saved) {
|
||||||
|
val msgCount = messages.size
|
||||||
|
chat.messageRepo.cacheMessages(cid, listOf(
|
||||||
|
dev.kaizen.app.db.MessageEntity(
|
||||||
|
id = userMsg.wireId, conversationId = cid,
|
||||||
|
role = "user", content = "",
|
||||||
|
attachments = listOf(att), sortOrder = msgCount - 2,
|
||||||
|
),
|
||||||
|
dev.kaizen.app.db.MessageEntity(
|
||||||
|
id = assistantWireId, conversationId = cid,
|
||||||
|
role = "assistant", content = finalContent,
|
||||||
|
attachments = emptyList(), sortOrder = msgCount - 1,
|
||||||
|
reasoning = finalReasoning,
|
||||||
|
sources = finalSources?.map { dev.kaizen.app.net.SearchSource(it.title, it.url, it.snippet) } ?: emptyList(),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
if (convIdDeferred != null) {
|
if (convIdDeferred != null) {
|
||||||
chat.conversationRepo.insertOptimistic(cid, "(Voice)")
|
chat.conversationRepo.insertOptimistic(cid, "(Voice)")
|
||||||
val title = KaizenApi.generateTitle(cfg.baseUrl, cfg.token, cid)
|
val title = KaizenApi.generateTitle(cfg.baseUrl, cfg.token, cid)
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@
|
||||||
<string name="chat_open_menu">Open menu</string>
|
<string name="chat_open_menu">Open menu</string>
|
||||||
<string name="chat_stop">Stop response</string>
|
<string name="chat_stop">Stop response</string>
|
||||||
<string name="chat_recording">Recording …</string>
|
<string name="chat_recording">Recording …</string>
|
||||||
|
<string name="chat_voice_message">Voice message</string>
|
||||||
<string name="chat_mic_permission">Microphone access required</string>
|
<string name="chat_mic_permission">Microphone access required</string>
|
||||||
<string name="chat_read_aloud">Read aloud</string>
|
<string name="chat_read_aloud">Read aloud</string>
|
||||||
<string name="chat_tts_error">Read aloud failed</string>
|
<string name="chat_tts_error">Read aloud failed</string>
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
<string name="chat_open_menu">Menü öffnen</string>
|
<string name="chat_open_menu">Menü öffnen</string>
|
||||||
<string name="chat_stop">Antwort stoppen</string>
|
<string name="chat_stop">Antwort stoppen</string>
|
||||||
<string name="chat_recording">Aufnahme läuft …</string>
|
<string name="chat_recording">Aufnahme läuft …</string>
|
||||||
|
<string name="chat_voice_message">Sprachnachricht</string>
|
||||||
<string name="chat_mic_permission">Mikrofonzugriff wird benötigt</string>
|
<string name="chat_mic_permission">Mikrofonzugriff wird benötigt</string>
|
||||||
<string name="chat_read_aloud">Vorlesen</string>
|
<string name="chat_read_aloud">Vorlesen</string>
|
||||||
<string name="chat_tts_error">Vorlesen fehlgeschlagen</string>
|
<string name="chat_tts_error">Vorlesen fehlgeschlagen</string>
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue