-
Notifications
You must be signed in to change notification settings - Fork 343
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui): voice recording attachment builder (#1907)
* feat(llc,ui): voice recording attachment builder * test: add coverage * fix: fix formatting * uncomment logic
- Loading branch information
Showing
24 changed files
with
1,573 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
...s/stream_chat_flutter/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
134 changes: 134 additions & 0 deletions
134
...chment/builder/voice_recording_attachment_builder/stream_voice_recording_list_player.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
import 'dart:async'; | ||
|
||
import 'package:collection/collection.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:just_audio/just_audio.dart'; | ||
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; | ||
|
||
/// {@template StreamVoiceRecordingListPlayer} | ||
/// Display many audios and displays a list of AudioPlayerMessage. | ||
/// {@endtemplate} | ||
class StreamVoiceRecordingListPlayer extends StatefulWidget { | ||
/// {@macro StreamVoiceRecordingListPlayer} | ||
const StreamVoiceRecordingListPlayer({ | ||
super.key, | ||
required this.playList, | ||
this.attachmentBorderRadiusGeometry, | ||
this.constraints, | ||
}); | ||
|
||
/// List of audio attachments. | ||
final List<PlayListItem> playList; | ||
|
||
/// The border radius of each audio. | ||
final BorderRadiusGeometry? attachmentBorderRadiusGeometry; | ||
|
||
/// Constraints of audio attachments | ||
final BoxConstraints? constraints; | ||
|
||
@override | ||
State<StreamVoiceRecordingListPlayer> createState() => | ||
_StreamVoiceRecordingListPlayerState(); | ||
} | ||
|
||
class _StreamVoiceRecordingListPlayerState | ||
extends State<StreamVoiceRecordingListPlayer> { | ||
final _player = AudioPlayer(); | ||
late StreamSubscription<PlayerState> _playerStateChangedSubscription; | ||
|
||
Widget _createAudioPlayer(int index, PlayListItem item) { | ||
final url = item.assetUrl; | ||
Widget child; | ||
|
||
if (url == null) { | ||
child = const StreamVoiceRecordingLoading(); | ||
} else { | ||
child = StreamVoiceRecordingPlayer( | ||
player: _player, | ||
duration: item.duration, | ||
waveBars: item.waveForm, | ||
index: index, | ||
); | ||
} | ||
|
||
final theme = | ||
StreamChatTheme.of(context).voiceRecordingTheme.listPlayerTheme; | ||
|
||
return Container( | ||
margin: theme.margin, | ||
constraints: widget.constraints, | ||
decoration: BoxDecoration( | ||
color: theme.backgroundColor, | ||
border: Border.all( | ||
color: theme.borderColor!, | ||
), | ||
borderRadius: | ||
widget.attachmentBorderRadiusGeometry ?? theme.borderRadius, | ||
), | ||
child: child, | ||
); | ||
} | ||
|
||
void _playerStateListener(PlayerState state) async { | ||
if (state.processingState == ProcessingState.completed) { | ||
await _player.stop(); | ||
await _player.seek(Duration.zero, index: 0); | ||
} | ||
} | ||
|
||
@override | ||
void initState() { | ||
super.initState(); | ||
|
||
_playerStateChangedSubscription = | ||
_player.playerStateStream.listen(_playerStateListener); | ||
} | ||
|
||
@override | ||
void dispose() { | ||
super.dispose(); | ||
|
||
_playerStateChangedSubscription.cancel(); | ||
_player.dispose(); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final playList = widget.playList | ||
.where((attachment) => attachment.assetUrl != null) | ||
.map((attachment) => AudioSource.uri(Uri.parse(attachment.assetUrl!))) | ||
.toList(); | ||
|
||
final audioSource = ConcatenatingAudioSource(children: playList); | ||
|
||
_player | ||
..setShuffleModeEnabled(false) | ||
..setLoopMode(LoopMode.off) | ||
..setAudioSource(audioSource, preload: false); | ||
|
||
return Column( | ||
children: widget.playList.mapIndexed(_createAudioPlayer).toList(), | ||
); | ||
} | ||
} | ||
|
||
/// {@template PlayListItem} | ||
/// Represents an audio attachment meta data. | ||
/// {@endtemplate} | ||
class PlayListItem { | ||
/// {@macro PlayListItem} | ||
const PlayListItem({ | ||
this.assetUrl, | ||
required this.duration, | ||
required this.waveForm, | ||
}); | ||
|
||
/// The url of the audio. | ||
final String? assetUrl; | ||
|
||
/// The duration of the audio. | ||
final Duration duration; | ||
|
||
/// The wave form of the audio. | ||
final List<double> waveForm; | ||
} |
29 changes: 29 additions & 0 deletions
29
...attachment/builder/voice_recording_attachment_builder/stream_voice_recording_loading.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:stream_chat_flutter/stream_chat_flutter.dart'; | ||
|
||
/// {@template StreamVoiceRecordingLoading} | ||
/// Loading widget for audio message. Use this when the url from the audio | ||
/// message is still not available. One use situation in when the audio is | ||
/// still being uploaded. | ||
/// {@endtemplate} | ||
class StreamVoiceRecordingLoading extends StatelessWidget { | ||
/// {@macro StreamVoiceRecordingLoading} | ||
const StreamVoiceRecordingLoading({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
final theme = StreamChatTheme.of(context).voiceRecordingTheme.loadingTheme; | ||
|
||
return Padding( | ||
padding: theme.padding!, | ||
child: SizedBox( | ||
height: theme.size!.height, | ||
width: theme.size!.width, | ||
child: CircularProgressIndicator( | ||
strokeWidth: theme.strokeWidth!, | ||
color: theme.color, | ||
), | ||
), | ||
); | ||
} | ||
} |
Oops, something went wrong.