From 2eb3d81dd1f654bd755d15e56968b545a94e50d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Ku=C3=9Fowski?= Date: Sun, 22 Mar 2026 12:45:51 +0100 Subject: [PATCH] fix: Always calc correct file extension for voice messages --- lib/pages/chat/chat.dart | 13 +++++++++++-- lib/pages/chat/recording_input_row.dart | 2 +- lib/pages/chat/recording_view_model.dart | 6 +++--- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 255f1c81..2dfc70d5 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -34,6 +34,7 @@ import 'package:flutter/services.dart'; import 'package:go_router/go_router.dart'; import 'package:image_picker/image_picker.dart'; import 'package:matrix/matrix.dart'; +import 'package:mime/mime.dart'; import 'package:scroll_to_index/scroll_to_index.dart'; import '../../utils/account_bundles.dart'; @@ -700,7 +701,7 @@ class ChatController extends State String path, int duration, List waveform, - String? fileName, + String fileName, ) async { final scaffoldMessenger = ScaffoldMessenger.of(context); final audioFile = XFile(path); @@ -712,9 +713,17 @@ class ChatController extends State final bytes = bytesResult.result; if (bytes == null) return; + final mimeType = lookupMimeType(fileName, headerBytes: bytes); + final extension = mimeType == null ? null : extensionFromMime(mimeType); + if (extension != null) { + fileName = + 'voice_message_${DateTime.now().millisecondsSinceEpoch}.$extension'; + } + final file = MatrixAudioFile( bytes: bytes, - name: fileName ?? audioFile.path, + name: fileName, + mimeType: mimeType, ); room diff --git a/lib/pages/chat/recording_input_row.dart b/lib/pages/chat/recording_input_row.dart index 66538cbd..ff295e88 100644 --- a/lib/pages/chat/recording_input_row.dart +++ b/lib/pages/chat/recording_input_row.dart @@ -6,7 +6,7 @@ import 'package:flutter/material.dart'; class RecordingInputRow extends StatelessWidget { final RecordingViewModelState state; - final Future Function(String, int, List, String?) onSend; + final Future Function(String, int, List, String) onSend; const RecordingInputRow({ required this.state, required this.onSend, diff --git a/lib/pages/chat/recording_view_model.dart b/lib/pages/chat/recording_view_model.dart index de587920..d66ccbe4 100644 --- a/lib/pages/chat/recording_view_model.dart +++ b/lib/pages/chat/recording_view_model.dart @@ -67,7 +67,7 @@ class RecordingViewModelState extends State { ? AudioEncoder.opus : AudioEncoder.aacLc; fileName = - 'recording${DateTime.now().microsecondsSinceEpoch}.${codec.fileExtension}'; + 'voice_message_${DateTime.now().millisecondsSinceEpoch}.${codec.fileExtension}'; String? path; if (!kIsWeb) { final tempDir = await getTemporaryDirectory(); @@ -168,7 +168,7 @@ class RecordingViewModelState extends State { String path, int duration, List waveform, - String? fileName, + String fileName, ) onSend, ) async { @@ -189,7 +189,7 @@ class RecordingViewModelState extends State { isSending = true; }); try { - await onSend(path, duration.inMilliseconds, waveform, fileName); + await onSend(path, duration.inMilliseconds, waveform, fileName!); } catch (e, s) { Logs().e('Unable to send voice message', e, s); setState(() {