diff --git a/lib/pages/chat/chat.dart b/lib/pages/chat/chat.dart index 7cd2bdbb2..b86067ddb 100644 --- a/lib/pages/chat/chat.dart +++ b/lib/pages/chat/chat.dart @@ -421,9 +421,9 @@ class ChatController extends State ); // #Pangea if (visibleEvents.length < 10 && timeline != null) { - int prevNumEvents = timeline!.events.length; + var prevNumEvents = timeline!.events.length; await requestHistory(); - int numRequests = 0; + var numRequests = 0; while (timeline!.events.length > prevNumEvents && visibleEvents.length < 10 && numRequests <= 5) { @@ -800,18 +800,11 @@ class ChatController extends State builder: (c) => const RecordingDialog(), ); if (result == null) return; - // #Pangea - // enable web recording - // final audioFile = File(result.path); - // final file = MatrixAudioFile( - // bytes: audioFile.readAsBytesSync(), - // name: audioFile.path, - // ); + final audioFile = XFile(result.path); final file = MatrixAudioFile( - bytes: result.bytes, - name: result.path, + bytes: await audioFile.readAsBytes(), + name: result.fileName ?? audioFile.path, ); - // Pangea# await room.sendFileEvent( file, inReplyTo: replyEvent, diff --git a/lib/pages/chat/recording_dialog.dart b/lib/pages/chat/recording_dialog.dart index 5b4e51252..2628874a6 100644 --- a/lib/pages/chat/recording_dialog.dart +++ b/lib/pages/chat/recording_dialog.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'dart:io'; import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/pangea/utils/update_version_dialog.dart'; @@ -8,7 +7,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:http/http.dart' as http; +import 'package:path/path.dart' as path_lib; import 'package:path_provider/path_provider.dart'; import 'package:record/record.dart'; import 'package:wakelock_plus/wakelock_plus.dart'; @@ -29,10 +28,12 @@ class RecordingDialogState extends State { Duration _duration = Duration.zero; bool error = false; - String? _recordedPath; + final _audioRecorder = AudioRecorder(); final List amplitudeTimeline = []; + String? fileName; + static const int bitRate = 64000; // #Pangea // static const int samplingRate = 44100; @@ -42,17 +43,23 @@ class RecordingDialogState extends State { Future startRecording() async { try { // #Pangea - // enable recording on web - // final useOpus = - // await _audioRecorder.isEncoderSupported(AudioEncoder.opus); - // final tempDir = await getTemporaryDirectory(); - // final path = _recordedPath = - // '${tempDir.path}/recording${DateTime.now().microsecondsSinceEpoch}.${useOpus ? 'ogg' : 'm4a'}'; - final tempDir = kIsWeb ? "." : (await getTemporaryDirectory()).path; - - final path = _recordedPath = - '$tempDir/recording${DateTime.now().microsecondsSinceEpoch}.wav'; + // final codec = kIsWeb + // // Web seems to create webm instead of ogg when using opus encoder + // // which does not play on iOS right now. So we use wav for now: + // ? AudioEncoder.wav + // // Everywhere else we use opus if supported by the platform: + // : await _audioRecorder.isEncoderSupported(AudioEncoder.opus) + // ? AudioEncoder.opus + // : AudioEncoder.aacLc; + const codec = AudioEncoder.wav; // Pangea# + fileName = + 'recording${DateTime.now().microsecondsSinceEpoch}.${codec.fileExtension}'; + String? path; + if (!kIsWeb) { + final tempDir = await getTemporaryDirectory(); + path = path_lib.join(tempDir.path, fileName); + } final result = await _audioRecorder.hasPermission(); if (result != true) { @@ -60,12 +67,13 @@ class RecordingDialogState extends State { return; } await WakelockPlus.enable(); + // #Pangea final isNotError = await showUpdateVersionDialog( future: () => // Pangea# + _audioRecorder.start( - path: _recordedPath!, const RecordConfig( bitRate: bitRate, sampleRate: samplingRate, @@ -73,10 +81,9 @@ class RecordingDialogState extends State { autoGain: true, echoCancel: true, noiseSuppress: true, - // #Pangea - encoder: AudioEncoder.wav, - // Pangea# + encoder: codec, ), + path: path ?? '', ), // #Pangea context: context, @@ -121,25 +128,9 @@ class RecordingDialogState extends State { void _stopAndSend() async { _recorderSubscription?.cancel(); - // #Pangea - // await _audioRecorder.stop(); - final outputPath = await _audioRecorder.stop(); - // Pangea# - final path = _recordedPath; + final path = await _audioRecorder.stop(); + if (path == null) throw ('Recording failed!'); - - // #Pangea - Uint8List bytes; - if (kIsWeb) { - if (outputPath == null) throw ('Recording failed!'); - final response = await http.get(Uri.parse(outputPath)); - bytes = response.bodyBytes; - } else { - final audioFile = File(path); - bytes = audioFile.readAsBytesSync(); - } - // Pangea# - const waveCount = AudioPlayerWidget.wavesCount; final step = amplitudeTimeline.length < waveCount ? 1 @@ -153,9 +144,7 @@ class RecordingDialogState extends State { path: path, duration: _duration.inMilliseconds, waveform: waveform, - // #Pangea - bytes: bytes, - // Pangea# + fileName: fileName, ), ); } @@ -266,35 +255,32 @@ class RecordingResult { final String path; final int duration; final List waveform; - // #Pangea - final Uint8List bytes; - // Pangea# + final String? fileName; const RecordingResult({ required this.path, required this.duration, required this.waveform, - // #Pangea - required this.bytes, - // Pangea# + required this.fileName, }); - - factory RecordingResult.fromJson(Map json) => - RecordingResult( - path: json['path'], - duration: json['duration'], - waveform: List.from(json['waveform']), - // #Pangea - bytes: Uint8List.fromList(json['bytes']), - // Pangea# - ); - - Map toJson() => { - 'path': path, - 'duration': duration, - 'waveform': waveform, - // #Pangea - 'bytes': bytes, - // Pangea# - }; +} + +extension on AudioEncoder { + String get fileExtension { + switch (this) { + case AudioEncoder.aacLc: + case AudioEncoder.aacEld: + case AudioEncoder.aacHe: + return 'm4a'; + case AudioEncoder.opus: + return 'ogg'; + case AudioEncoder.wav: + return 'wav'; + case AudioEncoder.amrNb: + case AudioEncoder.amrWb: + case AudioEncoder.flac: + case AudioEncoder.pcm16bits: + throw UnsupportedError('Not yet used'); + } + } } diff --git a/lib/utils/platform_infos.dart b/lib/utils/platform_infos.dart index 350fc914f..f515b6f1b 100644 --- a/lib/utils/platform_infos.dart +++ b/lib/utils/platform_infos.dart @@ -28,10 +28,7 @@ abstract class PlatformInfos { static bool get usesTouchscreen => !isMobile; - // #Pangea - // static bool get platformCanRecord => (isMobile || isMacOS); - static bool get platformCanRecord => (isMobile || isMacOS || kIsWeb); - // Pangea# + static bool get platformCanRecord => (isMobile || isMacOS || isWeb); static String get clientName => '${AppConfig.applicationName} ${isWeb ? 'web' : Platform.operatingSystem}${kReleaseMode ? '' : 'Debug'}';