Pin Android recording targets and stop capture outside the main thread
This commit is contained in:
1 parent
80b4e6f3e9
commit
dbec6e75e8
2 files changed
+38
-41
No files matched your search
+1
-6
@@ -296,12 +296,7 @@ private fun FileBubble(message: Message, textColor: Color, onDownload: (Message)
|
||||
private val VIDEO_EXTENSIONS = setOf("mp4", "m4v", "mov", "webm", "3gp", "mkv", "avi", "ts", "mpg", "mpeg")
|
||||
|
||||
private fun isVideoMessage(message: Message): Boolean {
|
||||
if (message.contentType.startsWith("video/")) return true
|
||||
if (message.contentType == "application/octet-stream") {
|
||||
val ext = message.text.substringAfterLast('.', "").lowercase()
|
||||
return ext in VIDEO_EXTENSIONS
|
||||
}
|
||||
return false
|
||||
return message.contentType.startsWith("video/")
|
||||
}
|
||||
|
||||
private fun isImageMessage(message: Message): Boolean = message.contentType.startsWith("image/")
|
||||
|
||||
@@ -946,17 +946,21 @@ class ChatViewModel : ViewModel() {
|
||||
r.joinChannel(channelId, nodeId, joinKey, pubkey, addrs, addrCount)
|
||||
}
|
||||
|
||||
fun startVoiceRecording() {
|
||||
val ch = _currentChannel.value ?: return
|
||||
if (!audioRecorder.startRecording(ch.id)) {
|
||||
private var recordingStopping = false
|
||||
private var recordingTarget: ConversationTarget? = null
|
||||
|
||||
fun startVoiceRecording(target: ConversationTarget) {
|
||||
if (recordingStopping) { LogManager.addLog("WARN", "VM", "recording is still stopping"); return }
|
||||
if (!audioRecorder.startRecording(target.nativeId)) {
|
||||
LogManager.addLog("ERROR", "VM", "voice recording failed to start")
|
||||
return
|
||||
}
|
||||
_isRecording.value = true
|
||||
recordingTarget = target
|
||||
_isRecordingLocked.value = false
|
||||
recordingStartTimeMs = System.currentTimeMillis()
|
||||
_recordingDurationMs.value = 0
|
||||
LogManager.addLog("INFO", "VM", "voice recording started ch=${ch.id}")
|
||||
LogManager.addLog("INFO", "VM", "voice recording started target=${target.nativeId}")
|
||||
}
|
||||
|
||||
fun lockVoiceRecording() {
|
||||
@@ -964,42 +968,44 @@ class ChatViewModel : ViewModel() {
|
||||
LogManager.addLog("DEBUG", "VM", "voice recording locked")
|
||||
}
|
||||
|
||||
fun stopVoiceRecording(): Int {
|
||||
if (!_isRecording.value) return 0
|
||||
val duration = audioRecorder.stopRecording()
|
||||
fun stopVoiceRecording() {
|
||||
if (!_isRecording.value || recordingStopping) return
|
||||
recordingStopping = true
|
||||
_isRecording.value = false
|
||||
_isRecordingLocked.value = false
|
||||
_recordingDurationMs.value = 0
|
||||
val ch = _currentChannel.value
|
||||
if (ch != null && duration >= 500) {
|
||||
viewModelScope.launch {
|
||||
delay(500)
|
||||
refreshMessages(ch.id)
|
||||
refreshChannels()
|
||||
try {
|
||||
val duration = withContext(Dispatchers.IO) { audioRecorder.stopRecording() }
|
||||
LogManager.addLog("INFO", "VM", "voice detached target=${recordingTarget?.nativeId} duration=$duration")
|
||||
} finally {
|
||||
recordingStopping = false
|
||||
recordingTarget = null
|
||||
}
|
||||
}
|
||||
LogManager.addLog("INFO", "VM", "voice recording stopped dur=${duration}ms")
|
||||
return duration
|
||||
}
|
||||
|
||||
fun cancelVoiceRecording() {
|
||||
audioRecorder.cancelRecording()
|
||||
if (recordingStopping) return
|
||||
recordingStopping = true
|
||||
_isRecording.value = false
|
||||
_isRecordingLocked.value = false
|
||||
_recordingDurationMs.value = 0
|
||||
LogManager.addLog("INFO", "VM", "voice recording cancelled")
|
||||
viewModelScope.launch {
|
||||
try { withContext(Dispatchers.IO) { audioRecorder.cancelRecording() } }
|
||||
finally { recordingStopping = false; recordingTarget = null }
|
||||
}
|
||||
LogManager.addLog("INFO", "VM", "voice recording cancelled target=${recordingTarget?.nativeId}")
|
||||
}
|
||||
|
||||
fun sendVoiceMessage() {
|
||||
val duration = stopVoiceRecording()
|
||||
if (duration < 1000) {
|
||||
LogManager.addLog("INFO", "VM", "voice too short (${duration}ms), discarded")
|
||||
}
|
||||
stopVoiceRecording()
|
||||
}
|
||||
|
||||
fun sendAttachment(filePath: String) {
|
||||
fun sendAttachment(filePath: String, target: ConversationTarget, name: String = File(filePath).name) {
|
||||
val r = repo ?: return
|
||||
val ch = _currentChannel.value ?: return
|
||||
if (target is ConversationTarget.Pm) { NativeLib.dmSendFile(target.id, filePath, name); return }
|
||||
val chId = target.id
|
||||
val ext = filePath.substringAfterLast('.', "").lowercase()
|
||||
if (ext in IMAGE_EXTENSIONS) {
|
||||
viewModelScope.launch {
|
||||
@@ -1010,29 +1016,28 @@ class ChatViewModel : ViewModel() {
|
||||
}
|
||||
val (w, h) = dims
|
||||
if (w > 0 && h > 0) {
|
||||
LogManager.addLog("INFO", "VM", "sendAttachment(image) ch=${ch.id} ext=$ext ${w}x${h}")
|
||||
r.sendPhoto(ch.id, filePath, w, h)
|
||||
LogManager.addLog("INFO", "VM", "sendAttachment(image) ch=$chId ext=$ext ${w}x${h}")
|
||||
r.sendPhoto(chId, filePath, w, h)
|
||||
} else {
|
||||
LogManager.addLog("WARN", "VM", "image decode failed, sent as file: $filePath")
|
||||
r.sendAttachment(ch.id, filePath)
|
||||
r.sendAttachment(chId, filePath)
|
||||
}
|
||||
delay(500)
|
||||
refreshMessages(ch.id)
|
||||
refreshMessages(chId)
|
||||
refreshChannels()
|
||||
}
|
||||
} else {
|
||||
r.sendAttachment(ch.id, filePath)
|
||||
r.sendAttachment(chId, filePath)
|
||||
viewModelScope.launch {
|
||||
delay(500)
|
||||
refreshMessages(ch.id)
|
||||
refreshMessages(chId)
|
||||
refreshChannels()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun sendVideoMessage(filePath: String) {
|
||||
fun sendVideoMessage(filePath: String, target: ConversationTarget) {
|
||||
val r = repo ?: return
|
||||
val ch = _currentChannel.value ?: return
|
||||
viewModelScope.launch {
|
||||
val meta = withContext(Dispatchers.IO) {
|
||||
var dur = 0; var w = 0; var h = 0
|
||||
@@ -1049,11 +1054,8 @@ class ChatViewModel : ViewModel() {
|
||||
}
|
||||
Triple(dur, w, h)
|
||||
}
|
||||
LogManager.addLog("INFO", "VM", "sendVideoMessage ch=${ch.id} dur=${meta.first} ${meta.second}x${meta.third}")
|
||||
r.sendVideo(ch.id, filePath, meta.first, meta.second, meta.third)
|
||||
delay(500)
|
||||
refreshMessages(ch.id)
|
||||
refreshChannels()
|
||||
LogManager.addLog("INFO", "VM", "sendVideoMessage target=${target.nativeId} dur=${meta.first} ${meta.second}x${meta.third}")
|
||||
r.sendVideo(target.nativeId, filePath, meta.first, meta.second, meta.third)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user