|
|
|
|
@ -320,7 +320,7 @@ class ChatViewModel : ViewModel() {
|
|
|
|
|
} |
|
|
|
|
4 -> { if (repo != null) { LogManager.addLog("INFO", "VM", "CHANNEL_UPDATED — refreshChannels"); refreshChannels() } else { LogManager.addLog("WARN", "VM", "CHANNEL_UPDATED skipped — repo is NULL") } } |
|
|
|
|
12 -> LogManager.addLog("INFO", "VM", "service started") |
|
|
|
|
13 -> LogManager.addLog("INFO", "VM", "service stopped") |
|
|
|
|
13 -> { _attachmentPreparations.value = emptyMap(); LogManager.addLog("INFO", "VM", "service stopped") } |
|
|
|
|
16 -> { /* NODEINFO_UPDATED: [node_id:8][presence:1][up:1][best_rtt:2][bgp_rtt:2][bgp_nodes:2] */ |
|
|
|
|
if (data == null || data.size < 12) return |
|
|
|
|
val ns = parseNodeStatus(data) ?: return |
|
|
|
|
@ -1024,7 +1024,7 @@ class ChatViewModel : ViewModel() {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fun sendAttachment(filePath: String, target: ConversationTarget, name: String = File(filePath).name) { |
|
|
|
|
val r = repo ?: return |
|
|
|
|
val r = repo ?: throw IllegalStateException("Сервис чата остановлен") |
|
|
|
|
if (target is ConversationTarget.Pm) { NativeLib.dmSendFile(target.id, filePath, name); return } |
|
|
|
|
val chId = target.id |
|
|
|
|
val ext = filePath.substringAfterLast('.', "").lowercase() |
|
|
|
|
@ -1057,26 +1057,37 @@ class ChatViewModel : ViewModel() {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Cache-файл передаётся native только после успешного чтения метаданных. */ |
|
|
|
|
fun sendVideoMessage(filePath: String, target: ConversationTarget) { |
|
|
|
|
val r = repo ?: return |
|
|
|
|
val job = java.util.UUID.randomUUID().toString() |
|
|
|
|
preparationState(target.nativeId, job, 0) |
|
|
|
|
viewModelScope.launch { |
|
|
|
|
val meta = withContext(Dispatchers.IO) { |
|
|
|
|
var dur = 0; var w = 0; var h = 0 |
|
|
|
|
val mmr = MediaMetadataRetriever() |
|
|
|
|
try { |
|
|
|
|
mmr.setDataSource(filePath) |
|
|
|
|
dur = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toIntOrNull() ?: 0 |
|
|
|
|
w = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0 |
|
|
|
|
h = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() ?: 0 |
|
|
|
|
} catch (e: Exception) { |
|
|
|
|
LogManager.addLog("WARN", "VM", "video metadata failed: ${e.message}") |
|
|
|
|
} finally { |
|
|
|
|
try { mmr.release() } catch (_: Exception) {} |
|
|
|
|
var accepted = false |
|
|
|
|
try { |
|
|
|
|
val r = repo ?: throw IllegalStateException("Сервис чата остановлен") |
|
|
|
|
val meta = withContext(Dispatchers.IO) { |
|
|
|
|
val mmr = MediaMetadataRetriever() |
|
|
|
|
try { |
|
|
|
|
mmr.setDataSource(filePath) |
|
|
|
|
Triple( |
|
|
|
|
mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toIntOrNull() ?: 0, |
|
|
|
|
mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toIntOrNull() ?: 0, |
|
|
|
|
mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toIntOrNull() ?: 0 |
|
|
|
|
) |
|
|
|
|
} finally { mmr.release() } |
|
|
|
|
} |
|
|
|
|
accepted = r.sendVideo(target.nativeId, filePath, meta.first, meta.second, meta.third) |
|
|
|
|
if (!accepted) throw IllegalStateException("Некорректное видео или сервис остановлен") |
|
|
|
|
LogManager.addLog("INFO", "VM", "video queued target=${target.nativeId} dur=${meta.first} ${meta.second}x${meta.third}") |
|
|
|
|
} catch (e: kotlinx.coroutines.CancellationException) { throw e } |
|
|
|
|
catch (e: Exception) { LogManager.addLog("ERROR", "VM", "video failed target=${target.nativeId}: ${e.message}") } |
|
|
|
|
finally { |
|
|
|
|
preparationState(target.nativeId, job, if (accepted) 1 else 2) |
|
|
|
|
if (!accepted) withContext(kotlinx.coroutines.NonCancellable + Dispatchers.IO) { |
|
|
|
|
if (!File(filePath).delete() && File(filePath).exists()) |
|
|
|
|
LogManager.addLog("ERROR", "VM", "video cache cleanup failed: $filePath") |
|
|
|
|
} |
|
|
|
|
Triple(dur, w, h) |
|
|
|
|
} |
|
|
|
|
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) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|