diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml index f87604b..df9ec06 100644 --- a/android/app/src/debug/AndroidManifest.xml +++ b/android/app/src/debug/AndroidManifest.xml @@ -4,4 +4,7 @@ to allow setting breakpoints, to provide hot reload, etc. --> + + + diff --git a/lib/ui/dialogs/audio_player_dialog.dart b/lib/ui/dialogs/audio_player_dialog.dart new file mode 100644 index 0000000..04b649c --- /dev/null +++ b/lib/ui/dialogs/audio_player_dialog.dart @@ -0,0 +1,82 @@ +import 'package:chewie_audio/chewie_audio.dart'; +import 'package:comunic/ui/widgets/async_screen_widget.dart'; +import 'package:comunic/utils/intl_utils.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:video_player/video_player.dart'; + +/// Audio player dialog +/// +/// @author Pierre Hubert + +/// Show audio player dialog +Future showAudioPlayerDialog(BuildContext context, String url) async { + showDialog(context: context, builder: (c) => _AudioPlayerDialog(url: url)); +} + +class _AudioPlayerDialog extends StatefulWidget { + final String url; + + const _AudioPlayerDialog({ + Key key, + @required this.url, + }) : assert(url != null), + super(key: key); + + @override + __AudioPlayerDialogState createState() => __AudioPlayerDialogState(); +} + +class __AudioPlayerDialogState extends State<_AudioPlayerDialog> { + VideoPlayerController _videoPlayerController; + ChewieAudioController _chewieAudioController; + + Future _initialize() async { + _videoPlayerController = VideoPlayerController.network(widget.url); + + await _videoPlayerController.initialize(); + + _chewieAudioController = ChewieAudioController( + videoPlayerController: _videoPlayerController, + autoPlay: true, + looping: false, + ); + } + + void _closeDialog() { + Navigator.pop(context); + } + + @override + void dispose() { + if (_videoPlayerController != null) _videoPlayerController.dispose(); + if (_chewieAudioController != null) _chewieAudioController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text(tr("Audio Player")), + content: _buildContent(), + actions: [ + MaterialButton( + onPressed: _closeDialog, + child: Text(tr("Close").toUpperCase()), + ) + ], + ); + } + + Widget _buildContent() => ConstrainedBox( + constraints: BoxConstraints(maxHeight: 300, maxWidth: 500), + child: AsyncScreenWidget( + onReload: _initialize, + onBuild: _buildReadyContent, + errorMessage: tr("Failed to initialize audio player!"), + ), + ); + + Widget _buildReadyContent() => + ChewieAudio(controller: _chewieAudioController); +} diff --git a/lib/ui/widgets/conversation_file_tile.dart b/lib/ui/widgets/conversation_file_tile.dart index c2eb2a3..cf899ad 100644 --- a/lib/ui/widgets/conversation_file_tile.dart +++ b/lib/ui/widgets/conversation_file_tile.dart @@ -2,6 +2,7 @@ /// /// @author Pierre Hubert import 'package:comunic/models/conversation_message.dart'; +import 'package:comunic/ui/dialogs/audio_player_dialog.dart'; import 'package:comunic/ui/widgets/network_image_widget.dart'; import 'package:filesize/filesize.dart'; import 'package:flutter/material.dart'; @@ -47,7 +48,7 @@ class _ConversationFileWidgetState extends State { ), ); - // The file is not downloadable, we open it in the browser + // We open it in the browser default: return Container( color: widget.defaultBackgroundColor, @@ -69,11 +70,22 @@ class _ConversationFileWidgetState extends State { Spacer(flex: 2), ], ), - onPressed: () => launch(file.url), + onPressed: _openFile, ), ), ); break; } } + + void _openFile() { + switch (file.fileType) { + case ConversationMessageFileType.AUDIO: + showAudioPlayerDialog(context, file.url); + break; + + default: + launch(file.url); + } + } } diff --git a/pubspec.lock b/pubspec.lock index b031f2f..15cfefb 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -50,6 +50,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0-nullsafety.1" + chewie_audio: + dependency: "direct main" + description: + name: chewie_audio + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.2" clipboard: dependency: "direct main" description: @@ -126,7 +133,7 @@ packages: name: cupertino_icons url: "https://pub.dartlang.org" source: hosted - version: "0.1.3" + version: "1.0.0" dio: dependency: "direct main" description: @@ -651,6 +658,27 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.2.0" + video_player: + dependency: "direct main" + description: + name: video_player + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + video_player_platform_interface: + dependency: transitive + description: + name: video_player_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.0" + video_player_web: + dependency: transitive + description: + name: video_player_web + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4+1" wakelock: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 910c534..f3f8937 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -22,7 +22,7 @@ dependencies: # The following adds the Cupertino Icons font to your application. # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.3 + cupertino_icons: ^1.0.0 # Preferences are useful for a lot of things (ex: login tokens) shared_preferences: ^0.5.6+3 @@ -103,6 +103,10 @@ dependencies: # Image manager image: ^2.1.19 + # Video / Audio player + video_player: ^1.0.1 + chewie_audio: ^1.1.2 + dev_dependencies: flutter_test: sdk: flutter