From a4adc7f03ee0e7d88bf453e58a55183d957de7ea Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Thu, 12 May 2022 13:04:32 +0530 Subject: [PATCH 01/67] flutter 3.0 breaking error --- .../live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt | 4 ++-- lib/src/hmssdk.dart | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt b/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt index 86d90b532..7172b9197 100644 --- a/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt +++ b/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt @@ -67,7 +67,7 @@ class HMSVideoViewFactory(private val plugin: HmssdkFlutterPlugin) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { - override fun create(context: Context, viewId: Int, args: Any?): PlatformView { + override fun create(context: Context?, viewId: Int, args: Any?): PlatformView { val creationParams = args as Map? @@ -86,6 +86,6 @@ class HMSVideoViewFactory(private val plugin: HmssdkFlutterPlugin) : Log.i("debugVideo", "HMSVideoViewFactory create peerName: $peerName") - return HMSVideoViewWidget(context, viewId, creationParams, track!!, setMirror!!, scaleType, matchParent, peerName!!) + return HMSVideoViewWidget(requireNotNull(context), viewId, creationParams, track!!, setMirror!!, scaleType, matchParent, peerName!!) } } \ No newline at end of file diff --git a/lib/src/hmssdk.dart b/lib/src/hmssdk.dart index 6676ed6be..133ffa723 100644 --- a/lib/src/hmssdk.dart +++ b/lib/src/hmssdk.dart @@ -55,7 +55,7 @@ class HMSSDK with WidgetsBindingObserver { isTerminal: false, params: {...config.getJson()}); } - WidgetsBinding.instance!.addObserver(this); + WidgetsBinding.instance.addObserver(this); return await PlatformService.invokeMethod(PlatformMethod.join, arguments: {...config.getJson()}); } @@ -92,7 +92,7 @@ class HMSSDK with WidgetsBindingObserver { hmsException: HMSException.fromMap(result["error"])); } } - WidgetsBinding.instance!.removeObserver(this); + WidgetsBinding.instance.removeObserver(this); } /// To switch local peer's audio on/off. From 940107b95bf8d4d92a812631504ba796d02eca26 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Fri, 20 May 2022 19:16:00 +0530 Subject: [PATCH 02/67] updated Changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecb23776c..16116a026 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.7.1 - 2022-05-20 + +- Added RTC Stats Listener which provides info about local & remote peer's audio/video quality +- Improved video rendering performance for Android devices +- Correct RTMP Streaming & Recording configuration settings +- Added support for Server-side Subscribe Degradation +- Updated to Native Android SDK 2.3.9 & Native iOS SDK 0.2.13 + ## 0.7.0 - 2022-04-19 ### Added From 1f89a3e7fc8ec85332c7f5b1d206cfb1ec52fe0e Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Fri, 20 May 2022 19:16:09 +0530 Subject: [PATCH 03/67] updated pubignore --- .pubignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.pubignore b/.pubignore index 12fff15a9..facedd980 100644 --- a/.pubignore +++ b/.pubignore @@ -19,3 +19,4 @@ example/android/app/google-services.json example/ios/Runner/GoogleService-Info.plist *.p8 release-apps.sh +example/lib/firebase_options.dart From e1c5e1f26aab85ccac053c57b0b2f5c5c27eb3cf Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Fri, 20 May 2022 19:21:01 +0530 Subject: [PATCH 04/67] updated pub version --- example/ios/Podfile.lock | 4 ++-- example/pubspec.lock | 2 +- ios/hmssdk_flutter.podspec | 2 +- pubspec.yaml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 4e021f4ef..1abe1a4f8 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -130,7 +130,7 @@ PODS: - GoogleUtilities/Logger - HMSSDK (0.2.13): - HMSWebRTC (= 1.0.4518) - - hmssdk_flutter (0.7.1): + - hmssdk_flutter (0.7.2): - Flutter - HMSSDK (= 0.2.13) - HMSWebRTC (1.0.4518) @@ -226,7 +226,7 @@ SPEC CHECKSUMS: GoogleDataTransport: 5fffe35792f8b96ec8d6775f5eccd83c998d5a3b GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1 HMSSDK: 45b5e25be25b74bb2ca71cce4c6128f57b7eccc4 - hmssdk_flutter: a65db31490c1152b6aaf4ec2708d56e41a6f7167 + hmssdk_flutter: 2e904fc421cc726447966dd16d14107114c5a4ba HMSWebRTC: 599fb1d886daecd6e58984f84224d708bce8b565 nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e diff --git a/example/pubspec.lock b/example/pubspec.lock index 6a1ac44f7..c33179029 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -246,7 +246,7 @@ packages: path: ".." relative: true source: path - version: "0.7.1" + version: "0.7.2" html: dependency: transitive description: diff --git a/ios/hmssdk_flutter.podspec b/ios/hmssdk_flutter.podspec index 96ea9686e..4a4c04e04 100644 --- a/ios/hmssdk_flutter.podspec +++ b/ios/hmssdk_flutter.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'hmssdk_flutter' - s.version = '0.7.1' + s.version = '0.7.2' s.summary = 'The Flutter plugin for 100ms SDK' s.description = <<-DESC A Flutter Project for 100ms SDK. diff --git a/pubspec.yaml b/pubspec.yaml index d184fe2b5..4d5af23f1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: hmssdk_flutter description: The Flutter package for 100ms SDK. Video Conferencing infrastructure for a Video first world. -version: 0.7.1 +version: 0.7.2 homepage: https://www.100ms.live/ repository: https://github.com/100mslive/100ms-flutter issue_tracker: https://github.com/100mslive/100ms-flutter/issues From 9055c361f139663aabd67eabada97b498567852b Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Mon, 23 May 2022 12:44:17 +0530 Subject: [PATCH 05/67] active speaker mode default --- example/lib/meeting/meeting_store.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index ed72771e8..5fe9cd3c8 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -68,7 +68,7 @@ class MeetingStore extends ChangeNotifier HMSPeer? localPeer; - bool isActiveSpeakerMode = false; + bool isActiveSpeakerMode = true; List audioTracks = []; From 7d4fb64fb4ce15014973465ef5b97475e3dbbf6c Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Mon, 23 May 2022 13:07:29 +0530 Subject: [PATCH 06/67] Removed RTC Stats listeners from update Listeners --- lib/src/model/hms_update_listener.dart | 23 ----------------------- lib/src/service/platform_service.dart | 11 +++++------ 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/lib/src/model/hms_update_listener.dart b/lib/src/model/hms_update_listener.dart index 55c66e326..54629c2dc 100644 --- a/lib/src/model/hms_update_listener.dart +++ b/lib/src/model/hms_update_listener.dart @@ -94,27 +94,4 @@ abstract class HMSUpdateListener { void onRemovedFromRoom( {required HMSPeerRemovedFromPeer hmsPeerRemovedFromPeer}); - void onLocalAudioStats( - {required HMSLocalAudioStats hmsLocalAudioStats, - required HMSLocalAudioTrack track, - required HMSPeer peer}); - - void onLocalVideoStats( - {required HMSLocalVideoStats hmsLocalVideoStats, - required HMSLocalVideoTrack track, - required HMSPeer peer}); - - void onRemoteAudioStats( - {required HMSRemoteAudioStats hmsRemoteAudioStats, - required HMSRemoteAudioTrack track, - required HMSPeer peer}); - - void onRemoteVideoStats( - {required HMSRemoteVideoStats hmsRemoteVideoStats, - required HMSRemoteVideoTrack track, - required HMSPeer peer}); - - void onRTCStats({ - required HMSRTCStatsReport hmsrtcStatsReport, - }); } diff --git a/lib/src/service/platform_service.dart b/lib/src/service/platform_service.dart index bf94e8896..e3b803bb6 100644 --- a/lib/src/service/platform_service.dart +++ b/lib/src/service/platform_service.dart @@ -428,35 +428,34 @@ class PlatformService { HMSStatsListenerMethod method, Map arguments) { switch (method) { case HMSStatsListenerMethod.onLocalAudioStats: - updateListeners.forEach((e) => e.onLocalAudioStats( + statsListeners.forEach((e) => e.onLocalAudioStats( hmsLocalAudioStats: arguments['local_audio_stats'], track: arguments["track"], peer: arguments["peer"])); break; case HMSStatsListenerMethod.onLocalVideoStats: - updateListeners.forEach((e) => e.onLocalVideoStats( + statsListeners.forEach((e) => e.onLocalVideoStats( hmsLocalVideoStats: arguments['local_video_stats'], track: arguments["track"], peer: arguments["peer"])); break; case HMSStatsListenerMethod.onRemoteAudioStats: - updateListeners.forEach((e) => e.onRemoteAudioStats( + statsListeners.forEach((e) => e.onRemoteAudioStats( hmsRemoteAudioStats: arguments['remote_audio_stats'], track: arguments["track"], peer: arguments["peer"])); break; case HMSStatsListenerMethod.onRemoteVideoStats: - updateListeners.forEach((e) => e.onRemoteVideoStats( + statsListeners.forEach((e) => e.onRemoteVideoStats( hmsRemoteVideoStats: arguments['remote_video_stats'], track: arguments["track"], peer: arguments["peer"])); break; case HMSStatsListenerMethod.onRtcStats: - updateListeners.forEach((e) => + statsListeners.forEach((e) => e.onRTCStats(hmsrtcStatsReport: arguments['rtc_stats_report'])); break; case HMSStatsListenerMethod.unknown: - // TODO: Handle this case. break; } } From 13697a5f17e1edbf924269b4dce02815f82fb1c3 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Mon, 23 May 2022 14:10:59 +0530 Subject: [PATCH 07/67] HMSRoom added session id in android --- .../kotlin/live/hms/hmssdk_flutter/HMSRoomExtension.kt | 1 + lib/src/model/hms_room.dart | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/android/src/main/kotlin/live/hms/hmssdk_flutter/HMSRoomExtension.kt b/android/src/main/kotlin/live/hms/hmssdk_flutter/HMSRoomExtension.kt index 970235df9..c31e7fb50 100644 --- a/android/src/main/kotlin/live/hms/hmssdk_flutter/HMSRoomExtension.kt +++ b/android/src/main/kotlin/live/hms/hmssdk_flutter/HMSRoomExtension.kt @@ -26,6 +26,7 @@ class HMSRoomExtension { hashMap["hls_streaming_state"] = HMSStreamingState.toDictionary(room.hlsStreamingState) hashMap["peer_count"] = room.peerCount hashMap["started_at"] = room.startedAt?:-1 + hashMap["session_id"] = room.sessionId return hashMap } diff --git a/lib/src/model/hms_room.dart b/lib/src/model/hms_room.dart index 6950cfd64..69476e83f 100644 --- a/lib/src/model/hms_room.dart +++ b/lib/src/model/hms_room.dart @@ -26,6 +26,7 @@ class HMSRoom { HMSHLSStreamingState? hmshlsStreamingState; int peerCount; int startedAt; + String sessionId; ///[peers] list which are in the room. final List? peers; @@ -40,7 +41,8 @@ class HMSRoom { this.hmsBrowserRecordingState, this.hmshlsStreamingState, this.peerCount = 0, - this.startedAt = 0}); + this.startedAt = 0, + required this.sessionId}); factory HMSRoom.fromMap(Map map) { List peers = []; @@ -73,11 +75,12 @@ class HMSRoom { peers: peers, metaData: map['meta_data'], peerCount: map["peer_count"] != null ? map["peer_count"] : 0, - startedAt: map["started_at"] != null ? map["started_at"] : 0); + startedAt: map["started_at"] != null ? map["started_at"] : 0, + sessionId: map.containsKey("session_id") ? map["session_id"] : ""); } @override String toString() { - return 'HMSRoom{id: $id, name: $name, metaData: $metaData, hmsBrowserRecordingState: $hmsBrowserRecordingState, hmsRtmpStreamingState: $hmsRtmpStreamingState, hmsServerRecordingState: $hmsServerRecordingState, peers: $peers}'; + return 'HMSRoom{id: $id, name: $name, metaData: $metaData, hmsBrowserRecordingState: $hmsBrowserRecordingState, hmsRtmpStreamingState: $hmsRtmpStreamingState, hmsServerRecordingState: $hmsServerRecordingState, peers: $peers, sessiosId: $sessionId}'; } } From c9d01d2a98d45144b60f54915b4eb78c66a6a78d Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 24 May 2022 12:42:32 +0530 Subject: [PATCH 08/67] remove peerName field from HMSVideoView --- .../lib/common/ui/organisms/video_view.dart | 2 -- example/lib/preview/preview_page.dart | 1 - lib/src/ui/meeting/hms_video_view.dart | 30 +++++++------------ 3 files changed, 11 insertions(+), 22 deletions(-) diff --git a/example/lib/common/ui/organisms/video_view.dart b/example/lib/common/ui/organisms/video_view.dart index d899c3321..f6e4c9d19 100644 --- a/example/lib/common/ui/organisms/video_view.dart +++ b/example/lib/common/ui/organisms/video_view.dart @@ -57,7 +57,6 @@ class _VideoViewState extends State { child: HMSVideoView( scaleType: widget.scaleType, track: data.item1!, - peerName: context.read().peer.name, setMirror: false, matchParent: false), ), @@ -72,7 +71,6 @@ class _VideoViewState extends State { child: HMSVideoView( scaleType: ScaleType.SCALE_ASPECT_FILL, track: data.item1!, - peerName: context.read().peer.name, setMirror: data.item1.runtimeType == HMSLocalVideoTrack ? context.read().isMirror : false, diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index bf3eaa0b5..88abf0b49 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -95,7 +95,6 @@ class _PreviewPageState extends State with WidgetsBindingObserver { ? HMSVideoView( scaleType: ScaleType.SCALE_ASPECT_FILL, track: _previewStore.localTracks[0], - peerName: _previewStore.peer!.name, setMirror: widget.mirror, matchParent: false, ) diff --git a/lib/src/ui/meeting/hms_video_view.dart b/lib/src/ui/meeting/hms_video_view.dart index a02ae7a29..59c2fa7b5 100644 --- a/lib/src/ui/meeting/hms_video_view.dart +++ b/lib/src/ui/meeting/hms_video_view.dart @@ -25,15 +25,12 @@ class HMSVideoView extends StatelessWidget { final ScaleType scaleType; final bool setMirror; - final String peerName; - HMSVideoView( {Key? key, required this.track, this.setMirror = false, this.matchParent = true, - this.scaleType = ScaleType.SCALE_ASPECT_FIT, - required this.peerName}) + this.scaleType = ScaleType.SCALE_ASPECT_FIT}) : super(key: key); @override @@ -42,8 +39,7 @@ class HMSVideoView extends StatelessWidget { track: track, matchParent: this.matchParent, setMirror: setMirror, - scaleType: this.scaleType, - peerName: this.peerName); + scaleType: this.scaleType); } } @@ -53,16 +49,14 @@ class _PlatformView extends StatelessWidget { final bool setMirror; final bool matchParent; final ScaleType scaleType; - final String peerName; - _PlatformView({ - Key? key, - required this.track, - this.setMirror = false, - this.matchParent = true, - required this.scaleType, - required this.peerName, - }) : super(key: key); + _PlatformView( + {Key? key, + required this.track, + this.setMirror = false, + this.matchParent = true, + required this.scaleType}) + : super(key: key); void onPlatformViewCreated(int id) {} @@ -78,8 +72,7 @@ class _PlatformView extends StatelessWidget { 'track_id': track.trackId, 'set_mirror': track.source != "REGULAR" ? false : setMirror, 'scale_type': scaleType.value, - 'match_parent': matchParent, - 'peerName': peerName + 'match_parent': matchParent }, gestureRecognizers: {}, ); @@ -93,8 +86,7 @@ class _PlatformView extends StatelessWidget { 'track_id': track.trackId, 'set_mirror': track.source != "REGULAR" ? false : setMirror, 'scale_type': scaleType.value, - 'match_parent': matchParent, - 'peerName': peerName + 'match_parent': matchParent }, gestureRecognizers: {}, ); From 53d8a1ed74195f44a4b79e2b63b4d8cf0ad2de6a Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Tue, 24 May 2022 18:23:05 +0530 Subject: [PATCH 09/67] Added Concentric circles UI --- .../ui/organisms/audio_level_avatar.dart | 57 +++++++++++++++++++ .../lib/common/ui/organisms/audio_tile.dart | 11 +--- .../lib/common/ui/organisms/tile_border.dart | 6 +- .../lib/common/ui/organisms/video_tile.dart | 4 ++ .../lib/common/ui/organisms/video_view.dart | 18 ++---- example/lib/common/util/custom_painter.dart | 47 +++++++++++++++ example/lib/meeting/meeting_store.dart | 10 ++-- example/pubspec.yaml | 3 +- 8 files changed, 127 insertions(+), 29 deletions(-) create mode 100644 example/lib/common/ui/organisms/audio_level_avatar.dart create mode 100644 example/lib/common/util/custom_painter.dart diff --git a/example/lib/common/ui/organisms/audio_level_avatar.dart b/example/lib/common/ui/organisms/audio_level_avatar.dart new file mode 100644 index 000000000..d49906d8f --- /dev/null +++ b/example/lib/common/ui/organisms/audio_level_avatar.dart @@ -0,0 +1,57 @@ +import 'package:avatar_glow/avatar_glow.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; +import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; +import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; +import 'package:provider/provider.dart'; + +class AudioLevelAvatar extends StatefulWidget { + const AudioLevelAvatar({Key? key}) : super(key: key); + + @override + State createState() => _AudioLevelAvatarState(); +} + +class _AudioLevelAvatarState extends State { + @override + Widget build(BuildContext context) { + return Center( + child: Selector( + selector: (_, meetingStore) => + meetingStore.isActiveSpeaker(context.read().uid), + builder: (_, isSpeaking, __) { + return isSpeaking == -1 + ? CircleAvatar( + backgroundColor: Utilities.getBackgroundColour( + context.read().peer.name), + radius: 36, + child: + Text( + Utilities.getAvatarTitle( + context.read().peer.name), + style: TextStyle(fontSize: 36, color: Colors.white), + )) + : AvatarGlow( + repeat: true, + showTwoGlows: true, + duration: Duration(seconds: 1), + endRadius: + (isSpeaking != -1) ? 36 + (isSpeaking).toDouble() : 36, + glowColor: Utilities.getBackgroundColour( + context.read().peer.name), + child: CircleAvatar( + backgroundColor: Utilities.getBackgroundColour( + context.read().peer.name), + radius: 36, + child: + Text( + Utilities.getAvatarTitle( + context.read().peer.name), + style: TextStyle(fontSize: 36, color: Colors.white), + )), + ); + }), + ); + } +} diff --git a/example/lib/common/ui/organisms/audio_tile.dart b/example/lib/common/ui/organisms/audio_tile.dart index c7c502d98..ed02dfe44 100644 --- a/example/lib/common/ui/organisms/audio_tile.dart +++ b/example/lib/common/ui/organisms/audio_tile.dart @@ -1,5 +1,6 @@ // Package imports import 'package:flutter/material.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/audio_level_avatar.dart'; import 'package:provider/provider.dart'; // Project imports @@ -84,15 +85,7 @@ class AudioTile extends StatelessWidget { child: Stack( children: [ Center( - child: CircleAvatar( - backgroundColor: Utilities.getBackgroundColour( - context.read().peer.name), - radius: 36, - child: Text( - Utilities.getAvatarTitle( - context.read().peer.name), - style: TextStyle(fontSize: 36, color: Colors.white), - ))), + child: AudioLevelAvatar(key:Key(context.read().uid + "audio_level"),)), PeerName(), HandRaise(), //bottom left BRBTag(), //top right diff --git a/example/lib/common/ui/organisms/tile_border.dart b/example/lib/common/ui/organisms/tile_border.dart index 23d8bc98e..24d5b1adc 100644 --- a/example/lib/common/ui/organisms/tile_border.dart +++ b/example/lib/common/ui/organisms/tile_border.dart @@ -20,7 +20,7 @@ class TileBorder extends StatelessWidget { @override Widget build(BuildContext context) { - return Selector( + return Selector( selector: (_, meetingStore) => meetingStore.isActiveSpeaker(uid), builder: (_, isHighestSpeaker, __) { return Container( @@ -28,10 +28,10 @@ class TileBorder extends StatelessWidget { width: itemWidth - 4, decoration: BoxDecoration( border: Border.all( - color: isHighestSpeaker + color: (isHighestSpeaker != -1) ? Utilities.getBackgroundColour(name) : Colors.grey, - width: isHighestSpeaker ? 4.0 : 1.0), + width: (isHighestSpeaker != -1) ? 4.0 : 1.0), borderRadius: BorderRadius.all(Radius.circular(10)), ), ); diff --git a/example/lib/common/ui/organisms/video_tile.dart b/example/lib/common/ui/organisms/video_tile.dart index 6722e2969..1b2633d60 100644 --- a/example/lib/common/ui/organisms/video_tile.dart +++ b/example/lib/common/ui/organisms/video_tile.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:focus_detector/focus_detector.dart'; import 'package:hmssdk_flutter/hmssdk_flutter.dart'; +import 'package:hmssdk_flutter_example/common/util/custom_painter.dart'; import 'package:provider/provider.dart'; // Project imports @@ -114,10 +115,12 @@ class _VideoTileState extends State { child: Stack( children: [ VideoView( + uid :context.read().uid, scaleType: widget.scaleType, itemHeight: widget.itemHeight, itemWidth: widget.itemWidth, ), + DegradeTile( itemHeight: widget.itemHeight, itemWidth: widget.itemWidth, @@ -148,6 +151,7 @@ class _VideoTileState extends State { child: Stack( children: [ VideoView( + uid: context.read().uid, scaleType: widget.scaleType, itemHeight: widget.itemHeight, itemWidth: widget.itemWidth, diff --git a/example/lib/common/ui/organisms/video_view.dart b/example/lib/common/ui/organisms/video_view.dart index f6e4c9d19..058c1ddee 100644 --- a/example/lib/common/ui/organisms/video_view.dart +++ b/example/lib/common/ui/organisms/video_view.dart @@ -1,5 +1,8 @@ //Package imports +import 'package:avatar_glow/avatar_glow.dart'; import 'package:flutter/material.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/audio_level_avatar.dart'; +import 'package:hmssdk_flutter_example/common/util/custom_painter.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -17,7 +20,7 @@ class VideoView extends StatefulWidget { final double itemHeight; final ScaleType scaleType; final double itemWidth; - + final String uid; VideoView( {Key? key, this.viewSize, @@ -25,6 +28,7 @@ class VideoView extends StatefulWidget { this.matchParent = true, this.itemHeight = 200, this.itemWidth = 200, + required this.uid, this.scaleType = ScaleType.SCALE_ASPECT_FILL}) : super(key: key); @@ -38,17 +42,7 @@ class _VideoViewState extends State { return Selector>( builder: (_, data, __) { if ((data.item1 == null) || data.item2 || data.item3) { - return Container( - child: Center( - child: CircleAvatar( - backgroundColor: Utilities.getBackgroundColour( - context.read().peer.name), - radius: 36, - child: Text( - Utilities.getAvatarTitle( - context.read().peer.name), - style: TextStyle(fontSize: 36, color: Colors.white), - )))); + return AudioLevelAvatar(key:Key(context.read().uid + "audio_level")); } else { return (data.item1?.source != "REGULAR") ? ClipRRect( diff --git a/example/lib/common/util/custom_painter.dart b/example/lib/common/util/custom_painter.dart new file mode 100644 index 000000000..050993ee7 --- /dev/null +++ b/example/lib/common/util/custom_painter.dart @@ -0,0 +1,47 @@ +//Dart imports +import 'dart:math' as math; + +//Package imports +import 'package:flutter/material.dart'; + +class CircleWavePainter extends CustomPainter { + final double waveRadius; + late Paint wavePaint, paint1; + final bool isAudioOff; + CircleWavePainter(this.waveRadius,this.isAudioOff) { + wavePaint = Paint() + ..color = Colors.blue.shade700 + ..style = PaintingStyle.stroke + ..strokeWidth = 2.0 + ..isAntiAlias = true; + + paint1 = Paint() + ..color = Colors.blue.shade700 + ..style = PaintingStyle.fill; + } + @override + void paint(Canvas canvas, Size size) { + double centerX = size.width; + double centerY = size.height; + double maxRadius = hypot(centerX, centerY); + + var currentRadius = waveRadius; + canvas.drawCircle(Offset(centerX, centerY), 50, paint1); + + if(!isAudioOff){ + while (currentRadius < maxRadius) { + canvas.drawCircle(Offset(centerX, centerY), currentRadius, wavePaint); + currentRadius += 10.0; + } + } + } + + @override + bool shouldRepaint(CircleWavePainter oldDelegate) { + return oldDelegate.waveRadius != waveRadius; + } + + double hypot(double x, double y) { + return math.sqrt(x * x + y * y); + } +} diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 5fe9cd3c8..151886511 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -76,7 +76,7 @@ class MeetingStore extends ChangeNotifier List peerTracks = []; - Map activeSpeakerIds = {}; + Map activeSpeakerIds = {}; HMSRoom? hmsRoom; @@ -118,6 +118,7 @@ class MeetingStore extends ChangeNotifier isScreenShareOn = false; _hmsSDKInteractor.stopScreenShare(); } + _hmsSDKInteractor.removeStatsListener(this); _hmsSDKInteractor.leave(hmsActionResultListener: this); } @@ -391,7 +392,7 @@ class MeetingStore extends ChangeNotifier } activeSpeakerIds.clear(); updateSpeakers.forEach((element) { - activeSpeakerIds[element.peer.peerId + "mainVideo"] = true; + activeSpeakerIds[element.peer.peerId + "mainVideo"] = element.audioLevel; }); int firstScreenPeersCount = isAudioViewOn ? 6 : 4; if ((isActiveSpeakerMode && peerTracks.length > firstScreenPeersCount) || @@ -884,8 +885,8 @@ class MeetingStore extends ChangeNotifier @override void onRTCStats({required HMSRTCStatsReport hmsrtcStatsReport}) {} - bool isActiveSpeaker(String uid) { - return activeSpeakerIds.containsKey(uid); + int isActiveSpeaker(String uid) { + return activeSpeakerIds.containsKey(uid) ? activeSpeakerIds[uid]! : -1; } @override @@ -897,6 +898,7 @@ class MeetingStore extends ChangeNotifier case HMSActionResultListenerMethod.leave: peerTracks.clear(); isRoomEnded = true; + screenShareCount = 0; notifyListeners(); break; case HMSActionResultListenerMethod.changeTrackState: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index d92b2893e..50a62e6ca 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -36,7 +36,8 @@ dependencies: flutter_staggered_grid_view: ^0.6.1 tuple: firebase_performance: ^0.8.0+11 - + avatar_glow: ^2.0.2 + dev_dependencies: flutter_test: sdk: flutter From 8273793729efc430f0bfa26c00981d0e689326bd Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Tue, 24 May 2022 21:42:02 +0530 Subject: [PATCH 10/67] Removed Custom Painter --- example/lib/common/util/custom_painter.dart | 47 --------------------- 1 file changed, 47 deletions(-) delete mode 100644 example/lib/common/util/custom_painter.dart diff --git a/example/lib/common/util/custom_painter.dart b/example/lib/common/util/custom_painter.dart deleted file mode 100644 index 050993ee7..000000000 --- a/example/lib/common/util/custom_painter.dart +++ /dev/null @@ -1,47 +0,0 @@ -//Dart imports -import 'dart:math' as math; - -//Package imports -import 'package:flutter/material.dart'; - -class CircleWavePainter extends CustomPainter { - final double waveRadius; - late Paint wavePaint, paint1; - final bool isAudioOff; - CircleWavePainter(this.waveRadius,this.isAudioOff) { - wavePaint = Paint() - ..color = Colors.blue.shade700 - ..style = PaintingStyle.stroke - ..strokeWidth = 2.0 - ..isAntiAlias = true; - - paint1 = Paint() - ..color = Colors.blue.shade700 - ..style = PaintingStyle.fill; - } - @override - void paint(Canvas canvas, Size size) { - double centerX = size.width; - double centerY = size.height; - double maxRadius = hypot(centerX, centerY); - - var currentRadius = waveRadius; - canvas.drawCircle(Offset(centerX, centerY), 50, paint1); - - if(!isAudioOff){ - while (currentRadius < maxRadius) { - canvas.drawCircle(Offset(centerX, centerY), currentRadius, wavePaint); - currentRadius += 10.0; - } - } - } - - @override - bool shouldRepaint(CircleWavePainter oldDelegate) { - return oldDelegate.waveRadius != waveRadius; - } - - double hypot(double x, double y) { - return math.sqrt(x * x + y * y); - } -} From 048d9e73b81638fb6bde971ee3294bf24be97e6a Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Wed, 25 May 2022 11:11:41 +0530 Subject: [PATCH 11/67] Removed imports --- example/lib/common/ui/organisms/video_tile.dart | 1 - example/lib/common/ui/organisms/video_view.dart | 1 - 2 files changed, 2 deletions(-) diff --git a/example/lib/common/ui/organisms/video_tile.dart b/example/lib/common/ui/organisms/video_tile.dart index 1b2633d60..4528673d2 100644 --- a/example/lib/common/ui/organisms/video_tile.dart +++ b/example/lib/common/ui/organisms/video_tile.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:focus_detector/focus_detector.dart'; import 'package:hmssdk_flutter/hmssdk_flutter.dart'; -import 'package:hmssdk_flutter_example/common/util/custom_painter.dart'; import 'package:provider/provider.dart'; // Project imports diff --git a/example/lib/common/ui/organisms/video_view.dart b/example/lib/common/ui/organisms/video_view.dart index 058c1ddee..c4a751649 100644 --- a/example/lib/common/ui/organisms/video_view.dart +++ b/example/lib/common/ui/organisms/video_view.dart @@ -2,7 +2,6 @@ import 'package:avatar_glow/avatar_glow.dart'; import 'package:flutter/material.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/audio_level_avatar.dart'; -import 'package:hmssdk_flutter_example/common/util/custom_painter.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; From d5912df281ce0b731a4255a7a8ff14fcc30d6b51 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 25 May 2022 11:29:50 +0530 Subject: [PATCH 12/67] single tile mode --- .../common/ui/organisms/full_screen_view.dart | 70 +++++++++++++++ .../lib/common/util/utility_components.dart | 3 +- example/lib/enum/meeting_mode.dart | 2 + example/lib/meeting/meeting_page.dart | 82 ++++++++++++------ example/lib/meeting/meeting_store.dart | 86 ++++++++++++++++--- 5 files changed, 206 insertions(+), 37 deletions(-) create mode 100644 example/lib/common/ui/organisms/full_screen_view.dart create mode 100644 example/lib/enum/meeting_mode.dart diff --git a/example/lib/common/ui/organisms/full_screen_view.dart b/example/lib/common/ui/organisms/full_screen_view.dart new file mode 100644 index 000000000..01fe1ee06 --- /dev/null +++ b/example/lib/common/ui/organisms/full_screen_view.dart @@ -0,0 +1,70 @@ +//Package imports +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; + +//Project imports +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; +import 'package:hmssdk_flutter/hmssdk_flutter.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/video_tile.dart'; +import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; +import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; + +Widget fullScreenView( + {required List peerTracks, + required int itemCount, + required int screenShareCount, + required BuildContext context, + required Size size}) { + return GridView.builder( + shrinkWrap: true, + cacheExtent: size.width, + itemCount: itemCount, + scrollDirection: Axis.horizontal, + physics: PageScrollPhysics(), + itemBuilder: (context, index) { + if (peerTracks[index].track?.source != "REGULAR") { + return ChangeNotifierProvider.value( + key: ValueKey(peerTracks[index].uid), + value: peerTracks[index], + child: peerTracks[index].peer.isLocal + ? Container( + margin: EdgeInsets.all(2), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1.0), + borderRadius: BorderRadius.all(Radius.circular(10))), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.screen_share), + Text("You are sharing your screen"), + ], + ), + ) + : VideoTile( + key: Key(peerTracks[index].uid), + scaleType: ScaleType.SCALE_ASPECT_FIT, + itemHeight: size.height, + itemWidth: size.width, + ), + ); + } + + if (screenShareCount == 0 && + index < 4 && + peerTracks[index].isOffscreen) { + peerTracks[index].setOffScreenStatus(false); + } + return ChangeNotifierProvider.value( + key: ValueKey(peerTracks[index].uid), + value: peerTracks[index], + child: VideoTile( + key: ValueKey(peerTracks[index].uid), + itemHeight: size.height, + itemWidth: size.width, + )); + }, + controller: Provider.of(context).controller, + gridDelegate: SliverStairedGridDelegate( + startCrossAxisDirectionReversed: false, + pattern: [StairedGridTile(1, (size.height * 0.81) / (size.width))])); +} diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index 58bd57067..da39ebd87 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:provider/provider.dart'; import 'package:clickable_list_wheel_view/clickable_list_wheel_widget.dart'; @@ -84,7 +85,7 @@ class UtilityComponents { )); if (answer == "OK") { if (meetingStore.isAudioViewOn) { - meetingStore.setAudioViewStatus(); + meetingStore.setMode(MeetingMode.Audio); } meetingStore.changeTracks(event); } else { diff --git a/example/lib/enum/meeting_mode.dart b/example/lib/enum/meeting_mode.dart new file mode 100644 index 000000000..f0ad1554e --- /dev/null +++ b/example/lib/enum/meeting_mode.dart @@ -0,0 +1,2 @@ +//enum to set the meeting flow +enum MeetingMode { Single, Hero, Video, Audio } diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 98ad2f455..25652326e 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -5,10 +5,12 @@ import 'dart:io'; import 'package:connectivity_checker/connectivity_checker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/full_screen_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/grid_audio_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/grid_hero_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/grid_video_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/title_bar.dart'; +import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:hmssdk_flutter_example/hls_viewer/hls_viewer.dart'; import 'package:provider/provider.dart'; @@ -141,27 +143,29 @@ class _MeetingPageState extends State ); break; case 5: - _meetingStore.setAudioViewStatus(); if (_meetingStore.isAudioViewOn) { - _meetingStore.setPlayBackAllowed(false); + _meetingStore.setMode(MeetingMode.Audio); } else { - _meetingStore.setPlayBackAllowed(true); + _meetingStore.setMode(MeetingMode.Video); } break; case 6: _meetingStore.setActiveSpeakerMode(); break; case 7: - _meetingStore.setHeroMode(); + _meetingStore.setMode(MeetingMode.Hero); break; case 8: + _meetingStore.setMode(MeetingMode.Single); + break; + case 9: String name = await UtilityComponents.showInputDialog( context: context, placeholder: "Enter Name"); if (name.isNotEmpty) { _meetingStore.changeName(name: name); } break; - case 9: + case 10: if (_meetingStore.hasHlsStarted) { _meetingStore.stopHLSStreaming(); } else { @@ -175,28 +179,28 @@ class _MeetingPageState extends State } break; - case 10: + case 11: List roles = await _meetingStore.getRoles(); List selectedRoles = await UtilityComponents.showRoleList(context, roles); if (selectedRoles.isNotEmpty) _meetingStore.changeTrackStateForRole(true, selectedRoles); break; - case 11: + case 12: _meetingStore.changeTrackStateForRole(true, null); break; - case 12: + case 13: _meetingStore.changeMetadataBRB(); // raisedHand = false; isBRB = !isBRB; break; - case 13: + case 14: _meetingStore.changeStatsVisible(); break; - case 14: + case 15: _meetingStore.toggleScreenShare(); break; - case 15: + case 16: _meetingStore.endRoom(false, "Room Ended From Flutter"); if (_meetingStore.isRoomEnded) { Navigator.pop(context); @@ -276,15 +280,14 @@ class _MeetingPageState extends State height: MediaQuery.of(context).size.height * 0.81, child: Selector< MeetingStore, - Tuple7, bool, int, int, - bool, bool, PeerTrackNode?>>( - selector: (_, meetingStore) => Tuple7( + Tuple6, bool, int, int, + MeetingMode, PeerTrackNode?>>( + selector: (_, meetingStore) => Tuple6( meetingStore.peerTracks, meetingStore.isHLSLink, meetingStore.peerTracks.length, meetingStore.screenShareCount, - meetingStore.isAudioViewOn, - meetingStore.isHeroMode, + meetingStore.meetingMode, meetingStore.peerTracks.length > 0 ? meetingStore.peerTracks[ meetingStore.screenShareCount] @@ -339,7 +342,7 @@ class _MeetingPageState extends State 'Waiting for others to join!')); } Size size = MediaQuery.of(context).size; - if (data.item6) { + if (data.item5 == MeetingMode.Hero) { return gridHeroView( peerTracks: data.item1, itemCount: data.item3, @@ -347,7 +350,7 @@ class _MeetingPageState extends State context: context, size: size); } - if (data.item5) { + if (data.item5 == MeetingMode.Audio) { return gridAudioView( peerTracks: data.item1.sublist(data.item4), @@ -356,6 +359,14 @@ class _MeetingPageState extends State .length, size: size); } + if (data.item5 == MeetingMode.Single) { + return fullScreenView( + peerTracks: data.item1, + itemCount: data.item3, + screenShareCount: data.item4, + context: context, + size: size); + } return gridVideoView( peerTracks: data.item1, itemCount: data.item3, @@ -712,6 +723,25 @@ class _MeetingPageState extends State ]), value: 7, ), + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Single Tile Mode", + style: TextStyle( + color: meetingStore.isSingleTileMode + ? Colors.red + : Colors.white, + )), + Icon( + CupertinoIcons.person, + color: meetingStore.isSingleTileMode + ? Colors.red + : Colors.white, + ), + ]), + value: 8, + ), PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -721,7 +751,7 @@ class _MeetingPageState extends State ), Icon(Icons.create_rounded), ]), - value: 8, + value: 9, ), if (!(meetingStore.localPeer?.role.name.contains("hls-") ?? true)) PopupMenuItem( @@ -741,7 +771,7 @@ class _MeetingPageState extends State ? Colors.red : Colors.white), ]), - value: 9, + value: 10, ), if (meetingStore.localPeer?.role.permissions.changeRole ?? false) PopupMenuItem( @@ -753,7 +783,7 @@ class _MeetingPageState extends State ), Icon(Icons.mic_off_sharp), ]), - value: 10, + value: 11, ), if (meetingStore.localPeer?.role.permissions.changeRole ?? false) PopupMenuItem( @@ -765,7 +795,7 @@ class _MeetingPageState extends State ), Icon(Icons.mic_off), ]), - value: 11, + value: 12, ), PopupMenuItem( child: Row( @@ -791,7 +821,7 @@ class _MeetingPageState extends State ), ), ]), - value: 12, + value: 13, ), PopupMenuItem( child: Row( @@ -809,7 +839,7 @@ class _MeetingPageState extends State ? Colors.red : Colors.white), ]), - value: 13, + value: 14, ), if ((meetingStore.localPeer != null) && meetingStore.localPeer!.role.publishSettings!.allowed @@ -833,7 +863,7 @@ class _MeetingPageState extends State : Colors.white, ), ]), - value: 14, + value: 15, ), if (meetingStore.localPeer!.role.permissions.endRoom!) PopupMenuItem( @@ -845,7 +875,7 @@ class _MeetingPageState extends State ), Icon(Icons.cancel_schedule_send), ]), - value: 15, + value: 16, ), ]; }, diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 5fe9cd3c8..14cc7d0cf 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -1,6 +1,7 @@ //Package imports import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/cupertino.dart'; +import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:hmssdk_flutter_example/model/rtc_stats.dart'; import 'package:intl/intl.dart'; @@ -98,6 +99,10 @@ class MeetingStore extends ChangeNotifier ScrollController controller = ScrollController(); + bool isSingleTileMode = false; + + MeetingMode meetingMode = MeetingMode.Video; + Future join(String user, String roomUrl) async { List? token = await RoomService().getToken(user: user, room: roomUrl); @@ -356,6 +361,9 @@ class MeetingStore extends ChangeNotifier PeerTrackNode peerTrackNode = peerTracks[index]; peerTrackNode.track = track as HMSVideoTrack; peerTrackNode.notify(); + if (isSingleTileMode) { + rearrangeTile(peerTrackNode, index); + } } else { return; } @@ -769,9 +777,56 @@ class MeetingStore extends ChangeNotifier true, HMSTrackKind.kHMSTrackKindAudio, "regular", roles, this); } - void setAudioViewStatus() { - this.isAudioViewOn = !this.isAudioViewOn; - this.isHeroMode = false; + void setMode(MeetingMode meetingMode) { + this.meetingMode = meetingMode; + switch (meetingMode) { + case MeetingMode.Video: + this.isAudioViewOn = false; + this.isSingleTileMode = false; + this.isHeroMode = false; + setPlayBackAllowed(true); + break; + case MeetingMode.Audio: + this.isAudioViewOn = true; + this.isSingleTileMode = false; + this.isHeroMode = false; + setPlayBackAllowed(false); + break; + case MeetingMode.Hero: + this.isHeroMode = !this.isHeroMode; + this.isActiveSpeakerMode = false; + if (isAudioViewOn) { + this.isAudioViewOn = false; + setPlayBackAllowed(true); + } + if (!isHeroMode) { + this.meetingMode = MeetingMode.Video; + } + break; + case MeetingMode.Single: + if (!this.isSingleTileMode) { + int type0 = 0; + int type1 = peerTracks.length - 1; + while (type0 < type1) { + if (peerTracks[type0].track!.isMute) { + if (peerTracks[type1].track!.isMute == false) { + PeerTrackNode peerTrackNode = peerTracks[type0]; + peerTracks[type0] = peerTracks[type1]; + peerTracks[type1] = peerTrackNode; + } + type1--; + } else + type0++; + } + this.isActiveSpeakerMode = false; + this.isAudioViewOn = false; + this.isHeroMode = false; + } else + this.meetingMode = MeetingMode.Video; + this.isSingleTileMode = !this.isSingleTileMode; + break; + default: + } notifyListeners(); } @@ -781,14 +836,25 @@ class MeetingStore extends ChangeNotifier notifyListeners(); } - void setHeroMode() { - this.isHeroMode = !this.isHeroMode; - this.isActiveSpeakerMode = false; - if (isAudioViewOn) { - this.isAudioViewOn = false; - setPlayBackAllowed(true); + rearrangeTile(PeerTrackNode peerTrackNode, int index) { + if (peerTrackNode.track!.isMute) { + if (peerTracks.length - 1 > index && + peerTracks[index + 1].track!.isMute) { + return; + } else { + peerTracks.removeAt(index); + peerTracks.add(peerTrackNode); + notifyListeners(); + } + } else { + if (index != 0 && peerTracks[index - 1].track!.isMute == false) { + return; + } else { + peerTracks.removeAt(index); + peerTracks.insert(screenShareCount, peerTrackNode); + notifyListeners(); + } } - notifyListeners(); } void setNewMessageFalse() { From 0a1a25c23fb030563b69574e9e4d2b09b291ec28 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Wed, 25 May 2022 12:41:01 +0530 Subject: [PATCH 13/67] Removed Keys --- example/lib/common/ui/organisms/audio_tile.dart | 2 +- example/lib/common/ui/organisms/video_view.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/lib/common/ui/organisms/audio_tile.dart b/example/lib/common/ui/organisms/audio_tile.dart index ed02dfe44..2c7f20309 100644 --- a/example/lib/common/ui/organisms/audio_tile.dart +++ b/example/lib/common/ui/organisms/audio_tile.dart @@ -85,7 +85,7 @@ class AudioTile extends StatelessWidget { child: Stack( children: [ Center( - child: AudioLevelAvatar(key:Key(context.read().uid + "audio_level"),)), + child: AudioLevelAvatar()), PeerName(), HandRaise(), //bottom left BRBTag(), //top right diff --git a/example/lib/common/ui/organisms/video_view.dart b/example/lib/common/ui/organisms/video_view.dart index c4a751649..f9a9266dc 100644 --- a/example/lib/common/ui/organisms/video_view.dart +++ b/example/lib/common/ui/organisms/video_view.dart @@ -41,7 +41,7 @@ class _VideoViewState extends State { return Selector>( builder: (_, data, __) { if ((data.item1 == null) || data.item2 || data.item3) { - return AudioLevelAvatar(key:Key(context.read().uid + "audio_level")); + return AudioLevelAvatar(); } else { return (data.item1?.source != "REGULAR") ? ClipRRect( From 3966432e8da6454368f82097c079c9a18215d15c Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 25 May 2022 14:22:42 +0530 Subject: [PATCH 14/67] remove extra variable --- .../lib/common/util/utility_components.dart | 4 +- example/lib/meeting/meeting_page.dart | 23 +++++++----- example/lib/meeting/meeting_store.dart | 37 +++++++------------ 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index da39ebd87..878603b8e 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -81,10 +81,10 @@ class UtilityComponents { context: context, builder: (ctx) => TrackChangeDialogOrganism( trackChangeRequest: event, - isAudioModeOn: meetingStore.isAudioViewOn, + isAudioModeOn: meetingStore.meetingMode == MeetingMode.Audio, )); if (answer == "OK") { - if (meetingStore.isAudioViewOn) { + if (meetingStore.meetingMode == MeetingMode.Audio) { meetingStore.setMode(MeetingMode.Audio); } meetingStore.changeTracks(event); diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 25652326e..7ab4afc6c 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -143,7 +143,7 @@ class _MeetingPageState extends State ); break; case 5: - if (_meetingStore.isAudioViewOn) { + if (_meetingStore.meetingMode == MeetingMode.Video) { _meetingStore.setMode(MeetingMode.Audio); } else { _meetingStore.setMode(MeetingMode.Video); @@ -430,7 +430,7 @@ class _MeetingPageState extends State meetingStore.localPeer?.role.publishSettings?.allowed .contains("video") ?? false, - meetingStore.isAudioViewOn), + meetingStore.meetingMode == MeetingMode.Audio), builder: (_, data, __) { return ((data.item1 != null) && data.item1!.role.publishSettings!.allowed.contains("video")) @@ -675,10 +675,12 @@ class _MeetingPageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - meetingStore.isAudioViewOn ? "Video View" : "Audio View", + meetingStore.meetingMode == MeetingMode.Audio + ? "Video View" + : "Audio View", ), Image.asset( - meetingStore.isAudioViewOn + meetingStore.meetingMode == MeetingMode.Audio ? 'assets/icons/video.png' : 'assets/icons/audio.png', color: Colors.white, @@ -713,12 +715,15 @@ class _MeetingPageState extends State children: [ Text("Hero Mode", style: TextStyle( - color: - meetingStore.isHeroMode ? Colors.red : Colors.white, + color: meetingStore.meetingMode == MeetingMode.Hero + ? Colors.red + : Colors.white, )), Icon( CupertinoIcons.person_3_fill, - color: meetingStore.isHeroMode ? Colors.red : Colors.white, + color: meetingStore.meetingMode == MeetingMode.Hero + ? Colors.red + : Colors.white, ), ]), value: 7, @@ -729,13 +734,13 @@ class _MeetingPageState extends State children: [ Text("Single Tile Mode", style: TextStyle( - color: meetingStore.isSingleTileMode + color: meetingStore.meetingMode == MeetingMode.Single ? Colors.red : Colors.white, )), Icon( CupertinoIcons.person, - color: meetingStore.isSingleTileMode + color: meetingStore.meetingMode == MeetingMode.Single ? Colors.red : Colors.white, ), diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 14cc7d0cf..2cad24723 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -85,8 +85,6 @@ class MeetingStore extends ChangeNotifier bool isStatsVisible = false; - bool isHeroMode = false; - bool isNewMessageReceived = false; String? highestSpeaker; @@ -95,12 +93,9 @@ class MeetingStore extends ChangeNotifier final DateFormat formatter = DateFormat('d MMM y h:mm:ss a'); bool isMirror = false; - bool isAudioViewOn = false; ScrollController controller = ScrollController(); - bool isSingleTileMode = false; - MeetingMode meetingMode = MeetingMode.Video; Future join(String user, String roomUrl) async { @@ -361,7 +356,7 @@ class MeetingStore extends ChangeNotifier PeerTrackNode peerTrackNode = peerTracks[index]; peerTrackNode.track = track as HMSVideoTrack; peerTrackNode.notify(); - if (isSingleTileMode) { + if (meetingMode == MeetingMode.Single) { rearrangeTile(peerTrackNode, index); } } else { @@ -401,9 +396,9 @@ class MeetingStore extends ChangeNotifier updateSpeakers.forEach((element) { activeSpeakerIds[element.peer.peerId + "mainVideo"] = true; }); - int firstScreenPeersCount = isAudioViewOn ? 6 : 4; + int firstScreenPeersCount = (meetingMode == MeetingMode.Audio) ? 6 : 4; if ((isActiveSpeakerMode && peerTracks.length > firstScreenPeersCount) || - isHeroMode) { + meetingMode == MeetingMode.Hero) { List activeSpeaker = []; if (updateSpeakers.length > firstScreenPeersCount) { activeSpeaker.addAll(updateSpeakers.sublist(0, firstScreenPeersCount)); @@ -778,33 +773,29 @@ class MeetingStore extends ChangeNotifier } void setMode(MeetingMode meetingMode) { - this.meetingMode = meetingMode; switch (meetingMode) { case MeetingMode.Video: - this.isAudioViewOn = false; - this.isSingleTileMode = false; - this.isHeroMode = false; setPlayBackAllowed(true); + this.meetingMode = meetingMode; + break; case MeetingMode.Audio: - this.isAudioViewOn = true; - this.isSingleTileMode = false; - this.isHeroMode = false; setPlayBackAllowed(false); + this.meetingMode = meetingMode; + break; case MeetingMode.Hero: - this.isHeroMode = !this.isHeroMode; this.isActiveSpeakerMode = false; - if (isAudioViewOn) { - this.isAudioViewOn = false; + if (this.meetingMode == MeetingMode.Audio) { setPlayBackAllowed(true); + this.meetingMode = meetingMode; } - if (!isHeroMode) { + if (this.meetingMode == MeetingMode.Hero) { this.meetingMode = MeetingMode.Video; } break; case MeetingMode.Single: - if (!this.isSingleTileMode) { + if (this.meetingMode != MeetingMode.Single) { int type0 = 0; int type1 = peerTracks.length - 1; while (type0 < type1) { @@ -819,11 +810,9 @@ class MeetingStore extends ChangeNotifier type0++; } this.isActiveSpeakerMode = false; - this.isAudioViewOn = false; - this.isHeroMode = false; + this.meetingMode = MeetingMode.Single; } else this.meetingMode = MeetingMode.Video; - this.isSingleTileMode = !this.isSingleTileMode; break; default: } @@ -832,7 +821,7 @@ class MeetingStore extends ChangeNotifier void setActiveSpeakerMode() { this.isActiveSpeakerMode = !this.isActiveSpeakerMode; - this.isHeroMode = false; + this.meetingMode = MeetingMode.Video; notifyListeners(); } From fa2fe42539ad03c9f4a59517122f9a3fd0a55300 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Wed, 25 May 2022 14:48:34 +0530 Subject: [PATCH 15/67] Fixed mode switching --- example/lib/meeting/meeting_page.dart | 17 +++++++++--- example/lib/meeting/meeting_store.dart | 37 +++++++++----------------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 7ab4afc6c..f6cff1117 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -143,9 +143,10 @@ class _MeetingPageState extends State ); break; case 5: - if (_meetingStore.meetingMode == MeetingMode.Video) { + if (_meetingStore.meetingMode != MeetingMode.Audio) { _meetingStore.setMode(MeetingMode.Audio); } else { + _meetingStore.setPlayBackAllowed(true); _meetingStore.setMode(MeetingMode.Video); } break; @@ -153,10 +154,20 @@ class _MeetingPageState extends State _meetingStore.setActiveSpeakerMode(); break; case 7: - _meetingStore.setMode(MeetingMode.Hero); + if (_meetingStore.meetingMode != MeetingMode.Hero) { + _meetingStore.setMode(MeetingMode.Hero); + } + else{ + _meetingStore.setMode(MeetingMode.Video); + } break; case 8: - _meetingStore.setMode(MeetingMode.Single); + if (_meetingStore.meetingMode != MeetingMode.Single) { + _meetingStore.setMode(MeetingMode.Single); + } + else{ + _meetingStore.setMode(MeetingMode.Video); + } break; case 9: String name = await UtilityComponents.showInputDialog( diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 13e3637b4..012729c1c 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -601,17 +601,13 @@ class MeetingStore extends ChangeNotifier peer: peer, uid: peer.peerId + track.trackId, track: track as HMSVideoTrack)); - isScreenShareActive(); - - for (var node in peerTracks) { - if (node.isOffscreen == false) { - node.setOffScreenStatus(true); - } - } - - controller.jumpTo(0); - + // for (var node in peerTracks) { + // if (node.isOffscreen == false) { + // node.setOffScreenStatus(true); + // } + // } + // controller.jumpTo(0); notifyListeners(); } break; @@ -776,28 +772,21 @@ class MeetingStore extends ChangeNotifier void setMode(MeetingMode meetingMode) { switch (meetingMode) { case MeetingMode.Video: - setPlayBackAllowed(true); - this.meetingMode = meetingMode; - break; case MeetingMode.Audio: setPlayBackAllowed(false); - this.meetingMode = meetingMode; - break; case MeetingMode.Hero: - this.isActiveSpeakerMode = false; if (this.meetingMode == MeetingMode.Audio) { setPlayBackAllowed(true); - this.meetingMode = meetingMode; - } - if (this.meetingMode == MeetingMode.Hero) { - this.meetingMode = MeetingMode.Video; } + this.isActiveSpeakerMode = false; break; case MeetingMode.Single: - if (this.meetingMode != MeetingMode.Single) { - int type0 = 0; + if (this.meetingMode == MeetingMode.Audio) { + setPlayBackAllowed(true); + } + int type0 = 0; int type1 = peerTracks.length - 1; while (type0 < type1) { if (peerTracks[type0].track!.isMute) { @@ -811,12 +800,10 @@ class MeetingStore extends ChangeNotifier type0++; } this.isActiveSpeakerMode = false; - this.meetingMode = MeetingMode.Single; - } else - this.meetingMode = MeetingMode.Video; break; default: } + this.meetingMode = meetingMode; notifyListeners(); } From b01917a5b6f5e9c714bbe49353d485b3bebb6d76 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 25 May 2022 16:59:24 +0530 Subject: [PATCH 16/67] fix errors --- .../ui/organisms/audio_level_avatar.dart | 7 +- .../lib/common/ui/organisms/audio_tile.dart | 5 +- .../common/ui/organisms/grid_audio_view.dart | 4 +- .../common/ui/organisms/grid_video_view.dart | 8 +- .../lib/common/ui/organisms/video_view.dart | 2 - example/lib/meeting/meeting_page.dart | 379 +++++++++--------- example/lib/meeting/meeting_store.dart | 26 +- 7 files changed, 212 insertions(+), 219 deletions(-) diff --git a/example/lib/common/ui/organisms/audio_level_avatar.dart b/example/lib/common/ui/organisms/audio_level_avatar.dart index d49906d8f..b8b7665b3 100644 --- a/example/lib/common/ui/organisms/audio_level_avatar.dart +++ b/example/lib/common/ui/organisms/audio_level_avatar.dart @@ -1,5 +1,4 @@ import 'package:avatar_glow/avatar_glow.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; @@ -26,8 +25,7 @@ class _AudioLevelAvatarState extends State { backgroundColor: Utilities.getBackgroundColour( context.read().peer.name), radius: 36, - child: - Text( + child: Text( Utilities.getAvatarTitle( context.read().peer.name), style: TextStyle(fontSize: 36, color: Colors.white), @@ -44,8 +42,7 @@ class _AudioLevelAvatarState extends State { backgroundColor: Utilities.getBackgroundColour( context.read().peer.name), radius: 36, - child: - Text( + child: Text( Utilities.getAvatarTitle( context.read().peer.name), style: TextStyle(fontSize: 36, color: Colors.white), diff --git a/example/lib/common/ui/organisms/audio_tile.dart b/example/lib/common/ui/organisms/audio_tile.dart index 2c7f20309..f008bfdb1 100644 --- a/example/lib/common/ui/organisms/audio_tile.dart +++ b/example/lib/common/ui/organisms/audio_tile.dart @@ -12,7 +12,6 @@ import 'package:hmssdk_flutter_example/common/ui/organisms/network_icon_widget.d import 'package:hmssdk_flutter_example/common/ui/organisms/peer_name.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/tile_border.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/rtc_stats_view.dart'; -import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/change_track_options.dart'; @@ -23,7 +22,6 @@ class AudioTile extends StatelessWidget { AudioTile({this.itemHeight = 200.0, this.itemWidth = 200.0, Key? key}) : super(key: key); - final GlobalKey key = GlobalKey(); @override Widget build(BuildContext context) { MeetingStore _meetingStore = context.read(); @@ -84,8 +82,7 @@ class AudioTile extends StatelessWidget { width: itemWidth - 5.0, child: Stack( children: [ - Center( - child: AudioLevelAvatar()), + Center(child: AudioLevelAvatar()), PeerName(), HandRaise(), //bottom left BRBTag(), //top right diff --git a/example/lib/common/ui/organisms/grid_audio_view.dart b/example/lib/common/ui/organisms/grid_audio_view.dart index 657ad9b1f..287d48748 100644 --- a/example/lib/common/ui/organisms/grid_audio_view.dart +++ b/example/lib/common/ui/organisms/grid_audio_view.dart @@ -16,10 +16,10 @@ Widget gridAudioView( itemCount: itemCount, itemBuilder: (context, index) { return ChangeNotifierProvider.value( - key: ValueKey(peerTracks[index].uid), + key: ValueKey(peerTracks[index].uid + "audio_view"), value: peerTracks[index], child: AudioTile( - key: ValueKey(peerTracks[index].uid), + key: ValueKey(peerTracks[index].uid + "audio_tile"), itemHeight: size.height, itemWidth: size.width, )); diff --git a/example/lib/common/ui/organisms/grid_video_view.dart b/example/lib/common/ui/organisms/grid_video_view.dart index 39186bb3c..51211c388 100644 --- a/example/lib/common/ui/organisms/grid_video_view.dart +++ b/example/lib/common/ui/organisms/grid_video_view.dart @@ -24,7 +24,7 @@ Widget gridVideoView( itemBuilder: (context, index) { if (peerTracks[index].track?.source != "REGULAR") { return ChangeNotifierProvider.value( - key: ValueKey(peerTracks[index].uid), + key: ValueKey(peerTracks[index].uid + "video_view"), value: peerTracks[index], child: peerTracks[index].peer.isLocal ? Container( @@ -41,7 +41,7 @@ Widget gridVideoView( ), ) : VideoTile( - key: Key(peerTracks[index].uid), + key: Key(peerTracks[index].uid + "video_tile"), scaleType: ScaleType.SCALE_ASPECT_FIT, itemHeight: size.height, itemWidth: size.width, @@ -55,10 +55,10 @@ Widget gridVideoView( peerTracks[index].setOffScreenStatus(false); } return ChangeNotifierProvider.value( - key: ValueKey(peerTracks[index].uid), + key: ValueKey(peerTracks[index].uid + "video_view"), value: peerTracks[index], child: VideoTile( - key: ValueKey(peerTracks[index].uid), + key: ValueKey(peerTracks[index].uid + "audio_view"), itemHeight: size.height, itemWidth: size.width, )); diff --git a/example/lib/common/ui/organisms/video_view.dart b/example/lib/common/ui/organisms/video_view.dart index f9a9266dc..edb0e8b7f 100644 --- a/example/lib/common/ui/organisms/video_view.dart +++ b/example/lib/common/ui/organisms/video_view.dart @@ -1,5 +1,4 @@ //Package imports -import 'package:avatar_glow/avatar_glow.dart'; import 'package:flutter/material.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/audio_level_avatar.dart'; import 'package:provider/provider.dart'; @@ -7,7 +6,6 @@ import 'package:tuple/tuple.dart'; //Project imports import 'package:hmssdk_flutter/hmssdk_flutter.dart'; -import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index f6cff1117..dfdfab8d3 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -156,16 +156,14 @@ class _MeetingPageState extends State case 7: if (_meetingStore.meetingMode != MeetingMode.Hero) { _meetingStore.setMode(MeetingMode.Hero); - } - else{ + } else { _meetingStore.setMode(MeetingMode.Video); } break; case 8: if (_meetingStore.meetingMode != MeetingMode.Single) { _meetingStore.setMode(MeetingMode.Single); - } - else{ + } else { _meetingStore.setMode(MeetingMode.Video); } break; @@ -227,202 +225,205 @@ class _MeetingPageState extends State Widget build(BuildContext context) { return ConnectivityAppWrapper( app: WillPopScope( - child: ConnectivityWidgetWrapper( - disableInteraction: true, - offlineWidget: OfflineWidget(), - child: Selector>( - selector: (_, meetingStore) => - Tuple2(meetingStore.reconnecting, meetingStore.isRoomEnded), - builder: (_, data, __) { - if (data.item2) { - WidgetsBinding.instance?.addPostFrameCallback((_) { - UtilityComponents.showSnackBarWithString( - context.read().description, context); - Navigator.of(context).popUntil((route) => route.isFirst); - }); - } - return data.item1 - ? OfflineWidget() - : Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - title: TitleBar(), - actions: [ - Selector( - selector: (_, meetingStore) => - meetingStore.isRecordingStarted, - builder: (_, isRecordingStarted, __) { - return isRecordingStarted - ? Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - width: 2, - color: Colors.red.shade600)), - child: Icon( - Icons.circle, - color: Colors.red, - size: 15, - ), - ) - : Container(); - }, - ), - IconButton( - iconSize: 24, - onPressed: () { - context.read().toggleSpeaker(); + child: SafeArea( + child: ConnectivityWidgetWrapper( + disableInteraction: true, + offlineWidget: OfflineWidget(), + child: Selector>( + selector: (_, meetingStore) => + Tuple2(meetingStore.reconnecting, meetingStore.isRoomEnded), + builder: (_, data, __) { + if (data.item2) { + WidgetsBinding.instance?.addPostFrameCallback((_) { + UtilityComponents.showSnackBarWithString( + context.read().description, context); + Navigator.of(context).popUntil((route) => route.isFirst); + }); + } + return data.item1 + ? OfflineWidget() + : Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title: TitleBar(), + actions: [ + Selector( + selector: (_, meetingStore) => + meetingStore.isRecordingStarted, + builder: (_, isRecordingStarted, __) { + return isRecordingStarted + ? Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + width: 2, + color: Colors.red.shade600)), + child: Icon( + Icons.circle, + color: Colors.red, + size: 15, + ), + ) + : Container(); }, - icon: Selector( - selector: (_, meetingStore) => - meetingStore.isSpeakerOn, - builder: (_, isSpeakerOn, __) { - return Icon(isSpeakerOn - ? Icons.volume_up - : Icons.volume_off); + ), + IconButton( + iconSize: 24, + onPressed: () { + context.read().toggleSpeaker(); }, - )), - dropDownMenu(), - ], - ), - body: Stack( - children: [ - Container( - height: MediaQuery.of(context).size.height * 0.81, - child: Selector< - MeetingStore, - Tuple6, bool, int, int, - MeetingMode, PeerTrackNode?>>( - selector: (_, meetingStore) => Tuple6( - meetingStore.peerTracks, - meetingStore.isHLSLink, - meetingStore.peerTracks.length, - meetingStore.screenShareCount, - meetingStore.meetingMode, - meetingStore.peerTracks.length > 0 - ? meetingStore.peerTracks[ - meetingStore.screenShareCount] - : null), - builder: (_, data, __) { - if (data.item2) { - return Selector( - selector: (_, meetingStore) => - meetingStore.hasHlsStarted, - builder: (_, hasHlsStarted, __) { - return hasHlsStarted - ? Center( - child: Container( - child: HLSViewer( - streamUrl: context - .read< - MeetingStore>() - .streamUrl), - ), - ) - : Center( - child: Column( - mainAxisAlignment: - MainAxisAlignment - .center, - crossAxisAlignment: - CrossAxisAlignment - .center, - children: [ - Padding( - padding: - const EdgeInsets - .only( - bottom: 8.0), - child: Text( - "Waiting for HLS to start...", - style: TextStyle( - fontSize: 20), + icon: Selector( + selector: (_, meetingStore) => + meetingStore.isSpeakerOn, + builder: (_, isSpeakerOn, __) { + return Icon(isSpeakerOn + ? Icons.volume_up + : Icons.volume_off); + }, + )), + dropDownMenu(), + ], + ), + body: Stack( + children: [ + Container( + height: MediaQuery.of(context).size.height * 0.81, + child: Selector< + MeetingStore, + Tuple6, bool, int, + int, MeetingMode, PeerTrackNode?>>( + selector: (_, meetingStore) => Tuple6( + meetingStore.peerTracks, + meetingStore.isHLSLink, + meetingStore.peerTracks.length, + meetingStore.screenShareCount, + meetingStore.meetingMode, + meetingStore.peerTracks.length > 0 + ? meetingStore.peerTracks[ + meetingStore.screenShareCount] + : null), + builder: (_, data, __) { + if (data.item2) { + return Selector( + selector: (_, meetingStore) => + meetingStore.hasHlsStarted, + builder: (_, hasHlsStarted, __) { + return hasHlsStarted + ? Center( + child: Container( + child: HLSViewer( + streamUrl: context + .read< + MeetingStore>() + .streamUrl), + ), + ) + : Center( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, + children: [ + Padding( + padding: + const EdgeInsets + .only( + bottom: 8.0), + child: Text( + "Waiting for HLS to start...", + style: TextStyle( + fontSize: 20), + ), ), - ), - CircularProgressIndicator( - strokeWidth: 1, - ) - ], - ), - ); - }); - } - if (data.item3 == 0) { - return Center( - child: Text( - 'Waiting for others to join!')); - } - Size size = MediaQuery.of(context).size; - if (data.item5 == MeetingMode.Hero) { - return gridHeroView( + CircularProgressIndicator( + strokeWidth: 1, + ) + ], + ), + ); + }); + } + if (data.item3 == 0) { + return Center( + child: Text( + 'Waiting for others to join!')); + } + Size size = MediaQuery.of(context).size; + if (data.item5 == MeetingMode.Hero) { + return gridHeroView( + peerTracks: data.item1, + itemCount: data.item3, + screenShareCount: data.item4, + context: context, + size: size); + } + if (data.item5 == MeetingMode.Audio) { + return gridAudioView( + peerTracks: + data.item1.sublist(data.item4), + itemCount: data.item1 + .sublist(data.item4) + .length, + size: size); + } + if (data.item5 == MeetingMode.Single) { + return fullScreenView( + peerTracks: data.item1, + itemCount: data.item3, + screenShareCount: data.item4, + context: context, + size: size); + } + return gridVideoView( peerTracks: data.item1, itemCount: data.item3, screenShareCount: data.item4, context: context, size: size); + }), + ), + Selector( + selector: (_, meetingStore) => + meetingStore.roleChangeRequest, + builder: (_, roleChangeRequest, __) { + if (roleChangeRequest != null) { + WidgetsBinding.instance! + .addPostFrameCallback((_) { + UtilityComponents.showRoleChangeDialog( + roleChangeRequest, context); + }); } - if (data.item5 == MeetingMode.Audio) { - return gridAudioView( - peerTracks: - data.item1.sublist(data.item4), - itemCount: data.item1 - .sublist(data.item4) - .length, - size: size); - } - if (data.item5 == MeetingMode.Single) { - return fullScreenView( - peerTracks: data.item1, - itemCount: data.item3, - screenShareCount: data.item4, - context: context, - size: size); + return Container(); + }), + Selector( + selector: (_, meetingStore) => + meetingStore.hmsTrackChangeRequest, + builder: (_, hmsTrackChangeRequest, __) { + if (hmsTrackChangeRequest != null) { + WidgetsBinding.instance! + .addPostFrameCallback((_) { + UtilityComponents.showTrackChangeDialog( + hmsTrackChangeRequest, context); + }); } - return gridVideoView( - peerTracks: data.item1, - itemCount: data.item3, - screenShareCount: data.item4, - context: context, - size: size); + return Container(); }), - ), - Selector( - selector: (_, meetingStore) => - meetingStore.roleChangeRequest, - builder: (_, roleChangeRequest, __) { - if (roleChangeRequest != null) { - WidgetsBinding.instance! - .addPostFrameCallback((_) { - UtilityComponents.showRoleChangeDialog( - roleChangeRequest, context); - }); - } - return Container(); - }), - Selector( - selector: (_, meetingStore) => - meetingStore.hmsTrackChangeRequest, - builder: (_, hmsTrackChangeRequest, __) { - if (hmsTrackChangeRequest != null) { - WidgetsBinding.instance! - .addPostFrameCallback((_) { - UtilityComponents.showTrackChangeDialog( - hmsTrackChangeRequest, context); - }); - } - return Container(); - }), - ], - ), - bottomNavigationBar: Selector( - selector: (_, meetingStore) => meetingStore.isHLSLink, - builder: (_, isHlsRunning, __) { - return isHlsRunning - ? hlsBottomBarWidget() - : normalBottomBarWidget(); - })); - }, - )), + ], + ), + bottomNavigationBar: Selector( + selector: (_, meetingStore) => + meetingStore.isHLSLink, + builder: (_, isHlsRunning, __) { + return isHlsRunning + ? hlsBottomBarWidget() + : normalBottomBarWidget(); + })); + }, + )), + ), onWillPop: () async { bool ans = await UtilityComponents.onBackPressed(context) ?? false; return ans; diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 012729c1c..92d851d05 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -787,19 +787,19 @@ class MeetingStore extends ChangeNotifier setPlayBackAllowed(true); } int type0 = 0; - int type1 = peerTracks.length - 1; - while (type0 < type1) { - if (peerTracks[type0].track!.isMute) { - if (peerTracks[type1].track!.isMute == false) { - PeerTrackNode peerTrackNode = peerTracks[type0]; - peerTracks[type0] = peerTracks[type1]; - peerTracks[type1] = peerTrackNode; - } - type1--; - } else - type0++; - } - this.isActiveSpeakerMode = false; + int type1 = peerTracks.length - 1; + while (type0 < type1) { + if (peerTracks[type0].track!.isMute) { + if (peerTracks[type1].track!.isMute == false) { + PeerTrackNode peerTrackNode = peerTracks[type0]; + peerTracks[type0] = peerTracks[type1]; + peerTracks[type1] = peerTrackNode; + } + type1--; + } else + type0++; + } + this.isActiveSpeakerMode = false; break; default: } From 0439f9674c601e546ec9d63825487b349bd4455b Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 25 May 2022 23:59:47 +0530 Subject: [PATCH 17/67] unable to start single tile mode if track is null fixed --- example/lib/meeting/meeting_store.dart | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 92d851d05..4b3526953 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -789,8 +789,11 @@ class MeetingStore extends ChangeNotifier int type0 = 0; int type1 = peerTracks.length - 1; while (type0 < type1) { - if (peerTracks[type0].track!.isMute) { - if (peerTracks[type1].track!.isMute == false) { + if (peerTracks[type0].track == null || + (peerTracks[type0].track != null && + peerTracks[type0].track!.isMute)) { + if (peerTracks[type1].track != null && + peerTracks[type1].track!.isMute == false) { PeerTrackNode peerTrackNode = peerTracks[type0]; peerTracks[type0] = peerTracks[type1]; peerTracks[type1] = peerTrackNode; From a179b7b0f986e0b96cb139f01010bf36053ed840 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Thu, 26 May 2022 12:00:09 +0530 Subject: [PATCH 18/67] fix --- example/lib/meeting/meeting_store.dart | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 4b3526953..5648a0d01 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -789,9 +789,7 @@ class MeetingStore extends ChangeNotifier int type0 = 0; int type1 = peerTracks.length - 1; while (type0 < type1) { - if (peerTracks[type0].track == null || - (peerTracks[type0].track != null && - peerTracks[type0].track!.isMute)) { + if (peerTracks[type0].track?.isMute??true) { if (peerTracks[type1].track != null && peerTracks[type1].track!.isMute == false) { PeerTrackNode peerTrackNode = peerTracks[type0]; From 776f6e17cffb61f16be5c540d781951142d947c3 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Thu, 26 May 2022 12:22:24 +0530 Subject: [PATCH 19/67] Degrade tile fix --- example/lib/common/ui/organisms/degrade_tile.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/lib/common/ui/organisms/degrade_tile.dart b/example/lib/common/ui/organisms/degrade_tile.dart index 9f1952601..13b41573a 100644 --- a/example/lib/common/ui/organisms/degrade_tile.dart +++ b/example/lib/common/ui/organisms/degrade_tile.dart @@ -31,7 +31,7 @@ class _DegradeTileState extends State { height: widget.itemHeight + 110, width: widget.itemWidth - 4, decoration: BoxDecoration( - color: Colors.grey[800], + color: Colors.black87, borderRadius: BorderRadius.all(Radius.circular(10))), child: Center( child: CircleAvatar( From 38facdb19b409a326e51218eb55373526741b4dd Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Thu, 26 May 2022 17:17:42 +0530 Subject: [PATCH 20/67] Fixed Participant page ui --- example/lib/common/ui/organisms/participant_organism.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/lib/common/ui/organisms/participant_organism.dart b/example/lib/common/ui/organisms/participant_organism.dart index 6ee017d2d..fc7f4cbc5 100644 --- a/example/lib/common/ui/organisms/participant_organism.dart +++ b/example/lib/common/ui/organisms/participant_organism.dart @@ -89,7 +89,7 @@ class _ParticipantOrganismState extends State { child: Padding( padding: const EdgeInsets.fromLTRB(10, 0, 10, 0), child: Container( - width: width / 4, + width: width / 6, padding: const EdgeInsets.all(5.0), decoration: BoxDecoration( color: Colors.blue, From 8f45808469009648936144b6aef79ec2f3df132f Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Fri, 27 May 2022 01:50:52 +0530 Subject: [PATCH 21/67] Added toast for error and success events --- example/lib/meeting/meeting_store.dart | 47 ++++++++++++++++++++------ example/pubspec.yaml | 1 + 2 files changed, 37 insertions(+), 11 deletions(-) diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 5648a0d01..4c61b1883 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -1,6 +1,8 @@ //Package imports import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:hmssdk_flutter_example/model/rtc_stats.dart'; import 'package:intl/intl.dart'; @@ -55,8 +57,6 @@ class MeetingStore extends ChangeNotifier bool isRecordingStarted = false; - String event = ''; - String description = "Meeting Ended"; HMSTrackChangeRequest? hmsTrackChangeRequest; @@ -90,6 +90,8 @@ class MeetingStore extends ChangeNotifier String? highestSpeaker; int firstTimeBuild = 0; + String message = ""; + final DateFormat formatter = DateFormat('d MMM y h:mm:ss a'); bool isMirror = false; @@ -789,7 +791,7 @@ class MeetingStore extends ChangeNotifier int type0 = 0; int type1 = peerTracks.length - 1; while (type0 < type1) { - if (peerTracks[type0].track?.isMute??true) { + if (peerTracks[type0].track?.isMute ?? true) { if (peerTracks[type1].track != null && peerTracks[type1].track!.isMute == false) { PeerTrackNode peerTrackNode = peerTracks[type0]; @@ -932,6 +934,10 @@ class MeetingStore extends ChangeNotifier return activeSpeakerIds.containsKey(uid) ? activeSpeakerIds[uid]! : -1; } + void showToast(String message) { + Fluttertoast.showToast(msg: message, backgroundColor: Colors.black87); + } + @override void onSuccess( {HMSActionResultListenerMethod methodType = @@ -946,6 +952,7 @@ class MeetingStore extends ChangeNotifier break; case HMSActionResultListenerMethod.changeTrackState: // TODO: Handle this case. + showToast("Track State Changed"); break; case HMSActionResultListenerMethod.changeMetadata: notifyListeners(); @@ -959,25 +966,30 @@ class MeetingStore extends ChangeNotifier break; case HMSActionResultListenerMethod.acceptChangeRole: // TODO: Handle this case. + showToast("Accept role change successful"); break; case HMSActionResultListenerMethod.changeRole: // TODO: Handle this case. + showToast("Change role successful"); break; case HMSActionResultListenerMethod.changeTrackStateForRole: - this.event = arguments!['roles'] == null + message = arguments!['roles'] == null ? "Successfully Muted All" : "Successfully Muted Role"; + showToast(message); break; case HMSActionResultListenerMethod.startRtmpOrRecording: + showToast("RTMP start successful"); //TODO: HmsException?.code == 400(To see what this means) break; case HMSActionResultListenerMethod.stopRtmpAndRecording: + showToast("RTMP stop successful"); break; case HMSActionResultListenerMethod.unknown: break; case HMSActionResultListenerMethod.changeName: - // this.event = "Name Changed to ${localPeer!.name}"; + showToast("Change name successful"); break; case HMSActionResultListenerMethod.sendBroadcastMessage: var message = HMSMessage( @@ -1018,29 +1030,28 @@ class MeetingStore extends ChangeNotifier hmsMessageRecipientType: HMSMessageRecipientType.DIRECT)); addMessage(message); notifyListeners(); - break; case HMSActionResultListenerMethod.hlsStreamingStarted: - this.event = "HLS Streaming Started"; hasHlsStarted = true; + showToast("HLS Streaming Started"); notifyListeners(); // TODO: Handle this case. break; case HMSActionResultListenerMethod.hlsStreamingStopped: hasHlsStarted = false; - this.event = "HLS Streaming Stopped"; + showToast("HLS Streaming Stopped"); notifyListeners(); // TODO: Handle this case. break; case HMSActionResultListenerMethod.startScreenShare: - this.event = "Screen Share Started"; + showToast("Screen Share Started"); isScreenShareActive(); break; case HMSActionResultListenerMethod.stopScreenShare: - this.event = "Screen Share Stopped"; + showToast("Screen Share Stopped"); isScreenShareActive(); break; } @@ -1057,40 +1068,49 @@ class MeetingStore extends ChangeNotifier switch (methodType) { case HMSActionResultListenerMethod.leave: // TODO: Handle this case. + showToast("Leave Operation failed"); break; case HMSActionResultListenerMethod.changeTrackState: // TODO: Handle this case. + showToast("Change Track state failed"); break; case HMSActionResultListenerMethod.changeMetadata: // TODO: Handle this case. break; case HMSActionResultListenerMethod.endRoom: // TODO: Handle this case. + showToast("End room failed"); break; case HMSActionResultListenerMethod.removePeer: // TODO: Handle this case. + showToast("Remove peer failed"); break; case HMSActionResultListenerMethod.acceptChangeRole: // TODO: Handle this case. + showToast("Accept change role failed"); break; case HMSActionResultListenerMethod.changeRole: // TODO: Handle this case. + showToast("Change role failed"); break; case HMSActionResultListenerMethod.changeTrackStateForRole: - this.event = "Failed to Mute"; + showToast("Failed to change track state"); break; case HMSActionResultListenerMethod.startRtmpOrRecording: if (hmsException.code?.errorCode == "400") { isRecordingStarted = true; } + showToast("Start RTMP Streaming failed"); break; case HMSActionResultListenerMethod.stopRtmpAndRecording: // TODO: Handle this case. + showToast("Stop RTMP Streaming failed"); break; case HMSActionResultListenerMethod.unknown: break; case HMSActionResultListenerMethod.changeName: // TODO: Handle this case. + showToast("Name change failed"); break; case HMSActionResultListenerMethod.sendBroadcastMessage: // TODO: Handle this case. @@ -1103,17 +1123,22 @@ class MeetingStore extends ChangeNotifier break; case HMSActionResultListenerMethod.hlsStreamingStarted: // TODO: Handle this case. + showToast("Start HLS failed"); break; case HMSActionResultListenerMethod.hlsStreamingStopped: // TODO: Handle this case. + showToast("Stop HLS failed"); + break; case HMSActionResultListenerMethod.startScreenShare: isScreenShareActive(); + showToast("Start screenshare failed"); break; case HMSActionResultListenerMethod.stopScreenShare: isScreenShareActive(); + showToast("Stop screenshare failed"); break; } } diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 50a62e6ca..34114d807 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -37,6 +37,7 @@ dependencies: tuple: firebase_performance: ^0.8.0+11 avatar_glow: ^2.0.2 + fluttertoast: ^8.0.9 dev_dependencies: flutter_test: From 558c2cc59f3574ead2929c5153ae5f10e07a970b Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Fri, 27 May 2022 12:57:57 +0530 Subject: [PATCH 22/67] rearrange tile null track error fix --- example/lib/meeting/meeting_store.dart | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 5648a0d01..d1215b391 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -789,7 +789,7 @@ class MeetingStore extends ChangeNotifier int type0 = 0; int type1 = peerTracks.length - 1; while (type0 < type1) { - if (peerTracks[type0].track?.isMute??true) { + if (peerTracks[type0].track?.isMute ?? true) { if (peerTracks[type1].track != null && peerTracks[type1].track!.isMute == false) { PeerTrackNode peerTrackNode = peerTracks[type0]; @@ -817,7 +817,7 @@ class MeetingStore extends ChangeNotifier rearrangeTile(PeerTrackNode peerTrackNode, int index) { if (peerTrackNode.track!.isMute) { if (peerTracks.length - 1 > index && - peerTracks[index + 1].track!.isMute) { + (peerTracks[index + 1].track?.isMute ?? true)) { return; } else { peerTracks.removeAt(index); @@ -825,7 +825,9 @@ class MeetingStore extends ChangeNotifier notifyListeners(); } } else { - if (index != 0 && peerTracks[index - 1].track!.isMute == false) { + if (index != 0 && + (peerTracks[index - 1].track != null && + peerTracks[index - 1].track!.isMute == false)) { return; } else { peerTracks.removeAt(index); @@ -942,6 +944,7 @@ class MeetingStore extends ChangeNotifier peerTracks.clear(); isRoomEnded = true; screenShareCount = 0; + this.meetingMode = MeetingMode.Video; notifyListeners(); break; case HMSActionResultListenerMethod.changeTrackState: From 25c89a6a2787f9b33aae3cb779a8f18a7fea8086 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Fri, 27 May 2022 14:43:38 +0530 Subject: [PATCH 23/67] video tile size fix --- example/lib/meeting/meeting_page.dart | 744 +++++++++++++------------- 1 file changed, 377 insertions(+), 367 deletions(-) diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index dfdfab8d3..bbd7efb2a 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -225,205 +225,207 @@ class _MeetingPageState extends State Widget build(BuildContext context) { return ConnectivityAppWrapper( app: WillPopScope( - child: SafeArea( - child: ConnectivityWidgetWrapper( - disableInteraction: true, - offlineWidget: OfflineWidget(), - child: Selector>( - selector: (_, meetingStore) => - Tuple2(meetingStore.reconnecting, meetingStore.isRoomEnded), - builder: (_, data, __) { - if (data.item2) { - WidgetsBinding.instance?.addPostFrameCallback((_) { - UtilityComponents.showSnackBarWithString( - context.read().description, context); - Navigator.of(context).popUntil((route) => route.isFirst); - }); - } - return data.item1 - ? OfflineWidget() - : Scaffold( - resizeToAvoidBottomInset: false, - appBar: AppBar( - title: TitleBar(), - actions: [ - Selector( - selector: (_, meetingStore) => - meetingStore.isRecordingStarted, - builder: (_, isRecordingStarted, __) { - return isRecordingStarted - ? Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - width: 2, - color: Colors.red.shade600)), - child: Icon( - Icons.circle, - color: Colors.red, - size: 15, - ), - ) - : Container(); + child: ConnectivityWidgetWrapper( + disableInteraction: true, + offlineWidget: OfflineWidget(), + child: Selector>( + selector: (_, meetingStore) => + Tuple2(meetingStore.reconnecting, meetingStore.isRoomEnded), + builder: (_, data, __) { + if (data.item2) { + WidgetsBinding.instance?.addPostFrameCallback((_) { + UtilityComponents.showSnackBarWithString( + context.read().description, context); + Navigator.of(context).popUntil((route) => route.isFirst); + }); + } + return data.item1 + ? OfflineWidget() + : Scaffold( + resizeToAvoidBottomInset: false, + appBar: AppBar( + title: TitleBar(), + actions: [ + Selector( + selector: (_, meetingStore) => + meetingStore.isRecordingStarted, + builder: (_, isRecordingStarted, __) { + return isRecordingStarted + ? Container( + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + width: 2, + color: Colors.red.shade600)), + child: Icon( + Icons.circle, + color: Colors.red, + size: 15, + ), + ) + : Container(); + }, + ), + IconButton( + iconSize: 24, + onPressed: () { + context.read().toggleSpeaker(); }, - ), - IconButton( - iconSize: 24, - onPressed: () { - context.read().toggleSpeaker(); + icon: Selector( + selector: (_, meetingStore) => + meetingStore.isSpeakerOn, + builder: (_, isSpeakerOn, __) { + return Icon(isSpeakerOn + ? Icons.volume_up + : Icons.volume_off); }, - icon: Selector( - selector: (_, meetingStore) => - meetingStore.isSpeakerOn, - builder: (_, isSpeakerOn, __) { - return Icon(isSpeakerOn - ? Icons.volume_up - : Icons.volume_off); - }, - )), - dropDownMenu(), - ], - ), - body: Stack( - children: [ - Container( - height: MediaQuery.of(context).size.height * 0.81, - child: Selector< - MeetingStore, - Tuple6, bool, int, - int, MeetingMode, PeerTrackNode?>>( - selector: (_, meetingStore) => Tuple6( - meetingStore.peerTracks, - meetingStore.isHLSLink, - meetingStore.peerTracks.length, - meetingStore.screenShareCount, - meetingStore.meetingMode, - meetingStore.peerTracks.length > 0 - ? meetingStore.peerTracks[ - meetingStore.screenShareCount] - : null), - builder: (_, data, __) { - if (data.item2) { - return Selector( - selector: (_, meetingStore) => - meetingStore.hasHlsStarted, - builder: (_, hasHlsStarted, __) { - return hasHlsStarted - ? Center( - child: Container( - child: HLSViewer( - streamUrl: context - .read< - MeetingStore>() - .streamUrl), - ), - ) - : Center( - child: Column( - mainAxisAlignment: - MainAxisAlignment - .center, - crossAxisAlignment: - CrossAxisAlignment - .center, - children: [ - Padding( - padding: - const EdgeInsets - .only( - bottom: 8.0), - child: Text( - "Waiting for HLS to start...", - style: TextStyle( - fontSize: 20), - ), + )), + dropDownMenu(), + ], + ), + body: Stack( + children: [ + Container( + height: MediaQuery.of(context).size.height * 0.81, + child: Selector< + MeetingStore, + Tuple6, bool, int, int, + MeetingMode, PeerTrackNode?>>( + selector: (_, meetingStore) => Tuple6( + meetingStore.peerTracks, + meetingStore.isHLSLink, + meetingStore.peerTracks.length, + meetingStore.screenShareCount, + meetingStore.meetingMode, + meetingStore.peerTracks.length > 0 + ? meetingStore.peerTracks[ + meetingStore.screenShareCount] + : null), + builder: (_, data, __) { + if (data.item2) { + return Selector( + selector: (_, meetingStore) => + meetingStore.hasHlsStarted, + builder: (_, hasHlsStarted, __) { + return hasHlsStarted + ? Center( + child: Container( + child: HLSViewer( + streamUrl: context + .read< + MeetingStore>() + .streamUrl), + ), + ) + : Center( + child: Column( + mainAxisAlignment: + MainAxisAlignment + .center, + crossAxisAlignment: + CrossAxisAlignment + .center, + children: [ + Padding( + padding: + const EdgeInsets + .only( + bottom: 8.0), + child: Text( + "Waiting for HLS to start...", + style: TextStyle( + fontSize: 20), ), - CircularProgressIndicator( - strokeWidth: 1, - ) - ], - ), - ); - }); - } - if (data.item3 == 0) { - return Center( - child: Text( - 'Waiting for others to join!')); - } - Size size = MediaQuery.of(context).size; - if (data.item5 == MeetingMode.Hero) { - return gridHeroView( - peerTracks: data.item1, - itemCount: data.item3, - screenShareCount: data.item4, - context: context, - size: size); - } - if (data.item5 == MeetingMode.Audio) { - return gridAudioView( - peerTracks: - data.item1.sublist(data.item4), - itemCount: data.item1 - .sublist(data.item4) - .length, - size: size); - } - if (data.item5 == MeetingMode.Single) { - return fullScreenView( - peerTracks: data.item1, - itemCount: data.item3, - screenShareCount: data.item4, - context: context, - size: size); - } - return gridVideoView( + ), + CircularProgressIndicator( + strokeWidth: 1, + ) + ], + ), + ); + }); + } + if (data.item3 == 0) { + return Center( + child: Text( + 'Waiting for others to join!')); + } + Size size = MediaQuery.of(context).size; + if (data.item5 == MeetingMode.Hero) { + return gridHeroView( peerTracks: data.item1, itemCount: data.item3, screenShareCount: data.item4, context: context, size: size); - }), - ), - Selector( - selector: (_, meetingStore) => - meetingStore.roleChangeRequest, - builder: (_, roleChangeRequest, __) { - if (roleChangeRequest != null) { - WidgetsBinding.instance! - .addPostFrameCallback((_) { - UtilityComponents.showRoleChangeDialog( - roleChangeRequest, context); - }); } - return Container(); - }), - Selector( - selector: (_, meetingStore) => - meetingStore.hmsTrackChangeRequest, - builder: (_, hmsTrackChangeRequest, __) { - if (hmsTrackChangeRequest != null) { - WidgetsBinding.instance! - .addPostFrameCallback((_) { - UtilityComponents.showTrackChangeDialog( - hmsTrackChangeRequest, context); - }); + if (data.item5 == MeetingMode.Audio) { + return gridAudioView( + peerTracks: + data.item1.sublist(data.item4), + itemCount: data.item1 + .sublist(data.item4) + .length, + size: size); } - return Container(); + if (data.item5 == MeetingMode.Single) { + return fullScreenView( + peerTracks: data.item1, + itemCount: data.item3, + screenShareCount: data.item4, + context: context, + size: size); + } + return gridVideoView( + peerTracks: data.item1, + itemCount: data.item3, + screenShareCount: data.item4, + context: context, + size: size); }), - ], - ), - bottomNavigationBar: Selector( - selector: (_, meetingStore) => - meetingStore.isHLSLink, - builder: (_, isHlsRunning, __) { - return isHlsRunning - ? hlsBottomBarWidget() - : normalBottomBarWidget(); - })); - }, - )), - ), + ), + Selector( + selector: (_, meetingStore) => + meetingStore.isHLSLink, + builder: (_, isHlsRunning, __) { + return Positioned( + bottom: 0, + child: isHlsRunning + ? hlsBottomBarWidget() + : normalBottomBarWidget(), + ); + }), + Selector( + selector: (_, meetingStore) => + meetingStore.roleChangeRequest, + builder: (_, roleChangeRequest, __) { + if (roleChangeRequest != null) { + WidgetsBinding.instance! + .addPostFrameCallback((_) { + UtilityComponents.showRoleChangeDialog( + roleChangeRequest, context); + }); + } + return Container(); + }), + Selector( + selector: (_, meetingStore) => + meetingStore.hmsTrackChangeRequest, + builder: (_, hmsTrackChangeRequest, __) { + if (hmsTrackChangeRequest != null) { + WidgetsBinding.instance! + .addPostFrameCallback((_) { + UtilityComponents.showTrackChangeDialog( + hmsTrackChangeRequest, context); + }); + } + return Container(); + }), + ], + ), + ); + }, + )), onWillPop: () async { bool ans = await UtilityComponents.onBackPressed(context) ?? false; return ans; @@ -432,191 +434,199 @@ class _MeetingPageState extends State } Widget normalBottomBarWidget() { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Selector>( - selector: (_, meetingStore) => Tuple4( - meetingStore.localPeer, - meetingStore.isVideoOn, - meetingStore.localPeer?.role.publishSettings?.allowed - .contains("video") ?? - false, - meetingStore.meetingMode == MeetingMode.Audio), - builder: (_, data, __) { - return ((data.item1 != null) && - data.item1!.role.publishSettings!.allowed.contains("video")) - ? Container( - padding: EdgeInsets.all(8), - child: IconButton( - tooltip: 'Video', - iconSize: 24, - onPressed: (data.item4) - ? null - : () { - context.read().switchVideo(); - }, - icon: Icon( - data.item2 ? Icons.videocam : Icons.videocam_off, - // color: Colors.grey.shade900, - ))) - : SizedBox(); - }, - ), - Selector>( - selector: (_, meetingStore) => Tuple3( - meetingStore.localPeer, - meetingStore.isMicOn, - meetingStore.localPeer?.role.publishSettings?.allowed - .contains("audio") ?? - false), - builder: (_, data, __) { - return ((data.item1 != null) && - data.item1!.role.publishSettings!.allowed.contains("audio")) - ? Container( - padding: EdgeInsets.all(8), - child: IconButton( - tooltip: 'Audio', - iconSize: 24, - onPressed: () { - context.read().switchAudio(); - }, - icon: Icon( - data.item2 ? Icons.mic : Icons.mic_off, - // color: Colors.grey.shade900 - ))) - : SizedBox(); - }, - ), - Selector( - selector: (_, meetingStore) => meetingStore.isRaisedHand, - builder: (_, raisedHand, __) { - return Container( - padding: EdgeInsets.all(8), - child: IconButton( - tooltip: 'RaiseHand', - iconSize: 20, - onPressed: () { - context.read().changeMetadata(); - UtilityComponents.showSnackBarWithString( - !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", - context); - }, - icon: Image.asset( - 'assets/icons/raise_hand.png', - color: raisedHand ? Colors.amber.shade300 : Colors.white, - ), - )); - }, - ), - Selector( - selector: (_, meetingStore) => meetingStore.isNewMessageReceived, - builder: (_, isNewMessageReceived, __) { + return SizedBox( + width: MediaQuery.of(context).size.width, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Selector>( + selector: (_, meetingStore) => Tuple4( + meetingStore.localPeer, + meetingStore.isVideoOn, + meetingStore.localPeer?.role.publishSettings?.allowed + .contains("video") ?? + false, + meetingStore.meetingMode == MeetingMode.Audio), + builder: (_, data, __) { + return ((data.item1 != null) && + data.item1!.role.publishSettings!.allowed + .contains("video")) + ? Container( + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'Video', + iconSize: 24, + onPressed: (data.item4) + ? null + : () { + context.read().switchVideo(); + }, + icon: Icon( + data.item2 ? Icons.videocam : Icons.videocam_off, + // color: Colors.grey.shade900, + ))) + : SizedBox(); + }, + ), + Selector>( + selector: (_, meetingStore) => Tuple3( + meetingStore.localPeer, + meetingStore.isMicOn, + meetingStore.localPeer?.role.publishSettings?.allowed + .contains("audio") ?? + false), + builder: (_, data, __) { + return ((data.item1 != null) && + data.item1!.role.publishSettings!.allowed + .contains("audio")) + ? Container( + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'Audio', + iconSize: 24, + onPressed: () { + context.read().switchAudio(); + }, + icon: Icon( + data.item2 ? Icons.mic : Icons.mic_off, + // color: Colors.grey.shade900 + ))) + : SizedBox(); + }, + ), + Selector( + selector: (_, meetingStore) => meetingStore.isRaisedHand, + builder: (_, raisedHand, __) { return Container( - padding: EdgeInsets.all(8), - child: IconButton( - tooltip: 'Chat', - iconSize: 24, - onPressed: () { - chatMessages(context); - context.read().setNewMessageFalse(); - }, - icon: Stack(children: [ - Icon(Icons.chat_bubble), - if (isNewMessageReceived) - Positioned( - top: -1, - right: -1, - child: new Icon(Icons.brightness_1, - size: 14.0, color: Colors.red), - ) - ]), - ), - ); - }), - Container( - padding: EdgeInsets.all(8), - child: IconButton( - color: Colors.white, - tooltip: 'Leave Or End', - iconSize: 24, - onPressed: () async { - await UtilityComponents.onBackPressed(context); - }, - icon: CircleAvatar( - backgroundColor: Colors.red, - child: Icon(Icons.call_end, color: Colors.white), - )), - ), - ], + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'RaiseHand', + iconSize: 20, + onPressed: () { + context.read().changeMetadata(); + UtilityComponents.showSnackBarWithString( + !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", + context); + }, + icon: Image.asset( + 'assets/icons/raise_hand.png', + color: raisedHand ? Colors.amber.shade300 : Colors.white, + ), + )); + }, + ), + Selector( + selector: (_, meetingStore) => meetingStore.isNewMessageReceived, + builder: (_, isNewMessageReceived, __) { + return Container( + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'Chat', + iconSize: 24, + onPressed: () { + chatMessages(context); + context.read().setNewMessageFalse(); + }, + icon: Stack(children: [ + Icon(Icons.chat_bubble), + if (isNewMessageReceived) + Positioned( + top: -1, + right: -1, + child: new Icon(Icons.brightness_1, + size: 14.0, color: Colors.red), + ) + ]), + ), + ); + }), + Container( + padding: EdgeInsets.all(8), + child: IconButton( + color: Colors.white, + tooltip: 'Leave Or End', + iconSize: 24, + onPressed: () async { + await UtilityComponents.onBackPressed(context); + }, + icon: CircleAvatar( + backgroundColor: Colors.red, + child: Icon(Icons.call_end, color: Colors.white), + )), + ), + ], + ), ); } Widget hlsBottomBarWidget() { - return Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Selector( - selector: (_, meetingStore) => meetingStore.isRaisedHand, - builder: (_, raisedHand, __) { - return Container( - padding: EdgeInsets.all(8), - child: IconButton( - tooltip: 'RaiseHand', - iconSize: 20, - onPressed: () { - context.read().changeMetadata(); - UtilityComponents.showSnackBarWithString( - !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", - context); - }, - icon: Image.asset( - 'assets/icons/raise_hand.png', - color: raisedHand ? Colors.amber.shade300 : Colors.white, - ), - )); - }, - ), - Selector( - selector: (_, meetingStore) => meetingStore.isNewMessageReceived, - builder: (_, isNewMessageReceived, __) { + return SizedBox( + width: MediaQuery.of(context).size.width, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Selector( + selector: (_, meetingStore) => meetingStore.isRaisedHand, + builder: (_, raisedHand, __) { return Container( - padding: EdgeInsets.all(8), - child: IconButton( - tooltip: 'Chat', - iconSize: 24, - onPressed: () { - chatMessages(context); - context.read().setNewMessageFalse(); - }, - icon: Stack(children: [ - Icon(Icons.chat_bubble), - if (isNewMessageReceived) - Positioned( - top: -1, - right: -1, - child: new Icon(Icons.brightness_1, - size: 14.0, color: Colors.red), - ) - ]), - ), - ); - }), - Container( - padding: EdgeInsets.all(8), - child: IconButton( - color: Colors.white, - tooltip: 'Leave Or End', - iconSize: 24, - onPressed: () async { - await UtilityComponents.onBackPressed(context); - }, - icon: CircleAvatar( - backgroundColor: Colors.red, - child: Icon(Icons.call_end, color: Colors.white), - )), - ), - ], + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'RaiseHand', + iconSize: 20, + onPressed: () { + context.read().changeMetadata(); + UtilityComponents.showSnackBarWithString( + !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", + context); + }, + icon: Image.asset( + 'assets/icons/raise_hand.png', + color: raisedHand ? Colors.amber.shade300 : Colors.white, + ), + )); + }, + ), + Selector( + selector: (_, meetingStore) => meetingStore.isNewMessageReceived, + builder: (_, isNewMessageReceived, __) { + return Container( + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'Chat', + iconSize: 24, + onPressed: () { + chatMessages(context); + context.read().setNewMessageFalse(); + }, + icon: Stack(children: [ + Icon(Icons.chat_bubble), + if (isNewMessageReceived) + Positioned( + top: -1, + right: -1, + child: new Icon(Icons.brightness_1, + size: 14.0, color: Colors.red), + ) + ]), + ), + ); + }), + Container( + padding: EdgeInsets.all(8), + child: IconButton( + color: Colors.white, + tooltip: 'Leave Or End', + iconSize: 24, + onPressed: () async { + await UtilityComponents.onBackPressed(context); + }, + icon: CircleAvatar( + backgroundColor: Colors.red, + child: Icon(Icons.call_end, color: Colors.white), + )), + ), + ], + ), ); } From 82964ada23ace4e1d2d585f601c4937f560ae2fa Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Fri, 27 May 2022 14:45:02 +0530 Subject: [PATCH 24/67] firebase plugin upgrade --- example/pubspec.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 50a62e6ca..7842ce2da 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -21,9 +21,10 @@ dependencies: http: ^0.13.3 permission_handler: intl: - firebase_crashlytics: ^2.7.2 - firebase_core: ^1.16.0 - firebase_analytics: ^9.1.7 + firebase_crashlytics: ^2.8.1 + firebase_core: ^1.17.1 + firebase_analytics: ^9.1.9 + firebase_performance: ^0.8.0+13 flutter_launcher_icons: ^0.9.1 package_info_plus: ^1.3.1 logger: ^1.1.0 @@ -35,7 +36,6 @@ dependencies: focus_detector: ^2.0.1 flutter_staggered_grid_view: ^0.6.1 tuple: - firebase_performance: ^0.8.0+11 avatar_glow: ^2.0.2 dev_dependencies: From 1e623dbaccb19e1167f3408d74ec54ba67ffc635 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Fri, 27 May 2022 15:19:12 +0530 Subject: [PATCH 25/67] UI Enhancements --- example/lib/meeting/meeting_page.dart | 30 +++++++++++++-------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index bbd7efb2a..c6866691c 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -657,13 +657,13 @@ class _MeetingPageState extends State : "Record", style: TextStyle( color: meetingStore.isRecordingStarted - ? Colors.red + ? Colors.blue : Colors.white, )), Icon( Icons.circle, color: meetingStore.isRecordingStarted - ? Colors.red + ? Colors.blue : Colors.white, ), ]), @@ -719,13 +719,13 @@ class _MeetingPageState extends State Text("Active Speaker Mode", style: TextStyle( color: meetingStore.isActiveSpeakerMode - ? Colors.red + ? Colors.blue : Colors.white, )), Icon( CupertinoIcons.person_3_fill, color: meetingStore.isActiveSpeakerMode - ? Colors.red + ? Colors.blue : Colors.white, ), ]), @@ -738,13 +738,13 @@ class _MeetingPageState extends State Text("Hero Mode", style: TextStyle( color: meetingStore.meetingMode == MeetingMode.Hero - ? Colors.red + ? Colors.blue : Colors.white, )), Icon( CupertinoIcons.person_3_fill, color: meetingStore.meetingMode == MeetingMode.Hero - ? Colors.red + ? Colors.blue : Colors.white, ), ]), @@ -757,13 +757,13 @@ class _MeetingPageState extends State Text("Single Tile Mode", style: TextStyle( color: meetingStore.meetingMode == MeetingMode.Single - ? Colors.red + ? Colors.blue : Colors.white, )), Icon( CupertinoIcons.person, color: meetingStore.meetingMode == MeetingMode.Single - ? Colors.red + ? Colors.blue : Colors.white, ), ]), @@ -789,13 +789,13 @@ class _MeetingPageState extends State meetingStore.hasHlsStarted ? "Stop HLS" : "Start HLS", style: TextStyle( color: meetingStore.hasHlsStarted - ? Colors.red + ? Colors.blue : Colors.white, ), ), Icon(Icons.stream, color: meetingStore.hasHlsStarted - ? Colors.red + ? Colors.blue : Colors.white), ]), value: 10, @@ -831,20 +831,20 @@ class _MeetingPageState extends State Text( "BRB", style: TextStyle( - color: meetingStore.isBRB ? Colors.red : Colors.white), + color: meetingStore.isBRB ? Colors.blue : Colors.white), ), Container( decoration: BoxDecoration( border: Border.all( width: 1, color: meetingStore.isBRB - ? Colors.red + ? Colors.blue : Colors.white)), child: Text( "BRB", style: TextStyle( color: - meetingStore.isBRB ? Colors.red : Colors.white), + meetingStore.isBRB ? Colors.blue : Colors.white), ), ), ]), @@ -858,12 +858,12 @@ class _MeetingPageState extends State "Stats", style: TextStyle( color: meetingStore.isStatsVisible - ? Colors.red + ? Colors.blue : Colors.white), ), Icon(Icons.bar_chart_outlined, color: meetingStore.isStatsVisible - ? Colors.red + ? Colors.blue : Colors.white), ]), value: 14, From 9ee5f9ccccadea09765c22e053c1b7f129ccfeb3 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Sun, 29 May 2022 17:55:22 +0530 Subject: [PATCH 26/67] bottom bar extra space remove on basis on permission for camera and mic --- example/lib/meeting/meeting_page.dart | 106 +++++++++++++------------- 1 file changed, 51 insertions(+), 55 deletions(-) diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index bbd7efb2a..09311a6cf 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -439,61 +439,57 @@ class _MeetingPageState extends State child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - Selector>( - selector: (_, meetingStore) => Tuple4( - meetingStore.localPeer, - meetingStore.isVideoOn, - meetingStore.localPeer?.role.publishSettings?.allowed - .contains("video") ?? - false, - meetingStore.meetingMode == MeetingMode.Audio), - builder: (_, data, __) { - return ((data.item1 != null) && - data.item1!.role.publishSettings!.allowed - .contains("video")) - ? Container( - padding: EdgeInsets.all(8), - child: IconButton( - tooltip: 'Video', - iconSize: 24, - onPressed: (data.item4) - ? null - : () { - context.read().switchVideo(); - }, - icon: Icon( - data.item2 ? Icons.videocam : Icons.videocam_off, - // color: Colors.grey.shade900, - ))) - : SizedBox(); - }, - ), - Selector>( - selector: (_, meetingStore) => Tuple3( - meetingStore.localPeer, - meetingStore.isMicOn, - meetingStore.localPeer?.role.publishSettings?.allowed - .contains("audio") ?? - false), - builder: (_, data, __) { - return ((data.item1 != null) && - data.item1!.role.publishSettings!.allowed - .contains("audio")) - ? Container( - padding: EdgeInsets.all(8), - child: IconButton( - tooltip: 'Audio', - iconSize: 24, - onPressed: () { - context.read().switchAudio(); - }, - icon: Icon( - data.item2 ? Icons.mic : Icons.mic_off, - // color: Colors.grey.shade900 - ))) - : SizedBox(); - }, - ), + if (Provider.of(context).localPeer != null && + (Provider.of(context) + .localPeer + ?.role + .publishSettings + ?.allowed + .contains("video") ?? + false)) + Selector>( + selector: (_, meetingStore) => Tuple2(meetingStore.isVideoOn, + meetingStore.meetingMode == MeetingMode.Audio), + builder: (_, data, __) { + return Container( + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'Video', + iconSize: 24, + onPressed: (data.item2) + ? null + : () { + context.read().switchVideo(); + }, + icon: Icon( + data.item1 ? Icons.videocam : Icons.videocam_off, + ))); + }, + ), + if (Provider.of(context).localPeer != null && + (Provider.of(context) + .localPeer + ?.role + .publishSettings + ?.allowed + .contains("audio") ?? + false)) + Selector( + selector: (_, meetingStore) => meetingStore.isMicOn, + builder: (_, isMicOn, __) { + return Container( + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'Audio', + iconSize: 24, + onPressed: () { + context.read().switchAudio(); + }, + icon: Icon( + isMicOn ? Icons.mic : Icons.mic_off, + ))); + }, + ), Selector( selector: (_, meetingStore) => meetingStore.isRaisedHand, builder: (_, raisedHand, __) { From d4dc91bb7c3d907f24113180da44fef18bca47f3 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Sun, 29 May 2022 18:49:04 +0530 Subject: [PATCH 27/67] ui fix --- .../ui/organisms/change_role_options.dart | 71 ++++++++++++++----- .../ui/organisms/participant_organism.dart | 18 +++-- .../lib/common/util/utility_components.dart | 1 + 3 files changed, 67 insertions(+), 23 deletions(-) diff --git a/example/lib/common/ui/organisms/change_role_options.dart b/example/lib/common/ui/organisms/change_role_options.dart index 745bcbb88..e7c78397b 100644 --- a/example/lib/common/ui/organisms/change_role_options.dart +++ b/example/lib/common/ui/organisms/change_role_options.dart @@ -1,4 +1,5 @@ //Package imports +import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; //Project imports @@ -22,6 +23,7 @@ class ChangeRoleOptionDialog extends StatefulWidget { class _ChangeRoleOptionDialogState extends State { late bool forceValue; + String valueChoose = ""; @override void initState() { @@ -40,28 +42,40 @@ class _ChangeRoleOptionDialogState extends State { if (data.connectionState != ConnectionState.done) { return CircularProgressIndicator(); } else if (data.hasData) { + if (valueChoose == "") { + valueChoose = data.data![0].name; + } return Container( width: 300, child: Column( mainAxisSize: MainAxisSize.min, children: [ - Flexible( - child: ListView.builder( - shrinkWrap: true, - itemCount: data.data?.length, - itemBuilder: (_, index) { - return ListTile( - title: Text(data.data![index].name), - trailing: IconButton( - onPressed: () { - widget.changeRole( - data.data![index], forceValue); - }, - icon: Icon( - Icons.done, - ), - )); - }), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text("Role To: "), + Flexible( + child: DropdownButton2( + buttonWidth: MediaQuery.of(context).size.width / 2, + value: valueChoose, + iconEnabledColor: Colors.white, + onChanged: (newvalue) { + setState(() { + valueChoose = newvalue as String; + }); + }, + items: data.data!.map((role) { + return DropdownMenuItem( + child: Text(role.name), + value: role.name, + ); + }).toList(), + ), + ), + ], + ), + SizedBox( + height: 10, ), GestureDetector( onTap: () { @@ -80,6 +94,29 @@ class _ChangeRoleOptionDialogState extends State { ], ), ), + SizedBox( + height: 10, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + style: + ElevatedButton.styleFrom(primary: Colors.red), + onPressed: () { + Navigator.pop(context); + }, + child: Text("Cancel")), + ElevatedButton( + onPressed: () { + widget.changeRole( + data.data!.firstWhere( + (element) => element.name == valueChoose), + forceValue); + }, + child: Text("Change Role")), + ], + ) ], ), ); diff --git a/example/lib/common/ui/organisms/participant_organism.dart b/example/lib/common/ui/organisms/participant_organism.dart index fc7f4cbc5..498af1ae3 100644 --- a/example/lib/common/ui/organisms/participant_organism.dart +++ b/example/lib/common/ui/organisms/participant_organism.dart @@ -49,7 +49,7 @@ class _ParticipantOrganismState extends State { ), Row( children: [ - if (peer.metadata == "{\"isHandRaised\":true}") + if (peer.metadata?.contains("\"isHandRaised\":true") ?? false) Padding( padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), child: Image.asset( @@ -59,13 +59,19 @@ class _ParticipantOrganismState extends State { height: 20, ), ), - if (peer.metadata == - "{\"isHandRaised\":false,\"isBRBOn\":true}") + if (peer.metadata?.contains("\"isBRBOn\":true") ?? false) Padding( padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), child: Container( - decoration: BoxDecoration(border: Border.all(width: 1)), - child: Text("BRB"), + width: 25, + decoration: BoxDecoration( + border: Border.all(width: 1, color: Colors.red)), + child: Center( + child: Text( + "BRB", + style: TextStyle(color: Colors.red, fontSize: 10), + ), + ), ), ), GestureDetector( @@ -102,7 +108,7 @@ class _ParticipantOrganismState extends State { maxLines: 1, style: TextStyle( color: Colors.white, - fontSize: 20.0, + fontSize: 18.0, fontWeight: FontWeight.bold), ), ), diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index 878603b8e..ffb329dfa 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -170,6 +170,7 @@ class UtilityComponents { HMSRole? selectedRole = await showDialog( context: context, builder: (context) => AlertDialog( + title: Text("Select Role for Mute"), content: Container( height: 100, child: ClickableListWheelScrollView( From 0f8aa8c26154657889e004f8facb61637d6b033b Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Mon, 30 May 2022 17:45:37 +0530 Subject: [PATCH 28/67] =?UTF-8?q?released=20sample=20app=20version=201.1.1?= =?UTF-8?q?9=20(69)=20=F0=9F=8D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/android/app/build.gradle | 4 +-- example/ios/Podfile.lock | 26 ++++++++++++++------ example/ios/Runner.xcodeproj/project.pbxproj | 6 ++--- example/ios/Runner/Info.plist | 4 +-- 4 files changed, 25 insertions(+), 15 deletions(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 293827f17..206439e14 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -32,8 +32,8 @@ android { applicationId "live.hms.flutter" minSdkVersion 21 targetSdkVersion 32 - versionCode 67 - versionName "1.1.17" + versionCode 69 + versionName "1.1.19" } signingConfigs { diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 1abe1a4f8..71dc7d3b2 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -12,18 +12,18 @@ PODS: - Firebase/Performance (8.15.0): - Firebase/CoreOnly - FirebasePerformance (~> 8.15.0) - - firebase_analytics (9.1.8): + - firebase_analytics (9.1.9): - Firebase/Analytics (= 8.15.0) - firebase_core - Flutter - - firebase_core (1.17.0): + - firebase_core (1.17.1): - Firebase/CoreOnly (= 8.15.0) - Flutter - - firebase_crashlytics (2.8.0): + - firebase_crashlytics (2.8.1): - Firebase/Crashlytics (= 8.15.0) - firebase_core - Flutter - - firebase_performance (0.8.0-12): + - firebase_performance (0.8.0-13): - Firebase/Performance (= 8.15.0) - firebase_core - Flutter @@ -84,6 +84,9 @@ PODS: - GoogleUtilities/Environment (~> 7.7) - "GoogleUtilities/NSData+zlib (~> 7.7)" - Flutter (1.0.0) + - fluttertoast (0.0.2): + - Flutter + - Toast - GoogleAppMeasurement (8.15.0): - GoogleAppMeasurement/AdIdSupport (= 8.15.0) - GoogleUtilities/AppDelegateSwizzler (~> 7.7) @@ -146,6 +149,7 @@ PODS: - permission_handler_apple (9.0.4): - Flutter - PromisesObjC (2.1.0) + - Toast (4.0.0) - video_player_avfoundation (0.0.1): - Flutter - wakelock (0.0.1): @@ -157,6 +161,7 @@ DEPENDENCIES: - firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`) - firebase_performance (from `.symlinks/plugins/firebase_performance/ios`) - Flutter (from `Flutter`) + - fluttertoast (from `.symlinks/plugins/fluttertoast/ios`) - hmssdk_flutter (from `.symlinks/plugins/hmssdk_flutter/ios`) - package_info_plus (from `.symlinks/plugins/package_info_plus/ios`) - path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`) @@ -182,6 +187,7 @@ SPEC REPOS: - HMSWebRTC - nanopb - PromisesObjC + - Toast EXTERNAL SOURCES: firebase_analytics: @@ -194,6 +200,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/firebase_performance/ios" Flutter: :path: Flutter + fluttertoast: + :path: ".symlinks/plugins/fluttertoast/ios" hmssdk_flutter: :path: ".symlinks/plugins/hmssdk_flutter/ios" package_info_plus: @@ -209,10 +217,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Firebase: 5f8193dff4b5b7c5d5ef72ae54bb76c08e2b841d - firebase_analytics: 92d27947c7516981cabdc0acbb33cd0687bcda44 - firebase_core: aa1b92020533f5c23955e388c347c58fd64f8627 - firebase_crashlytics: d42b108fa870b889f4c4ea22094647f2aca5f765 - firebase_performance: 8184e4dd714cbcde323995133a077727923d8d2d + firebase_analytics: 99eefffcacf3ab694db7926dd1291833e1300853 + firebase_core: 318de541b0e61d3f24262982a3f0b54afe72439b + firebase_crashlytics: 3ccd7b4f26a7fc546774b1074d2d10b0c6f92ab6 + firebase_performance: 41f6ab0cb84134c550a0624ec91e513faf667684 FirebaseABTesting: 10cbce8db9985ae2e3847ea44e9947dd18f94e10 FirebaseAnalytics: 7761cbadb00a717d8d0939363eb46041526474fa FirebaseCore: 5743c5785c074a794d35f2fff7ecc254a91e08b1 @@ -222,6 +230,7 @@ SPEC CHECKSUMS: FirebasePerformance: 66eb58c3e3568a0501a9be271c8ff424dea0ff34 FirebaseRemoteConfig: 2d6e2cfdb49af79535c8af8a80a4a5009038ec2b Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a + fluttertoast: 16fbe6039d06a763f3533670197d01fc73459037 GoogleAppMeasurement: 4c19f031220c72464d460c9daa1fb5d1acce958e GoogleDataTransport: 5fffe35792f8b96ec8d6775f5eccd83c998d5a3b GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1 @@ -233,6 +242,7 @@ SPEC CHECKSUMS: path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce PromisesObjC: 99b6f43f9e1044bd87a95a60beff28c2c44ddb72 + Toast: 91b396c56ee72a5790816f40d3a94dd357abc196 video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index a71594498..4af07fb35 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -384,7 +384,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 67; + CURRENT_PROJECT_VERSION = 69; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; @@ -522,7 +522,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 67; + CURRENT_PROJECT_VERSION = 69; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; @@ -555,7 +555,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 67; + CURRENT_PROJECT_VERSION = 69; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index c28dc2661..4687ca808 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.17 + 1.1.19 CFBundleSignature ???? CFBundleURLTypes @@ -34,7 +34,7 @@ CFBundleVersion - 67 + 69 ITSAppUsesNonExemptEncryption LSApplicationCategoryType From 84606a367b66dcecdfb29384f1ba156fa0c83cf9 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Mon, 30 May 2022 17:55:53 +0530 Subject: [PATCH 29/67] updated packages --- example/android/Gemfile.lock | 12 +++++------ example/ios/Gemfile.lock | 12 +++++------ example/pubspec.lock | 42 ++++++++++++++++++++++++------------ example/pubspec.yaml | 38 ++++++++++++++++---------------- 4 files changed, 59 insertions(+), 45 deletions(-) diff --git a/example/android/Gemfile.lock b/example/android/Gemfile.lock index 5d34fe92d..cdf0a18ee 100644 --- a/example/android/Gemfile.lock +++ b/example/android/Gemfile.lock @@ -8,12 +8,12 @@ GEM artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.589.0) - aws-sdk-core (3.131.0) + aws-partitions (1.594.0) + aws-sdk-core (3.131.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.525.0) aws-sigv4 (~> 1.1) - jmespath (~> 1.0) + jmespath (~> 1, >= 1.6.1) aws-sdk-kms (1.57.0) aws-sdk-core (~> 3, >= 3.127.0) aws-sigv4 (~> 1.1) @@ -66,7 +66,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.2.6) - fastlane (2.206.0) + fastlane (2.206.2) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -146,7 +146,7 @@ GEM os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.4) + http-cookie (1.0.5) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.1) @@ -193,7 +193,7 @@ GEM uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.8.1) + unf_ext (0.0.8.2) unicode-display_width (1.8.0) webrick (1.7.0) word_wrap (1.0.0) diff --git a/example/ios/Gemfile.lock b/example/ios/Gemfile.lock index 5d34fe92d..cdf0a18ee 100644 --- a/example/ios/Gemfile.lock +++ b/example/ios/Gemfile.lock @@ -8,12 +8,12 @@ GEM artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.589.0) - aws-sdk-core (3.131.0) + aws-partitions (1.594.0) + aws-sdk-core (3.131.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.525.0) aws-sigv4 (~> 1.1) - jmespath (~> 1.0) + jmespath (~> 1, >= 1.6.1) aws-sdk-kms (1.57.0) aws-sdk-core (~> 3, >= 3.127.0) aws-sigv4 (~> 1.1) @@ -66,7 +66,7 @@ GEM faraday_middleware (1.2.0) faraday (~> 1.0) fastimage (2.2.6) - fastlane (2.206.0) + fastlane (2.206.2) CFPropertyList (>= 2.3, < 4.0.0) addressable (>= 2.8, < 3.0.0) artifactory (~> 3.0) @@ -146,7 +146,7 @@ GEM os (>= 0.9, < 2.0) signet (>= 0.16, < 2.a) highline (2.0.3) - http-cookie (1.0.4) + http-cookie (1.0.5) domain_name (~> 0.5) httpclient (2.8.3) jmespath (1.6.1) @@ -193,7 +193,7 @@ GEM uber (0.1.0) unf (0.1.4) unf_ext - unf_ext (0.0.8.1) + unf_ext (0.0.8.2) unicode-display_width (1.8.0) webrick (1.7.0) word_wrap (1.0.0) diff --git a/example/pubspec.lock b/example/pubspec.lock index c33179029..37132d8dc 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -22,6 +22,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.8.2" + avatar_glow: + dependency: "direct main" + description: + name: avatar_glow + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.2" boolean_selector: dependency: transitive description: @@ -49,7 +56,7 @@ packages: name: clickable_list_wheel_view url: "https://pub.dartlang.org" source: hosted - version: "0.0.4" + version: "0.1.0" clock: dependency: transitive description: @@ -84,7 +91,7 @@ packages: name: csslib url: "https://pub.dartlang.org" source: hosted - version: "0.17.1" + version: "0.17.2" cupertino_icons: dependency: "direct main" description: @@ -133,28 +140,28 @@ packages: name: firebase_analytics url: "https://pub.dartlang.org" source: hosted - version: "9.1.8" + version: "9.1.9" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.1.6" + version: "3.1.7" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web url: "https://pub.dartlang.org" source: hosted - version: "0.4.0+13" + version: "0.4.0+14" firebase_core: dependency: "direct main" description: name: firebase_core url: "https://pub.dartlang.org" source: hosted - version: "1.17.0" + version: "1.17.1" firebase_core_platform_interface: dependency: transitive description: @@ -175,35 +182,35 @@ packages: name: firebase_crashlytics url: "https://pub.dartlang.org" source: hosted - version: "2.8.0" + version: "2.8.1" firebase_crashlytics_platform_interface: dependency: transitive description: name: firebase_crashlytics_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "3.2.6" + version: "3.2.7" firebase_performance: dependency: "direct main" description: name: firebase_performance url: "https://pub.dartlang.org" source: hosted - version: "0.8.0+12" + version: "0.8.0+13" firebase_performance_platform_interface: dependency: transitive description: name: firebase_performance_platform_interface url: "https://pub.dartlang.org" source: hosted - version: "0.1.1+6" + version: "0.1.1+7" firebase_performance_web: dependency: transitive description: name: firebase_performance_web url: "https://pub.dartlang.org" source: hosted - version: "0.1.0+12" + version: "0.1.0+13" flutter: dependency: "direct main" description: flutter @@ -233,6 +240,13 @@ packages: description: flutter source: sdk version: "0.0.0" + fluttertoast: + dependency: "direct main" + description: + name: fluttertoast + url: "https://pub.dartlang.org" + source: hosted + version: "8.0.9" focus_detector: dependency: "direct main" description: @@ -400,7 +414,7 @@ packages: name: path_provider_linux url: "https://pub.dartlang.org" source: hosted - version: "2.1.6" + version: "2.1.7" path_provider_macos: dependency: transitive description: @@ -421,7 +435,7 @@ packages: name: path_provider_windows url: "https://pub.dartlang.org" source: hosted - version: "2.0.6" + version: "2.0.7" permission_handler: dependency: "direct main" description: @@ -491,7 +505,7 @@ packages: name: provider url: "https://pub.dartlang.org" source: hosted - version: "6.0.2" + version: "6.0.3" quiver: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 676a22975..bbc37341d 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -15,29 +15,29 @@ dependencies: hmssdk_flutter: path: ../ - wakelock: ^0.6.1+1 - cupertino_icons: ^1.0.2 - provider: ^6.0.2 - http: ^0.13.3 + wakelock: + cupertino_icons: + provider: + http: permission_handler: intl: - firebase_crashlytics: ^2.8.1 - firebase_core: ^1.17.1 - firebase_analytics: ^9.1.9 - firebase_performance: ^0.8.0+13 - flutter_launcher_icons: ^0.9.1 - package_info_plus: ^1.3.1 - logger: ^1.1.0 - path_provider: ^2.0.9 - connectivity_checker: ^1.1.0 - dropdown_button2: ^1.1.1 + firebase_crashlytics: + firebase_core: + firebase_analytics: + firebase_performance: + flutter_launcher_icons: + package_info_plus: + logger: + path_provider: + connectivity_checker: + dropdown_button2: video_player: - clickable_list_wheel_view: ^0.0.4 - focus_detector: ^2.0.1 - flutter_staggered_grid_view: ^0.6.1 + clickable_list_wheel_view: + focus_detector: + flutter_staggered_grid_view: tuple: - avatar_glow: ^2.0.2 - fluttertoast: ^8.0.9 + avatar_glow: + fluttertoast: dev_dependencies: flutter_test: From a085d103ad656b70c48a4befe85c19f945912511 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Tue, 31 May 2022 11:47:46 +0530 Subject: [PATCH 30/67] updated gradle version --- example/android/build.gradle | 2 +- example/android/gradle/wrapper/gradle-wrapper.properties | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/example/android/build.gradle b/example/android/build.gradle index 20beb43f5..296ffc317 100755 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:7.1.3' + classpath 'com.android.tools.build:gradle:7.2.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1' classpath 'com.google.gms:google-services:4.3.10' diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index 595fb867a..562c5e444 100755 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip From 28a7bd628bd93e21ceedaa31af061fef297ea683 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 31 May 2022 16:04:22 +0530 Subject: [PATCH 31/67] icon added --- example/assets/icons/brb.svg | 3 + example/assets/icons/bug.svg | 3 + example/assets/icons/cam_state_off.svg | 3 + example/assets/icons/cam_state_on.svg | 3 + example/assets/icons/camera.svg | 3 + example/assets/icons/degrade.svg | 3 + example/assets/icons/end_room.svg | 3 + example/assets/icons/hand_state_off.svg | 9 + example/assets/icons/hand_state_on.svg | 3 + example/assets/icons/hls.svg | 3 + example/assets/icons/leave.svg | 3 + example/assets/icons/message_badge_off.svg | 3 + example/assets/icons/message_badge_on.svg | 4 + example/assets/icons/mic_state_off.svg | 3 + example/assets/icons/mic_state_on.svg | 6 + example/assets/icons/participants.svg | 3 + example/assets/icons/pencil.svg | 3 + example/assets/icons/preview_state_off.svg | 3 + example/assets/icons/preview_state_on.svg | 3 + example/assets/icons/record.svg | 3 + example/assets/icons/screen_share.svg | 3 + example/assets/icons/send.svg | 3 + example/assets/icons/settings.svg | 3 + example/assets/icons/single_tile.svg | 3 + example/assets/icons/speaker_state_off.svg | 3 + example/assets/icons/speaker_state_on.svg | 3 + example/assets/icons/stats.svg | 3 + example/assets/icons/stream.svg | 3 + example/ios/Podfile.lock | 16 +- example/ios/Runner.xcodeproj/project.pbxproj | 4 +- example/lib/common/ui/organisms/brb_tag.dart | 12 +- .../common/ui/organisms/full_screen_view.dart | 2 +- .../common/ui/organisms/grid_audio_view.dart | 2 +- .../common/ui/organisms/grid_hero_view.dart | 2 +- .../common/ui/organisms/grid_video_view.dart | 2 +- .../lib/common/ui/organisms/hand_raise.dart | 8 +- .../ui/organisms/participant_organism.dart | 27 +- example/lib/common/util/utility_function.dart | 15 +- example/lib/main.dart | 24 +- example/lib/meeting/meeting_page.dart | 234 ++++++++---------- .../meeting/meeting_participants_list.dart | 8 +- example/lib/preview/preview_page.dart | 30 ++- example/pubspec.yaml | 1 + 43 files changed, 285 insertions(+), 196 deletions(-) create mode 100644 example/assets/icons/brb.svg create mode 100644 example/assets/icons/bug.svg create mode 100644 example/assets/icons/cam_state_off.svg create mode 100644 example/assets/icons/cam_state_on.svg create mode 100644 example/assets/icons/camera.svg create mode 100644 example/assets/icons/degrade.svg create mode 100644 example/assets/icons/end_room.svg create mode 100644 example/assets/icons/hand_state_off.svg create mode 100644 example/assets/icons/hand_state_on.svg create mode 100644 example/assets/icons/hls.svg create mode 100644 example/assets/icons/leave.svg create mode 100644 example/assets/icons/message_badge_off.svg create mode 100644 example/assets/icons/message_badge_on.svg create mode 100644 example/assets/icons/mic_state_off.svg create mode 100644 example/assets/icons/mic_state_on.svg create mode 100644 example/assets/icons/participants.svg create mode 100644 example/assets/icons/pencil.svg create mode 100644 example/assets/icons/preview_state_off.svg create mode 100644 example/assets/icons/preview_state_on.svg create mode 100644 example/assets/icons/record.svg create mode 100644 example/assets/icons/screen_share.svg create mode 100644 example/assets/icons/send.svg create mode 100644 example/assets/icons/settings.svg create mode 100644 example/assets/icons/single_tile.svg create mode 100644 example/assets/icons/speaker_state_off.svg create mode 100644 example/assets/icons/speaker_state_on.svg create mode 100644 example/assets/icons/stats.svg create mode 100644 example/assets/icons/stream.svg diff --git a/example/assets/icons/brb.svg b/example/assets/icons/brb.svg new file mode 100644 index 000000000..2928fa682 --- /dev/null +++ b/example/assets/icons/brb.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/bug.svg b/example/assets/icons/bug.svg new file mode 100644 index 000000000..a03213233 --- /dev/null +++ b/example/assets/icons/bug.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/cam_state_off.svg b/example/assets/icons/cam_state_off.svg new file mode 100644 index 000000000..805f3e17c --- /dev/null +++ b/example/assets/icons/cam_state_off.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/cam_state_on.svg b/example/assets/icons/cam_state_on.svg new file mode 100644 index 000000000..d638445de --- /dev/null +++ b/example/assets/icons/cam_state_on.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/camera.svg b/example/assets/icons/camera.svg new file mode 100644 index 000000000..9d82f62c5 --- /dev/null +++ b/example/assets/icons/camera.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/degrade.svg b/example/assets/icons/degrade.svg new file mode 100644 index 000000000..dc4616c1a --- /dev/null +++ b/example/assets/icons/degrade.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/end_room.svg b/example/assets/icons/end_room.svg new file mode 100644 index 000000000..439a85824 --- /dev/null +++ b/example/assets/icons/end_room.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/hand_state_off.svg b/example/assets/icons/hand_state_off.svg new file mode 100644 index 000000000..3ed0e9895 --- /dev/null +++ b/example/assets/icons/hand_state_off.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/example/assets/icons/hand_state_on.svg b/example/assets/icons/hand_state_on.svg new file mode 100644 index 000000000..340aa4269 --- /dev/null +++ b/example/assets/icons/hand_state_on.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/hls.svg b/example/assets/icons/hls.svg new file mode 100644 index 000000000..0141d4d38 --- /dev/null +++ b/example/assets/icons/hls.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/leave.svg b/example/assets/icons/leave.svg new file mode 100644 index 000000000..0031ece37 --- /dev/null +++ b/example/assets/icons/leave.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/message_badge_off.svg b/example/assets/icons/message_badge_off.svg new file mode 100644 index 000000000..851ce8496 --- /dev/null +++ b/example/assets/icons/message_badge_off.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/message_badge_on.svg b/example/assets/icons/message_badge_on.svg new file mode 100644 index 000000000..d1e43a56f --- /dev/null +++ b/example/assets/icons/message_badge_on.svg @@ -0,0 +1,4 @@ + + + + diff --git a/example/assets/icons/mic_state_off.svg b/example/assets/icons/mic_state_off.svg new file mode 100644 index 000000000..78b10533c --- /dev/null +++ b/example/assets/icons/mic_state_off.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/mic_state_on.svg b/example/assets/icons/mic_state_on.svg new file mode 100644 index 000000000..3c673b702 --- /dev/null +++ b/example/assets/icons/mic_state_on.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/example/assets/icons/participants.svg b/example/assets/icons/participants.svg new file mode 100644 index 000000000..978a9a77d --- /dev/null +++ b/example/assets/icons/participants.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/pencil.svg b/example/assets/icons/pencil.svg new file mode 100644 index 000000000..769cb5366 --- /dev/null +++ b/example/assets/icons/pencil.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/preview_state_off.svg b/example/assets/icons/preview_state_off.svg new file mode 100644 index 000000000..87cd7d962 --- /dev/null +++ b/example/assets/icons/preview_state_off.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/preview_state_on.svg b/example/assets/icons/preview_state_on.svg new file mode 100644 index 000000000..bd00a00d9 --- /dev/null +++ b/example/assets/icons/preview_state_on.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/record.svg b/example/assets/icons/record.svg new file mode 100644 index 000000000..44acbf4d0 --- /dev/null +++ b/example/assets/icons/record.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/screen_share.svg b/example/assets/icons/screen_share.svg new file mode 100644 index 000000000..4755f094e --- /dev/null +++ b/example/assets/icons/screen_share.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/send.svg b/example/assets/icons/send.svg new file mode 100644 index 000000000..50688cc3d --- /dev/null +++ b/example/assets/icons/send.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/settings.svg b/example/assets/icons/settings.svg new file mode 100644 index 000000000..a659e9428 --- /dev/null +++ b/example/assets/icons/settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/single_tile.svg b/example/assets/icons/single_tile.svg new file mode 100644 index 000000000..2febef3c4 --- /dev/null +++ b/example/assets/icons/single_tile.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/speaker_state_off.svg b/example/assets/icons/speaker_state_off.svg new file mode 100644 index 000000000..f0498120a --- /dev/null +++ b/example/assets/icons/speaker_state_off.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/speaker_state_on.svg b/example/assets/icons/speaker_state_on.svg new file mode 100644 index 000000000..e285cc8d9 --- /dev/null +++ b/example/assets/icons/speaker_state_on.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/stats.svg b/example/assets/icons/stats.svg new file mode 100644 index 000000000..1eba77c40 --- /dev/null +++ b/example/assets/icons/stats.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/stream.svg b/example/assets/icons/stream.svg new file mode 100644 index 000000000..ce942fc35 --- /dev/null +++ b/example/assets/icons/stream.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 1abe1a4f8..9d29636bd 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -12,18 +12,18 @@ PODS: - Firebase/Performance (8.15.0): - Firebase/CoreOnly - FirebasePerformance (~> 8.15.0) - - firebase_analytics (9.1.8): + - firebase_analytics (9.1.9): - Firebase/Analytics (= 8.15.0) - firebase_core - Flutter - - firebase_core (1.17.0): + - firebase_core (1.17.1): - Firebase/CoreOnly (= 8.15.0) - Flutter - - firebase_crashlytics (2.8.0): + - firebase_crashlytics (2.8.1): - Firebase/Crashlytics (= 8.15.0) - firebase_core - Flutter - - firebase_performance (0.8.0-12): + - firebase_performance (0.8.0-13): - Firebase/Performance (= 8.15.0) - firebase_core - Flutter @@ -209,10 +209,10 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: Firebase: 5f8193dff4b5b7c5d5ef72ae54bb76c08e2b841d - firebase_analytics: 92d27947c7516981cabdc0acbb33cd0687bcda44 - firebase_core: aa1b92020533f5c23955e388c347c58fd64f8627 - firebase_crashlytics: d42b108fa870b889f4c4ea22094647f2aca5f765 - firebase_performance: 8184e4dd714cbcde323995133a077727923d8d2d + firebase_analytics: 99eefffcacf3ab694db7926dd1291833e1300853 + firebase_core: 318de541b0e61d3f24262982a3f0b54afe72439b + firebase_crashlytics: 3ccd7b4f26a7fc546774b1074d2d10b0c6f92ab6 + firebase_performance: 41f6ab0cb84134c550a0624ec91e513faf667684 FirebaseABTesting: 10cbce8db9985ae2e3847ea44e9947dd18f94e10 FirebaseAnalytics: 7761cbadb00a717d8d0939363eb46041526474fa FirebaseCore: 5743c5785c074a794d35f2fff7ecc254a91e08b1 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index a71594498..642f87048 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -161,7 +161,7 @@ 97C146E61CF9000F007C117D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1330; + LastUpgradeCheck = 1300; ORGANIZATIONNAME = 100ms; TargetAttributes = { 97C146ED1CF9000F007C117D = { @@ -247,7 +247,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; CC19BBB77EA3E7F699588CF7 /* [firebase_crashlytics] Crashlytics Upload Symbols */ = { isa = PBXShellScriptBuildPhase; diff --git a/example/lib/common/ui/organisms/brb_tag.dart b/example/lib/common/ui/organisms/brb_tag.dart index bb103f8a5..029493e75 100644 --- a/example/lib/common/ui/organisms/brb_tag.dart +++ b/example/lib/common/ui/organisms/brb_tag.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; //Project imports @@ -14,13 +15,10 @@ class BRBTag extends StatelessWidget { ? Positioned( child: Padding( padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), - child: Container( - decoration: BoxDecoration( - border: Border.all(width: 1, color: Colors.red)), - child: Text( - "BRB", - style: TextStyle(color: Colors.red), - ), + child: SvgPicture.asset( + "assets/icons/brb.svg", + color: Colors.red, + width: 35, ), ), top: 10.0, diff --git a/example/lib/common/ui/organisms/full_screen_view.dart b/example/lib/common/ui/organisms/full_screen_view.dart index 01fe1ee06..3541011ad 100644 --- a/example/lib/common/ui/organisms/full_screen_view.dart +++ b/example/lib/common/ui/organisms/full_screen_view.dart @@ -66,5 +66,5 @@ Widget fullScreenView( controller: Provider.of(context).controller, gridDelegate: SliverStairedGridDelegate( startCrossAxisDirectionReversed: false, - pattern: [StairedGridTile(1, (size.height * 0.81) / (size.width))])); + pattern: [StairedGridTile(1, (size.height * 0.84) / (size.width))])); } diff --git a/example/lib/common/ui/organisms/grid_audio_view.dart b/example/lib/common/ui/organisms/grid_audio_view.dart index 287d48748..558008df2 100644 --- a/example/lib/common/ui/organisms/grid_audio_view.dart +++ b/example/lib/common/ui/organisms/grid_audio_view.dart @@ -33,7 +33,7 @@ Widget gridAudioView( } List pattern(int itemCount, Size size) { - double ratio = (size.height * 0.81) / (size.width); + double ratio = (size.height * 0.84) / (size.width); List tiles = []; int gridView = itemCount ~/ 6; int tileLeft = itemCount - (gridView * 6); diff --git a/example/lib/common/ui/organisms/grid_hero_view.dart b/example/lib/common/ui/organisms/grid_hero_view.dart index 28d8afac6..95e438ae8 100644 --- a/example/lib/common/ui/organisms/grid_hero_view.dart +++ b/example/lib/common/ui/organisms/grid_hero_view.dart @@ -63,7 +63,7 @@ Widget gridHeroView( } List pattern(int itemCount, int screenShareCount, Size size) { - double ratio = (size.width) / (size.height * 0.81); + double ratio = (size.width) / (size.height * 0.84); List tiles = []; for (int i = 0; i < screenShareCount; i++) { diff --git a/example/lib/common/ui/organisms/grid_video_view.dart b/example/lib/common/ui/organisms/grid_video_view.dart index 51211c388..9b35d63f9 100644 --- a/example/lib/common/ui/organisms/grid_video_view.dart +++ b/example/lib/common/ui/organisms/grid_video_view.dart @@ -70,7 +70,7 @@ Widget gridVideoView( } List pattern(int itemCount, int screenShareCount, Size size) { - double ratio = (size.height * 0.81) / (size.width); + double ratio = (size.height * 0.84) / (size.width); List tiles = []; for (int i = 0; i < screenShareCount; i++) { tiles.add(StairedGridTile(1, ratio)); diff --git a/example/lib/common/ui/organisms/hand_raise.dart b/example/lib/common/ui/organisms/hand_raise.dart index cc1374bf4..3d073f38c 100644 --- a/example/lib/common/ui/organisms/hand_raise.dart +++ b/example/lib/common/ui/organisms/hand_raise.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; //Project imports @@ -14,9 +15,10 @@ class HandRaise extends StatelessWidget { ? Positioned( child: Padding( padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), - child: Image.asset( - 'assets/icons/raise_hand.png', - color: Colors.amber.shade300, + child: SvgPicture.asset( + "assets/icons/hand_state_on.svg", + color: Colors.yellow, + height: 50, ), ), bottom: 5.0, diff --git a/example/lib/common/ui/organisms/participant_organism.dart b/example/lib/common/ui/organisms/participant_organism.dart index 498af1ae3..e7b0d84eb 100644 --- a/example/lib/common/ui/organisms/participant_organism.dart +++ b/example/lib/common/ui/organisms/participant_organism.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; //Project imports @@ -51,27 +52,19 @@ class _ParticipantOrganismState extends State { children: [ if (peer.metadata?.contains("\"isHandRaised\":true") ?? false) Padding( - padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), - child: Image.asset( - 'assets/icons/raise_hand.png', - color: Colors.amber.shade300, - width: 20, - height: 20, - ), - ), + padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), + child: SvgPicture.asset( + "assets/icons/hand_state_on.svg", + color: Colors.yellow, + height: 25, + )), if (peer.metadata?.contains("\"isBRBOn\":true") ?? false) Padding( padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), - child: Container( + child: SvgPicture.asset( + "assets/icons/brb.svg", + color: Colors.red, width: 25, - decoration: BoxDecoration( - border: Border.all(width: 1, color: Colors.red)), - child: Center( - child: Text( - "BRB", - style: TextStyle(color: Colors.red, fontSize: 10), - ), - ), ), ), GestureDetector( diff --git a/example/lib/common/util/utility_function.dart b/example/lib/common/util/utility_function.dart index 70fde1f8b..9df8dbfcc 100644 --- a/example/lib/common/util/utility_function.dart +++ b/example/lib/common/util/utility_function.dart @@ -23,15 +23,10 @@ class Utilities { } static List colors = [ - Colors.red, - Colors.pink, - Colors.purple, - Colors.deepPurple, - Colors.indigo, - Colors.blue, - Colors.lightBlue, - Colors.teal, - Colors.green, - Colors.deepOrange, + Color(0xFFFAC919), + Color(0xFF00AE63), + Color(0xFF6554C0), + Color(0xFFF69133), + Color(0xFF8FF5FB) ]; } diff --git a/example/lib/main.dart b/example/lib/main.dart index 56c425eab..ccfac0566 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -5,8 +5,8 @@ import 'dart:io'; //Package imports import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:wakelock/wakelock.dart'; @@ -21,7 +21,6 @@ import 'package:hmssdk_flutter_example/common/constant.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/user_name_dialog_organism.dart'; import 'package:hmssdk_flutter_example/enum/meeting_flow.dart'; import 'package:hmssdk_flutter_example/preview/preview_page.dart'; -import 'package:hmssdk_flutter_example/service/deeplink_service.dart'; import './logs/custom_singleton_logger.dart'; void main() async { @@ -145,7 +144,9 @@ class _HomePageState extends State { actions: [ PopupMenuButton( onSelected: handleClick, - icon: Icon(CupertinoIcons.gear), + icon: SvgPicture.asset( + 'assets/icons/settings.svg', + ), itemBuilder: (BuildContext context) { return [ PopupMenuItem( @@ -159,8 +160,15 @@ class _HomePageState extends State { "Disable Preview", style: TextStyle(color: Colors.blue), ), - Icon(Icons.preview, - color: skipPreview ? Colors.white : Colors.blue), + if (skipPreview) + SvgPicture.asset( + 'assets/icons/preview_state_on.svg', + ) + else + SvgPicture.asset( + 'assets/icons/preview_state_off.svg', + color: Colors.blue, + ), ], ), value: 1, @@ -191,8 +199,10 @@ class _HomePageState extends State { style: TextStyle(color: Colors.blue)) else Text("Enable Stats"), - Icon(Icons.bar_chart, - color: showStats ? Colors.blue : Colors.white), + SvgPicture.asset( + 'assets/icons/stats.svg', + color: showStats ? Colors.blue : Colors.white, + ), ], ), value: 3, diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 81aed410b..dca7bb525 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -3,8 +3,8 @@ import 'dart:io'; //Package imports import 'package:connectivity_checker/connectivity_checker.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/full_screen_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/grid_audio_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/grid_hero_view.dart'; @@ -199,17 +199,12 @@ class _MeetingPageState extends State _meetingStore.changeTrackStateForRole(true, null); break; case 13: - _meetingStore.changeMetadataBRB(); - // raisedHand = false; - isBRB = !isBRB; - break; - case 14: _meetingStore.changeStatsVisible(); break; - case 15: + case 14: _meetingStore.toggleScreenShare(); break; - case 16: + case 15: _meetingStore.endRoom(false, "Room Ended From Flutter"); if (_meetingStore.isRoomEnded) { Navigator.pop(context); @@ -257,10 +252,9 @@ class _MeetingPageState extends State border: Border.all( width: 2, color: Colors.red.shade600)), - child: Icon( - Icons.circle, + child: SvgPicture.asset( + "assets/icons/record.svg", color: Colors.red, - size: 15, ), ) : Container(); @@ -275,9 +269,13 @@ class _MeetingPageState extends State selector: (_, meetingStore) => meetingStore.isSpeakerOn, builder: (_, isSpeakerOn, __) { - return Icon(isSpeakerOn - ? Icons.volume_up - : Icons.volume_off); + return (isSpeakerOn) + ? SvgPicture.asset( + "assets/icons/speaker_state_on.svg", + ) + : SvgPicture.asset( + "assets/icons/speaker_state_off.svg", + ); }, )), dropDownMenu(), @@ -286,7 +284,7 @@ class _MeetingPageState extends State body: Stack( children: [ Container( - height: MediaQuery.of(context).size.height * 0.81, + height: MediaQuery.of(context).size.height * 0.84, child: Selector< MeetingStore, Tuple6, bool, int, int, @@ -461,9 +459,10 @@ class _MeetingPageState extends State : () { context.read().switchVideo(); }, - icon: Icon( - data.item1 ? Icons.videocam : Icons.videocam_off, - ))); + icon: data.item1 + ? SvgPicture.asset("assets/icons/cam_state_on.svg") + : SvgPicture.asset( + "assets/icons/cam_state_off.svg"))); }, ), if (Provider.of(context).localPeer != null && @@ -485,9 +484,10 @@ class _MeetingPageState extends State onPressed: () { context.read().switchAudio(); }, - icon: Icon( - isMicOn ? Icons.mic : Icons.mic_off, - ))); + icon: isMicOn + ? SvgPicture.asset("assets/icons/mic_state_on.svg") + : SvgPicture.asset( + "assets/icons/mic_state_off.svg"))); }, ), Selector( @@ -496,19 +496,35 @@ class _MeetingPageState extends State return Container( padding: EdgeInsets.all(8), child: IconButton( - tooltip: 'RaiseHand', - iconSize: 20, - onPressed: () { - context.read().changeMetadata(); - UtilityComponents.showSnackBarWithString( - !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", - context); - }, - icon: Image.asset( - 'assets/icons/raise_hand.png', - color: raisedHand ? Colors.amber.shade300 : Colors.white, - ), - )); + tooltip: 'RaiseHand', + iconSize: 20, + onPressed: () { + context.read().changeMetadata(); + // UtilityComponents.showSnackBarWithString( + // !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", + // context); + }, + icon: SvgPicture.asset( + "assets/icons/hand_state_on.svg", + color: raisedHand ? Colors.yellow : Colors.white, + ))); + }, + ), + Selector( + selector: (_, meetingStore) => meetingStore.isBRB, + builder: (_, isBRB, __) { + return Container( + padding: EdgeInsets.all(8), + child: IconButton( + tooltip: 'BRB', + iconSize: 20, + onPressed: () { + context.read().changeMetadataBRB(); + }, + icon: SvgPicture.asset( + "assets/icons/brb.svg", + color: isBRB ? Colors.red : Colors.white, + ))); }, ), Selector( @@ -517,23 +533,17 @@ class _MeetingPageState extends State return Container( padding: EdgeInsets.all(8), child: IconButton( - tooltip: 'Chat', - iconSize: 24, - onPressed: () { - chatMessages(context); - context.read().setNewMessageFalse(); - }, - icon: Stack(children: [ - Icon(Icons.chat_bubble), - if (isNewMessageReceived) - Positioned( - top: -1, - right: -1, - child: new Icon(Icons.brightness_1, - size: 14.0, color: Colors.red), - ) - ]), - ), + tooltip: 'Chat', + iconSize: 24, + onPressed: () { + chatMessages(context); + context.read().setNewMessageFalse(); + }, + icon: isNewMessageReceived + ? SvgPicture.asset( + "assets/icons/message_badge_on.svg") + : SvgPicture.asset( + "assets/icons/message_badge_off.svg")), ); }), Container( @@ -547,7 +557,7 @@ class _MeetingPageState extends State }, icon: CircleAvatar( backgroundColor: Colors.red, - child: Icon(Icons.call_end, color: Colors.white), + child: SvgPicture.asset("assets/icons/leave.svg"), )), ), ], @@ -575,10 +585,14 @@ class _MeetingPageState extends State !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", context); }, - icon: Image.asset( - 'assets/icons/raise_hand.png', - color: raisedHand ? Colors.amber.shade300 : Colors.white, - ), + icon: raisedHand + ? SvgPicture.asset( + 'assets/icons/hand_state_on.svg', + color: Colors.amber.shade300, + ) + : SvgPicture.asset( + 'assets/icons/hand_state_off.svg', + ), )); }, ), @@ -588,23 +602,17 @@ class _MeetingPageState extends State return Container( padding: EdgeInsets.all(8), child: IconButton( - tooltip: 'Chat', - iconSize: 24, - onPressed: () { - chatMessages(context); - context.read().setNewMessageFalse(); - }, - icon: Stack(children: [ - Icon(Icons.chat_bubble), - if (isNewMessageReceived) - Positioned( - top: -1, - right: -1, - child: new Icon(Icons.brightness_1, - size: 14.0, color: Colors.red), - ) - ]), - ), + tooltip: 'Chat', + iconSize: 24, + onPressed: () { + chatMessages(context); + context.read().setNewMessageFalse(); + }, + icon: isNewMessageReceived + ? SvgPicture.asset( + "assets/icons/message_badge_on.svg") + : SvgPicture.asset( + "assets/icons/message_badge_off.svg")), ); }), Container( @@ -618,7 +626,7 @@ class _MeetingPageState extends State }, icon: CircleAvatar( backgroundColor: Colors.red, - child: Icon(Icons.call_end, color: Colors.white), + child: SvgPicture.asset("assets/icons/leave.svg"), )), ), ], @@ -628,7 +636,7 @@ class _MeetingPageState extends State Widget dropDownMenu() { return PopupMenuButton( - icon: Icon(CupertinoIcons.gear), + icon: SvgPicture.asset("assets/icons/settings.svg"), itemBuilder: (context) { final meetingStore = context.read(); return [ @@ -637,7 +645,7 @@ class _MeetingPageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("Send Logs"), - Icon(Icons.bug_report), + SvgPicture.asset("assets/icons/bug.svg"), ], ), value: 1, @@ -656,8 +664,8 @@ class _MeetingPageState extends State ? Colors.blue : Colors.white, )), - Icon( - Icons.circle, + SvgPicture.asset( + "assets/icons/record.svg", color: meetingStore.isRecordingStarted ? Colors.blue : Colors.white, @@ -673,7 +681,7 @@ class _MeetingPageState extends State Text( "Toggle Camera ", ), - Icon(Icons.switch_camera), + SvgPicture.asset("assets/icons/camera.svg"), ]), value: 3, ), @@ -684,7 +692,7 @@ class _MeetingPageState extends State Text( "Participants ", ), - Icon(CupertinoIcons.person_3_fill), + SvgPicture.asset("assets/icons/participants.svg"), ]), value: 4, ), @@ -697,10 +705,10 @@ class _MeetingPageState extends State ? "Video View" : "Audio View", ), - Image.asset( + SvgPicture.asset( meetingStore.meetingMode == MeetingMode.Audio - ? 'assets/icons/video.png' - : 'assets/icons/audio.png', + ? 'assets/icons/cam_state_on.svg' + : 'assets/icons/mic_state_on.svg', color: Colors.white, height: 24.0, width: 24.0, @@ -718,8 +726,8 @@ class _MeetingPageState extends State ? Colors.blue : Colors.white, )), - Icon( - CupertinoIcons.person_3_fill, + SvgPicture.asset( + "assets/icons/participants.svg", color: meetingStore.isActiveSpeakerMode ? Colors.blue : Colors.white, @@ -737,8 +745,8 @@ class _MeetingPageState extends State ? Colors.blue : Colors.white, )), - Icon( - CupertinoIcons.person_3_fill, + SvgPicture.asset( + "assets/icons/participants.svg", color: meetingStore.meetingMode == MeetingMode.Hero ? Colors.blue : Colors.white, @@ -756,8 +764,8 @@ class _MeetingPageState extends State ? Colors.blue : Colors.white, )), - Icon( - CupertinoIcons.person, + SvgPicture.asset( + "assets/icons/single_tile.svg", color: meetingStore.meetingMode == MeetingMode.Single ? Colors.blue : Colors.white, @@ -772,7 +780,7 @@ class _MeetingPageState extends State Text( "Change Name", ), - Icon(Icons.create_rounded), + SvgPicture.asset("assets/icons/pencil.svg"), ]), value: 9, ), @@ -789,7 +797,7 @@ class _MeetingPageState extends State : Colors.white, ), ), - Icon(Icons.stream, + SvgPicture.asset("assets/icons/hls.svg", color: meetingStore.hasHlsStarted ? Colors.blue : Colors.white), @@ -804,7 +812,7 @@ class _MeetingPageState extends State Text( "Mute Roles", ), - Icon(Icons.mic_off_sharp), + SvgPicture.asset("assets/icons/mic_state_off.svg"), ]), value: 11, ), @@ -816,36 +824,10 @@ class _MeetingPageState extends State Text( "Mute All", ), - Icon(Icons.mic_off), + SvgPicture.asset("assets/icons/mic_state_off.svg"), ]), value: 12, ), - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "BRB", - style: TextStyle( - color: meetingStore.isBRB ? Colors.blue : Colors.white), - ), - Container( - decoration: BoxDecoration( - border: Border.all( - width: 1, - color: meetingStore.isBRB - ? Colors.blue - : Colors.white)), - child: Text( - "BRB", - style: TextStyle( - color: - meetingStore.isBRB ? Colors.blue : Colors.white), - ), - ), - ]), - value: 13, - ), PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -857,12 +839,12 @@ class _MeetingPageState extends State ? Colors.blue : Colors.white), ), - Icon(Icons.bar_chart_outlined, + SvgPicture.asset("assets/icons/stats.svg", color: meetingStore.isStatsVisible ? Colors.blue : Colors.white), ]), - value: 14, + value: 13, ), if ((meetingStore.localPeer != null) && meetingStore.localPeer!.role.publishSettings!.allowed @@ -879,14 +861,14 @@ class _MeetingPageState extends State ? Colors.blue : Colors.white), ), - Icon( - Icons.screen_share, + SvgPicture.asset( + "assets/icons/screen_share.svg", color: meetingStore.isScreenShareOn ? Colors.blue : Colors.white, ), ]), - value: 15, + value: 14, ), if (meetingStore.localPeer!.role.permissions.endRoom!) PopupMenuItem( @@ -896,9 +878,9 @@ class _MeetingPageState extends State Text( "End Room", ), - Icon(Icons.cancel_schedule_send), + SvgPicture.asset("assets/icons/end_room.svg"), ]), - value: 16, + value: 15, ), ]; }, diff --git a/example/lib/meeting/meeting_participants_list.dart b/example/lib/meeting/meeting_participants_list.dart index 37a9f8bdb..7fca8d24d 100644 --- a/example/lib/meeting/meeting_participants_list.dart +++ b/example/lib/meeting/meeting_participants_list.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -23,7 +24,12 @@ class _ParticipantsListState extends State { title: Selector( selector: (_, meetingStore) => meetingStore.peers.length, builder: (_, length, __) { - return Text("👥 Participants ($length)"); + return Row( + children: [ + SvgPicture.asset("assets/icons/participants.svg"), + Text(" Participants ($length)"), + ], + ); }), ), body: Container( diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index 88abf0b49..d9d76f38d 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -3,6 +3,7 @@ import 'package:connectivity_checker/connectivity_checker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:hmssdk_flutter/hmssdk_flutter.dart'; import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; @@ -269,11 +270,15 @@ class _PreviewPageState extends State with WidgetsBindingObserver { radius: 25, backgroundColor: Colors.transparent.withOpacity(0.2), - child: Icon( - _previewStore.isVideoOn - ? Icons.videocam - : Icons.videocam_off, - color: Colors.blue), + child: (_previewStore.isVideoOn) + ? SvgPicture.asset( + "assets/icons/cam_state_on.svg", + color: Colors.blue, + ) + : SvgPicture.asset( + "assets/icons/cam_state_off.svg", + color: Colors.blue, + ), ), ) : Container(), @@ -372,12 +377,15 @@ class _PreviewPageState extends State with WidgetsBindingObserver { radius: 25, backgroundColor: Colors.transparent.withOpacity(0.2), - child: Icon( - (_previewStore.isAudioOn) - ? Icons.mic - : Icons.mic_off, - color: Colors.blue, - ), + child: (_previewStore.isAudioOn) + ? SvgPicture.asset( + "assets/icons/mic_state_on.svg", + color: Colors.blue, + ) + : SvgPicture.asset( + "assets/icons/mic_state_off.svg", + color: Colors.blue, + ), ), ) : Container(), diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 676a22975..981df6cdc 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: tuple: avatar_glow: ^2.0.2 fluttertoast: ^8.0.9 + flutter_svg: dev_dependencies: flutter_test: From 0d919594424ea1091175a888a19fc86cc5266a54 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 31 May 2022 16:52:12 +0530 Subject: [PATCH 32/67] mute role and all --- .../lib/common/util/utility_components.dart | 115 ++++++++++++------ example/lib/meeting/meeting_page.dart | 32 ++--- example/pubspec.yaml | 1 - 3 files changed, 86 insertions(+), 62 deletions(-) diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index ffb329dfa..0c1ab8950 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:provider/provider.dart'; -import 'package:clickable_list_wheel_view/clickable_list_wheel_widget.dart'; //Project imports import 'package:hmssdk_flutter/hmssdk_flutter.dart'; @@ -161,44 +160,88 @@ class UtilityComponents { return answer; } - static Future> showRoleList( - BuildContext context, List roles) async { + static showRoleList(BuildContext context, List roles, + MeetingStore _meetingStore) async { List _selectedRoles = []; - FixedExtentScrollController _scrollController = - FixedExtentScrollController(); - - HMSRole? selectedRole = await showDialog( + bool muteAll = false; + showDialog( context: context, - builder: (context) => AlertDialog( - title: Text("Select Role for Mute"), - content: Container( - height: 100, - child: ClickableListWheelScrollView( - scrollController: _scrollController, - itemHeight: 50, - itemCount: roles.length, - onItemTapCallback: (index) { - Navigator.pop(context, roles[index]); - }, - child: ListWheelScrollView.useDelegate( - controller: _scrollController, - physics: FixedExtentScrollPhysics(), - overAndUnderCenterOpacity: 0.5, - perspective: 0.002, - itemExtent: 50, - childDelegate: ListWheelChildBuilderDelegate( - childCount: roles.length, - builder: (context, index) { - return Container( - height: 50, - child: ListTile( - title: Text(roles[index].name), - ), + builder: (context) => StatefulBuilder(builder: (context, setState) { + return AlertDialog( + title: Text("Select Role for Mute"), + content: Container( + width: 300, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Flexible( + fit: FlexFit.tight, + child: ListView.builder( + itemCount: roles.length, + itemBuilder: (context, index) { + return Row( + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text(roles[index].name), + Checkbox( + value: _selectedRoles + .contains(roles[index]), + onChanged: (bool? value) { + if (value != null && value) { + _selectedRoles.add(roles[index]); + } else if (_selectedRoles + .contains(roles[index])) { + _selectedRoles.remove(roles[index]); + } + setState(() {}); + }), + ], ); - })))), - )); - if (selectedRole != null) _selectedRoles.add(selectedRole); - return _selectedRoles; + }), + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Mute All"), + Checkbox( + value: muteAll, + onChanged: (bool? value) { + if (value != null) { + muteAll = value; + } + setState(() {}); + }), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.red), + onPressed: () { + Navigator.pop(context); + }, + child: Text("Cancel")), + ElevatedButton( + onPressed: () { + if (muteAll) { + _meetingStore.changeTrackStateForRole( + true, null); + } else if (_selectedRoles.isNotEmpty) { + _meetingStore.changeTrackStateForRole( + true, _selectedRoles); + } + Navigator.pop(context); + }, + child: Text("Mute Roles")) + ], + ) + ], + )), + ); + })); } static Future> showRTMPInputDialog( diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index dca7bb525..4a7890c24 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -190,21 +190,15 @@ class _MeetingPageState extends State case 11: List roles = await _meetingStore.getRoles(); - List selectedRoles = - await UtilityComponents.showRoleList(context, roles); - if (selectedRoles.isNotEmpty) - _meetingStore.changeTrackStateForRole(true, selectedRoles); + UtilityComponents.showRoleList(context, roles,_meetingStore); break; case 12: - _meetingStore.changeTrackStateForRole(true, null); - break; - case 13: _meetingStore.changeStatsVisible(); break; - case 14: + case 13: _meetingStore.toggleScreenShare(); break; - case 15: + case 14: _meetingStore.endRoom(false, "Room Ended From Flutter"); if (_meetingStore.isRoomEnded) { Navigator.pop(context); @@ -810,24 +804,12 @@ class _MeetingPageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Mute Roles", + "Mute", ), SvgPicture.asset("assets/icons/mic_state_off.svg"), ]), value: 11, ), - if (meetingStore.localPeer?.role.permissions.changeRole ?? false) - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Mute All", - ), - SvgPicture.asset("assets/icons/mic_state_off.svg"), - ]), - value: 12, - ), PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -844,7 +826,7 @@ class _MeetingPageState extends State ? Colors.blue : Colors.white), ]), - value: 13, + value: 12, ), if ((meetingStore.localPeer != null) && meetingStore.localPeer!.role.publishSettings!.allowed @@ -868,7 +850,7 @@ class _MeetingPageState extends State : Colors.white, ), ]), - value: 14, + value: 13, ), if (meetingStore.localPeer!.role.permissions.endRoom!) PopupMenuItem( @@ -880,7 +862,7 @@ class _MeetingPageState extends State ), SvgPicture.asset("assets/icons/end_room.svg"), ]), - value: 15, + value: 14, ), ]; }, diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 981df6cdc..384634f54 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -32,7 +32,6 @@ dependencies: connectivity_checker: ^1.1.0 dropdown_button2: ^1.1.1 video_player: - clickable_list_wheel_view: ^0.0.4 focus_detector: ^2.0.1 flutter_staggered_grid_view: ^0.6.1 tuple: From 08b882b2e0506d6dae74ce752d006cfd35d4dbbf Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 31 May 2022 17:46:12 +0530 Subject: [PATCH 33/67] font added inter --- .../ui/organisms/audio_level_avatar.dart | 7 +- .../ui/organisms/change_role_options.dart | 15 ++-- .../ui/organisms/change_track_options.dart | 21 ++++- .../ui/organisms/chat_bottom_sheet.dart | 17 ++-- .../lib/common/ui/organisms/degrade_tile.dart | 4 +- .../common/ui/organisms/full_screen_view.dart | 6 +- .../common/ui/organisms/grid_hero_view.dart | 3 +- .../common/ui/organisms/grid_video_view.dart | 3 +- .../common/ui/organisms/offline_screen.dart | 4 +- .../ui/organisms/participant_organism.dart | 5 +- .../lib/common/ui/organisms/peer_name.dart | 3 +- .../organisms/role_change_request_dialog.dart | 16 +++- .../common/ui/organisms/rtc_stats_view.dart | 44 +++++++--- .../lib/common/ui/organisms/title_bar.dart | 7 +- .../track_change_request_dialog.dart | 7 +- .../organisms/user_name_dialog_organism.dart | 15 +++- .../lib/common/util/utility_components.dart | 86 ++++--------------- example/lib/hls_viewer/hls_viewer.dart | 3 +- example/lib/main.dart | 33 ++++--- example/lib/meeting/meeting_page.dart | 37 +++++--- .../meeting/meeting_participants_list.dart | 11 ++- example/lib/preview/preview_page.dart | 26 +++--- example/pubspec.lock | 35 ++++++-- example/pubspec.yaml | 1 + 24 files changed, 243 insertions(+), 166 deletions(-) diff --git a/example/lib/common/ui/organisms/audio_level_avatar.dart b/example/lib/common/ui/organisms/audio_level_avatar.dart index b8b7665b3..7755a437c 100644 --- a/example/lib/common/ui/organisms/audio_level_avatar.dart +++ b/example/lib/common/ui/organisms/audio_level_avatar.dart @@ -1,5 +1,6 @@ import 'package:avatar_glow/avatar_glow.dart'; import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; @@ -28,7 +29,8 @@ class _AudioLevelAvatarState extends State { child: Text( Utilities.getAvatarTitle( context.read().peer.name), - style: TextStyle(fontSize: 36, color: Colors.white), + style: + GoogleFonts.inter(fontSize: 36, color: Colors.white), )) : AvatarGlow( repeat: true, @@ -45,7 +47,8 @@ class _AudioLevelAvatarState extends State { child: Text( Utilities.getAvatarTitle( context.read().peer.name), - style: TextStyle(fontSize: 36, color: Colors.white), + style: GoogleFonts.inter( + fontSize: 36, color: Colors.white), )), ); }), diff --git a/example/lib/common/ui/organisms/change_role_options.dart b/example/lib/common/ui/organisms/change_role_options.dart index e7c78397b..8ff3ad03a 100644 --- a/example/lib/common/ui/organisms/change_role_options.dart +++ b/example/lib/common/ui/organisms/change_role_options.dart @@ -1,6 +1,7 @@ //Package imports import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; //Project imports import 'package:hmssdk_flutter/hmssdk_flutter.dart'; @@ -34,7 +35,7 @@ class _ChangeRoleOptionDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(widget.peerName), + title: Text(widget.peerName,style: GoogleFonts.inter(),), content: Container( width: double.infinity, child: FutureBuilder>( @@ -53,7 +54,7 @@ class _ChangeRoleOptionDialogState extends State { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text("Role To: "), + Text("Role To: ",style: GoogleFonts.inter(),), Flexible( child: DropdownButton2( buttonWidth: MediaQuery.of(context).size.width / 2, @@ -66,7 +67,7 @@ class _ChangeRoleOptionDialogState extends State { }, items: data.data!.map((role) { return DropdownMenuItem( - child: Text(role.name), + child: Text(role.name,style: GoogleFonts.inter(),), value: role.name, ); }).toList(), @@ -90,7 +91,7 @@ class _ChangeRoleOptionDialogState extends State { SizedBox( width: 16, ), - Text('Force change') + Text('Force change',style: GoogleFonts.inter(),) ], ), ), @@ -106,7 +107,7 @@ class _ChangeRoleOptionDialogState extends State { onPressed: () { Navigator.pop(context); }, - child: Text("Cancel")), + child: Text("Cancel",style: GoogleFonts.inter(),)), ElevatedButton( onPressed: () { widget.changeRole( @@ -114,14 +115,14 @@ class _ChangeRoleOptionDialogState extends State { (element) => element.name == valueChoose), forceValue); }, - child: Text("Change Role")), + child: Text("Change Role",style: GoogleFonts.inter(),)), ], ) ], ), ); } - return Text('No roles available'); + return Text('No roles available',style: GoogleFonts.inter(),); }, future: widget.getRoleFunction, ), diff --git a/example/lib/common/ui/organisms/change_track_options.dart b/example/lib/common/ui/organisms/change_track_options.dart index 5e8ef024f..30f4fb002 100644 --- a/example/lib/common/ui/organisms/change_track_options.dart +++ b/example/lib/common/ui/organisms/change_track_options.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; class ChangeTrackOptionDialog extends StatefulWidget { final String peerName; @@ -31,7 +32,10 @@ class _ChangeTrackOptionDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(widget.peerName), + title: Text( + widget.peerName, + style: GoogleFonts.inter(), + ), content: Container( width: double.infinity, child: Column( @@ -53,7 +57,10 @@ class _ChangeTrackOptionDialogState extends State { SizedBox( width: 16, ), - Text("${widget.isVideoMuted ? "Unmute" : "Mute"} video") + Text( + "${widget.isVideoMuted ? "Unmute" : "Mute"} video", + style: GoogleFonts.inter(), + ) ], ), ), @@ -77,7 +84,10 @@ class _ChangeTrackOptionDialogState extends State { SizedBox( width: 16, ), - Text("${widget.isAudioMuted ? "Unmute" : "Mute"} audio") + Text( + "${widget.isAudioMuted ? "Unmute" : "Mute"} audio", + style: GoogleFonts.inter(), + ), ], ), ), @@ -98,7 +108,10 @@ class _ChangeTrackOptionDialogState extends State { SizedBox( width: 16, ), - Text("Remove Peer") + Text( + "Remove Peer", + style: GoogleFonts.inter(), + ) ], ), ), diff --git a/example/lib/common/ui/organisms/chat_bottom_sheet.dart b/example/lib/common/ui/organisms/chat_bottom_sheet.dart index 33c5817cf..92aa1439b 100644 --- a/example/lib/common/ui/organisms/chat_bottom_sheet.dart +++ b/example/lib/common/ui/organisms/chat_bottom_sheet.dart @@ -2,6 +2,7 @@ import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -76,7 +77,7 @@ class _ChatWidgetState extends State { }, items: [ DropdownMenuItem( - child: Text("Everyone"), + child: Text("Everyone",style: GoogleFonts.inter(),), value: "Everyone", ), ...data.item2 @@ -84,7 +85,7 @@ class _ChatWidgetState extends State { return !peer.isLocal ? DropdownMenuItem( child: Text( - "${peer.name} ${peer.isLocal ? "(You)" : ""}"), + "${peer.name} ${peer.isLocal ? "(You)" : ""}",style: GoogleFonts.inter(),), value: peer.peerId, ) : null; @@ -94,7 +95,7 @@ class _ChatWidgetState extends State { ...roles .map((role) => DropdownMenuItem( - child: Text("${role.name}"), + child: Text("${role.name}",style: GoogleFonts.inter(),), value: role.name, )) .toList() @@ -129,7 +130,7 @@ class _ChatWidgetState extends State { // if (!_meetingStore.isMeetingStarted) return SizedBox(); if (data.item2 == 0) - return Center(child: Text('No messages')); + return Center(child: Text('No messages',style: GoogleFonts.inter(),)); return ListView( children: List.generate( @@ -147,7 +148,7 @@ class _ChatWidgetState extends State { Expanded( child: Text( data.item1[index].sender?.name ?? "", - style: TextStyle( + style: GoogleFonts.inter( fontSize: 14.0, color: MediaQuery.of(context) .platformBrightness == @@ -160,7 +161,7 @@ class _ChatWidgetState extends State { Text( formatter .format(data.item1[index].time), - style: TextStyle( + style: GoogleFonts.inter( fontSize: 10.0, color: Colors.white, fontWeight: FontWeight.w900), @@ -176,7 +177,7 @@ class _ChatWidgetState extends State { Flexible( child: Text( data.item1[index].message.toString(), - style: TextStyle( + style: GoogleFonts.inter( fontSize: 14.0, color: Colors.white, fontWeight: FontWeight.w700), @@ -190,7 +191,7 @@ class _ChatWidgetState extends State { .hmsMessageRecipient! .hmsMessageRecipientType) .toLowerCase(), - style: TextStyle( + style: GoogleFonts.inter( fontSize: 14.0, color: Colors.blue, fontWeight: FontWeight.w500), diff --git a/example/lib/common/ui/organisms/degrade_tile.dart b/example/lib/common/ui/organisms/degrade_tile.dart index 13b41573a..78fd2dcc2 100644 --- a/example/lib/common/ui/organisms/degrade_tile.dart +++ b/example/lib/common/ui/organisms/degrade_tile.dart @@ -1,5 +1,6 @@ //package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; //Package imports @@ -41,7 +42,8 @@ class _DegradeTileState extends State { child: Text( Utilities.getAvatarTitle( context.read().peer.name), - style: TextStyle(fontSize: 36, color: Colors.white), + style: GoogleFonts.inter( + fontSize: 36, color: Colors.white), ))), )); }, diff --git a/example/lib/common/ui/organisms/full_screen_view.dart b/example/lib/common/ui/organisms/full_screen_view.dart index 3541011ad..eade0f05a 100644 --- a/example/lib/common/ui/organisms/full_screen_view.dart +++ b/example/lib/common/ui/organisms/full_screen_view.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; //Project imports @@ -36,7 +37,10 @@ Widget fullScreenView( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.screen_share), - Text("You are sharing your screen"), + Text( + "You are sharing your screen", + style: GoogleFonts.inter(), + ), ], ), ) diff --git a/example/lib/common/ui/organisms/grid_hero_view.dart b/example/lib/common/ui/organisms/grid_hero_view.dart index 95e438ae8..b06e59d2c 100644 --- a/example/lib/common/ui/organisms/grid_hero_view.dart +++ b/example/lib/common/ui/organisms/grid_hero_view.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; //Project imports @@ -35,7 +36,7 @@ Widget gridHeroView( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.screen_share), - Text("You are sharing your screen"), + Text("You are sharing your screen",style: GoogleFonts.inter(),), ], ), ) diff --git a/example/lib/common/ui/organisms/grid_video_view.dart b/example/lib/common/ui/organisms/grid_video_view.dart index 9b35d63f9..1e19c8c1c 100644 --- a/example/lib/common/ui/organisms/grid_video_view.dart +++ b/example/lib/common/ui/organisms/grid_video_view.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; //Project imports @@ -36,7 +37,7 @@ Widget gridVideoView( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.screen_share), - Text("You are sharing your screen"), + Text("You are sharing your screen",style: GoogleFonts.inter(),), ], ), ) diff --git a/example/lib/common/ui/organisms/offline_screen.dart b/example/lib/common/ui/organisms/offline_screen.dart index 22e8125da..eca69a4ed 100644 --- a/example/lib/common/ui/organisms/offline_screen.dart +++ b/example/lib/common/ui/organisms/offline_screen.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; class OfflineWidget extends StatelessWidget { @override @@ -27,7 +28,8 @@ class OfflineWidget extends StatelessWidget { child: Center( child: Text( 'Oops, No internet connection.\n\nReconnecting...', - style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + style: GoogleFonts.inter( + fontSize: 20, fontWeight: FontWeight.bold), ), ), ), diff --git a/example/lib/common/ui/organisms/participant_organism.dart b/example/lib/common/ui/organisms/participant_organism.dart index e7b0d84eb..beb420d09 100644 --- a/example/lib/common/ui/organisms/participant_organism.dart +++ b/example/lib/common/ui/organisms/participant_organism.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; //Project imports @@ -43,7 +44,7 @@ class _ParticipantOrganismState extends State { width: width / 3, child: Text( peer.name, - style: TextStyle(fontSize: 20.0), + style: GoogleFonts.inter(fontSize: 20.0), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -99,7 +100,7 @@ class _ParticipantOrganismState extends State { "${peer.role.name}", overflow: TextOverflow.clip, maxLines: 1, - style: TextStyle( + style: GoogleFonts.inter( color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.bold), diff --git a/example/lib/common/ui/organisms/peer_name.dart b/example/lib/common/ui/organisms/peer_name.dart index c70fa1bf8..a35ce3d8d 100644 --- a/example/lib/common/ui/organisms/peer_name.dart +++ b/example/lib/common/ui/organisms/peer_name.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -29,7 +30,7 @@ class _PeerNameState extends State { maxLines: 1, softWrap: true, overflow: TextOverflow.ellipsis, - style: TextStyle( + style: GoogleFonts.inter( fontWeight: FontWeight.w500, color: Colors.white, fontSize: 16), diff --git a/example/lib/common/ui/organisms/role_change_request_dialog.dart b/example/lib/common/ui/organisms/role_change_request_dialog.dart index 88357fbe0..1598ce287 100644 --- a/example/lib/common/ui/organisms/role_change_request_dialog.dart +++ b/example/lib/common/ui/organisms/role_change_request_dialog.dart @@ -1,5 +1,6 @@ // Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; // Project imports import 'package:hmssdk_flutter/hmssdk_flutter.dart'; @@ -26,19 +27,28 @@ class _RoleChangeDialogOrganismState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text(message), + Text( + message, + style: GoogleFonts.inter(), + ), ], ), ), actions: [ ElevatedButton( - child: Text('Cancel'), + child: Text( + 'Cancel', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context, ''); }, ), ElevatedButton( - child: Text('OK'), + child: Text( + 'OK', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context, 'OK'); }, diff --git a/example/lib/common/ui/organisms/rtc_stats_view.dart b/example/lib/common/ui/organisms/rtc_stats_view.dart index d2ead4db4..67496a799 100644 --- a/example/lib/common/ui/organisms/rtc_stats_view.dart +++ b/example/lib/common/ui/organisms/rtc_stats_view.dart @@ -1,4 +1,5 @@ //Package imports +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; import 'package:flutter/material.dart'; @@ -47,16 +48,23 @@ class Stats extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Text( - "Width\t ${data.item3?.hmsLocalVideoStats?.resolution.width.toStringAsFixed(2) ?? "0.00"}"), + "Width\t ${data.item3?.hmsLocalVideoStats?.resolution.width.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter(), + ), Text( - "Height\t ${data.item3?.hmsLocalVideoStats?.resolution.height.toStringAsFixed(2) ?? "0.00"}"), + "Height\t ${data.item3?.hmsLocalVideoStats?.resolution.height.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), Text( - "FPS\t ${data.item3?.hmsLocalVideoStats?.frameRate.toStringAsFixed(2) ?? "0.00"}"), - Text("Downlink\t ${data.item4 ?? "-1"}"), + "FPS\t ${data.item3?.hmsLocalVideoStats?.frameRate.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), + Text("Downlink\t ${data.item4 ?? "-1"}", + style: GoogleFonts.inter()), Text( - "Bitrate(V)\t ${data.item3?.hmsLocalVideoStats?.bitrate.toStringAsFixed(2) ?? "0.00"}"), + "Bitrate(V)\t ${data.item3?.hmsLocalVideoStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), Text( - "Bitrate(A)\t ${data.item3?.hmsLocalAudioStats?.bitrate.toStringAsFixed(2) ?? "0.00"}"), + "Bitrate(A)\t ${data.item3?.hmsLocalAudioStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), ], ), ); @@ -79,20 +87,28 @@ class Stats extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Text( - "Width\t ${data.item3?.hmsRemoteVideoStats?.resolution.width.toStringAsFixed(2) ?? "0.00"}"), + "Width\t ${data.item3?.hmsRemoteVideoStats?.resolution.width.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), Text( - "Height\t ${data.item3?.hmsRemoteVideoStats?.resolution.height.toStringAsFixed(2) ?? "0.00"}"), + "Height\t ${data.item3?.hmsRemoteVideoStats?.resolution.height.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), Text( - "FPS\t ${data.item3?.hmsRemoteVideoStats?.frameRate.toStringAsFixed(2) ?? "0.00"}"), - Text("Downlink\t ${data.item4 ?? "-1"}"), + "FPS\t ${data.item3?.hmsRemoteVideoStats?.frameRate.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), + Text("Downlink\t ${data.item4 ?? "-1"}", + style: GoogleFonts.inter()), Text( - "Bitrate(V)\t ${data.item3?.hmsRemoteVideoStats?.bitrate.toStringAsFixed(2) ?? "0.00"}"), + "Bitrate(V)\t ${data.item3?.hmsRemoteVideoStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), Text( - "Bitrate(A)\t ${data.item3?.hmsRemoteAudioStats?.bitrate.toStringAsFixed(2) ?? "0.00"}"), + "Bitrate(A)\t ${data.item3?.hmsRemoteAudioStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), Text( - "Jitter(V)\t ${data.item3?.hmsRemoteVideoStats?.jitter.toStringAsFixed(2) ?? "0.00"}"), + "Jitter(V)\t ${data.item3?.hmsRemoteVideoStats?.jitter.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), Text( - "Jitter(A)\t ${data.item3?.hmsRemoteAudioStats?.jitter.toStringAsFixed(2) ?? "0.00"}"), + "Jitter(A)\t ${data.item3?.hmsRemoteAudioStats?.jitter.toStringAsFixed(2) ?? "0.00"}", + style: GoogleFonts.inter()), ], ), ); diff --git a/example/lib/common/ui/organisms/title_bar.dart b/example/lib/common/ui/organisms/title_bar.dart index 959e2a7a4..8ffdb9956 100644 --- a/example/lib/common/ui/organisms/title_bar.dart +++ b/example/lib/common/ui/organisms/title_bar.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/meeting/meeting_participants_list.dart'; import 'package:provider/provider.dart'; @@ -20,8 +21,10 @@ class TitleBar extends StatelessWidget { return (speakerName != null) ? Container( width: 164, - child: Text("🔊 $speakerName", overflow: TextOverflow.clip)) - : Text("▼ " + Constant.meetingCode); + child: Text("🔊 $speakerName", + overflow: TextOverflow.clip, + style: GoogleFonts.inter())) + : Text("▼ " + Constant.meetingCode, style: GoogleFonts.inter()); }), ); } diff --git a/example/lib/common/ui/organisms/track_change_request_dialog.dart b/example/lib/common/ui/organisms/track_change_request_dialog.dart index 1d3b7d07b..12799c685 100644 --- a/example/lib/common/ui/organisms/track_change_request_dialog.dart +++ b/example/lib/common/ui/organisms/track_change_request_dialog.dart @@ -1,5 +1,6 @@ // Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; // Project imports import 'package:hmssdk_flutter/hmssdk_flutter.dart'; @@ -33,19 +34,19 @@ class _RoleChangeDialogOrganismState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text(message), + Text(message,style: GoogleFonts.inter(),), ], ), ), actions: [ ElevatedButton( - child: Text('Cancel'), + child: Text('Cancel',style: GoogleFonts.inter(),), onPressed: () { Navigator.pop(context, ''); }, ), ElevatedButton( - child: Text('OK'), + child: Text('OK',style: GoogleFonts.inter(),), onPressed: () { Navigator.pop(context, 'OK'); }, diff --git a/example/lib/common/ui/organisms/user_name_dialog_organism.dart b/example/lib/common/ui/organisms/user_name_dialog_organism.dart index f13ec7685..f89cb887a 100644 --- a/example/lib/common/ui/organisms/user_name_dialog_organism.dart +++ b/example/lib/common/ui/organisms/user_name_dialog_organism.dart @@ -1,5 +1,6 @@ // Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; class UserNameDialogOrganism extends StatefulWidget { const UserNameDialogOrganism({Key? key}) : super(key: key); @@ -21,24 +22,32 @@ class _UserNameDialogOrganismState extends State { TextField( autofocus: true, controller: userNameController, + style: GoogleFonts.inter(), decoration: InputDecoration( border: OutlineInputBorder( borderRadius: BorderRadius.all(Radius.circular(16)), ), - hintText: 'Enter your Name'), + hintText: 'Enter your Name', + hintStyle: GoogleFonts.inter()), ), ], ), ), actions: [ ElevatedButton( - child: Text('Cancel'), + child: Text( + 'Cancel', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context, ''); }, ), ElevatedButton( - child: Text('OK'), + child: Text( + 'OK', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context, userNameController.text); }, diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index 0c1ab8950..4614409f8 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:provider/provider.dart'; @@ -17,7 +18,7 @@ class UtilityComponents { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( event, - style: TextStyle(color: Colors.white), + style: GoogleFonts.inter(color: Colors.white), ), backgroundColor: Colors.black87, )); @@ -30,7 +31,7 @@ class UtilityComponents { builder: (ctx) => AlertDialog( title: Text( 'Leave Room?', - style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700), + style: GoogleFonts.inter(fontSize: 24, fontWeight: FontWeight.w700), ), actions: [ ElevatedButton( @@ -41,12 +42,12 @@ class UtilityComponents { _meetingStore.leave(), Navigator.popUntil(context, (route) => route.isFirst) }, - child: Text('Yes', style: TextStyle(fontSize: 24))), + child: Text('Yes', style: GoogleFonts.inter(fontSize: 24))), ElevatedButton( onPressed: () => Navigator.pop(context, false), child: Text( 'Cancel', - style: TextStyle(fontSize: 24), + style: GoogleFonts.inter(fontSize: 24), ), ), ], @@ -100,10 +101,10 @@ class UtilityComponents { context: context, builder: (context) { return AlertDialog( - content: Text(message), + content: Text(message,style: GoogleFonts.inter(),), actions: [ ElevatedButton( - child: Text('OK'), + child: Text('OK',style: GoogleFonts.inter(),), onPressed: () { Navigator.pop(context); }, @@ -140,13 +141,13 @@ class UtilityComponents { ), actions: [ ElevatedButton( - child: Text('Cancel'), + child: Text('Cancel',style: GoogleFonts.inter(),), onPressed: () { Navigator.pop(context, ''); }, ), ElevatedButton( - child: Text('OK'), + child: Text('OK',style: GoogleFonts.inter(),), onPressed: () { if (textController.text == "") { } else { @@ -168,7 +169,7 @@ class UtilityComponents { context: context, builder: (context) => StatefulBuilder(builder: (context, setState) { return AlertDialog( - title: Text("Select Role for Mute"), + title: Text("Select Role for Mute",style: GoogleFonts.inter(),), content: Container( width: 300, child: Column( @@ -183,7 +184,7 @@ class UtilityComponents { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(roles[index].name), + Text(roles[index].name,style: GoogleFonts.inter(),), Checkbox( value: _selectedRoles .contains(roles[index]), @@ -203,7 +204,7 @@ class UtilityComponents { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Mute All"), + Text("Mute All",style: GoogleFonts.inter(),), Checkbox( value: muteAll, onChanged: (bool? value) { @@ -223,7 +224,7 @@ class UtilityComponents { onPressed: () { Navigator.pop(context); }, - child: Text("Cancel")), + child: Text("Cancel",style: GoogleFonts.inter(),)), ElevatedButton( onPressed: () { if (muteAll) { @@ -235,7 +236,7 @@ class UtilityComponents { } Navigator.pop(context); }, - child: Text("Mute Roles")) + child: Text("Mute Roles",style: GoogleFonts.inter(),)) ], ) ], @@ -272,7 +273,7 @@ class UtilityComponents { hintText: placeholder), ), CheckboxListTile( - title: Text("Recording"), + title: Text("Recording",style: GoogleFonts.inter(),), activeColor: Colors.blue, controlAffinity: ListTileControlAffinity.trailing, value: isRecordingEnabled, @@ -286,13 +287,13 @@ class UtilityComponents { ), actions: [ ElevatedButton( - child: Text('Cancel'), + child: Text('Cancel',style: GoogleFonts.inter(),), onPressed: () { Navigator.pop(context, {"url": "", "toRecord": "false"}); }, ), ElevatedButton( - child: Text('OK'), + child: Text('OK',style: GoogleFonts.inter(),), onPressed: () { if (textController.text == "" && !isRecordingEnabled) { } else { @@ -310,57 +311,4 @@ class UtilityComponents { return answer; } - static List videoTileWidget( - int itemCount, List peerTracks, Size size) { - return List.generate(itemCount, (index) { - if (peerTracks[index].track?.source != "REGULAR") { - return ChangeNotifierProvider.value( - key: ValueKey(peerTracks[index].uid), - value: peerTracks[index], - child: peerTracks[index].peer.isLocal - ? Container( - margin: EdgeInsets.all(2), - decoration: BoxDecoration( - border: Border.all(color: Colors.grey, width: 1.0), - borderRadius: BorderRadius.all(Radius.circular(10))), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Icon(Icons.screen_share), - Text("You are sharing your screen"), - ], - ), - ) - : VideoTile( - key: Key(peerTracks[index].uid), - scaleType: ScaleType.SCALE_ASPECT_FIT, - itemHeight: size.height, - itemWidth: size.width, - ), - ); - } - return ChangeNotifierProvider.value( - key: ValueKey(peerTracks[index].uid), - value: peerTracks[index], - child: VideoTile( - key: ValueKey(peerTracks[index].uid), - itemHeight: size.height, - itemWidth: size.width, - )); - }); - } - - static List audioTileWidget( - int itemCount, List peerTracks, Size size) { - return List.generate(itemCount, (index) { - return ChangeNotifierProvider.value( - key: ValueKey(peerTracks[index].uid), - value: peerTracks[index], - child: AudioTile( - key: ValueKey(peerTracks[index].uid), - itemHeight: size.height, - itemWidth: size.width, - )); - }); - } } diff --git a/example/lib/hls_viewer/hls_viewer.dart b/example/lib/hls_viewer/hls_viewer.dart index d711acc0d..bceca9e2e 100644 --- a/example/lib/hls_viewer/hls_viewer.dart +++ b/example/lib/hls_viewer/hls_viewer.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'package:video_player/video_player.dart'; @@ -48,7 +49,7 @@ class _HLSViewerState extends State { ) : Text( "Waiting for the HLS Streaming to start...", - style: TextStyle(fontSize: 20.0), + style: GoogleFonts.inter(fontSize: 20.0), ), ), ); diff --git a/example/lib/main.dart b/example/lib/main.dart index ccfac0566..54461e7f1 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -7,6 +7,7 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:wakelock/wakelock.dart'; @@ -140,7 +141,10 @@ class _HomePageState extends State { onWillPop: _closeApp, child: Scaffold( appBar: AppBar( - title: Text('100ms'), + title: Text( + '100ms', + style: GoogleFonts.inter(), + ), actions: [ PopupMenuButton( onSelected: handleClick, @@ -154,11 +158,11 @@ class _HomePageState extends State { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ if (skipPreview) - Text("Enable Preview") + Text("Enable Preview", style: GoogleFonts.inter()) else Text( "Disable Preview", - style: TextStyle(color: Colors.blue), + style: GoogleFonts.inter(color: Colors.blue), ), if (skipPreview) SvgPicture.asset( @@ -179,9 +183,12 @@ class _HomePageState extends State { children: [ if (mirrorCamera) Text("Disable Mirroring", - style: TextStyle(color: Colors.blue)) + style: GoogleFonts.inter(color: Colors.blue)) else - Text("Enable Mirroring"), + Text( + "Enable Mirroring", + style: GoogleFonts.inter(), + ), Icon( Icons.camera_front, color: mirrorCamera ? Colors.blue : Colors.white, @@ -196,9 +203,12 @@ class _HomePageState extends State { children: [ if (showStats) Text("Disable Stats", - style: TextStyle(color: Colors.blue)) + style: GoogleFonts.inter(color: Colors.blue)) else - Text("Enable Stats"), + Text( + "Enable Stats", + style: GoogleFonts.inter(), + ), SvgPicture.asset( 'assets/icons/stats.svg', color: showStats ? Colors.blue : Colors.white, @@ -211,7 +221,8 @@ class _HomePageState extends State { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Version ${_packageInfo.version}"), + Text("Version ${_packageInfo.version}", + style: GoogleFonts.inter()), ], ), value: 4, @@ -234,7 +245,7 @@ class _HomePageState extends State { height: 70, ), Text('Join Meeting', - style: TextStyle( + style: GoogleFonts.inter( height: 1, fontSize: 24, fontWeight: FontWeight.bold)), @@ -244,10 +255,12 @@ class _HomePageState extends State { Padding( padding: const EdgeInsets.symmetric(horizontal: 10), child: TextField( + style: GoogleFonts.inter(), controller: roomIdController, keyboardType: TextInputType.url, decoration: InputDecoration( hintText: 'Enter Room URL', + hintStyle: GoogleFonts.inter(), suffixIcon: IconButton( onPressed: roomIdController.clear, icon: Icon(Icons.clear), @@ -322,7 +335,7 @@ class _HomePageState extends State { mainAxisAlignment: MainAxisAlignment.center, children: [ Text('Join Meeting', - style: TextStyle(height: 1, fontSize: 20)), + style: GoogleFonts.inter(height: 1, fontSize: 20)), SizedBox( width: 5, ), diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 4a7890c24..6b5a05f3f 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -5,6 +5,7 @@ import 'dart:io'; import 'package:connectivity_checker/connectivity_checker.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/full_screen_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/grid_audio_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/grid_hero_view.dart'; @@ -190,7 +191,7 @@ class _MeetingPageState extends State case 11: List roles = await _meetingStore.getRoles(); - UtilityComponents.showRoleList(context, roles,_meetingStore); + UtilityComponents.showRoleList(context, roles, _meetingStore); break; case 12: _meetingStore.changeStatsVisible(); @@ -325,8 +326,9 @@ class _MeetingPageState extends State bottom: 8.0), child: Text( "Waiting for HLS to start...", - style: TextStyle( - fontSize: 20), + style: + GoogleFonts.inter( + fontSize: 20), ), ), CircularProgressIndicator( @@ -340,7 +342,9 @@ class _MeetingPageState extends State if (data.item3 == 0) { return Center( child: Text( - 'Waiting for others to join!')); + 'Waiting for others to join!', + style: GoogleFonts.inter(), + )); } Size size = MediaQuery.of(context).size; if (data.item5 == MeetingMode.Hero) { @@ -638,7 +642,10 @@ class _MeetingPageState extends State child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Send Logs"), + Text( + "Send Logs", + style: GoogleFonts.inter(), + ), SvgPicture.asset("assets/icons/bug.svg"), ], ), @@ -653,7 +660,7 @@ class _MeetingPageState extends State meetingStore.isRecordingStarted ? "Recording " : "Record", - style: TextStyle( + style: GoogleFonts.inter( color: meetingStore.isRecordingStarted ? Colors.blue : Colors.white, @@ -674,6 +681,7 @@ class _MeetingPageState extends State children: [ Text( "Toggle Camera ", + style: GoogleFonts.inter(), ), SvgPicture.asset("assets/icons/camera.svg"), ]), @@ -685,6 +693,7 @@ class _MeetingPageState extends State children: [ Text( "Participants ", + style: GoogleFonts.inter(), ), SvgPicture.asset("assets/icons/participants.svg"), ]), @@ -698,6 +707,7 @@ class _MeetingPageState extends State meetingStore.meetingMode == MeetingMode.Audio ? "Video View" : "Audio View", + style: GoogleFonts.inter(), ), SvgPicture.asset( meetingStore.meetingMode == MeetingMode.Audio @@ -715,7 +725,7 @@ class _MeetingPageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("Active Speaker Mode", - style: TextStyle( + style: GoogleFonts.inter( color: meetingStore.isActiveSpeakerMode ? Colors.blue : Colors.white, @@ -734,7 +744,7 @@ class _MeetingPageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("Hero Mode", - style: TextStyle( + style: GoogleFonts.inter( color: meetingStore.meetingMode == MeetingMode.Hero ? Colors.blue : Colors.white, @@ -753,7 +763,7 @@ class _MeetingPageState extends State mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text("Single Tile Mode", - style: TextStyle( + style: GoogleFonts.inter( color: meetingStore.meetingMode == MeetingMode.Single ? Colors.blue : Colors.white, @@ -773,6 +783,7 @@ class _MeetingPageState extends State children: [ Text( "Change Name", + style: GoogleFonts.inter(), ), SvgPicture.asset("assets/icons/pencil.svg"), ]), @@ -785,7 +796,7 @@ class _MeetingPageState extends State children: [ Text( meetingStore.hasHlsStarted ? "Stop HLS" : "Start HLS", - style: TextStyle( + style: GoogleFonts.inter( color: meetingStore.hasHlsStarted ? Colors.blue : Colors.white, @@ -805,6 +816,7 @@ class _MeetingPageState extends State children: [ Text( "Mute", + style: GoogleFonts.inter(), ), SvgPicture.asset("assets/icons/mic_state_off.svg"), ]), @@ -816,7 +828,7 @@ class _MeetingPageState extends State children: [ Text( "Stats", - style: TextStyle( + style: GoogleFonts.inter( color: meetingStore.isStatsVisible ? Colors.blue : Colors.white), @@ -838,7 +850,7 @@ class _MeetingPageState extends State children: [ Text( "Screen share", - style: TextStyle( + style: GoogleFonts.inter( color: meetingStore.isScreenShareOn ? Colors.blue : Colors.white), @@ -859,6 +871,7 @@ class _MeetingPageState extends State children: [ Text( "End Room", + style: GoogleFonts.inter(), ), SvgPicture.asset("assets/icons/end_room.svg"), ]), diff --git a/example/lib/meeting/meeting_participants_list.dart b/example/lib/meeting/meeting_participants_list.dart index 7fca8d24d..9f9d8262a 100644 --- a/example/lib/meeting/meeting_participants_list.dart +++ b/example/lib/meeting/meeting_participants_list.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -27,7 +28,10 @@ class _ParticipantsListState extends State { return Row( children: [ SvgPicture.asset("assets/icons/participants.svg"), - Text(" Participants ($length)"), + Text( + " Participants ($length)", + style: GoogleFonts.inter(), + ), ], ); }), @@ -52,7 +56,10 @@ class _ParticipantsListState extends State { .toList(), ); } else { - return Text(("No Participants")); + return Text( + "No Participants", + style: GoogleFonts.inter(), + ); } }), ); diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index d9d76f38d..69040fcca 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -4,6 +4,7 @@ import 'package:connectivity_checker/connectivity_checker.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; +import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter/hmssdk_flutter.dart'; import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; @@ -113,7 +114,7 @@ class _PreviewPageState extends State with WidgetsBindingObserver { child: Text( Utilities.getAvatarTitle( _previewStore.peer!.name), - style: TextStyle( + style: GoogleFonts.inter( fontSize: 36, color: Colors.white), ))), @@ -189,15 +190,16 @@ class _PreviewPageState extends State with WidgetsBindingObserver { children: [ Text( peer.name, - style: TextStyle( - fontWeight: - FontWeight - .bold, - color: - Colors.white), + style: + GoogleFonts.inter( + fontWeight: + FontWeight + .bold, + color: Colors + .white), ), Text(peer.role.name, - style: TextStyle( + style: GoogleFonts.inter( fontWeight: FontWeight .bold, @@ -237,7 +239,7 @@ class _PreviewPageState extends State with WidgetsBindingObserver { Text( _previewStore.peers.length .toString(), - style: TextStyle( + style: GoogleFonts.inter( fontWeight: FontWeight.bold, fontSize: 16), ) @@ -318,7 +320,8 @@ class _PreviewPageState extends State with WidgetsBindingObserver { }, child: Text( 'Join HLS ', - style: TextStyle(height: 1, fontSize: 18), + style: GoogleFonts.inter( + height: 1, fontSize: 18), ), ) : ElevatedButton( @@ -357,7 +360,8 @@ class _PreviewPageState extends State with WidgetsBindingObserver { }, child: Text( 'Join Now', - style: TextStyle(height: 1, fontSize: 18), + style: GoogleFonts.inter( + height: 1, fontSize: 18), ), ) : Container(), diff --git a/example/pubspec.lock b/example/pubspec.lock index 37132d8dc..9310f268a 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -50,13 +50,6 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.3.1" - clickable_list_wheel_view: - dependency: "direct main" - description: - name: clickable_list_wheel_view - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.0" clock: dependency: transitive description: @@ -230,6 +223,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.6.1" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.3" flutter_test: dependency: "direct dev" description: flutter @@ -254,6 +254,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + google_fonts: + dependency: "direct main" + description: + name: google_fonts + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.1" hmssdk_flutter: dependency: "direct main" description: @@ -387,6 +394,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.8.0" + path_drawing: + dependency: transitive + description: + name: path_drawing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" path_provider: dependency: "direct main" description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 097b5968c..d6b9105fb 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: avatar_glow: fluttertoast: flutter_svg: + google_fonts: dev_dependencies: flutter_test: From fe6826c9a8e877c58ceb6c0275ebdd457e72890f Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 31 May 2022 18:05:42 +0530 Subject: [PATCH 34/67] ui fix --- example/lib/common/ui/organisms/full_screen_view.dart | 2 +- example/lib/common/ui/organisms/grid_audio_view.dart | 2 +- example/lib/common/ui/organisms/grid_hero_view.dart | 2 +- example/lib/common/ui/organisms/grid_video_view.dart | 7 +++++-- example/lib/common/util/utility_function.dart | 4 ++-- example/lib/meeting/meeting_page.dart | 2 +- example/lib/preview/preview_page.dart | 8 +++----- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/example/lib/common/ui/organisms/full_screen_view.dart b/example/lib/common/ui/organisms/full_screen_view.dart index eade0f05a..f33dab464 100644 --- a/example/lib/common/ui/organisms/full_screen_view.dart +++ b/example/lib/common/ui/organisms/full_screen_view.dart @@ -70,5 +70,5 @@ Widget fullScreenView( controller: Provider.of(context).controller, gridDelegate: SliverStairedGridDelegate( startCrossAxisDirectionReversed: false, - pattern: [StairedGridTile(1, (size.height * 0.84) / (size.width))])); + pattern: [StairedGridTile(1, (size.height * 0.83) / (size.width))])); } diff --git a/example/lib/common/ui/organisms/grid_audio_view.dart b/example/lib/common/ui/organisms/grid_audio_view.dart index 558008df2..ba5f2f8ae 100644 --- a/example/lib/common/ui/organisms/grid_audio_view.dart +++ b/example/lib/common/ui/organisms/grid_audio_view.dart @@ -33,7 +33,7 @@ Widget gridAudioView( } List pattern(int itemCount, Size size) { - double ratio = (size.height * 0.84) / (size.width); + double ratio = (size.height * 0.83) / (size.width); List tiles = []; int gridView = itemCount ~/ 6; int tileLeft = itemCount - (gridView * 6); diff --git a/example/lib/common/ui/organisms/grid_hero_view.dart b/example/lib/common/ui/organisms/grid_hero_view.dart index b06e59d2c..f9d5612ee 100644 --- a/example/lib/common/ui/organisms/grid_hero_view.dart +++ b/example/lib/common/ui/organisms/grid_hero_view.dart @@ -64,7 +64,7 @@ Widget gridHeroView( } List pattern(int itemCount, int screenShareCount, Size size) { - double ratio = (size.width) / (size.height * 0.84); + double ratio = (size.width) / (size.height * 0.83); List tiles = []; for (int i = 0; i < screenShareCount; i++) { diff --git a/example/lib/common/ui/organisms/grid_video_view.dart b/example/lib/common/ui/organisms/grid_video_view.dart index 1e19c8c1c..845f5412e 100644 --- a/example/lib/common/ui/organisms/grid_video_view.dart +++ b/example/lib/common/ui/organisms/grid_video_view.dart @@ -37,7 +37,10 @@ Widget gridVideoView( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.screen_share), - Text("You are sharing your screen",style: GoogleFonts.inter(),), + Text( + "You are sharing your screen", + style: GoogleFonts.inter(), + ), ], ), ) @@ -71,7 +74,7 @@ Widget gridVideoView( } List pattern(int itemCount, int screenShareCount, Size size) { - double ratio = (size.height * 0.84) / (size.width); + double ratio = (size.height * 0.83) / (size.width); List tiles = []; for (int i = 0; i < screenShareCount; i++) { tiles.add(StairedGridTile(1, ratio)); diff --git a/example/lib/common/util/utility_function.dart b/example/lib/common/util/utility_function.dart index 9df8dbfcc..2d90ab344 100644 --- a/example/lib/common/util/utility_function.dart +++ b/example/lib/common/util/utility_function.dart @@ -14,12 +14,12 @@ class Utilities { name += parts[1][0]; } } - return name; + return name.toUpperCase(); } static Color getBackgroundColour(String name) { return Utilities - .colors[name.toLowerCase().codeUnitAt(0) % Utilities.colors.length]; + .colors[name.toUpperCase().codeUnitAt(0) % Utilities.colors.length]; } static List colors = [ diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 6b5a05f3f..fe1a01e43 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -279,7 +279,7 @@ class _MeetingPageState extends State body: Stack( children: [ Container( - height: MediaQuery.of(context).size.height * 0.84, + height: MediaQuery.of(context).size.height * 0.83, child: Selector< MeetingStore, Tuple6, bool, int, int, diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index 69040fcca..2214acbd1 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -105,11 +105,9 @@ class _PreviewPageState extends State with WidgetsBindingObserver { width: itemWidth, child: Center( child: CircleAvatar( - backgroundColor: Utilities.colors[ - _previewStore.peer!.name - .toLowerCase() - .codeUnitAt(0) % - Utilities.colors.length], + backgroundColor: + Utilities.getBackgroundColour( + _previewStore.peer!.name), radius: 36, child: Text( Utilities.getAvatarTitle( From 01fdeb05b34f7a2fb9a2f444849dd10a0be6f787 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 31 May 2022 18:31:55 +0530 Subject: [PATCH 35/67] checkbox color fix --- .../lib/common/util/utility_components.dart | 74 ++++++++++++++----- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index 4614409f8..5de520c22 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -9,16 +9,13 @@ import 'package:hmssdk_flutter/hmssdk_flutter.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/role_change_request_dialog.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/track_change_request_dialog.dart'; import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; -import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; -import 'package:hmssdk_flutter_example/common/ui/organisms/audio_tile.dart'; -import 'package:hmssdk_flutter_example/common/ui/organisms/video_tile.dart'; class UtilityComponents { static void showSnackBarWithString(event, context) { ScaffoldMessenger.of(context).showSnackBar(SnackBar( content: Text( event, - style: GoogleFonts.inter(color: Colors.white), + style: GoogleFonts.inter(color: Colors.white), ), backgroundColor: Colors.black87, )); @@ -31,7 +28,7 @@ class UtilityComponents { builder: (ctx) => AlertDialog( title: Text( 'Leave Room?', - style: GoogleFonts.inter(fontSize: 24, fontWeight: FontWeight.w700), + style: GoogleFonts.inter(fontSize: 24, fontWeight: FontWeight.w700), ), actions: [ ElevatedButton( @@ -42,12 +39,12 @@ class UtilityComponents { _meetingStore.leave(), Navigator.popUntil(context, (route) => route.isFirst) }, - child: Text('Yes', style: GoogleFonts.inter(fontSize: 24))), + child: Text('Yes', style: GoogleFonts.inter(fontSize: 24))), ElevatedButton( onPressed: () => Navigator.pop(context, false), child: Text( 'Cancel', - style: GoogleFonts.inter(fontSize: 24), + style: GoogleFonts.inter(fontSize: 24), ), ), ], @@ -101,10 +98,16 @@ class UtilityComponents { context: context, builder: (context) { return AlertDialog( - content: Text(message,style: GoogleFonts.inter(),), + content: Text( + message, + style: GoogleFonts.inter(), + ), actions: [ ElevatedButton( - child: Text('OK',style: GoogleFonts.inter(),), + child: Text( + 'OK', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context); }, @@ -141,13 +144,19 @@ class UtilityComponents { ), actions: [ ElevatedButton( - child: Text('Cancel',style: GoogleFonts.inter(),), + child: Text( + 'Cancel', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context, ''); }, ), ElevatedButton( - child: Text('OK',style: GoogleFonts.inter(),), + child: Text( + 'OK', + style: GoogleFonts.inter(), + ), onPressed: () { if (textController.text == "") { } else { @@ -169,7 +178,10 @@ class UtilityComponents { context: context, builder: (context) => StatefulBuilder(builder: (context, setState) { return AlertDialog( - title: Text("Select Role for Mute",style: GoogleFonts.inter(),), + title: Text( + "Select Role for Mute", + style: GoogleFonts.inter(), + ), content: Container( width: 300, child: Column( @@ -184,10 +196,14 @@ class UtilityComponents { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text(roles[index].name,style: GoogleFonts.inter(),), + Text( + roles[index].name, + style: GoogleFonts.inter(), + ), Checkbox( value: _selectedRoles .contains(roles[index]), + activeColor: Colors.blue, onChanged: (bool? value) { if (value != null && value) { _selectedRoles.add(roles[index]); @@ -204,9 +220,13 @@ class UtilityComponents { Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text("Mute All",style: GoogleFonts.inter(),), + Text( + "Mute All", + style: GoogleFonts.inter(), + ), Checkbox( value: muteAll, + activeColor: Colors.blue, onChanged: (bool? value) { if (value != null) { muteAll = value; @@ -224,7 +244,10 @@ class UtilityComponents { onPressed: () { Navigator.pop(context); }, - child: Text("Cancel",style: GoogleFonts.inter(),)), + child: Text( + "Cancel", + style: GoogleFonts.inter(), + )), ElevatedButton( onPressed: () { if (muteAll) { @@ -236,7 +259,10 @@ class UtilityComponents { } Navigator.pop(context); }, - child: Text("Mute Roles",style: GoogleFonts.inter(),)) + child: Text( + "Mute Roles", + style: GoogleFonts.inter(), + )) ], ) ], @@ -273,7 +299,10 @@ class UtilityComponents { hintText: placeholder), ), CheckboxListTile( - title: Text("Recording",style: GoogleFonts.inter(),), + title: Text( + "Recording", + style: GoogleFonts.inter(), + ), activeColor: Colors.blue, controlAffinity: ListTileControlAffinity.trailing, value: isRecordingEnabled, @@ -287,13 +316,19 @@ class UtilityComponents { ), actions: [ ElevatedButton( - child: Text('Cancel',style: GoogleFonts.inter(),), + child: Text( + 'Cancel', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context, {"url": "", "toRecord": "false"}); }, ), ElevatedButton( - child: Text('OK',style: GoogleFonts.inter(),), + child: Text( + 'OK', + style: GoogleFonts.inter(), + ), onPressed: () { if (textController.text == "" && !isRecordingEnabled) { } else { @@ -310,5 +345,4 @@ class UtilityComponents { return answer; } - } From 0a15eb5521a5c26250970e8168db0f7f7c4bf0b6 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 31 May 2022 18:38:15 +0530 Subject: [PATCH 36/67] mute all dialog size fix --- .../lib/common/util/utility_components.dart | 112 +++++++++--------- 1 file changed, 56 insertions(+), 56 deletions(-) diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index 5de520c22..ce88baa31 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -184,12 +184,12 @@ class UtilityComponents { ), content: Container( width: 300, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Flexible( - fit: FlexFit.tight, - child: ListView.builder( + child: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + ListView.builder( + shrinkWrap: true, itemCount: roles.length, itemBuilder: (context, index) { return Row( @@ -216,56 +216,56 @@ class UtilityComponents { ], ); }), - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Mute All", - style: GoogleFonts.inter(), - ), - Checkbox( - value: muteAll, - activeColor: Colors.blue, - onChanged: (bool? value) { - if (value != null) { - muteAll = value; - } - setState(() {}); - }), - ], - ), - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - ElevatedButton( - style: ElevatedButton.styleFrom( - primary: Colors.red), - onPressed: () { - Navigator.pop(context); - }, - child: Text( - "Cancel", - style: GoogleFonts.inter(), - )), - ElevatedButton( - onPressed: () { - if (muteAll) { - _meetingStore.changeTrackStateForRole( - true, null); - } else if (_selectedRoles.isNotEmpty) { - _meetingStore.changeTrackStateForRole( - true, _selectedRoles); - } - Navigator.pop(context); - }, - child: Text( - "Mute Roles", - style: GoogleFonts.inter(), - )) - ], - ) - ], + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Mute All", + style: GoogleFonts.inter(color: Colors.red), + ), + Checkbox( + value: muteAll, + activeColor: Colors.blue, + onChanged: (bool? value) { + if (value != null) { + muteAll = value; + } + setState(() {}); + }), + ], + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.red), + onPressed: () { + Navigator.pop(context); + }, + child: Text( + "Cancel", + style: GoogleFonts.inter(), + )), + ElevatedButton( + onPressed: () { + if (muteAll) { + _meetingStore.changeTrackStateForRole( + true, null); + } else if (_selectedRoles.isNotEmpty) { + _meetingStore.changeTrackStateForRole( + true, _selectedRoles); + } + Navigator.pop(context); + }, + child: Text( + "Mute Roles", + style: GoogleFonts.inter(), + )) + ], + ) + ], + ), )), ); })); From 8b0cef4edc6815b003c36bb043d4018ca9eead89 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Tue, 31 May 2022 19:51:59 +0530 Subject: [PATCH 37/67] Fixed UI for small size devices --- .../ui/organisms/chat_bottom_sheet.dart | 19 +++++++++--- .../common/ui/organisms/full_screen_view.dart | 3 +- .../common/ui/organisms/grid_audio_view.dart | 4 ++- .../common/ui/organisms/grid_hero_view.dart | 4 ++- .../common/ui/organisms/grid_video_view.dart | 3 +- .../lib/common/util/utility_components.dart | 17 ++++------ example/lib/common/util/utility_function.dart | 4 +++ example/lib/meeting/meeting_page.dart | 31 +++++++++---------- example/lib/preview/preview_page.dart | 2 +- 9 files changed, 49 insertions(+), 38 deletions(-) diff --git a/example/lib/common/ui/organisms/chat_bottom_sheet.dart b/example/lib/common/ui/organisms/chat_bottom_sheet.dart index 92aa1439b..4cd0e69c5 100644 --- a/example/lib/common/ui/organisms/chat_bottom_sheet.dart +++ b/example/lib/common/ui/organisms/chat_bottom_sheet.dart @@ -66,7 +66,7 @@ class _ChatWidgetState extends State { if (roles.length > 0) { return DropdownButtonHideUnderline( child: DropdownButton2( - buttonWidth: 150, + buttonWidth: 120, value: valueChoose, iconEnabledColor: Colors.white, onChanged: (newvalue) { @@ -77,15 +77,20 @@ class _ChatWidgetState extends State { }, items: [ DropdownMenuItem( - child: Text("Everyone",style: GoogleFonts.inter(),), + child: Container( + width: 90, + child: Text("Everyone",style: GoogleFonts.inter(),overflow: TextOverflow.clip,)), value: "Everyone", ), ...data.item2 .map((peer) { return !peer.isLocal ? DropdownMenuItem( - child: Text( - "${peer.name} ${peer.isLocal ? "(You)" : ""}",style: GoogleFonts.inter(),), + child: Container( + width: 90, + child: Text( + "${peer.name} ${peer.isLocal ? "(You)" : ""}",style: GoogleFonts.inter(),overflow: TextOverflow.clip,), + ), value: peer.peerId, ) : null; @@ -95,7 +100,11 @@ class _ChatWidgetState extends State { ...roles .map((role) => DropdownMenuItem( - child: Text("${role.name}",style: GoogleFonts.inter(),), + child: Container( + width: 90, + child: Text("${role.name}", + overflow: TextOverflow.clip, + style: GoogleFonts.inter(),)), value: role.name, )) .toList() diff --git a/example/lib/common/ui/organisms/full_screen_view.dart b/example/lib/common/ui/organisms/full_screen_view.dart index f33dab464..1e9c387dd 100644 --- a/example/lib/common/ui/organisms/full_screen_view.dart +++ b/example/lib/common/ui/organisms/full_screen_view.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; //Project imports @@ -70,5 +71,5 @@ Widget fullScreenView( controller: Provider.of(context).controller, gridDelegate: SliverStairedGridDelegate( startCrossAxisDirectionReversed: false, - pattern: [StairedGridTile(1, (size.height * 0.83) / (size.width))])); + pattern: [StairedGridTile(1, Utilities.getRatio(size))])); } diff --git a/example/lib/common/ui/organisms/grid_audio_view.dart b/example/lib/common/ui/organisms/grid_audio_view.dart index ba5f2f8ae..8e642510b 100644 --- a/example/lib/common/ui/organisms/grid_audio_view.dart +++ b/example/lib/common/ui/organisms/grid_audio_view.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; //Project imports @@ -33,7 +34,8 @@ Widget gridAudioView( } List pattern(int itemCount, Size size) { - double ratio = (size.height * 0.83) / (size.width); + double ratio = Utilities.getRatio(size); + List tiles = []; int gridView = itemCount ~/ 6; int tileLeft = itemCount - (gridView * 6); diff --git a/example/lib/common/ui/organisms/grid_hero_view.dart b/example/lib/common/ui/organisms/grid_hero_view.dart index f9d5612ee..11f83ac5b 100644 --- a/example/lib/common/ui/organisms/grid_hero_view.dart +++ b/example/lib/common/ui/organisms/grid_hero_view.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; //Project imports @@ -64,7 +65,8 @@ Widget gridHeroView( } List pattern(int itemCount, int screenShareCount, Size size) { - double ratio = (size.width) / (size.height * 0.83); + double ratio = Utilities.getRatio(size); + List tiles = []; for (int i = 0; i < screenShareCount; i++) { diff --git a/example/lib/common/ui/organisms/grid_video_view.dart b/example/lib/common/ui/organisms/grid_video_view.dart index 845f5412e..a57bb4099 100644 --- a/example/lib/common/ui/organisms/grid_video_view.dart +++ b/example/lib/common/ui/organisms/grid_video_view.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; //Project imports @@ -74,7 +75,7 @@ Widget gridVideoView( } List pattern(int itemCount, int screenShareCount, Size size) { - double ratio = (size.height * 0.83) / (size.width); + double ratio = Utilities.getRatio(size); List tiles = []; for (int i = 0; i < screenShareCount; i++) { tiles.add(StairedGridTile(1, ratio)); diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index ce88baa31..64fa7998d 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:fluttertoast/fluttertoast.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:provider/provider.dart'; @@ -11,14 +12,8 @@ import 'package:hmssdk_flutter_example/common/ui/organisms/track_change_request_ import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; class UtilityComponents { - static void showSnackBarWithString(event, context) { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - event, - style: GoogleFonts.inter(color: Colors.white), - ), - backgroundColor: Colors.black87, - )); + static void showToastWithString(String message) { + Fluttertoast.showToast(msg: message); } static Future onBackPressed(BuildContext context) { @@ -62,8 +57,8 @@ class UtilityComponents { Provider.of(context, listen: false); if (answer == "OK") { meetingStore.acceptChangeRole(event); - UtilityComponents.showSnackBarWithString( - "Role Change to " + event.suggestedRole.name, context); + UtilityComponents.showToastWithString( + "Role Change to " + event.suggestedRole.name); } else { meetingStore.roleChangeRequest = null; } @@ -259,7 +254,7 @@ class UtilityComponents { Navigator.pop(context); }, child: Text( - "Mute Roles", + "Mute", style: GoogleFonts.inter(), )) ], diff --git a/example/lib/common/util/utility_function.dart b/example/lib/common/util/utility_function.dart index 2d90ab344..327d5483f 100644 --- a/example/lib/common/util/utility_function.dart +++ b/example/lib/common/util/utility_function.dart @@ -29,4 +29,8 @@ class Utilities { Color(0xFFF69133), Color(0xFF8FF5FB) ]; + + static double getRatio(Size size) { + return (size.height * 0.82) / (size.width); + } } diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index fe1a01e43..8fc2f9afa 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -73,7 +73,7 @@ class _MeetingPageState extends State bool ans = await context.read().join(widget.user, widget.roomId); if (!ans) { - UtilityComponents.showSnackBarWithString("Unable to Join", context); + UtilityComponents.showToastWithString("Unable to Join"); Navigator.of(context).pop(); } } @@ -102,7 +102,7 @@ class _MeetingPageState extends State // StaticLogger.logger?.close(); // ShareExtend.share(CustomLogger.file?.path ?? '', 'file'); // logger.getCustomLogger(); - UtilityComponents.showSnackBarWithString("Coming Soon...", context); + UtilityComponents.showToastWithString("Coming Soon..."); break; case 2: @@ -224,8 +224,8 @@ class _MeetingPageState extends State builder: (_, data, __) { if (data.item2) { WidgetsBinding.instance?.addPostFrameCallback((_) { - UtilityComponents.showSnackBarWithString( - context.read().description, context); + UtilityComponents.showToastWithString( + context.read().description); Navigator.of(context).popUntil((route) => route.isFirst); }); } @@ -279,7 +279,7 @@ class _MeetingPageState extends State body: Stack( children: [ Container( - height: MediaQuery.of(context).size.height * 0.83, + height: MediaQuery.of(context).size.height * 0.82, child: Selector< MeetingStore, Tuple6, bool, int, int, @@ -448,7 +448,7 @@ class _MeetingPageState extends State meetingStore.meetingMode == MeetingMode.Audio), builder: (_, data, __) { return Container( - padding: EdgeInsets.all(8), + padding: EdgeInsets.all(5), child: IconButton( tooltip: 'Video', iconSize: 24, @@ -475,7 +475,7 @@ class _MeetingPageState extends State selector: (_, meetingStore) => meetingStore.isMicOn, builder: (_, isMicOn, __) { return Container( - padding: EdgeInsets.all(8), + padding: EdgeInsets.all(5), child: IconButton( tooltip: 'Audio', iconSize: 24, @@ -492,15 +492,12 @@ class _MeetingPageState extends State selector: (_, meetingStore) => meetingStore.isRaisedHand, builder: (_, raisedHand, __) { return Container( - padding: EdgeInsets.all(8), + padding: EdgeInsets.symmetric(vertical: 5, horizontal: 5), child: IconButton( tooltip: 'RaiseHand', iconSize: 20, onPressed: () { context.read().changeMetadata(); - // UtilityComponents.showSnackBarWithString( - // !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", - // context); }, icon: SvgPicture.asset( "assets/icons/hand_state_on.svg", @@ -512,7 +509,7 @@ class _MeetingPageState extends State selector: (_, meetingStore) => meetingStore.isBRB, builder: (_, isBRB, __) { return Container( - padding: EdgeInsets.all(8), + padding: EdgeInsets.all(5), child: IconButton( tooltip: 'BRB', iconSize: 20, @@ -529,7 +526,7 @@ class _MeetingPageState extends State selector: (_, meetingStore) => meetingStore.isNewMessageReceived, builder: (_, isNewMessageReceived, __) { return Container( - padding: EdgeInsets.all(8), + padding: EdgeInsets.all(5), child: IconButton( tooltip: 'Chat', iconSize: 24, @@ -545,7 +542,7 @@ class _MeetingPageState extends State ); }), Container( - padding: EdgeInsets.all(8), + padding: EdgeInsets.all(5), child: IconButton( color: Colors.white, tooltip: 'Leave Or End', @@ -579,9 +576,9 @@ class _MeetingPageState extends State iconSize: 20, onPressed: () { context.read().changeMetadata(); - UtilityComponents.showSnackBarWithString( - !raisedHand ? "Raised Hand ON" : "Raised Hand OFF", - context); + UtilityComponents.showToastWithString( + !raisedHand ? "Raised Hand ON" : "Raised Hand OFF" + ); }, icon: raisedHand ? SvgPicture.asset( diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index 2214acbd1..79c57d208 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -53,7 +53,7 @@ class _PreviewPageState extends State with WidgetsBindingObserver { .read() .startPreview(user: widget.user, roomId: widget.roomId); if (ans == false) { - UtilityComponents.showSnackBarWithString("Unable to preview", context); + UtilityComponents.showToastWithString("Unable to preview"); Navigator.of(context).pop(); } } From 994e45c4d8279f583e6f880c2d30852a2d9972e8 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 31 May 2022 20:02:30 +0530 Subject: [PATCH 38/67] remove extra icons and recording icon fix --- example/assets/icons/audio.png | Bin 1007 -> 0 bytes example/assets/icons/raise_hand.png | Bin 1004 -> 0 bytes example/assets/icons/video.png | Bin 361 -> 0 bytes example/lib/meeting/meeting_page.dart | 11 ++--------- 4 files changed, 2 insertions(+), 9 deletions(-) delete mode 100644 example/assets/icons/audio.png delete mode 100644 example/assets/icons/raise_hand.png delete mode 100644 example/assets/icons/video.png diff --git a/example/assets/icons/audio.png b/example/assets/icons/audio.png deleted file mode 100644 index fa30b0add29735aef7c844a49170f2fdd851b894..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1007 zcmV3BpaWdpS#T=Oj@nFgWDIt_hib*Li@}PJ? z9>{~#6wxRi7?^&U|~@w_}ew|2pl{ z`hR=v@3(L3TWdo>1^rhl0yY5cKo@WjNX42_040I*Kqlu`7iUs_l>{2-3y}d{#F&>a zC4r0R5E-D?XMf`(&Ca7rflD|;SU;~?EAcmgNs(siBCimBK&An2WuI=K7ATG`<-SS+ z7w`t*2Lxa!uovi&eXjz;BFQ>OrN9-uL-+-;G#mTsJOqY^$~s3uAcBGbQ~-~qkGsH- z5PkhtDdsZ!g>VB&0ylw^K-wXu9B7h$8Zd)yU=0ib;RZ4ocrP&@fn^SHX`n;m)`fw% z76RgLx7Il9ap)(o*&%L`_+NoazYwJnKzMydHem)&x3hjk{A1aTDWD$spd5Iq#O#Uy z!q3CL3Uk(f05cT70{9}pRaWCZmjjQMn3w+;1niU7g1IAdwMYE@Rzs)Dfvq>g&xk<= z0o#EUIG6WH;Hm7lUhyZ3_g-Q>9XJYz?EdCvwY33r9AIiBrX9URxi5ZoTp-23O5mBa zcLNKQM2mn{iJ7PPb>eM{3&c_ha7es&zz8K~hxoe{Z;5!<;|2k9)^CentN7L8-BP?t z?AtST5P*f^H!5C*c&`<&OuSG11!T1NpA|19-WP{`zX6%NPFDV<`U}WZ**;gik+S`u zcx9Nu@^gOxDFU|0{|3dMEZY{v8ztM$xIs#Q!%#`gt#hW7ACWz-@F9ud) zPn5m`^OZ!i2Sjc3-znbKxInT?lvltkB}uSLls5F|xl#OTh^J^wVT#7(=#?$}Su|?% zk}B~!B$j%Y16yy5R+pG4#t}`sWuImT*uCP{TMa2`)UHg8#MCKXK0&OBRSz&-@za>8 zZZGy*&6E5t#DxLbh?yB?FfRm6)>QYX9|%isEA3H$jLqu57xR5Z(_-w!hrkQnVPTw9 z0=$u!E=+l@X&m-)(3+qSmYhE1guNoiffK+O2frLs!eoGRp$M`R6eg(Bz!T}?4rW0w zG9@r)Cf^`)uotl(kf#;-1aOx8faHEwxGZgXlOGtb%Knt_9a9~LTD0~muP|O!EAiKX ziIHaNK?&dt&Ja#hRZRnc2~j8LM+x9GI>@6K^9rN{aEiVl+OlWAS25=EKr`l{t;3Ao d1r_wa=@%6_5F3mqV-^4a002ovPDHLkV1imZ$y@*c diff --git a/example/assets/icons/raise_hand.png b/example/assets/icons/raise_hand.png deleted file mode 100644 index 8290ad46d100b71b2ec6cacb858d5769e280a3d1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1004 zcmVr>D2ihP@S$_(IG~T9Ra55Wu;j- zcLGWuHnwPOETz(nf#?-2%^u#cMQL_*GpICUAlr0B2MsYLQo1Z;;EL*e?jeMefFkmg zVn~~ge|@#%u6ln5 zn&BIZ+LW!Q-Wo6r54|+d1$fv3Stt!W^uj<&z>Q?ofEIGg(Ln9z%iJ?->KZa;`VMTX z??nOMXgmnvgZbQVky=|O3&kI>H^ynxPUa`FbwJuaGFv7K^%x!+?tsqk-+|@79R!;9 zykMzX^*>q;sxR$$@Rz@1^<)A*)fljX7k~-Nl7URd+UYp<(?gb1IRD-qLmT$8N$?PP zg!E!PXbG8&h2z+_4qT}(H=FqCwe1hoPihjr0~7V{Li+i=8Ls%}W8nTU76gjt1yo(X z;=0~U^-}QGg^Ii9(nashy?aN7*X8RFUKQ;7iiy5eMJnqzcVC59Er8w`#(ZD#{Q%eX zaa|AB^{G@=*mKLZ#^E8kfk+mTu`^|Codil@%(eyFw#a5}ve^vTtj*wH>+G8r-pE8I z_Z0sCISN$5*jf{74H$tpH4{sI@jFBw1A;KtY$C$5N$}8SB9jA)AAr2r7z<4}j(wTO zB)sXhkmMI%0i9}$+4gFRg)YE%WidC9IRTt*4B57933!NMK<+xbLMHnt@KdZFQ^0ra zrC!F)l<|W};C$PPY2lS}9G*tSUX9A3AAU!Oq}P_P&ByWKLG)Z)o=}OF({iBrEz09- za9hFGw%G81DDNcUfezjW<+Tyr@{ z=kP0fR385RucREQ{-xB<_Fs+TKdHzhs<)wB*9_MNei`^t(08q}cS?@`TusB$S6_Yo aNA)jWgU%B%Vrr@Y0000bEAG}Y7EM@{i2qA>HA^}oh3mjU^7FYxEZ%DkfT)r&R zCK8DO0XL(cilhe0yIIxj-vOSX{coZwnWsPmjDh#lT=3#WsbUDc meetingStore.isRecordingStarted, builder: (_, isRecordingStarted, __) { return isRecordingStarted - ? Container( - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - width: 2, - color: Colors.red.shade600)), - child: SvgPicture.asset( + ? SvgPicture.asset( "assets/icons/record.svg", color: Colors.red, - ), - ) + ) : Container(); }, ), From e4c6c3e4eaeff5356bf83a9a3785df25c1e9db6e Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Tue, 31 May 2022 23:37:13 +0530 Subject: [PATCH 39/67] network icon convert to svg --- example/assets/icons/network_0.png | Bin 2035 -> 0 bytes example/assets/icons/network_0.svg | 8 ++++++++ example/assets/icons/network_1.png | Bin 1596 -> 0 bytes example/assets/icons/network_1.svg | 7 +++++++ example/assets/icons/network_2.png | Bin 1643 -> 0 bytes example/assets/icons/network_2.svg | 7 +++++++ example/assets/icons/network_3.png | Bin 1667 -> 0 bytes example/assets/icons/network_3.svg | 7 +++++++ example/assets/icons/network_4.png | Bin 1597 -> 0 bytes example/assets/icons/network_4.svg | 7 +++++++ example/assets/icons/network_5.png | Bin 1597 -> 0 bytes example/assets/icons/network_5.svg | 7 +++++++ .../common/ui/organisms/network_icon_widget.dart | 6 +++--- example/lib/preview/preview_page.dart | 5 ++--- 14 files changed, 48 insertions(+), 6 deletions(-) delete mode 100644 example/assets/icons/network_0.png create mode 100644 example/assets/icons/network_0.svg delete mode 100644 example/assets/icons/network_1.png create mode 100644 example/assets/icons/network_1.svg delete mode 100644 example/assets/icons/network_2.png create mode 100644 example/assets/icons/network_2.svg delete mode 100644 example/assets/icons/network_3.png create mode 100644 example/assets/icons/network_3.svg delete mode 100644 example/assets/icons/network_4.png create mode 100644 example/assets/icons/network_4.svg delete mode 100644 example/assets/icons/network_5.png create mode 100644 example/assets/icons/network_5.svg diff --git a/example/assets/icons/network_0.png b/example/assets/icons/network_0.png deleted file mode 100644 index b0bea53e932a74c038c6e75b63330be9198a146f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2035 zcmV;)YvdO7KWu|~MC1ga{@_tsgN6l!|M3oSz z5Nxzo=esThhUs<~6+lWvgtTu}<4oBO>=`azE9~K_A>}(+Eqk+EN6K=bFFf!@%?&RC zjmpT>6SR7WM%VYtsGEQ)oP+i6dcg;XVfx z?xaEbjnQrxekK&v!5%U4~^XtM667%BEbsrWvsm2U=R&X~q*L z&Uy|u>@1$7Q}~6y2}AXMq{9918X*K*+fd)&Bg5U$v^{z8y~kUx9BXawM0ZawIoy(K zYhw)+z$0`!MRUWba-ccb@iuX*vz!*Pon3gQxfMO>G%oC9@Tk5XN$tdy$({w|5IfU( z_8bz4MPxD=lmoJtC%1oza_QsodeMLBO1=mG5Q`&}Ok&D&27gIysvfmgRupX*bLktWJ*tgm4yHjl;mIk?N!UXTe!N7HXtu{d_p_H_^o7x5 zoL8UB_duXojZQMToo{DxVGbM&9ZJ^KouNpzlCN_dgpe`4xwT^?w*fyM+#p}vc$9j5 zYil$Aj7KL)ktOW$qC1ntb3(@hzaJT~x71?8xVJmI&MD!tBTfY3(8^A*PS`0P+0sO< zc|_>qfJ7DOKGzE)6jpTc(r8>?h#^QnemCI9|NJ?v6w7%-9p>=MMspjbPF#l|qLG51pax(;pTBr%U&M*i_3wsULgQDf7W$GY3ZvZ^ zd|?Q+fV6SnMQM`=r^BiR)5!tH@wpjOt%vT?ePe4E*W>P?r5iw6d>yODe|nN z8VJ}Cz0ucYYA*ZFs1mlcRg;s^hiZl{Tn~M^wT`PqsXpC>XLi!~a3_fwa|+dha;Z0T z%UVqC>cBu1a29HXn&3?ik4$r& z?)5k0^Q!FcT}D-z4L(!gPvrpbEol^Pp@t}q>zQm$6FkX{ZhogGH+G_;%m$q$I0>%& z+l~IN2#NWRs8J%9mkzwi=cNL3e#U&9e>S$cfuGZU+NkrOP7@fTxu6`7cwey+32UDN zEM`igdUubEss@Xi*F79kmuP`k2wp4k#)p#vya{@LZB-=-N&(q-b1FLiUjDwg0%g8V z?JR(!5+}<3xe_b!4QW1}c+^{1av+UhYnfM2V?iH+ zFhU``q%?emu!u6Zj-yO5%KxhY=Tf1MK#EsUJ1E05$&I&6(=025SN>-Y<%l*cZS8s$ z6W=Jkd#4h^9aQW + + + + + + + diff --git a/example/assets/icons/network_1.png b/example/assets/icons/network_1.png deleted file mode 100644 index 74ed4c367c3f2207c2d57de6cf28aa624de787e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1596 zcmV-C2E+M@P)`+$1U zT+qa>3^IhDg&;z};Ei#E8|abk6%dV=#?Br@;m| zhY;iXTs_9rY`_QN>|uTj*A32}WTeb&t%lTOz>t69k>kWoK(7QhRwJ`k>svBF85>h1 z-SsQVB>)WpQ#0)JwiRzk)hZ18uick<%ZtX5CvZjPt{21p>oe7A%9Ub`2v|5QM3eb^ru_J{dgnQ?I@ z9oHr_KeWuhu0d4|Y4jr}AsOUH@c#f#Wzr9gAHoApw7##S6TIGw;OoS5TRXU1=kRce zd#ThrNS&OBLyI4RrX7mwI*{{%_<{`5G}r(U9QbSykD(mdQgFLl#Q_}veU}H$7@#40 zyF0M=dIxO4@Ip|0mFp5si)+Hbl|fL3{S}Eq33_r>=ER9OPp(!kK5yc zvGGaq@qDDyX>8F~kW3~(J311wF+fI=2fXd=(B0FA$EBk8svE0#yo6eSGU{N%W8)8i zOTSoofV3T$x>?Zb)N<|W zT3u@SFTVPwfc(z(CM-vuL*lK5@6wB&p}LYJ72P9(v4c0F4^X4HJ+0Yqv_fZhFYNAY zgB5Vjwp>Vl(n@8LfI*%JP)kvZnF&*;CV6?=E*2O|(n=;0*lAzkb4Q{ql{$gYU(ZB8 zP=>CGGOxE?Ja2w?DKLpEE?jIYxY({*nO+!O4kM`+q4j(>lXsLse=fq50uiHw>Im7P z=8XtM*91dSsgrkL4bmhV9-XMpz5*&mBg4pYkt%ku2WzX#^^6Icy%?AUxt-i!@J961 z&bEr@Sb>+Q^}BofL@SfW2o#ZM@QeJt2+89F*nrQr2k7GylT(mSJh~JXx~_(N%^S~B zU$6t33u#~ju9gqZBP|mFE942J`Nd~{;-T-uwEm zq0v?3EESjvoL_xmgt2!a1iF!cCz(pFTqG~<+2h^d*P>p zUD!Q+FRp)2#9`qdTXUU~pp6jYx?m-YiLD^^1xM2>ZIbM)_8H8sMI*u7Z*v7SqQQFs zwScSZD@%j?1R&k7uPm3`uPD1ia}?X3Zw4dGown#cRDsxNW1R9vjovfRaJc

d_S_7H|h)7i|n-GOf&pIxv++<9Ll7Qf3r(EAO8Ugw0`?OxWE4Z0000 + + + + + + diff --git a/example/assets/icons/network_2.png b/example/assets/icons/network_2.png deleted file mode 100644 index a780785b887b4b28e8fc1f13b41b30ee29600c2d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1643 zcmV-x29)`UP)|0AQT7~m>4HE!JgZ5u04)l_%WUk=aWV=zH?{hJNJC&KF&1*3!o^9 zORj4k;gUYUfGHf=Q9aepHPEA6{-XSlOWPkz2kevU>JW6 zg9&gB0mk+5YK*DafH%b1t;`m#8l2xtNQtpZ4XMb09$)_*%ZcXzz2aY9m>ny(epv=6 zeSM0g+x|eg48n8E+aCA&E{v3_DHpq$lFVJa zw8P26j`|pNx3t0j?)Kzym5wzaNgn+0jzPU#F(V2Z(ChnngfZzCs1cA6o|aa1e|Kjl z?_O>J1uSX)ZT2)Kp(R-SVs2pP1+m2I9@HRtf{S{>+`=pgrF361^4}GZTL;Di!+4lT zml+pH>DX4F_Ms&XZQZIG(C9~6LNdsA;QatjW#YGtAHoAxw7$#j0f*x>xIB1nc7n}T zkB3d%i^X0+EE*Muw!aISwkxiyK-vr93o=N%(q5deUSI!ESF92e<(`I=hk# z(2%W-b=cZm2NN*7;1^%zxWnqQr|baJPs<>G45e`k#tDf_yKDbEWdJ zH#9)s`2q3qOvK}HY|&>BiG)Gh+Y_=eKt_@W98M>ATRZS*&wH=Bynx3dR05QdoAvgc zzX4qOwVVe?+k-=2WVJfAoVv0Aq3tbUL^-hA8-({d&U9s!ldNWErpkT~==!&^yQTdG zs^{}kb*be){p`yu^6P6WFgH65;TIadOV4|T>PnK7caI2$cAkqEphmGbG^W1M2p(@6 zY^<+AIpCbF+K~J}Ih9EQ26-YtEk!MsOPGS1+nMoV&1sL9BoYkQd_dqpTjI z8N1CZP7e$!T}m(0VX62fK{*nH(T1_wzo5jJdxZydYx78YxK^~T|Hn0xDGQm zOq&EK9ab$aH9FJRzoR66(?YNrPm(92zQSIJywh1%557|ka2Ain!>Xp#xE9a@Oi>11 z@~QYfREaB2Hw-s9k@zl5M{OrZ#dVs@ZDot(~Znt*AsLLy^ui^QdwMDA}SAgmIIGx3sSbuG! z^r5No;5ZoM2_&6MO-`^9w5LF4VF0Zy(F@~XA#z*W%GRg71S7$f&PrJAg&%h|U?bIq z-p2uK@};S{PC?K{h;f~@62`=qA7jDN^a^#MmTI5D*wf&wKm9wm0vd6`djXYzt4s4w zx-(1ia-+HwzX}!yv_-(=ZsKxoVcw)g3xzaKtM@rNr?zsWJaKJhKA1P>E;#Gj5A6h6 zTH8oo!%zbt-7n4072K~lcG|cX+McKdBXWZ_?>>}(*l1&%@Rj?q0D< zeO#*0ZN7nT3jfO4rI`+>9T zU>yYUcr0>PRn>~RaPxom5Qa#@sm!+7fo}qzoisz-fN29Vkv4|IAj51~D%+=IRMD_Z p!?FMeeU&jekcb`pX_j;*{s&Kqf52L$G`;`;002ovPDHLkV1is@{b2wA diff --git a/example/assets/icons/network_2.svg b/example/assets/icons/network_2.svg new file mode 100644 index 000000000..17b455718 --- /dev/null +++ b/example/assets/icons/network_2.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/example/assets/icons/network_3.png b/example/assets/icons/network_3.png deleted file mode 100644 index cf5e3e3ab4b99c20e8852e416888eae17f41bc9b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1667 zcmV-}27LL6P)#4CuxJBpac+AD}fpW64&_F3W?A&RKTsEN;s!niNv82haw~n zJ%vjTNJRv-5{Q=INGWk>A)7Q%AP!kbNE~DD^u2M`vDc2hUN0g2NvqwR9q+z3^M7x4 zXUxC>d_JF7c2)IoN$+I9d>mL81MmWHuTclfR0dq-z(Y*uBMDg_Qo~^tN`!$;$Y`m| zbBZzO#?x-F0p}26TpuXKnW7z7HJqJJZ{d>R{BlA{^cCw!Q4X|q>^$$d;U=(Gf{!1L z_F1iO$pN3=?~`<85arSZ>jF~~?Cn7-y&)B<(BAQBugqQd*Uxx@`(&=%Z|~UEQ>dn# z@8XJNF5saX)*m4L6FD7d@7UhMnDhf|5XgzT z`bKqbc4j2&nz?`imNfq^GmTBO1dH!B2X60 z!+ljXC`uV_intbyE<$u^No?BOENI%SI4*%yFNi0|Aa#Qc$iU{7R@~ZB#^%E9t`r;8 z0yJ%DPFjGDJbO9~&;FeT8yLM16i?;4M6bm~(fm;>_}V-28lKmJ+Iq41+BzUKe7oo# zL3_Ux`(oweuBZV2j!yCLbmH+iw&*{wu<#nRmoJ5E49H390Z(-`G&DBh_CeNt)yEHU z`wNNzWmL=B{X32WmwvSJ1JZWa-Y+s*omx(vcnFaf&x8|JaJwr+?=^kcoKa4)8Xft= z@_j(pzmaR}KRAx+`MgkFYWY3;_GcJBJv9LjMu*|`D-G|ZXZ@zCQipOEhuGUpeUgEZ zndc$~s8QS%l`GGvgt~^!@N{|#tiU;&RPffFRw|PO4CBcFYAI?lv%$xXEW>Bp-@^8m zIG*#=weXY-W0MLD{#FjZkGVuyG`a+#dv`<}_}V@ZWgbtpkf-_HxnL6av9@iyCh%k1 z2Ns|Vq9`t*_4IDu+K_+~fh7nWShjK-coLD|;$S6Q`?Wk(Mot)#3f;RcoGT1Y6tr*K z$)N;}9f`upz+y&g8_d5+N~da5?nm6XR|fr8E7766pC$RwN^;-?8h$d6*;04M6u5G| z0`7)gFu%B}eSb>=4)0xtp8dXjj~I04sTM8Rp35KV`b%3%y@gDcnFA`=5MbJtLliaeyE4_GXy#u}{2GByhlTl`>f61T_%@xpzbzTc72ChCD|Fbo{BukjO6c2#I0qqbtxtlm>F3d{KS|p;? zH8woQ&e>RVq&)HU#CZ6Qxj5(OG8dT%)i-V?d3D1EfOP+8{6Wt3iZzGFmys7k8^H;4 z&}LnS0*Hk+#%bPYz1Ivh9B$7%3O~4 + + + + + + diff --git a/example/assets/icons/network_4.png b/example/assets/icons/network_4.png deleted file mode 100644 index 02d122eae96b47208c1a72422cfbfc43dd13a39d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1597 zcmV-D2EzG?P)vyH49GkQE-n@QguOu9Om6D$o{ub&xUX64VGt ziKgZjWqD~~yy%{}fdZB||1>j=O~h4}=`#m*Q4mYK?p6&7PiUY_Xl^W^P>%OyBmY?e zW!s1Gz%U*n`8NF|OC8TF)IQ?sy62#xMB{Xkr;rTt5Ii5isZ8d)ejz;IhV|=??F0F6 z6L^p92Tw;6fZq$!F0Z(!&98#`5B~7DaeE#zw;zgg2grNDLsv3LA+Q040`54`1-_F< z^1^NfX}@3m>hRn*&@S3GP>Iy_d$4|e8f-xKLRfeJgSX)vRv}=7_5&z0FFvn0VzY?^9>v>XeU}d z`TVBk_kgB-C^t60bQ*c|M!CLZ`8`(#3WQHyy90?YMTm9Mpz+?TJFGK3b7+3-4Y|ewi_gLvH;mh+`1uc|7OOeIQ0#i_njD+4Q z@Dx&O1Ajy_{W+r9%Gn#j8#_Ph%PN7-(evhaZv`gt06WxibQTxe0k8ndAPm!E>euN4 zH*(g-0Hv~#mQ!-OOqGs2fd9Vv z%gLA!cccKhorE`n2CC$>NkM@EFCjJRLkEPF$zwW5_{3*7A%pa?1KSFCQJCFdzXL|W z6T`n-a=nrB*=HY$Sg-?{3&p_(B>yHYC@@#f{$`Q4*_^-p!7q90NUeUbi;9BS4Dtfe z#F#NC6V<=hzBwmCh(4waBm_q)Q6DqiDiB`;F)b2YSp!&^UQq6*z_llE5h4->z#O;$ z;}DPv478}c$KR?*9_Ihnb_o(`xV>n&^%sz6sZLz%t2dpAId;%v@uR~qiXLN#BsR2 zFf%oIwNxkT+pJu^MV}Es6~H-P1CSDoWw@KlTucNFlCC=Nt@t5qx&kj^H|MD_}%k84kS+q#h0| vU@8>Eu`P~mQ4ZQ1V{%kYC4ROmv=RRUp@oid6zj4)00000NkvXXu0mjf_c_-n diff --git a/example/assets/icons/network_4.svg b/example/assets/icons/network_4.svg new file mode 100644 index 000000000..ea5b1f7e9 --- /dev/null +++ b/example/assets/icons/network_4.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/example/assets/icons/network_5.png b/example/assets/icons/network_5.png deleted file mode 100644 index 02d122eae96b47208c1a72422cfbfc43dd13a39d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1597 zcmV-D2EzG?P)vyH49GkQE-n@QguOu9Om6D$o{ub&xUX64VGt ziKgZjWqD~~yy%{}fdZB||1>j=O~h4}=`#m*Q4mYK?p6&7PiUY_Xl^W^P>%OyBmY?e zW!s1Gz%U*n`8NF|OC8TF)IQ?sy62#xMB{Xkr;rTt5Ii5isZ8d)ejz;IhV|=??F0F6 z6L^p92Tw;6fZq$!F0Z(!&98#`5B~7DaeE#zw;zgg2grNDLsv3LA+Q040`54`1-_F< z^1^NfX}@3m>hRn*&@S3GP>Iy_d$4|e8f-xKLRfeJgSX)vRv}=7_5&z0FFvn0VzY?^9>v>XeU}d z`TVBk_kgB-C^t60bQ*c|M!CLZ`8`(#3WQHyy90?YMTm9Mpz+?TJFGK3b7+3-4Y|ewi_gLvH;mh+`1uc|7OOeIQ0#i_njD+4Q z@Dx&O1Ajy_{W+r9%Gn#j8#_Ph%PN7-(evhaZv`gt06WxibQTxe0k8ndAPm!E>euN4 zH*(g-0Hv~#mQ!-OOqGs2fd9Vv z%gLA!cccKhorE`n2CC$>NkM@EFCjJRLkEPF$zwW5_{3*7A%pa?1KSFCQJCFdzXL|W z6T`n-a=nrB*=HY$Sg-?{3&p_(B>yHYC@@#f{$`Q4*_^-p!7q90NUeUbi;9BS4Dtfe z#F#NC6V<=hzBwmCh(4waBm_q)Q6DqiDiB`;F)b2YSp!&^UQq6*z_llE5h4->z#O;$ z;}DPv478}c$KR?*9_Ihnb_o(`xV>n&^%sz6sZLz%t2dpAId;%v@uR~qiXLN#BsR2 zFf%oIwNxkT+pJu^MV}Es6~H-P1CSDoWw@KlTucNFlCC=Nt@t5qx&kj^H|MD_}%k84kS+q#h0| vU@8>Eu`P~mQ4ZQ1V{%kYC4ROmv=RRUp@oid6zj4)00000NkvXXu0mjf_c_-n diff --git a/example/assets/icons/network_5.svg b/example/assets/icons/network_5.svg new file mode 100644 index 000000000..ea5b1f7e9 --- /dev/null +++ b/example/assets/icons/network_5.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/example/lib/common/ui/organisms/network_icon_widget.dart b/example/lib/common/ui/organisms/network_icon_widget.dart index 70d72837f..06173ad0b 100644 --- a/example/lib/common/ui/organisms/network_icon_widget.dart +++ b/example/lib/common/ui/organisms/network_icon_widget.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:provider/provider.dart'; //Project imports @@ -14,9 +15,8 @@ class NetworkIconWidget extends StatelessWidget { ? Positioned( child: Padding( padding: const EdgeInsets.fromLTRB(5, 5, 0, 0), - child: Image.asset( - 'assets/icons/network_$networkQuality.png', - scale: 2, + child: SvgPicture.asset( + 'assets/icons/network_$networkQuality.svg', ), ), top: 5.0, diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index 79c57d208..5d0f35eff 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -124,9 +124,8 @@ class _PreviewPageState extends State with WidgetsBindingObserver { padding: const EdgeInsets.only(top: 40, left: 20), child: Align( alignment: Alignment.topLeft, - child: Image.asset( - 'assets/icons/network_${_previewStore.networkQuality}.png', - scale: 2, + child: SvgPicture.asset( + 'assets/icons/network_${_previewStore.networkQuality}.svg', ), ), ), From 6398c4a21f392fa294185cc67786c8f081bd2c2a Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 1 Jun 2022 01:55:04 +0530 Subject: [PATCH 40/67] preview page icon change and peer count fix --- example/lib/preview/preview_page.dart | 144 +++++++++++++------------ example/lib/preview/preview_store.dart | 5 + 2 files changed, 80 insertions(+), 69 deletions(-) diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index 5d0f35eff..1d87357b8 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -142,100 +142,106 @@ class _PreviewPageState extends State with WidgetsBindingObserver { width: 35, decoration: BoxDecoration( color: Colors.transparent.withOpacity(0.2), - borderRadius: BorderRadius.circular(5)), - child: Icon( - Icons.circle, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(5), + bottomRight: Radius.circular(5))), + child: SvgPicture.asset( + "assets/icons/record.svg", color: Colors.red, - size: 24, ), ), - if (_previewStore.peers.isNotEmpty) + if (_previewStore.peerCount != 0) GestureDetector( onTap: () { - showModalBottomSheet( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(10.0), - ), - context: context, - builder: (BuildContext context) { - return Container( - height: MediaQuery.of(context) - .size - .height / - 2, - padding: EdgeInsets.only(top: 15), - child: ListView.separated( - itemBuilder: (context, index) { - HMSPeer peer = _previewStore - .peers[index]; - return Container( - padding: EdgeInsets.all(15), - margin: - EdgeInsets.symmetric( - horizontal: 10), - decoration: BoxDecoration( - color: Color.fromARGB( - 174, 0, 0, 0), - borderRadius: - BorderRadius - .circular(8)), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Text( - peer.name, - style: - GoogleFonts.inter( - fontWeight: - FontWeight - .bold, - color: Colors - .white), - ), - Text(peer.role.name, + if (_previewStore.peers.isNotEmpty) + showModalBottomSheet( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10.0), + ), + context: context, + builder: (BuildContext context) { + return Container( + height: MediaQuery.of(context) + .size + .height / + 2, + padding: EdgeInsets.only(top: 15), + child: ListView.separated( + itemBuilder: + (context, index) { + HMSPeer peer = _previewStore + .peers[index]; + return Container( + padding: + EdgeInsets.all(15), + margin: + EdgeInsets.symmetric( + horizontal: 10), + decoration: BoxDecoration( + color: Color.fromARGB( + 174, 0, 0, 0), + borderRadius: + BorderRadius + .circular(8)), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + peer.name, style: GoogleFonts.inter( fontWeight: FontWeight .bold, color: Colors - .white)) - ], - ), - ); - }, - separatorBuilder: - (context, index) { - return Divider(); - }, - itemCount: _previewStore - .peers.length)); - }, - ); + .white), + ), + Text(peer.role.name, + style: GoogleFonts.inter( + fontWeight: + FontWeight + .bold, + color: Colors + .white)) + ], + ), + ); + }, + separatorBuilder: + (context, index) { + return Divider(); + }, + itemCount: _previewStore + .peers.length)); + }, + ); }, child: Container( padding: EdgeInsets.all(5), decoration: BoxDecoration( color: Colors.transparent .withOpacity(0.2), - borderRadius: - BorderRadius.circular(5)), + borderRadius: _previewStore + .isRecordingStarted + ? BorderRadius.only( + topRight: Radius.circular(5), + bottomRight: + Radius.circular(5)) + : BorderRadius.circular(5)), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon( - Icons.person, - size: 24, + SvgPicture.asset( + "assets/icons/participants.svg", ), SizedBox( width: 2, ), Text( - _previewStore.peers.length - .toString(), + _previewStore.peerCount.toString(), style: GoogleFonts.inter( fontWeight: FontWeight.bold, fontSize: 16), diff --git a/example/lib/preview/preview_store.dart b/example/lib/preview/preview_store.dart index db11249df..4fa17cd32 100644 --- a/example/lib/preview/preview_store.dart +++ b/example/lib/preview/preview_store.dart @@ -32,6 +32,8 @@ class PreviewStore extends ChangeNotifier int? networkQuality; + int peerCount = 0; + @override void onError({required HMSException error}) { updateError(error); @@ -120,6 +122,9 @@ class PreviewStore extends ChangeNotifier case HMSRoomUpdate.hlsStreamingStateUpdated: isRecordingStarted = room.hmshlsStreamingState?.running ?? false; break; + case HMSRoomUpdate.RoomPeerCountUpdated: + peerCount = room.peerCount; + break; default: break; } From f4f99393c802b4c4ee842590fddaaf5562ca6f79 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Wed, 1 Jun 2022 16:08:42 +0530 Subject: [PATCH 41/67] Added Light-Dark Mode --- example/assets/icons/dark_mode.svg | 3 + example/assets/icons/light_mode.svg | 3 + example/lib/common/constant.dart | 2 + .../ui/organisms/change_role_options.dart | 9 +- .../ui/organisms/change_track_options.dart | 10 +- .../ui/organisms/chat_bottom_sheet.dart | 20 +- .../lib/common/ui/organisms/degrade_tile.dart | 28 +- .../common/ui/organisms/full_screen_view.dart | 6 +- .../common/ui/organisms/grid_hero_view.dart | 8 +- .../common/ui/organisms/grid_video_view.dart | 6 +- .../common/ui/organisms/offline_screen.dart | 3 +- .../ui/organisms/participant_organism.dart | 7 +- .../lib/common/ui/organisms/peer_name.dart | 4 +- .../organisms/role_change_request_dialog.dart | 5 +- .../common/ui/organisms/rtc_stats_view.dart | 29 +- .../track_change_request_dialog.dart | 3 +- .../organisms/user_name_dialog_organism.dart | 3 +- example/lib/common/util/app_color.dart | 8 + .../lib/common/util/utility_components.dart | 11 +- example/lib/hls_viewer/hls_viewer.dart | 3 +- example/lib/main.dart | 453 ++++++++++-------- example/lib/meeting/meeting_page.dart | 85 ++-- .../meeting/meeting_participants_list.dart | 3 +- example/lib/preview/preview_page.dart | 11 +- 24 files changed, 407 insertions(+), 316 deletions(-) create mode 100644 example/assets/icons/dark_mode.svg create mode 100644 example/assets/icons/light_mode.svg create mode 100644 example/lib/common/util/app_color.dart diff --git a/example/assets/icons/dark_mode.svg b/example/assets/icons/dark_mode.svg new file mode 100644 index 000000000..3c0cefd9e --- /dev/null +++ b/example/assets/icons/dark_mode.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/light_mode.svg b/example/assets/icons/light_mode.svg new file mode 100644 index 000000000..c0e478948 --- /dev/null +++ b/example/assets/icons/light_mode.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/lib/common/constant.dart b/example/lib/common/constant.dart index 2f2f487d8..d458e6aab 100644 --- a/example/lib/common/constant.dart +++ b/example/lib/common/constant.dart @@ -21,4 +21,6 @@ class Constant { static String meetingUrl = defaultRoomID; static String meetingCode = ""; static String rtmpUrl = ""; + + static bool isDarkMode = true; } diff --git a/example/lib/common/ui/organisms/change_role_options.dart b/example/lib/common/ui/organisms/change_role_options.dart index 8ff3ad03a..89f295ee1 100644 --- a/example/lib/common/ui/organisms/change_role_options.dart +++ b/example/lib/common/ui/organisms/change_role_options.dart @@ -5,6 +5,7 @@ import 'package:google_fonts/google_fonts.dart'; //Project imports import 'package:hmssdk_flutter/hmssdk_flutter.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; class ChangeRoleOptionDialog extends StatefulWidget { final String peerName; @@ -35,7 +36,7 @@ class _ChangeRoleOptionDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(widget.peerName,style: GoogleFonts.inter(),), + title: Text(widget.peerName,style: GoogleFonts.inter(color:iconColor),), content: Container( width: double.infinity, child: FutureBuilder>( @@ -54,7 +55,7 @@ class _ChangeRoleOptionDialogState extends State { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text("Role To: ",style: GoogleFonts.inter(),), + Text("Role To: ",style: GoogleFonts.inter(color:iconColor),), Flexible( child: DropdownButton2( buttonWidth: MediaQuery.of(context).size.width / 2, @@ -67,7 +68,7 @@ class _ChangeRoleOptionDialogState extends State { }, items: data.data!.map((role) { return DropdownMenuItem( - child: Text(role.name,style: GoogleFonts.inter(),), + child: Text(role.name,style: GoogleFonts.inter(color:iconColor),), value: role.name, ); }).toList(), @@ -91,7 +92,7 @@ class _ChangeRoleOptionDialogState extends State { SizedBox( width: 16, ), - Text('Force change',style: GoogleFonts.inter(),) + Text('Force change',style: GoogleFonts.inter(color:iconColor),) ], ), ), diff --git a/example/lib/common/ui/organisms/change_track_options.dart b/example/lib/common/ui/organisms/change_track_options.dart index 30f4fb002..179a087ea 100644 --- a/example/lib/common/ui/organisms/change_track_options.dart +++ b/example/lib/common/ui/organisms/change_track_options.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; class ChangeTrackOptionDialog extends StatefulWidget { final String peerName; @@ -33,8 +34,9 @@ class _ChangeTrackOptionDialogState extends State { Widget build(BuildContext context) { return AlertDialog( title: Text( + widget.peerName, - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor), ), content: Container( width: double.infinity, @@ -59,7 +61,7 @@ class _ChangeTrackOptionDialogState extends State { ), Text( "${widget.isVideoMuted ? "Unmute" : "Mute"} video", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor), ) ], ), @@ -86,7 +88,7 @@ class _ChangeTrackOptionDialogState extends State { ), Text( "${widget.isAudioMuted ? "Unmute" : "Mute"} audio", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor), ), ], ), @@ -110,7 +112,7 @@ class _ChangeTrackOptionDialogState extends State { ), Text( "Remove Peer", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor), ) ], ), diff --git a/example/lib/common/ui/organisms/chat_bottom_sheet.dart b/example/lib/common/ui/organisms/chat_bottom_sheet.dart index 4cd0e69c5..041864475 100644 --- a/example/lib/common/ui/organisms/chat_bottom_sheet.dart +++ b/example/lib/common/ui/organisms/chat_bottom_sheet.dart @@ -3,6 +3,7 @@ import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:collection/collection.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:intl/intl.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -68,7 +69,7 @@ class _ChatWidgetState extends State { child: DropdownButton2( buttonWidth: 120, value: valueChoose, - iconEnabledColor: Colors.white, + iconEnabledColor: Colors.black, onChanged: (newvalue) { setState(() { this.valueChoose = @@ -89,7 +90,7 @@ class _ChatWidgetState extends State { child: Container( width: 90, child: Text( - "${peer.name} ${peer.isLocal ? "(You)" : ""}",style: GoogleFonts.inter(),overflow: TextOverflow.clip,), + "${peer.name} ${peer.isLocal ? "(You)" : ""}",style: GoogleFonts.inter(color:iconColor),overflow: TextOverflow.clip,), ), value: peer.peerId, ) @@ -104,7 +105,7 @@ class _ChatWidgetState extends State { width: 90, child: Text("${role.name}", overflow: TextOverflow.clip, - style: GoogleFonts.inter(),)), + style: GoogleFonts.inter(color:iconColor),)), value: role.name, )) .toList() @@ -139,7 +140,7 @@ class _ChatWidgetState extends State { // if (!_meetingStore.isMeetingStarted) return SizedBox(); if (data.item2 == 0) - return Center(child: Text('No messages',style: GoogleFonts.inter(),)); + return Center(child: Text('No messages',style: GoogleFonts.inter(color:iconColor),)); return ListView( children: List.generate( @@ -159,11 +160,7 @@ class _ChatWidgetState extends State { data.item1[index].sender?.name ?? "", style: GoogleFonts.inter( fontSize: 14.0, - color: MediaQuery.of(context) - .platformBrightness == - Brightness.light - ? Colors.grey - : Colors.white70, + color:iconColor, fontWeight: FontWeight.w600), ), ), @@ -172,7 +169,7 @@ class _ChatWidgetState extends State { .format(data.item1[index].time), style: GoogleFonts.inter( fontSize: 10.0, - color: Colors.white, + color:iconColor, fontWeight: FontWeight.w900), ) ], @@ -188,7 +185,7 @@ class _ChatWidgetState extends State { data.item1[index].message.toString(), style: GoogleFonts.inter( fontSize: 14.0, - color: Colors.white, + color:iconColor, fontWeight: FontWeight.w700), ), ), @@ -230,6 +227,7 @@ class _ChatWidgetState extends State { margin: EdgeInsets.only(bottom: 5.0, left: 5.0), child: TextField( autofocus: true, + style: GoogleFonts.inter(color:iconColor), controller: messageTextController, decoration: new InputDecoration( border: InputBorder.none, diff --git a/example/lib/common/ui/organisms/degrade_tile.dart b/example/lib/common/ui/organisms/degrade_tile.dart index 78fd2dcc2..1437249dc 100644 --- a/example/lib/common/ui/organisms/degrade_tile.dart +++ b/example/lib/common/ui/organisms/degrade_tile.dart @@ -1,6 +1,8 @@ //package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/audio_level_avatar.dart'; import 'package:provider/provider.dart'; //Package imports @@ -34,17 +36,21 @@ class _DegradeTileState extends State { decoration: BoxDecoration( color: Colors.black87, borderRadius: BorderRadius.all(Radius.circular(10))), - child: Center( - child: CircleAvatar( - backgroundColor: Utilities.getBackgroundColour( - context.read().peer.name), - radius: 36, - child: Text( - Utilities.getAvatarTitle( - context.read().peer.name), - style: GoogleFonts.inter( - fontSize: 36, color: Colors.white), - ))), + child: Stack( + children: [ + Positioned( + child: Padding( + padding: const EdgeInsets.fromLTRB(5, 5, 0, 0), + child: SvgPicture.asset( + 'assets/icons/degrade.svg', + ), + ), + top: 5.0, + left: 5.0, + ), + AudioLevelAvatar() + ], + ), )); }, selector: (_, peerTrackNode) => diff --git a/example/lib/common/ui/organisms/full_screen_view.dart b/example/lib/common/ui/organisms/full_screen_view.dart index 1e9c387dd..6829dcd97 100644 --- a/example/lib/common/ui/organisms/full_screen_view.dart +++ b/example/lib/common/ui/organisms/full_screen_view.dart @@ -1,6 +1,8 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; @@ -37,10 +39,10 @@ Widget fullScreenView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.screen_share), + SvgPicture.asset("assets/icons/screen_share.svg",color:iconColor,), Text( "You are sharing your screen", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), ], ), diff --git a/example/lib/common/ui/organisms/grid_hero_view.dart b/example/lib/common/ui/organisms/grid_hero_view.dart index 11f83ac5b..beb9fe250 100644 --- a/example/lib/common/ui/organisms/grid_hero_view.dart +++ b/example/lib/common/ui/organisms/grid_hero_view.dart @@ -1,6 +1,8 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; @@ -36,8 +38,10 @@ Widget gridHeroView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.screen_share), - Text("You are sharing your screen",style: GoogleFonts.inter(),), + SvgPicture.asset("assets/icons/screen_share.svg",color:iconColor,), + Text( + "You are sharing your screen", + style: GoogleFonts.inter(color:iconColor,)), ], ), ) diff --git a/example/lib/common/ui/organisms/grid_video_view.dart b/example/lib/common/ui/organisms/grid_video_view.dart index a57bb4099..aeb0617a9 100644 --- a/example/lib/common/ui/organisms/grid_video_view.dart +++ b/example/lib/common/ui/organisms/grid_video_view.dart @@ -1,6 +1,8 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; @@ -37,10 +39,10 @@ Widget gridVideoView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - Icon(Icons.screen_share), + SvgPicture.asset("assets/icons/screen_share.svg",color:iconColor,), Text( "You are sharing your screen", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), ], ), diff --git a/example/lib/common/ui/organisms/offline_screen.dart b/example/lib/common/ui/organisms/offline_screen.dart index eca69a4ed..255dc8862 100644 --- a/example/lib/common/ui/organisms/offline_screen.dart +++ b/example/lib/common/ui/organisms/offline_screen.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; class OfflineWidget extends StatelessWidget { @override @@ -28,7 +29,7 @@ class OfflineWidget extends StatelessWidget { child: Center( child: Text( 'Oops, No internet connection.\n\nReconnecting...', - style: GoogleFonts.inter( + style: GoogleFonts.inter(color:iconColor, fontSize: 20, fontWeight: FontWeight.bold), ), ), diff --git a/example/lib/common/ui/organisms/participant_organism.dart b/example/lib/common/ui/organisms/participant_organism.dart index beb420d09..370b0e82a 100644 --- a/example/lib/common/ui/organisms/participant_organism.dart +++ b/example/lib/common/ui/organisms/participant_organism.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:provider/provider.dart'; //Project imports @@ -44,7 +45,9 @@ class _ParticipantOrganismState extends State { width: width / 3, child: Text( peer.name, - style: GoogleFonts.inter(fontSize: 20.0), + style: GoogleFonts.inter(fontSize: 20.0, + color:iconColor, + ), maxLines: 1, overflow: TextOverflow.ellipsis, ), @@ -101,7 +104,7 @@ class _ParticipantOrganismState extends State { overflow: TextOverflow.clip, maxLines: 1, style: GoogleFonts.inter( - color: Colors.white, + color:Colors.white, fontSize: 18.0, fontWeight: FontWeight.bold), ), diff --git a/example/lib/common/ui/organisms/peer_name.dart b/example/lib/common/ui/organisms/peer_name.dart index a35ce3d8d..1421bd6d2 100644 --- a/example/lib/common/ui/organisms/peer_name.dart +++ b/example/lib/common/ui/organisms/peer_name.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -32,7 +33,8 @@ class _PeerNameState extends State { overflow: TextOverflow.ellipsis, style: GoogleFonts.inter( fontWeight: FontWeight.w500, - color: Colors.white, + color:iconColor, + fontSize: 16), ), ), diff --git a/example/lib/common/ui/organisms/role_change_request_dialog.dart b/example/lib/common/ui/organisms/role_change_request_dialog.dart index 1598ce287..80f8843da 100644 --- a/example/lib/common/ui/organisms/role_change_request_dialog.dart +++ b/example/lib/common/ui/organisms/role_change_request_dialog.dart @@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart'; // Project imports import 'package:hmssdk_flutter/hmssdk_flutter.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; class RoleChangeDialogOrganism extends StatefulWidget { final HMSRoleChangeRequest roleChangeRequest; @@ -29,7 +30,9 @@ class _RoleChangeDialogOrganismState extends State { children: [ Text( message, - style: GoogleFonts.inter(), + style: GoogleFonts.inter( + color:iconColor, + ), ), ], ), diff --git a/example/lib/common/ui/organisms/rtc_stats_view.dart b/example/lib/common/ui/organisms/rtc_stats_view.dart index 67496a799..cb1cd63b9 100644 --- a/example/lib/common/ui/organisms/rtc_stats_view.dart +++ b/example/lib/common/ui/organisms/rtc_stats_view.dart @@ -1,5 +1,6 @@ //Package imports import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; import 'package:flutter/material.dart'; @@ -49,22 +50,22 @@ class Stats extends StatelessWidget { children: [ Text( "Width\t ${data.item3?.hmsLocalVideoStats?.resolution.width.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), Text( "Height\t ${data.item3?.hmsLocalVideoStats?.resolution.height.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "FPS\t ${data.item3?.hmsLocalVideoStats?.frameRate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text("Downlink\t ${data.item4 ?? "-1"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "Bitrate(V)\t ${data.item3?.hmsLocalVideoStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "Bitrate(A)\t ${data.item3?.hmsLocalAudioStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), ], ), ); @@ -88,27 +89,27 @@ class Stats extends StatelessWidget { children: [ Text( "Width\t ${data.item3?.hmsRemoteVideoStats?.resolution.width.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "Height\t ${data.item3?.hmsRemoteVideoStats?.resolution.height.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "FPS\t ${data.item3?.hmsRemoteVideoStats?.frameRate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text("Downlink\t ${data.item4 ?? "-1"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "Bitrate(V)\t ${data.item3?.hmsRemoteVideoStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "Bitrate(A)\t ${data.item3?.hmsRemoteAudioStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "Jitter(V)\t ${data.item3?.hmsRemoteVideoStats?.jitter.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), Text( "Jitter(A)\t ${data.item3?.hmsRemoteAudioStats?.jitter.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter()), + style: GoogleFonts.inter(color:iconColor,)), ], ), ); diff --git a/example/lib/common/ui/organisms/track_change_request_dialog.dart b/example/lib/common/ui/organisms/track_change_request_dialog.dart index 12799c685..4e51ff39c 100644 --- a/example/lib/common/ui/organisms/track_change_request_dialog.dart +++ b/example/lib/common/ui/organisms/track_change_request_dialog.dart @@ -4,6 +4,7 @@ import 'package:google_fonts/google_fonts.dart'; // Project imports import 'package:hmssdk_flutter/hmssdk_flutter.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; class TrackChangeDialogOrganism extends StatefulWidget { final HMSTrackChangeRequest trackChangeRequest; @@ -34,7 +35,7 @@ class _RoleChangeDialogOrganismState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text(message,style: GoogleFonts.inter(),), + Text(message,style: GoogleFonts.inter(color:iconColor,),), ], ), ), diff --git a/example/lib/common/ui/organisms/user_name_dialog_organism.dart b/example/lib/common/ui/organisms/user_name_dialog_organism.dart index f89cb887a..4df8da476 100644 --- a/example/lib/common/ui/organisms/user_name_dialog_organism.dart +++ b/example/lib/common/ui/organisms/user_name_dialog_organism.dart @@ -1,6 +1,7 @@ // Package imports import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; class UserNameDialogOrganism extends StatefulWidget { const UserNameDialogOrganism({Key? key}) : super(key: key); @@ -28,7 +29,7 @@ class _UserNameDialogOrganismState extends State { borderRadius: BorderRadius.all(Radius.circular(16)), ), hintText: 'Enter your Name', - hintStyle: GoogleFonts.inter()), + hintStyle: GoogleFonts.inter(color:iconColor,)), ), ], ), diff --git a/example/lib/common/util/app_color.dart b/example/lib/common/util/app_color.dart new file mode 100644 index 000000000..3646d7755 --- /dev/null +++ b/example/lib/common/util/app_color.dart @@ -0,0 +1,8 @@ +import 'package:flutter/material.dart'; +import 'package:hmssdk_flutter_example/common/constant.dart'; + +Color iconColor = Constant.isDarkMode ? Colors.white : Colors.black; + +void updateColor() { + iconColor = Constant.isDarkMode ? Colors.white : Colors.black; +} diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index 64fa7998d..a0eb0d7cd 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:provider/provider.dart'; @@ -23,7 +24,7 @@ class UtilityComponents { builder: (ctx) => AlertDialog( title: Text( 'Leave Room?', - style: GoogleFonts.inter(fontSize: 24, fontWeight: FontWeight.w700), + style: GoogleFonts.inter(color:iconColor,fontSize: 24, fontWeight: FontWeight.w700), ), actions: [ ElevatedButton( @@ -95,7 +96,7 @@ class UtilityComponents { return AlertDialog( content: Text( message, - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), actions: [ ElevatedButton( @@ -175,7 +176,7 @@ class UtilityComponents { return AlertDialog( title: Text( "Select Role for Mute", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), content: Container( width: 300, @@ -193,7 +194,7 @@ class UtilityComponents { children: [ Text( roles[index].name, - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), Checkbox( value: _selectedRoles @@ -296,7 +297,7 @@ class UtilityComponents { CheckboxListTile( title: Text( "Recording", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), activeColor: Colors.blue, controlAffinity: ListTileControlAffinity.trailing, diff --git a/example/lib/hls_viewer/hls_viewer.dart b/example/lib/hls_viewer/hls_viewer.dart index bceca9e2e..775c025c6 100644 --- a/example/lib/hls_viewer/hls_viewer.dart +++ b/example/lib/hls_viewer/hls_viewer.dart @@ -1,6 +1,7 @@ //Package imports import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:provider/provider.dart'; import 'package:video_player/video_player.dart'; @@ -49,7 +50,7 @@ class _HLSViewerState extends State { ) : Text( "Waiting for the HLS Streaming to start...", - style: GoogleFonts.inter(fontSize: 20.0), + style: GoogleFonts.inter(color:iconColor,fontSize: 20.0), ), ), ); diff --git a/example/lib/main.dart b/example/lib/main.dart index 54461e7f1..0888fd041 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -8,6 +8,7 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:provider/provider.dart'; import 'package:wakelock/wakelock.dart'; @@ -35,19 +36,11 @@ void main() async { } class HMSExampleApp extends StatelessWidget { - const HMSExampleApp({Key? key}) : super(key: key); + HMSExampleApp({Key? key}) : super(key: key); @override Widget build(BuildContext context) { - return MaterialApp( - theme: ThemeData( - brightness: Brightness.dark, - primaryColor: Color.fromARGB(255, 13, 107, 184), - appBarTheme: AppBarTheme(color: Colors.black), - scaffoldBackgroundColor: Colors.black), - scaffoldMessengerKey: GlobalKey(), - home: HomePage(), - ); + return MaterialApp(home: HomePage()); } } @@ -65,6 +58,8 @@ class _HomePageState extends State { bool skipPreview = false; bool mirrorCamera = true; bool showStats = false; + bool _isDarkMode = true; + PackageInfo _packageInfo = PackageInfo( appName: 'Unknown', packageName: 'Unknown', @@ -135,218 +130,264 @@ class _HomePageState extends State { } } + void setTheme() { + Constant.isDarkMode = !Constant.isDarkMode; + updateColor(); + setState(() {}); + } + + ThemeData _darkTheme = ThemeData( + brightness: Brightness.dark, + primaryColor: Color.fromARGB(255, 13, 107, 184), + appBarTheme: AppBarTheme(color: Colors.black), + scaffoldBackgroundColor: Colors.black); + + ThemeData _lightTheme = ThemeData( + appBarTheme: AppBarTheme(color: Colors.white), + primaryColor: Color.fromARGB(255, 13, 107, 184), + brightness: Brightness.light, + scaffoldBackgroundColor: Colors.white, + dividerColor: Colors.white54, + ); + @override Widget build(BuildContext context) { - return WillPopScope( - onWillPop: _closeApp, - child: Scaffold( - appBar: AppBar( - title: Text( - '100ms', - style: GoogleFonts.inter(), - ), - actions: [ - PopupMenuButton( - onSelected: handleClick, - icon: SvgPicture.asset( - 'assets/icons/settings.svg', - ), - itemBuilder: (BuildContext context) { - return [ - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (skipPreview) - Text("Enable Preview", style: GoogleFonts.inter()) - else - Text( - "Disable Preview", - style: GoogleFonts.inter(color: Colors.blue), + return MaterialApp( + theme: Constant.isDarkMode ? _darkTheme : _lightTheme, + scaffoldMessengerKey: GlobalKey(), + home: WillPopScope( + onWillPop: _closeApp, + child: Scaffold( + appBar: AppBar( + elevation: 0, + title: Text( + '100ms', + style: GoogleFonts.inter(color:iconColor), + ), + actions: [ + IconButton( + onPressed: () { + setTheme(); + }, + icon: Constant.isDarkMode + ? SvgPicture.asset( + 'assets/icons/light_mode.svg', + color: iconColor + ) + : SvgPicture.asset( + 'assets/icons/dark_mode.svg', + color: iconColor + )), + PopupMenuButton( + onSelected: handleClick, + icon: SvgPicture.asset( + 'assets/icons/settings.svg', + color: iconColor + ), + itemBuilder: (BuildContext context) { + return [ + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (skipPreview) + Text("Enable Preview", style: GoogleFonts.inter(color:iconColor)) + else + Text( + "Disable Preview", + style: GoogleFonts.inter(color: Colors.blue), + ), + if (skipPreview) + SvgPicture.asset( + 'assets/icons/preview_state_on.svg', + color:iconColor + ) + else + SvgPicture.asset( + 'assets/icons/preview_state_off.svg', + color: Colors.blue, + ), + ], + ), + value: 1, + ), + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (mirrorCamera) + Text("Disable Mirroring", + style: GoogleFonts.inter(color: Colors.blue)) + else + Text( + "Enable Mirroring", + style: GoogleFonts.inter(color:iconColor), + ), + Icon( + Icons.camera_front, + color: mirrorCamera ? Colors.blue : iconColor, ), - if (skipPreview) - SvgPicture.asset( - 'assets/icons/preview_state_on.svg', - ) - else + ], + ), + value: 2, + ), + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (showStats) + Text("Disable Stats", + style: GoogleFonts.inter(color: Colors.blue)) + else + Text( + "Enable Stats", + style: GoogleFonts.inter(color:iconColor), + ), SvgPicture.asset( - 'assets/icons/preview_state_off.svg', - color: Colors.blue, + 'assets/icons/stats.svg', + color: showStats ? Colors.blue : iconColor, ), - ], + ], + ), + value: 3, ), - value: 1, - ), - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (mirrorCamera) - Text("Disable Mirroring", - style: GoogleFonts.inter(color: Colors.blue)) - else - Text( - "Enable Mirroring", - style: GoogleFonts.inter(), - ), - Icon( - Icons.camera_front, - color: mirrorCamera ? Colors.blue : Colors.white, - ), - ], + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Version ${_packageInfo.version}", + style: GoogleFonts.inter(color:iconColor)), + ], + ), + value: 4, ), - value: 2, + ]; + }, + ), + ], + ), + body: Center( + child: SingleChildScrollView( + child: Column( + children: [ + Image.asset( + "assets/100ms.gif", + width: 120, + height: 120, ), - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (showStats) - Text("Disable Stats", - style: GoogleFonts.inter(color: Colors.blue)) - else - Text( - "Enable Stats", - style: GoogleFonts.inter(), + SizedBox( + height: 70, + ), + Text('Join Meeting', + style: GoogleFonts.inter( + height: 1, + fontSize: 24, + fontWeight: FontWeight.bold)), + SizedBox( + height: 8, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: TextField( + style: GoogleFonts.inter(), + controller: roomIdController, + keyboardType: TextInputType.url, + decoration: InputDecoration( + hintText: 'Enter Room URL', + hintStyle: GoogleFonts.inter(), + suffixIcon: IconButton( + onPressed: roomIdController.clear, + icon: Icon(Icons.clear), ), - SvgPicture.asset( - 'assets/icons/stats.svg', - color: showStats ? Colors.blue : Colors.white, - ), - ], + border: OutlineInputBorder( + borderRadius: + BorderRadius.all(Radius.circular(16)))), ), - value: 3, ), - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("Version ${_packageInfo.version}", - style: GoogleFonts.inter()), - ], - ), - value: 4, + SizedBox( + height: 30, ), - ]; - }, - ), - ], - ), - body: Center( - child: SingleChildScrollView( - child: Column( - children: [ - Image.asset( - "assets/100ms.gif", - width: 120, - height: 120, - ), - SizedBox( - height: 70, - ), - Text('Join Meeting', - style: GoogleFonts.inter( - height: 1, - fontSize: 24, - fontWeight: FontWeight.bold)), - SizedBox( - height: 8, - ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: TextField( - style: GoogleFonts.inter(), - controller: roomIdController, - keyboardType: TextInputType.url, - decoration: InputDecoration( - hintText: 'Enter Room URL', - hintStyle: GoogleFonts.inter(), - suffixIcon: IconButton( - onPressed: roomIdController.clear, - icon: Icon(Icons.clear), - ), - border: OutlineInputBorder( - borderRadius: - BorderRadius.all(Radius.circular(16)))), - ), - ), - SizedBox( - height: 30, - ), - ElevatedButton( - style: ButtonStyle( - shadowColor: MaterialStateProperty.all(Colors.blue), - shape: - MaterialStateProperty.all( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16.0), - ))), - onPressed: () async { - if (roomIdController.text.isEmpty) { - return; - } - setRTMPUrl(roomIdController.text); - String user = await showDialog( - context: context, - builder: (_) => UserNameDialogOrganism()); - if (user.isNotEmpty) { - bool res = await getPermissions(); - if (res) { - FocusManager.instance.primaryFocus?.unfocus(); - if (skipPreview) { - HMSSDKInteractor _hmsSDKInteractor = - HMSSDKInteractor(); - _hmsSDKInteractor.showStats = showStats; - _hmsSDKInteractor.mirrorCamera = mirrorCamera; - _hmsSDKInteractor.skipPreview = true; - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ListenableProvider.value( - value: MeetingStore( - hmsSDKInteractor: _hmsSDKInteractor), - child: MeetingPage( - roomId: roomIdController.text.trim(), - flow: MeetingFlow.join, - user: user, - isAudioOn: true)))); - } else { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ListenableProvider.value( - value: PreviewStore(), - child: PreviewPage( - roomId: roomIdController.text.trim(), - user: user, - flow: MeetingFlow.join, - mirror: mirrorCamera, - showStats: showStats, - ), - ))); + ElevatedButton( + style: ButtonStyle( + shadowColor: MaterialStateProperty.all(Colors.blue), + shape: MaterialStateProperty.all< + RoundedRectangleBorder>(RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + ))), + onPressed: () async { + if (roomIdController.text.isEmpty) { + return; + } + setRTMPUrl(roomIdController.text); + String user = await showDialog( + context: context, + builder: (_) => UserNameDialogOrganism()); + if (user.isNotEmpty) { + bool res = await getPermissions(); + if (res) { + FocusManager.instance.primaryFocus?.unfocus(); + if (skipPreview) { + HMSSDKInteractor _hmsSDKInteractor = + HMSSDKInteractor(); + _hmsSDKInteractor.showStats = showStats; + _hmsSDKInteractor.mirrorCamera = mirrorCamera; + _hmsSDKInteractor.skipPreview = true; + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ListenableProvider.value( + value: MeetingStore( + hmsSDKInteractor: + _hmsSDKInteractor), + child: MeetingPage( + roomId: + roomIdController.text.trim(), + flow: MeetingFlow.join, + user: user, + isAudioOn: true)))); + } else { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ListenableProvider.value( + value: PreviewStore(), + child: PreviewPage( + roomId: + roomIdController.text.trim(), + user: user, + flow: MeetingFlow.join, + mirror: mirrorCamera, + showStats: showStats, + ), + ))); + } } } - } - }, - child: Container( - width: 250, - padding: const EdgeInsets.fromLTRB(4, 10, 4, 10), - decoration: BoxDecoration( - borderRadius: - BorderRadius.all(Radius.circular(12))), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('Join Meeting', - style: GoogleFonts.inter(height: 1, fontSize: 20)), - SizedBox( - width: 5, - ), - Icon(Icons.arrow_right_alt_outlined, size: 22), - ], + }, + child: Container( + width: 250, + padding: const EdgeInsets.fromLTRB(4, 10, 4, 10), + decoration: BoxDecoration( + borderRadius: + BorderRadius.all(Radius.circular(12))), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('Join Meeting', + style: GoogleFonts.inter( + height: 1, fontSize: 20)), + SizedBox( + width: 5, + ), + Icon(Icons.arrow_right_alt_outlined, size: 22), + ], + ), ), - )), - ], + ), + SizedBox(height: 50,), + Text("Made with ❤️ by 100ms",style: GoogleFonts.inter(color:iconColor)) + ], + ), ), - ), - )), + )), + ), ); } } diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index affb9cb8c..85a5bf066 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -11,6 +11,7 @@ import 'package:hmssdk_flutter_example/common/ui/organisms/grid_audio_view.dart' import 'package:hmssdk_flutter_example/common/ui/organisms/grid_hero_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/grid_video_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/title_bar.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; import 'package:hmssdk_flutter_example/hls_viewer/hls_viewer.dart'; import 'package:provider/provider.dart'; @@ -320,7 +321,7 @@ class _MeetingPageState extends State child: Text( "Waiting for HLS to start...", style: - GoogleFonts.inter( + GoogleFonts.inter(color:iconColor, fontSize: 20), ), ), @@ -336,7 +337,7 @@ class _MeetingPageState extends State return Center( child: Text( 'Waiting for others to join!', - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), )); } Size size = MediaQuery.of(context).size; @@ -451,9 +452,9 @@ class _MeetingPageState extends State context.read().switchVideo(); }, icon: data.item1 - ? SvgPicture.asset("assets/icons/cam_state_on.svg") + ? SvgPicture.asset("assets/icons/cam_state_on.svg",color:iconColor,) : SvgPicture.asset( - "assets/icons/cam_state_off.svg"))); + "assets/icons/cam_state_off.svg",color:iconColor,))); }, ), if (Provider.of(context).localPeer != null && @@ -476,9 +477,9 @@ class _MeetingPageState extends State context.read().switchAudio(); }, icon: isMicOn - ? SvgPicture.asset("assets/icons/mic_state_on.svg") + ? SvgPicture.asset("assets/icons/mic_state_on.svg",color:iconColor,) : SvgPicture.asset( - "assets/icons/mic_state_off.svg"))); + "assets/icons/mic_state_off.svg",color:iconColor,))); }, ), Selector( @@ -494,7 +495,7 @@ class _MeetingPageState extends State }, icon: SvgPicture.asset( "assets/icons/hand_state_on.svg", - color: raisedHand ? Colors.yellow : Colors.white, + color: raisedHand ? Colors.yellow : iconColor, ))); }, ), @@ -511,7 +512,7 @@ class _MeetingPageState extends State }, icon: SvgPicture.asset( "assets/icons/brb.svg", - color: isBRB ? Colors.red : Colors.white, + color: isBRB ? Colors.red : iconColor, ))); }, ), @@ -529,9 +530,9 @@ class _MeetingPageState extends State }, icon: isNewMessageReceived ? SvgPicture.asset( - "assets/icons/message_badge_on.svg") + "assets/icons/message_badge_on.svg",color:iconColor,) : SvgPicture.asset( - "assets/icons/message_badge_off.svg")), + "assets/icons/message_badge_off.svg",color:iconColor,)), ); }), Container( @@ -580,6 +581,7 @@ class _MeetingPageState extends State ) : SvgPicture.asset( 'assets/icons/hand_state_off.svg', + color:iconColor, ), )); }, @@ -598,9 +600,10 @@ class _MeetingPageState extends State }, icon: isNewMessageReceived ? SvgPicture.asset( - "assets/icons/message_badge_on.svg") + "assets/icons/message_badge_on.svg",color:iconColor,) + : SvgPicture.asset( - "assets/icons/message_badge_off.svg")), + "assets/icons/message_badge_off.svg",color:iconColor,)), ); }), Container( @@ -634,9 +637,9 @@ class _MeetingPageState extends State children: [ Text( "Send Logs", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), - SvgPicture.asset("assets/icons/bug.svg"), + SvgPicture.asset("assets/icons/bug.svg",color:iconColor,), ], ), value: 1, @@ -653,13 +656,13 @@ class _MeetingPageState extends State style: GoogleFonts.inter( color: meetingStore.isRecordingStarted ? Colors.blue - : Colors.white, + : iconColor, )), SvgPicture.asset( "assets/icons/record.svg", color: meetingStore.isRecordingStarted - ? Colors.blue - : Colors.white, + ? Colors.red + : iconColor, ), ]), value: 2, @@ -671,9 +674,9 @@ class _MeetingPageState extends State children: [ Text( "Toggle Camera ", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), - SvgPicture.asset("assets/icons/camera.svg"), + SvgPicture.asset("assets/icons/camera.svg",color:iconColor,), ]), value: 3, ), @@ -683,9 +686,9 @@ class _MeetingPageState extends State children: [ Text( "Participants ", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), - SvgPicture.asset("assets/icons/participants.svg"), + SvgPicture.asset("assets/icons/participants.svg",color:iconColor,), ]), value: 4, ), @@ -697,13 +700,13 @@ class _MeetingPageState extends State meetingStore.meetingMode == MeetingMode.Audio ? "Video View" : "Audio View", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), SvgPicture.asset( meetingStore.meetingMode == MeetingMode.Audio ? 'assets/icons/cam_state_on.svg' : 'assets/icons/mic_state_on.svg', - color: Colors.white, + color: iconColor, height: 24.0, width: 24.0, ), @@ -718,13 +721,13 @@ class _MeetingPageState extends State style: GoogleFonts.inter( color: meetingStore.isActiveSpeakerMode ? Colors.blue - : Colors.white, + : iconColor, )), SvgPicture.asset( "assets/icons/participants.svg", color: meetingStore.isActiveSpeakerMode ? Colors.blue - : Colors.white, + : iconColor, ), ]), value: 6, @@ -737,13 +740,13 @@ class _MeetingPageState extends State style: GoogleFonts.inter( color: meetingStore.meetingMode == MeetingMode.Hero ? Colors.blue - : Colors.white, + : iconColor, )), SvgPicture.asset( "assets/icons/participants.svg", color: meetingStore.meetingMode == MeetingMode.Hero ? Colors.blue - : Colors.white, + : iconColor, ), ]), value: 7, @@ -756,13 +759,13 @@ class _MeetingPageState extends State style: GoogleFonts.inter( color: meetingStore.meetingMode == MeetingMode.Single ? Colors.blue - : Colors.white, + : iconColor, )), SvgPicture.asset( "assets/icons/single_tile.svg", color: meetingStore.meetingMode == MeetingMode.Single ? Colors.blue - : Colors.white, + : iconColor, ), ]), value: 8, @@ -773,9 +776,9 @@ class _MeetingPageState extends State children: [ Text( "Change Name", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), - SvgPicture.asset("assets/icons/pencil.svg"), + SvgPicture.asset("assets/icons/pencil.svg",color:iconColor,), ]), value: 9, ), @@ -789,13 +792,13 @@ class _MeetingPageState extends State style: GoogleFonts.inter( color: meetingStore.hasHlsStarted ? Colors.blue - : Colors.white, + : iconColor, ), ), SvgPicture.asset("assets/icons/hls.svg", color: meetingStore.hasHlsStarted ? Colors.blue - : Colors.white), + : iconColor), ]), value: 10, ), @@ -806,9 +809,9 @@ class _MeetingPageState extends State children: [ Text( "Mute", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), - SvgPicture.asset("assets/icons/mic_state_off.svg"), + SvgPicture.asset("assets/icons/mic_state_off.svg",color:iconColor,), ]), value: 11, ), @@ -821,12 +824,12 @@ class _MeetingPageState extends State style: GoogleFonts.inter( color: meetingStore.isStatsVisible ? Colors.blue - : Colors.white), + : iconColor), ), SvgPicture.asset("assets/icons/stats.svg", color: meetingStore.isStatsVisible ? Colors.blue - : Colors.white), + : iconColor), ]), value: 12, ), @@ -843,13 +846,13 @@ class _MeetingPageState extends State style: GoogleFonts.inter( color: meetingStore.isScreenShareOn ? Colors.blue - : Colors.white), + : iconColor), ), SvgPicture.asset( "assets/icons/screen_share.svg", color: meetingStore.isScreenShareOn ? Colors.blue - : Colors.white, + : iconColor, ), ]), value: 13, @@ -861,9 +864,9 @@ class _MeetingPageState extends State children: [ Text( "End Room", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ), - SvgPicture.asset("assets/icons/end_room.svg"), + SvgPicture.asset("assets/icons/end_room.svg",color:iconColor,), ]), value: 14, ), diff --git a/example/lib/meeting/meeting_participants_list.dart b/example/lib/meeting/meeting_participants_list.dart index 9f9d8262a..6b6fdda02 100644 --- a/example/lib/meeting/meeting_participants_list.dart +++ b/example/lib/meeting/meeting_participants_list.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:provider/provider.dart'; import 'package:tuple/tuple.dart'; @@ -58,7 +59,7 @@ class _ParticipantsListState extends State { } else { return Text( "No Participants", - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color:iconColor,), ); } }), diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index 1d87357b8..991067299 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter/hmssdk_flutter.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; @@ -114,7 +115,7 @@ class _PreviewPageState extends State with WidgetsBindingObserver { _previewStore.peer!.name), style: GoogleFonts.inter( fontSize: 36, - color: Colors.white), + color:Colors.white,), ))), ), ), @@ -195,16 +196,14 @@ class _PreviewPageState extends State with WidgetsBindingObserver { fontWeight: FontWeight .bold, - color: Colors - .white), + color:Colors.white,), ), Text(peer.role.name, style: GoogleFonts.inter( fontWeight: FontWeight .bold, - color: Colors - .white)) + color:Colors.white,)) ], ), ); @@ -236,6 +235,7 @@ class _PreviewPageState extends State with WidgetsBindingObserver { children: [ SvgPicture.asset( "assets/icons/participants.svg", + color:iconColor, ), SizedBox( width: 2, @@ -243,6 +243,7 @@ class _PreviewPageState extends State with WidgetsBindingObserver { Text( _previewStore.peerCount.toString(), style: GoogleFonts.inter( + color:iconColor, fontWeight: FontWeight.bold, fontSize: 16), ) From 4ea6ed505885fbf4b5dcf4029398ace472dd71ca Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 1 Jun 2022 17:40:52 +0530 Subject: [PATCH 42/67] dark and light mode switch fix --- .../ui/organisms/chat_bottom_sheet.dart | 2 +- example/lib/main.dart | 504 +++++++++--------- 2 files changed, 259 insertions(+), 247 deletions(-) diff --git a/example/lib/common/ui/organisms/chat_bottom_sheet.dart b/example/lib/common/ui/organisms/chat_bottom_sheet.dart index 041864475..b2361076f 100644 --- a/example/lib/common/ui/organisms/chat_bottom_sheet.dart +++ b/example/lib/common/ui/organisms/chat_bottom_sheet.dart @@ -69,7 +69,7 @@ class _ChatWidgetState extends State { child: DropdownButton2( buttonWidth: 120, value: valueChoose, - iconEnabledColor: Colors.black, + iconEnabledColor: iconColor, onChanged: (newvalue) { setState(() { this.valueChoose = diff --git a/example/lib/main.dart b/example/lib/main.dart index 0888fd041..ed5e073ce 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -35,12 +35,48 @@ void main() async { () => runApp(HMSExampleApp()), FirebaseCrashlytics.instance.recordError); } -class HMSExampleApp extends StatelessWidget { +class HMSExampleApp extends StatefulWidget { HMSExampleApp({Key? key}) : super(key: key); + @override + _HMSExampleAppState createState() => _HMSExampleAppState(); + static _HMSExampleAppState of(BuildContext context) => + context.findAncestorStateOfType<_HMSExampleAppState>()!; +} + +class _HMSExampleAppState extends State { + ThemeMode _themeMode = ThemeMode.dark; + + ThemeData _darkTheme = ThemeData( + brightness: Brightness.dark, + primaryColor: Color.fromARGB(255, 13, 107, 184), + backgroundColor: Colors.black, + scaffoldBackgroundColor: Colors.black); + + ThemeData _lightTheme = ThemeData( + primaryColor: Color.fromARGB(255, 13, 107, 184), + brightness: Brightness.light, + scaffoldBackgroundColor: Colors.white, + backgroundColor: Colors.black, + dividerColor: Colors.white54, + ); + @override Widget build(BuildContext context) { - return MaterialApp(home: HomePage()); + return MaterialApp( + home: HomePage(), + theme: _lightTheme, + darkTheme: _darkTheme, + themeMode: _themeMode, + ); + } + + void changeTheme(ThemeMode themeMode) { + setState(() { + _themeMode = themeMode; + Constant.isDarkMode = _themeMode == ThemeMode.dark ? true : false; + updateColor(); + }); } } @@ -58,7 +94,6 @@ class _HomePageState extends State { bool skipPreview = false; bool mirrorCamera = true; bool showStats = false; - bool _isDarkMode = true; PackageInfo _packageInfo = PackageInfo( appName: 'Unknown', @@ -130,264 +165,241 @@ class _HomePageState extends State { } } - void setTheme() { - Constant.isDarkMode = !Constant.isDarkMode; - updateColor(); - setState(() {}); - } - - ThemeData _darkTheme = ThemeData( - brightness: Brightness.dark, - primaryColor: Color.fromARGB(255, 13, 107, 184), - appBarTheme: AppBarTheme(color: Colors.black), - scaffoldBackgroundColor: Colors.black); - - ThemeData _lightTheme = ThemeData( - appBarTheme: AppBarTheme(color: Colors.white), - primaryColor: Color.fromARGB(255, 13, 107, 184), - brightness: Brightness.light, - scaffoldBackgroundColor: Colors.white, - dividerColor: Colors.white54, - ); - @override Widget build(BuildContext context) { - return MaterialApp( - theme: Constant.isDarkMode ? _darkTheme : _lightTheme, - scaffoldMessengerKey: GlobalKey(), - home: WillPopScope( - onWillPop: _closeApp, - child: Scaffold( - appBar: AppBar( - elevation: 0, - title: Text( - '100ms', - style: GoogleFonts.inter(color:iconColor), - ), - actions: [ - IconButton( - onPressed: () { - setTheme(); - }, - icon: Constant.isDarkMode - ? SvgPicture.asset( - 'assets/icons/light_mode.svg', - color: iconColor - ) - : SvgPicture.asset( - 'assets/icons/dark_mode.svg', - color: iconColor - )), - PopupMenuButton( - onSelected: handleClick, - icon: SvgPicture.asset( - 'assets/icons/settings.svg', - color: iconColor - ), - itemBuilder: (BuildContext context) { - return [ - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (skipPreview) - Text("Enable Preview", style: GoogleFonts.inter(color:iconColor)) - else - Text( - "Disable Preview", - style: GoogleFonts.inter(color: Colors.blue), - ), - if (skipPreview) - SvgPicture.asset( - 'assets/icons/preview_state_on.svg', - color:iconColor - ) - else - SvgPicture.asset( - 'assets/icons/preview_state_off.svg', - color: Colors.blue, - ), - ], - ), - value: 1, - ), - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (mirrorCamera) - Text("Disable Mirroring", - style: GoogleFonts.inter(color: Colors.blue)) - else - Text( - "Enable Mirroring", - style: GoogleFonts.inter(color:iconColor), - ), - Icon( - Icons.camera_front, - color: mirrorCamera ? Colors.blue : iconColor, + return WillPopScope( + onWillPop: _closeApp, + child: Scaffold( + appBar: AppBar( + elevation: 0, + title: Text( + '100ms', + style: GoogleFonts.inter(), + ), + actions: [ + IconButton( + onPressed: () { + if (Constant.isDarkMode) { + HMSExampleApp.of(context).changeTheme(ThemeMode.light); + } else { + HMSExampleApp.of(context).changeTheme(ThemeMode.dark); + } + }, + icon: Constant.isDarkMode + ? SvgPicture.asset( + 'assets/icons/light_mode.svg', + ) + : SvgPicture.asset( + 'assets/icons/dark_mode.svg', + )), + PopupMenuButton( + onSelected: handleClick, + icon: SvgPicture.asset( + 'assets/icons/settings.svg', + ), + itemBuilder: (BuildContext context) { + return [ + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (skipPreview) + Text("Enable Preview", + style: GoogleFonts.inter(color: iconColor)) + else + Text( + "Disable Preview", + style: GoogleFonts.inter(color: Colors.blue), ), - ], - ), - value: 2, - ), - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - if (showStats) - Text("Disable Stats", - style: GoogleFonts.inter(color: Colors.blue)) - else - Text( - "Enable Stats", - style: GoogleFonts.inter(color:iconColor), - ), + if (skipPreview) + SvgPicture.asset( + 'assets/icons/preview_state_on.svg', + color: iconColor) + else SvgPicture.asset( - 'assets/icons/stats.svg', - color: showStats ? Colors.blue : iconColor, + 'assets/icons/preview_state_off.svg', + color: Colors.blue, ), - ], - ), - value: 3, + ], ), - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("Version ${_packageInfo.version}", - style: GoogleFonts.inter(color:iconColor)), - ], - ), - value: 4, - ), - ]; - }, - ), - ], - ), - body: Center( - child: SingleChildScrollView( - child: Column( - children: [ - Image.asset( - "assets/100ms.gif", - width: 120, - height: 120, - ), - SizedBox( - height: 70, + value: 1, ), - Text('Join Meeting', - style: GoogleFonts.inter( - height: 1, - fontSize: 24, - fontWeight: FontWeight.bold)), - SizedBox( - height: 8, + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (mirrorCamera) + Text("Disable Mirroring", + style: GoogleFonts.inter(color: Colors.blue)) + else + Text( + "Enable Mirroring", + style: GoogleFonts.inter(color: iconColor), + ), + Icon( + Icons.camera_front, + color: mirrorCamera ? Colors.blue : iconColor, + ), + ], + ), + value: 2, ), - Padding( - padding: const EdgeInsets.symmetric(horizontal: 10), - child: TextField( - style: GoogleFonts.inter(), - controller: roomIdController, - keyboardType: TextInputType.url, - decoration: InputDecoration( - hintText: 'Enter Room URL', - hintStyle: GoogleFonts.inter(), - suffixIcon: IconButton( - onPressed: roomIdController.clear, - icon: Icon(Icons.clear), + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + if (showStats) + Text("Disable Stats", + style: GoogleFonts.inter(color: Colors.blue)) + else + Text( + "Enable Stats", + style: GoogleFonts.inter(color: iconColor), ), - border: OutlineInputBorder( - borderRadius: - BorderRadius.all(Radius.circular(16)))), + SvgPicture.asset( + 'assets/icons/stats.svg', + color: showStats ? Colors.blue : iconColor, + ), + ], ), + value: 3, ), - SizedBox( - height: 30, + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text("Version ${_packageInfo.version}", + style: GoogleFonts.inter(color: iconColor)), + ], + ), + value: 4, ), - ElevatedButton( - style: ButtonStyle( - shadowColor: MaterialStateProperty.all(Colors.blue), - shape: MaterialStateProperty.all< - RoundedRectangleBorder>(RoundedRectangleBorder( - borderRadius: BorderRadius.circular(16.0), - ))), - onPressed: () async { - if (roomIdController.text.isEmpty) { - return; - } - setRTMPUrl(roomIdController.text); - String user = await showDialog( - context: context, - builder: (_) => UserNameDialogOrganism()); - if (user.isNotEmpty) { - bool res = await getPermissions(); - if (res) { - FocusManager.instance.primaryFocus?.unfocus(); - if (skipPreview) { - HMSSDKInteractor _hmsSDKInteractor = - HMSSDKInteractor(); - _hmsSDKInteractor.showStats = showStats; - _hmsSDKInteractor.mirrorCamera = mirrorCamera; - _hmsSDKInteractor.skipPreview = true; - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ListenableProvider.value( - value: MeetingStore( - hmsSDKInteractor: - _hmsSDKInteractor), - child: MeetingPage( - roomId: - roomIdController.text.trim(), - flow: MeetingFlow.join, - user: user, - isAudioOn: true)))); - } else { - Navigator.of(context).push(MaterialPageRoute( - builder: (_) => ListenableProvider.value( - value: PreviewStore(), - child: PreviewPage( - roomId: - roomIdController.text.trim(), - user: user, - flow: MeetingFlow.join, - mirror: mirrorCamera, - showStats: showStats, - ), - ))); - } - } - } - }, - child: Container( - width: 250, - padding: const EdgeInsets.fromLTRB(4, 10, 4, 10), - decoration: BoxDecoration( + ]; + }, + ), + ], + ), + body: Center( + child: SingleChildScrollView( + child: Column( + children: [ + Image.asset( + "assets/100ms.gif", + width: 120, + height: 120, + ), + SizedBox( + height: 70, + ), + Text('Join Meeting', + style: GoogleFonts.inter( + height: 1, + fontSize: 24, + fontWeight: FontWeight.bold)), + SizedBox( + height: 8, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: TextField( + style: GoogleFonts.inter(), + controller: roomIdController, + keyboardType: TextInputType.url, + decoration: InputDecoration( + hintText: 'Enter Room URL', + hintStyle: GoogleFonts.inter(), + suffixIcon: IconButton( + onPressed: roomIdController.clear, + icon: Icon(Icons.clear), + ), + border: OutlineInputBorder( borderRadius: - BorderRadius.all(Radius.circular(12))), - child: Row( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text('Join Meeting', - style: GoogleFonts.inter( - height: 1, fontSize: 20)), - SizedBox( - width: 5, - ), - Icon(Icons.arrow_right_alt_outlined, size: 22), - ], + BorderRadius.all(Radius.circular(16)))), + ), + ), + SizedBox( + height: 30, + ), + ElevatedButton( + style: ButtonStyle( + shadowColor: MaterialStateProperty.all(Colors.blue), + shape: + MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + ))), + onPressed: () async { + if (roomIdController.text.isEmpty) { + return; + } + setRTMPUrl(roomIdController.text); + String user = await showDialog( + context: context, + builder: (_) => UserNameDialogOrganism()); + if (user.isNotEmpty) { + bool res = await getPermissions(); + if (res) { + FocusManager.instance.primaryFocus?.unfocus(); + if (skipPreview) { + HMSSDKInteractor _hmsSDKInteractor = + HMSSDKInteractor(); + _hmsSDKInteractor.showStats = showStats; + _hmsSDKInteractor.mirrorCamera = mirrorCamera; + _hmsSDKInteractor.skipPreview = true; + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ListenableProvider.value( + value: MeetingStore( + hmsSDKInteractor: _hmsSDKInteractor), + child: MeetingPage( + roomId: roomIdController.text.trim(), + flow: MeetingFlow.join, + user: user, + isAudioOn: true)))); + } else { + Navigator.of(context).push(MaterialPageRoute( + builder: (_) => ListenableProvider.value( + value: PreviewStore(), + child: PreviewPage( + roomId: roomIdController.text.trim(), + user: user, + flow: MeetingFlow.join, + mirror: mirrorCamera, + showStats: showStats, + ), + ))); + } + } + } + }, + child: Container( + width: 250, + padding: const EdgeInsets.fromLTRB(4, 10, 4, 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.all(Radius.circular(12))), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text('Join Meeting', + style: + GoogleFonts.inter(height: 1, fontSize: 20)), + SizedBox( + width: 5, ), - ), - ), - SizedBox(height: 50,), - Text("Made with ❤️ by 100ms",style: GoogleFonts.inter(color:iconColor)) - ], - ), + Icon(Icons.arrow_right_alt_outlined, size: 22), + ], + ), + ), + ), + SizedBox( + height: 50, + ), + Text("Made with ❤️ by 100ms", + style: GoogleFonts.inter(color: iconColor)) + ], ), - )), - ), + ), + )), ); } } From 9d10cc8bd2b196546fb21afe6be4a81986ac2120 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 1 Jun 2022 17:55:18 +0530 Subject: [PATCH 43/67] homepage appbar color change --- example/lib/main.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index ed5e073ce..f729b0925 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -171,10 +171,11 @@ class _HomePageState extends State { onWillPop: _closeApp, child: Scaffold( appBar: AppBar( + backgroundColor: Constant.isDarkMode ? Colors.black : Colors.white, elevation: 0, title: Text( '100ms', - style: GoogleFonts.inter(), + style: GoogleFonts.inter(color: iconColor), ), actions: [ IconButton( @@ -188,14 +189,17 @@ class _HomePageState extends State { icon: Constant.isDarkMode ? SvgPicture.asset( 'assets/icons/light_mode.svg', + color: iconColor, ) : SvgPicture.asset( 'assets/icons/dark_mode.svg', + color: iconColor, )), PopupMenuButton( onSelected: handleClick, icon: SvgPicture.asset( 'assets/icons/settings.svg', + color: iconColor, ), itemBuilder: (BuildContext context) { return [ From df88d8a1214195dd0b038355370b0075bc518a81 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Wed, 1 Jun 2022 18:44:42 +0530 Subject: [PATCH 44/67] Fixed degrade icon location --- example/lib/common/ui/organisms/degrade_tile.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/lib/common/ui/organisms/degrade_tile.dart b/example/lib/common/ui/organisms/degrade_tile.dart index 1437249dc..6740d98d5 100644 --- a/example/lib/common/ui/organisms/degrade_tile.dart +++ b/example/lib/common/ui/organisms/degrade_tile.dart @@ -45,8 +45,8 @@ class _DegradeTileState extends State { 'assets/icons/degrade.svg', ), ), - top: 5.0, - left: 5.0, + top: 10.0, + right: 5.0, ), AudioLevelAvatar() ], From d8735ce283f87c7cd262a4acce15d8890035665d Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Wed, 1 Jun 2022 19:02:17 +0530 Subject: [PATCH 45/67] updated Native iOS SDK version --- example/android/Gemfile.lock | 2 +- example/android/app/build.gradle | 4 ++-- example/ios/Gemfile.lock | 2 +- example/ios/Podfile | 2 +- example/ios/Podfile.lock | 16 ++++++++-------- example/ios/Runner.xcodeproj/project.pbxproj | 18 +++++++++--------- example/ios/Runner/Info.plist | 4 ++-- example/pubspec.lock | 2 +- example/pubspec.yaml | 2 +- ios/Classes/SwiftHmssdkFlutterPlugin.swift | 3 ++- ios/hmssdk_flutter.podspec | 6 +++--- 11 files changed, 31 insertions(+), 30 deletions(-) diff --git a/example/android/Gemfile.lock b/example/android/Gemfile.lock index cdf0a18ee..8c89dd116 100644 --- a/example/android/Gemfile.lock +++ b/example/android/Gemfile.lock @@ -8,7 +8,7 @@ GEM artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.594.0) + aws-partitions (1.595.0) aws-sdk-core (3.131.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.525.0) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 206439e14..2153a79c4 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -32,8 +32,8 @@ android { applicationId "live.hms.flutter" minSdkVersion 21 targetSdkVersion 32 - versionCode 69 - versionName "1.1.19" + versionCode 70 + versionName "1.1.20" } signingConfigs { diff --git a/example/ios/Gemfile.lock b/example/ios/Gemfile.lock index cdf0a18ee..8c89dd116 100644 --- a/example/ios/Gemfile.lock +++ b/example/ios/Gemfile.lock @@ -8,7 +8,7 @@ GEM artifactory (3.0.15) atomos (0.1.3) aws-eventstream (1.2.0) - aws-partitions (1.594.0) + aws-partitions (1.595.0) aws-sdk-core (3.131.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.525.0) diff --git a/example/ios/Podfile b/example/ios/Podfile index 988a9dba6..717fff83e 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '10.0' +platform :ios, '12.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 71dc7d3b2..9f00338af 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -131,12 +131,12 @@ PODS: - GoogleUtilities/Logger - GoogleUtilities/UserDefaults (7.7.0): - GoogleUtilities/Logger - - HMSSDK (0.2.13): - - HMSWebRTC (= 1.0.4518) + - HMSSDK (0.3.1): + - HMSWebRTC (= 1.0.4897) - hmssdk_flutter (0.7.2): - Flutter - - HMSSDK (= 0.2.13) - - HMSWebRTC (1.0.4518) + - HMSSDK (= 0.3.1) + - HMSWebRTC (1.0.4897) - nanopb (2.30908.0): - nanopb/decode (= 2.30908.0) - nanopb/encode (= 2.30908.0) @@ -234,9 +234,9 @@ SPEC CHECKSUMS: GoogleAppMeasurement: 4c19f031220c72464d460c9daa1fb5d1acce958e GoogleDataTransport: 5fffe35792f8b96ec8d6775f5eccd83c998d5a3b GoogleUtilities: e0913149f6b0625b553d70dae12b49fc62914fd1 - HMSSDK: 45b5e25be25b74bb2ca71cce4c6128f57b7eccc4 - hmssdk_flutter: 2e904fc421cc726447966dd16d14107114c5a4ba - HMSWebRTC: 599fb1d886daecd6e58984f84224d708bce8b565 + HMSSDK: 9780df180a4c8bd3446fd2981b338856fd02b3a4 + hmssdk_flutter: 3fed63723ebebd88699728f9a6fd93984bf51c74 + HMSWebRTC: aa317dbbf56a191463a90491e5e37f298f8fa29c nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96 package_info_plus: 6c92f08e1f853dc01228d6f553146438dafcd14e path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02 @@ -246,6 +246,6 @@ SPEC CHECKSUMS: video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff wakelock: d0fc7c864128eac40eba1617cb5264d9c940b46f -PODFILE CHECKSUM: 4243bd56b6b40b83d3e32bd65fa10fffb54f8ea7 +PODFILE CHECKSUM: e57a6b233c1c6fff78fd48a8b8a1b5b9fcc1e3a5 COCOAPODS: 1.11.3 diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index e34637878..5cc566185 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -366,7 +366,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -384,11 +384,11 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 69; + CURRENT_PROJECT_VERSION = 70; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -453,7 +453,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -502,7 +502,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -522,12 +522,12 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 69; + CURRENT_PROJECT_VERSION = 70; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -555,11 +555,11 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 69; + CURRENT_PROJECT_VERSION = 70; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index 4687ca808..13de3d5b7 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.19 + 1.1.20 CFBundleSignature ???? CFBundleURLTypes @@ -34,7 +34,7 @@ CFBundleVersion - 69 + 70 ITSAppUsesNonExemptEncryption LSApplicationCategoryType diff --git a/example/pubspec.lock b/example/pubspec.lock index 9310f268a..2c843d3cc 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -615,7 +615,7 @@ packages: name: video_player_android url: "https://pub.dartlang.org" source: hosted - version: "2.3.4" + version: "2.3.5" video_player_avfoundation: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index d6b9105fb..ca35ab3e4 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -36,9 +36,9 @@ dependencies: flutter_staggered_grid_view: tuple: avatar_glow: - fluttertoast: flutter_svg: google_fonts: + fluttertoast: ^8.0.9 dev_dependencies: flutter_test: diff --git a/ios/Classes/SwiftHmssdkFlutterPlugin.swift b/ios/Classes/SwiftHmssdkFlutterPlugin.swift index 173216ba2..f76b391e8 100644 --- a/ios/Classes/SwiftHmssdkFlutterPlugin.swift +++ b/ios/Classes/SwiftHmssdkFlutterPlugin.swift @@ -280,7 +280,8 @@ public class SwiftHmssdkFlutterPlugin: NSObject, FlutterPlugin, HMSUpdateListene maxBitrate: bitrate, maxFrameRate: framerate, cameraFacing: .front, - trackDescription: desc) + trackDescription: desc, + videoPlugins: nil) } } diff --git a/ios/hmssdk_flutter.podspec b/ios/hmssdk_flutter.podspec index 4a4c04e04..da5ebb95d 100644 --- a/ios/hmssdk_flutter.podspec +++ b/ios/hmssdk_flutter.podspec @@ -12,9 +12,9 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/100mslive/100ms-flutter.git' } s.source_files = 'Classes/**/*' s.dependency 'Flutter' - s.dependency 'HMSSDK', '0.2.13' - s.platform = :ios, '10.0' - s.ios.deployment_target = '10.0' + s.dependency 'HMSSDK', '0.3.1' + s.platform = :ios, '12.0' + s.ios.deployment_target = '12.0' # Flutter.framework does not contain a i386 slice. s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' } s.swift_version = '5.0' From 26bf071f1723d2e1f0769d3e415f04d80da6c865 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 1 Jun 2022 19:28:46 +0530 Subject: [PATCH 46/67] session id for ios --- ios/Classes/Models/HMSRoomExtension.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ios/Classes/Models/HMSRoomExtension.swift b/ios/Classes/Models/HMSRoomExtension.swift index 219f02540..8e7c954fc 100644 --- a/ios/Classes/Models/HMSRoomExtension.swift +++ b/ios/Classes/Models/HMSRoomExtension.swift @@ -25,6 +25,10 @@ class HMSRoomExtension { if let data = room.metaData { dict["meta_data"] = data } + + if let sessionId = room.sessionID { + dict["session_id"] = sessionId + } var peers = [[String: Any]]() room.peers.forEach { peers.append(HMSPeerExtension.toDictionary($0)) } From 0c36a16d3d772a80144ab65ad05edc20a7c75c95 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Wed, 1 Jun 2022 20:01:09 +0530 Subject: [PATCH 47/67] Fixed VideoView --- .../live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt | 2 +- lib/src/hmssdk.dart | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt b/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt index ac6707a3c..1b57ae937 100644 --- a/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt +++ b/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt @@ -73,6 +73,6 @@ class HMSVideoViewFactory(private val plugin: HmssdkFlutterPlugin) : val track = HmsUtilities.getVideoTrack(trackId!!, room!!) - return HMSVideoViewWidget(requireNotNull(context), viewId, creationParams, track!!, setMirror!!, scaleType, matchParent) + return HMSVideoViewWidget(context, viewId, creationParams, track!!, setMirror!!, scaleType, matchParent) } } \ No newline at end of file diff --git a/lib/src/hmssdk.dart b/lib/src/hmssdk.dart index d360e8398..14f5a72b5 100644 --- a/lib/src/hmssdk.dart +++ b/lib/src/hmssdk.dart @@ -63,7 +63,7 @@ class HMSSDK with WidgetsBindingObserver { isTerminal: false, params: {...config.getJson()}); } - WidgetsBinding.instance.addObserver(this); + WidgetsBinding.instance!.addObserver(this); return await PlatformService.invokeMethod(PlatformMethod.join, arguments: {...config.getJson()}); } @@ -100,7 +100,7 @@ class HMSSDK with WidgetsBindingObserver { hmsException: HMSException.fromMap(result["error"])); } } - WidgetsBinding.instance.removeObserver(this); + WidgetsBinding.instance!.removeObserver(this); } /// To switch local peer's audio on/off. From ea1df1bd2c7c507e2f172b762e5c349dbd5df911 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Wed, 1 Jun 2022 20:09:09 +0530 Subject: [PATCH 48/67] bumped sample app version --- example/android/app/build.gradle | 4 ++-- example/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- example/ios/Runner/Info.plist | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 2153a79c4..dea308527 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -32,8 +32,8 @@ android { applicationId "live.hms.flutter" minSdkVersion 21 targetSdkVersion 32 - versionCode 70 - versionName "1.1.20" + versionCode 71 + versionName "1.1.21" } signingConfigs { diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 5cc566185..161de1302 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -384,7 +384,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 70; + CURRENT_PROJECT_VERSION = 71; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; @@ -522,7 +522,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 70; + CURRENT_PROJECT_VERSION = 71; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; @@ -555,7 +555,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 70; + CURRENT_PROJECT_VERSION = 71; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index 13de3d5b7..afa4242f2 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.20 + 1.1.21 CFBundleSignature ???? CFBundleURLTypes @@ -34,7 +34,7 @@ CFBundleVersion - 70 + 71 ITSAppUsesNonExemptEncryption LSApplicationCategoryType From 14b9ba8e6f1eb53048573e7ae27065ad6a37d8c5 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 1 Jun 2022 20:21:25 +0530 Subject: [PATCH 49/67] preview count and hero mode fixed --- .../common/ui/organisms/grid_hero_view.dart | 16 +- example/lib/preview/preview_page.dart | 137 +++++++++--------- example/lib/preview/preview_store.dart | 5 - lib/src/enum/hms_room_update.dart | 7 - 4 files changed, 79 insertions(+), 86 deletions(-) diff --git a/example/lib/common/ui/organisms/grid_hero_view.dart b/example/lib/common/ui/organisms/grid_hero_view.dart index beb9fe250..1f1f0c038 100644 --- a/example/lib/common/ui/organisms/grid_hero_view.dart +++ b/example/lib/common/ui/organisms/grid_hero_view.dart @@ -3,7 +3,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/common/util/app_color.dart'; -import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:provider/provider.dart'; //Project imports @@ -38,10 +37,14 @@ Widget gridHeroView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/screen_share.svg",color:iconColor,), - Text( - "You are sharing your screen", - style: GoogleFonts.inter(color:iconColor,)), + SvgPicture.asset( + "assets/icons/screen_share.svg", + color: iconColor, + ), + Text("You are sharing your screen", + style: GoogleFonts.inter( + color: iconColor, + )), ], ), ) @@ -69,8 +72,7 @@ Widget gridHeroView( } List pattern(int itemCount, int screenShareCount, Size size) { - double ratio = Utilities.getRatio(size); - + double ratio = (size.width) / (size.height * 0.82); List tiles = []; for (int i = 0; i < screenShareCount; i++) { diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index 991067299..ab19f8653 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -114,8 +114,9 @@ class _PreviewPageState extends State with WidgetsBindingObserver { Utilities.getAvatarTitle( _previewStore.peer!.name), style: GoogleFonts.inter( - fontSize: 36, - color:Colors.white,), + fontSize: 36, + color: Colors.white, + ), ))), ), ), @@ -151,71 +152,72 @@ class _PreviewPageState extends State with WidgetsBindingObserver { color: Colors.red, ), ), - if (_previewStore.peerCount != 0) + if (_previewStore.peers.isNotEmpty) GestureDetector( onTap: () { - if (_previewStore.peers.isNotEmpty) - showModalBottomSheet( - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.circular(10.0), - ), - context: context, - builder: (BuildContext context) { - return Container( - height: MediaQuery.of(context) - .size - .height / - 2, - padding: EdgeInsets.only(top: 15), - child: ListView.separated( - itemBuilder: - (context, index) { - HMSPeer peer = _previewStore - .peers[index]; - return Container( - padding: - EdgeInsets.all(15), - margin: - EdgeInsets.symmetric( - horizontal: 10), - decoration: BoxDecoration( - color: Color.fromARGB( - 174, 0, 0, 0), - borderRadius: - BorderRadius - .circular(8)), - child: Row( - mainAxisAlignment: - MainAxisAlignment - .spaceBetween, - children: [ - Text( - peer.name, - style: GoogleFonts.inter( - fontWeight: - FontWeight - .bold, - color:Colors.white,), + showModalBottomSheet( + shape: RoundedRectangleBorder( + borderRadius: + BorderRadius.circular(10.0), + ), + context: context, + builder: (BuildContext context) { + return Container( + height: MediaQuery.of(context) + .size + .height / + 2, + padding: EdgeInsets.only(top: 15), + child: ListView.separated( + itemBuilder: (context, index) { + HMSPeer peer = _previewStore + .peers[index]; + return Container( + padding: EdgeInsets.all(15), + margin: + EdgeInsets.symmetric( + horizontal: 10), + decoration: BoxDecoration( + color: Color.fromARGB( + 174, 0, 0, 0), + borderRadius: + BorderRadius + .circular(8)), + child: Row( + mainAxisAlignment: + MainAxisAlignment + .spaceBetween, + children: [ + Text( + peer.name, + style: + GoogleFonts.inter( + fontWeight: + FontWeight.bold, + color: Colors.white, ), - Text(peer.role.name, - style: GoogleFonts.inter( - fontWeight: - FontWeight - .bold, - color:Colors.white,)) - ], - ), - ); - }, - separatorBuilder: - (context, index) { - return Divider(); - }, - itemCount: _previewStore - .peers.length)); - }, - ); + ), + Text(peer.role.name, + style: GoogleFonts + .inter( + fontWeight: + FontWeight + .bold, + color: + Colors.white, + )) + ], + ), + ); + }, + separatorBuilder: + (context, index) { + return Divider(); + }, + itemCount: _previewStore + .peers.length)); + }, + ); }, child: Container( padding: EdgeInsets.all(5), @@ -235,15 +237,16 @@ class _PreviewPageState extends State with WidgetsBindingObserver { children: [ SvgPicture.asset( "assets/icons/participants.svg", - color:iconColor, + color: iconColor, ), SizedBox( width: 2, ), Text( - _previewStore.peerCount.toString(), + _previewStore.peers.length + .toString(), style: GoogleFonts.inter( - color:iconColor, + color: iconColor, fontWeight: FontWeight.bold, fontSize: 16), ) diff --git a/example/lib/preview/preview_store.dart b/example/lib/preview/preview_store.dart index 4fa17cd32..db11249df 100644 --- a/example/lib/preview/preview_store.dart +++ b/example/lib/preview/preview_store.dart @@ -32,8 +32,6 @@ class PreviewStore extends ChangeNotifier int? networkQuality; - int peerCount = 0; - @override void onError({required HMSException error}) { updateError(error); @@ -122,9 +120,6 @@ class PreviewStore extends ChangeNotifier case HMSRoomUpdate.hlsStreamingStateUpdated: isRecordingStarted = room.hmshlsStreamingState?.running ?? false; break; - case HMSRoomUpdate.RoomPeerCountUpdated: - peerCount = room.peerCount; - break; default: break; } diff --git a/lib/src/enum/hms_room_update.dart b/lib/src/enum/hms_room_update.dart index 7fc9a039f..c90e0c008 100644 --- a/lib/src/enum/hms_room_update.dart +++ b/lib/src/enum/hms_room_update.dart @@ -6,7 +6,6 @@ enum HMSRoomUpdate { rtmpStreamingStateUpdated, hlsStreamingStateUpdated, RoomNameUpdated, - RoomPeerCountUpdated, defaultUpdate } @@ -34,9 +33,6 @@ extension HMSRoomUpdateValues on HMSRoomUpdate { case "room_name_updated": return HMSRoomUpdate.RoomNameUpdated; - case "room_peer_count_updated": - return HMSRoomUpdate.RoomPeerCountUpdated; - default: return HMSRoomUpdate.defaultUpdate; } @@ -65,9 +61,6 @@ extension HMSRoomUpdateValues on HMSRoomUpdate { case HMSRoomUpdate.RoomNameUpdated: return "room_name_updated"; - case HMSRoomUpdate.RoomPeerCountUpdated: - return "room_peer_count_updated"; - default: return 'defaultUpdate'; } From e2a55afaf2584ba9df397060cb75102add25585c Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 1 Jun 2022 21:25:36 +0530 Subject: [PATCH 50/67] setting menu, dialog and android build error --- .../views/HMSVideoViewFactory.kt | 2 +- .../lib/common/util/utility_components.dart | 53 ++- example/lib/meeting/meeting_page.dart | 411 +++++++++--------- 3 files changed, 257 insertions(+), 209 deletions(-) diff --git a/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt b/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt index 1b57ae937..cf3b2bc14 100644 --- a/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt +++ b/android/src/main/kotlin/live/hms/hmssdk_flutter/views/HMSVideoViewFactory.kt @@ -58,7 +58,7 @@ class HMSVideoViewFactory(private val plugin: HmssdkFlutterPlugin) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { - override fun create(context: Context?, viewId: Int, args: Any?): PlatformView { + override fun create(context: Context, viewId: Int, args: Any?): PlatformView { val creationParams = args as Map? diff --git a/example/lib/common/util/utility_components.dart b/example/lib/common/util/utility_components.dart index a0eb0d7cd..b95ecc985 100644 --- a/example/lib/common/util/utility_components.dart +++ b/example/lib/common/util/utility_components.dart @@ -24,7 +24,8 @@ class UtilityComponents { builder: (ctx) => AlertDialog( title: Text( 'Leave Room?', - style: GoogleFonts.inter(color:iconColor,fontSize: 24, fontWeight: FontWeight.w700), + style: GoogleFonts.inter( + color: iconColor, fontSize: 24, fontWeight: FontWeight.w700), ), actions: [ ElevatedButton( @@ -96,7 +97,9 @@ class UtilityComponents { return AlertDialog( content: Text( message, - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ), actions: [ ElevatedButton( @@ -176,7 +179,9 @@ class UtilityComponents { return AlertDialog( title: Text( "Select Role for Mute", - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ), content: Container( width: 300, @@ -194,7 +199,9 @@ class UtilityComponents { children: [ Text( roles[index].name, - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ), Checkbox( value: _selectedRoles @@ -297,7 +304,9 @@ class UtilityComponents { CheckboxListTile( title: Text( "Recording", - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ), activeColor: Colors.blue, controlAffinity: ListTileControlAffinity.trailing, @@ -341,4 +350,38 @@ class UtilityComponents { return answer; } + + static Future onEndRoomPressed(BuildContext context) { + MeetingStore _meetingStore = context.read(); + return showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text( + 'End Room?', + style: GoogleFonts.inter( + color: iconColor, fontSize: 24, fontWeight: FontWeight.w700), + ), + actions: [ + ElevatedButton( + style: ElevatedButton.styleFrom( + primary: Colors.red, + ), + onPressed: () { + _meetingStore.endRoom(false, "Room Ended From Flutter"); + if (_meetingStore.isRoomEnded) { + Navigator.popUntil(context, (route) => route.isFirst); + } + }, + child: Text('Yes', style: GoogleFonts.inter(fontSize: 24))), + ElevatedButton( + onPressed: () => Navigator.pop(context, false), + child: Text( + 'Cancel', + style: GoogleFonts.inter(fontSize: 24), + ), + ), + ], + ), + ); + } } diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 85a5bf066..0254025b6 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -29,7 +29,6 @@ import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; // ignore: implementation_imports import 'package:tuple/tuple.dart'; -import 'meeting_participants_list.dart'; class MeetingPage extends StatefulWidget { final String roomId; @@ -98,53 +97,9 @@ class _MeetingPageState extends State final _meetingStore = context.read(); switch (value) { case 1: - // StaticLogger.logger?.d( - // "\n----------------------------Sending Logs-----------------\n"); - // StaticLogger.logger?.close(); - // ShareExtend.share(CustomLogger.file?.path ?? '', 'file'); - // logger.getCustomLogger(); - UtilityComponents.showToastWithString("Coming Soon..."); + _meetingStore.setActiveSpeakerMode(); break; - case 2: - if (_meetingStore.isRecordingStarted) { - _meetingStore.stopRtmpAndRecording(); - isRecordingStarted = false; - } else { - if (isRecordingStarted == false) { - Map data = - await UtilityComponents.showRTMPInputDialog( - context: context, - placeholder: "Enter Comma separated RTMP Urls", - isRecordingEnabled: false); - List? urls; - if (data["url"]!.isNotEmpty) { - urls = data["url"]!.split(","); - } - if (data["toRecord"] == "true" || urls != null) { - _meetingStore.startRtmpOrRecording( - meetingUrl: Constant.rtmpUrl, - toRecord: data["toRecord"] == "true" ? true : false, - rtmpUrls: urls); - isRecordingStarted = true; - } - } - } - break; - - case 3: - if (_meetingStore.isVideoOn) _meetingStore.switchCamera(); - - break; - case 4: - Navigator.of(context).push( - MaterialPageRoute( - builder: (_) => ChangeNotifierProvider.value( - value: context.read(), child: ParticipantsList()), - ), - ); - break; - case 5: if (_meetingStore.meetingMode != MeetingMode.Audio) { _meetingStore.setMode(MeetingMode.Audio); } else { @@ -152,30 +107,62 @@ class _MeetingPageState extends State _meetingStore.setMode(MeetingMode.Video); } break; - case 6: - _meetingStore.setActiveSpeakerMode(); - break; - case 7: + case 3: if (_meetingStore.meetingMode != MeetingMode.Hero) { _meetingStore.setMode(MeetingMode.Hero); } else { _meetingStore.setMode(MeetingMode.Video); } break; - case 8: + case 4: if (_meetingStore.meetingMode != MeetingMode.Single) { _meetingStore.setMode(MeetingMode.Single); } else { _meetingStore.setMode(MeetingMode.Video); } break; - case 9: + case 5: + _meetingStore.toggleScreenShare(); + break; + case 6: + if (_meetingStore.isVideoOn) _meetingStore.switchCamera(); + break; + case 7: String name = await UtilityComponents.showInputDialog( context: context, placeholder: "Enter Name"); if (name.isNotEmpty) { _meetingStore.changeName(name: name); } break; + case 8: + List roles = await _meetingStore.getRoles(); + UtilityComponents.showRoleList(context, roles, _meetingStore); + break; + case 9: + if (_meetingStore.isRecordingStarted) { + _meetingStore.stopRtmpAndRecording(); + isRecordingStarted = false; + } else { + if (isRecordingStarted == false) { + Map data = + await UtilityComponents.showRTMPInputDialog( + context: context, + placeholder: "Enter Comma separated RTMP Urls", + isRecordingEnabled: false); + List? urls; + if (data["url"]!.isNotEmpty) { + urls = data["url"]!.split(","); + } + if (data["toRecord"] == "true" || urls != null) { + _meetingStore.startRtmpOrRecording( + meetingUrl: Constant.rtmpUrl, + toRecord: data["toRecord"] == "true" ? true : false, + rtmpUrls: urls); + isRecordingStarted = true; + } + } + } + break; case 10: if (_meetingStore.hasHlsStarted) { _meetingStore.stopHLSStreaming(); @@ -189,24 +176,12 @@ class _MeetingPageState extends State } } break; - case 11: - List roles = await _meetingStore.getRoles(); - UtilityComponents.showRoleList(context, roles, _meetingStore); - break; - case 12: _meetingStore.changeStatsVisible(); break; - case 13: - _meetingStore.toggleScreenShare(); - break; - case 14: - _meetingStore.endRoom(false, "Room Ended From Flutter"); - if (_meetingStore.isRoomEnded) { - Navigator.pop(context); - } + case 12: + UtilityComponents.onEndRoomPressed(context); break; - default: break; } @@ -243,9 +218,9 @@ class _MeetingPageState extends State builder: (_, isRecordingStarted, __) { return isRecordingStarted ? SvgPicture.asset( - "assets/icons/record.svg", - color: Colors.red, - ) + "assets/icons/record.svg", + color: Colors.red, + ) : Container(); }, ), @@ -321,7 +296,9 @@ class _MeetingPageState extends State child: Text( "Waiting for HLS to start...", style: - GoogleFonts.inter(color:iconColor, + GoogleFonts.inter( + color: + iconColor, fontSize: 20), ), ), @@ -337,7 +314,9 @@ class _MeetingPageState extends State return Center( child: Text( 'Waiting for others to join!', - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), )); } Size size = MediaQuery.of(context).size; @@ -452,9 +431,14 @@ class _MeetingPageState extends State context.read().switchVideo(); }, icon: data.item1 - ? SvgPicture.asset("assets/icons/cam_state_on.svg",color:iconColor,) + ? SvgPicture.asset( + "assets/icons/cam_state_on.svg", + color: iconColor, + ) : SvgPicture.asset( - "assets/icons/cam_state_off.svg",color:iconColor,))); + "assets/icons/cam_state_off.svg", + color: iconColor, + ))); }, ), if (Provider.of(context).localPeer != null && @@ -477,9 +461,14 @@ class _MeetingPageState extends State context.read().switchAudio(); }, icon: isMicOn - ? SvgPicture.asset("assets/icons/mic_state_on.svg",color:iconColor,) + ? SvgPicture.asset( + "assets/icons/mic_state_on.svg", + color: iconColor, + ) : SvgPicture.asset( - "assets/icons/mic_state_off.svg",color:iconColor,))); + "assets/icons/mic_state_off.svg", + color: iconColor, + ))); }, ), Selector( @@ -530,9 +519,13 @@ class _MeetingPageState extends State }, icon: isNewMessageReceived ? SvgPicture.asset( - "assets/icons/message_badge_on.svg",color:iconColor,) + "assets/icons/message_badge_on.svg", + color: iconColor, + ) : SvgPicture.asset( - "assets/icons/message_badge_off.svg",color:iconColor,)), + "assets/icons/message_badge_off.svg", + color: iconColor, + )), ); }), Container( @@ -571,8 +564,7 @@ class _MeetingPageState extends State onPressed: () { context.read().changeMetadata(); UtilityComponents.showToastWithString( - !raisedHand ? "Raised Hand ON" : "Raised Hand OFF" - ); + !raisedHand ? "Raised Hand ON" : "Raised Hand OFF"); }, icon: raisedHand ? SvgPicture.asset( @@ -581,7 +573,7 @@ class _MeetingPageState extends State ) : SvgPicture.asset( 'assets/icons/hand_state_off.svg', - color:iconColor, + color: iconColor, ), )); }, @@ -600,10 +592,13 @@ class _MeetingPageState extends State }, icon: isNewMessageReceived ? SvgPicture.asset( - "assets/icons/message_badge_on.svg",color:iconColor,) - + "assets/icons/message_badge_on.svg", + color: iconColor, + ) : SvgPicture.asset( - "assets/icons/message_badge_off.svg",color:iconColor,)), + "assets/icons/message_badge_off.svg", + color: iconColor, + )), ); }), Container( @@ -631,66 +626,37 @@ class _MeetingPageState extends State itemBuilder: (context) { final meetingStore = context.read(); return [ - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Send Logs", - style: GoogleFonts.inter(color:iconColor,), - ), - SvgPicture.asset("assets/icons/bug.svg",color:iconColor,), - ], - ), - value: 1, - ), - if (!(meetingStore.localPeer?.role.name.contains("hls-") ?? true)) - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - meetingStore.isRecordingStarted - ? "Recording " - : "Record", - style: GoogleFonts.inter( - color: meetingStore.isRecordingStarted - ? Colors.blue - : iconColor, - )), - SvgPicture.asset( - "assets/icons/record.svg", - color: meetingStore.isRecordingStarted - ? Colors.red - : iconColor, - ), - ]), - value: 2, - ), - if (!(meetingStore.localPeer?.role.name.contains("hls-") ?? true)) - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Toggle Camera ", - style: GoogleFonts.inter(color:iconColor,), - ), - SvgPicture.asset("assets/icons/camera.svg",color:iconColor,), - ]), - value: 3, - ), + // PopupMenuItem( + // child: Row( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + // children: [ + // Text( + // "Send Logs", + // style: GoogleFonts.inter(color:iconColor,), + // ), + // SvgPicture.asset("assets/icons/bug.svg",color:iconColor,), + // ], + // ), + // value: 1, + // ), PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - "Participants ", - style: GoogleFonts.inter(color:iconColor,), + Text("Active Speaker Mode", + style: GoogleFonts.inter( + color: meetingStore.isActiveSpeakerMode + ? Colors.blue + : iconColor, + )), + SvgPicture.asset( + "assets/icons/participants.svg", + color: meetingStore.isActiveSpeakerMode + ? Colors.blue + : iconColor, ), - SvgPicture.asset("assets/icons/participants.svg",color:iconColor,), ]), - value: 4, + value: 1, ), PopupMenuItem( child: Row( @@ -700,7 +666,9 @@ class _MeetingPageState extends State meetingStore.meetingMode == MeetingMode.Audio ? "Video View" : "Audio View", - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ), SvgPicture.asset( meetingStore.meetingMode == MeetingMode.Audio @@ -711,26 +679,7 @@ class _MeetingPageState extends State width: 24.0, ), ]), - value: 5, - ), - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text("Active Speaker Mode", - style: GoogleFonts.inter( - color: meetingStore.isActiveSpeakerMode - ? Colors.blue - : iconColor, - )), - SvgPicture.asset( - "assets/icons/participants.svg", - color: meetingStore.isActiveSpeakerMode - ? Colors.blue - : iconColor, - ), - ]), - value: 6, + value: 2, ), PopupMenuItem( child: Row( @@ -749,7 +698,7 @@ class _MeetingPageState extends State : iconColor, ), ]), - value: 7, + value: 3, ), PopupMenuItem( child: Row( @@ -768,20 +717,108 @@ class _MeetingPageState extends State : iconColor, ), ]), - value: 8, + value: 4, ), + if ((meetingStore.localPeer != null) && + meetingStore.localPeer!.role.publishSettings!.allowed + .contains("screen") && + Platform.isAndroid) + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Screen share", + style: GoogleFonts.inter( + color: meetingStore.isScreenShareOn + ? Colors.blue + : iconColor), + ), + SvgPicture.asset( + "assets/icons/screen_share.svg", + color: meetingStore.isScreenShareOn + ? Colors.blue + : iconColor, + ), + ]), + value: 5, + ), + if (!(meetingStore.localPeer?.role.name.contains("hls-") ?? true)) + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Toggle Camera ", + style: GoogleFonts.inter( + color: iconColor, + ), + ), + SvgPicture.asset( + "assets/icons/camera.svg", + color: iconColor, + ), + ]), + value: 6, + ), PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( "Change Name", - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), + ), + SvgPicture.asset( + "assets/icons/pencil.svg", + color: iconColor, ), - SvgPicture.asset("assets/icons/pencil.svg",color:iconColor,), ]), - value: 9, + value: 7, ), + if (meetingStore.localPeer?.role.permissions.changeRole ?? false) + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + "Mute", + style: GoogleFonts.inter( + color: iconColor, + ), + ), + SvgPicture.asset( + "assets/icons/mic_state_off.svg", + color: iconColor, + ), + ]), + value: 8, + ), + if (!(meetingStore.localPeer?.role.name.contains("hls-") ?? true)) + PopupMenuItem( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + meetingStore.isRecordingStarted + ? "Recording " + : "Record", + style: GoogleFonts.inter( + color: meetingStore.isRecordingStarted + ? Colors.blue + : iconColor, + )), + SvgPicture.asset( + "assets/icons/record.svg", + color: meetingStore.isRecordingStarted + ? Colors.red + : iconColor, + ), + ]), + value: 9, + ), if (!(meetingStore.localPeer?.role.name.contains("hls-") ?? true)) PopupMenuItem( child: Row( @@ -802,19 +839,6 @@ class _MeetingPageState extends State ]), value: 10, ), - if (meetingStore.localPeer?.role.permissions.changeRole ?? false) - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "Mute", - style: GoogleFonts.inter(color:iconColor,), - ), - SvgPicture.asset("assets/icons/mic_state_off.svg",color:iconColor,), - ]), - value: 11, - ), PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, @@ -831,44 +855,25 @@ class _MeetingPageState extends State ? Colors.blue : iconColor), ]), - value: 12, + value: 11, ), - if ((meetingStore.localPeer != null) && - meetingStore.localPeer!.role.publishSettings!.allowed - .contains("screen") && - Platform.isAndroid) + if (meetingStore.localPeer!.role.permissions.endRoom!) PopupMenuItem( child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "Screen share", + "End Room", style: GoogleFonts.inter( - color: meetingStore.isScreenShareOn - ? Colors.blue - : iconColor), + color: iconColor, + ), ), SvgPicture.asset( - "assets/icons/screen_share.svg", - color: meetingStore.isScreenShareOn - ? Colors.blue - : iconColor, - ), - ]), - value: 13, - ), - if (meetingStore.localPeer!.role.permissions.endRoom!) - PopupMenuItem( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - "End Room", - style: GoogleFonts.inter(color:iconColor,), + "assets/icons/end_room.svg", + color: iconColor, ), - SvgPicture.asset("assets/icons/end_room.svg",color:iconColor,), ]), - value: 14, + value: 12, ), ]; }, From 26bb69fc57892884f0cc36aef337d2bf245d2435 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 1 Jun 2022 21:57:43 +0530 Subject: [PATCH 51/67] #595 Change Role option should be available on long press of all peers --- example/assets/icons/camera.svg | 2 +- example/assets/icons/peer_remove.svg | 3 + example/assets/icons/role_change.svg | 3 + .../lib/common/ui/organisms/audio_tile.dart | 72 +++++++++------ .../ui/organisms/change_track_options.dart | 90 ++++++++++++++----- .../lib/common/ui/organisms/video_tile.dart | 79 ++++++++++------ 6 files changed, 172 insertions(+), 77 deletions(-) create mode 100644 example/assets/icons/peer_remove.svg create mode 100644 example/assets/icons/role_change.svg diff --git a/example/assets/icons/camera.svg b/example/assets/icons/camera.svg index 9d82f62c5..e2df14b58 100644 --- a/example/assets/icons/camera.svg +++ b/example/assets/icons/camera.svg @@ -1,3 +1,3 @@ - + diff --git a/example/assets/icons/peer_remove.svg b/example/assets/icons/peer_remove.svg new file mode 100644 index 000000000..7ac7ace50 --- /dev/null +++ b/example/assets/icons/peer_remove.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/role_change.svg b/example/assets/icons/role_change.svg new file mode 100644 index 000000000..814f7e9ef --- /dev/null +++ b/example/assets/icons/role_change.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/lib/common/ui/organisms/audio_tile.dart b/example/lib/common/ui/organisms/audio_tile.dart index f008bfdb1..32bc091fb 100644 --- a/example/lib/common/ui/organisms/audio_tile.dart +++ b/example/lib/common/ui/organisms/audio_tile.dart @@ -1,6 +1,7 @@ // Package imports import 'package:flutter/material.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/audio_level_avatar.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/change_role_options.dart'; import 'package:provider/provider.dart'; // Project imports @@ -32,12 +33,14 @@ class AudioTile extends StatelessWidget { _meetingStore.localPeer?.role.permissions.unMute ?? false; bool removePeerPermission = _meetingStore.localPeer?.role.permissions.removeOthers ?? false; + bool changeRolePermission = + _meetingStore.localPeer!.role.permissions.changeRole ?? false; return InkWell( onLongPress: () { var peerTrackNode = context.read(); HMSPeer peerNode = peerTrackNode.peer; - if (!mutePermission || !unMutePermission || !removePeerPermission) + if (!mutePermission || !unMutePermission || !removePeerPermission || !changeRolePermission) return; if (peerTrackNode.peer.peerId != _meetingStore.localPeer!.peerId) showDialog( @@ -45,31 +48,48 @@ class AudioTile extends StatelessWidget { builder: (_) => Column( children: [ ChangeTrackOptionDialog( - isAudioMuted: - peerTrackNode.audioTrack?.isMute ?? true, - isVideoMuted: peerTrackNode.track == null - ? true - : peerTrackNode.track!.isMute, - peerName: peerNode.name, - changeVideoTrack: (mute, isVideoTrack) { - Navigator.pop(context); - _meetingStore.changeTrackState( - peerTrackNode.track!, mute); - }, - changeAudioTrack: (mute, isAudioTrack) { - Navigator.pop(context); - _meetingStore.changeTrackState( - peerTrackNode.audioTrack!, mute); - }, - removePeer: () async { - Navigator.pop(context); - var peer = await _meetingStore.getPeer( - peerId: peerNode.peerId); - _meetingStore.removePeerFromRoom(peer!); - }, - mute: mutePermission, - unMute: unMutePermission, - removeOthers: removePeerPermission), + isAudioMuted: peerTrackNode.audioTrack?.isMute ?? true, + isVideoMuted: peerTrackNode.track == null + ? true + : peerTrackNode.track!.isMute, + peerName: peerNode.name, + changeVideoTrack: (mute, isVideoTrack) { + Navigator.pop(context); + _meetingStore.changeTrackState( + peerTrackNode.track!, mute); + }, + changeAudioTrack: (mute, isAudioTrack) { + Navigator.pop(context); + _meetingStore.changeTrackState( + peerTrackNode.audioTrack!, mute); + }, + removePeer: () async { + Navigator.pop(context); + var peer = await _meetingStore.getPeer( + peerId: peerNode.peerId); + _meetingStore.removePeerFromRoom(peer!); + }, + changeRole: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (_) => ChangeRoleOptionDialog( + peerName: peerNode.name, + getRoleFunction: _meetingStore.getRoles(), + changeRole: (role, forceChange) { + Navigator.pop(context); + _meetingStore.changeRole( + peer: peerNode, + roleName: role, + forceChange: forceChange); + }, + )); + }, + mute: mutePermission, + unMute: unMutePermission, + removeOthers: removePeerPermission, + roles: changeRolePermission, + ), ], )); }, diff --git a/example/lib/common/ui/organisms/change_track_options.dart b/example/lib/common/ui/organisms/change_track_options.dart index 179a087ea..496020bfb 100644 --- a/example/lib/common/ui/organisms/change_track_options.dart +++ b/example/lib/common/ui/organisms/change_track_options.dart @@ -1,5 +1,6 @@ //Package imports import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/common/util/app_color.dart'; @@ -10,19 +11,24 @@ class ChangeTrackOptionDialog extends StatefulWidget { final Function(bool, bool) changeVideoTrack; final Function(bool, bool) changeAudioTrack; final Function() removePeer; + final Function() changeRole; final mute; final unMute; final removeOthers; - const ChangeTrackOptionDialog( - {required this.isVideoMuted, - required this.isAudioMuted, - required this.changeVideoTrack, - required this.changeAudioTrack, - required this.peerName, - required this.removePeer, - required this.mute, - required this.unMute, - required this.removeOthers}); + final roles; + const ChangeTrackOptionDialog({ + required this.isVideoMuted, + required this.isAudioMuted, + required this.changeVideoTrack, + required this.changeAudioTrack, + required this.peerName, + required this.removePeer, + required this.changeRole, + required this.mute, + required this.unMute, + required this.removeOthers, + required this.roles, + }); @override _ChangeTrackOptionDialogState createState() => @@ -34,9 +40,8 @@ class _ChangeTrackOptionDialogState extends State { Widget build(BuildContext context) { return AlertDialog( title: Text( - widget.peerName, - style: GoogleFonts.inter(color:iconColor), + style: GoogleFonts.inter(color: iconColor), ), content: Container( width: double.infinity, @@ -53,15 +58,22 @@ class _ChangeTrackOptionDialogState extends State { }, child: Row( children: [ - Icon(widget.isVideoMuted - ? Icons.videocam - : Icons.videocam_off), + if (widget.isVideoMuted) + SvgPicture.asset( + "assets/icons/cam_state_on.svg", + color: iconColor, + ) + else + SvgPicture.asset( + "assets/icons/cam_state_off.svg", + color: iconColor, + ), SizedBox( width: 16, ), Text( "${widget.isVideoMuted ? "Unmute" : "Mute"} video", - style: GoogleFonts.inter(color:iconColor), + style: GoogleFonts.inter(color: iconColor), ) ], ), @@ -80,15 +92,22 @@ class _ChangeTrackOptionDialogState extends State { }, child: Row( children: [ - Icon(widget.isAudioMuted - ? Icons.mic_sharp - : Icons.mic_off), + if (widget.isAudioMuted) + SvgPicture.asset( + "assets/icons/mic_state_on.svg", + color: iconColor, + ) + else + SvgPicture.asset( + "assets/icons/mic_state_off.svg", + color: iconColor, + ), SizedBox( width: 16, ), Text( "${widget.isAudioMuted ? "Unmute" : "Mute"} audio", - style: GoogleFonts.inter(color:iconColor), + style: GoogleFonts.inter(color: iconColor), ), ], ), @@ -106,13 +125,40 @@ class _ChangeTrackOptionDialogState extends State { }, child: Row( children: [ - Icon(Icons.highlight_remove_outlined), + SvgPicture.asset( + "assets/icons/peer_remove.svg", + color: iconColor, + ), SizedBox( width: 16, ), Text( "Remove Peer", - style: GoogleFonts.inter(color:iconColor), + style: GoogleFonts.inter(color: iconColor), + ) + ], + ), + ), + ), + if (widget.roles) + Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: GestureDetector( + onTap: () { + widget.changeRole(); + }, + child: Row( + children: [ + SvgPicture.asset( + "assets/icons/role_change.svg", + color: iconColor, + ), + SizedBox( + width: 16, + ), + Text( + "Change Role", + style: GoogleFonts.inter(color: iconColor), ) ], ), diff --git a/example/lib/common/ui/organisms/video_tile.dart b/example/lib/common/ui/organisms/video_tile.dart index 4528673d2..8838d34d8 100644 --- a/example/lib/common/ui/organisms/video_tile.dart +++ b/example/lib/common/ui/organisms/video_tile.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:focus_detector/focus_detector.dart'; import 'package:hmssdk_flutter/hmssdk_flutter.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/change_role_options.dart'; import 'package:provider/provider.dart'; // Project imports @@ -48,6 +49,8 @@ class _VideoTileState extends State { _meetingStore.localPeer?.role.permissions.unMute ?? false; bool removePeerPermission = _meetingStore.localPeer?.role.permissions.removeOthers ?? false; + bool changeRolePermission = + _meetingStore.localPeer!.role.permissions.changeRole ?? false; return FocusDetector( onFocusLost: () { @@ -68,7 +71,8 @@ class _VideoTileState extends State { HMSPeer peerNode = peerTrackNode.peer; if (!mutePermission || !unMutePermission || - !removePeerPermission) return; + !removePeerPermission || + !changeRolePermission) return; if (peerTrackNode.peer.peerId != _meetingStore.localPeer!.peerId) showDialog( @@ -76,31 +80,50 @@ class _VideoTileState extends State { builder: (_) => Column( children: [ ChangeTrackOptionDialog( - isAudioMuted: - peerTrackNode.audioTrack?.isMute ?? true, - isVideoMuted: peerTrackNode.track == null - ? true - : peerTrackNode.track!.isMute, - peerName: peerNode.name, - changeVideoTrack: (mute, isVideoTrack) { - Navigator.pop(context); - _meetingStore.changeTrackState( - peerTrackNode.track!, mute); - }, - changeAudioTrack: (mute, isAudioTrack) { - Navigator.pop(context); - _meetingStore.changeTrackState( - peerTrackNode.audioTrack!, mute); - }, - removePeer: () async { - Navigator.pop(context); - var peer = await _meetingStore.getPeer( - peerId: peerNode.peerId); - _meetingStore.removePeerFromRoom(peer!); - }, - mute: mutePermission, - unMute: unMutePermission, - removeOthers: removePeerPermission), + isAudioMuted: + peerTrackNode.audioTrack?.isMute ?? true, + isVideoMuted: peerTrackNode.track == null + ? true + : peerTrackNode.track!.isMute, + peerName: peerNode.name, + changeVideoTrack: (mute, isVideoTrack) { + Navigator.pop(context); + _meetingStore.changeTrackState( + peerTrackNode.track!, mute); + }, + changeAudioTrack: (mute, isAudioTrack) { + Navigator.pop(context); + _meetingStore.changeTrackState( + peerTrackNode.audioTrack!, mute); + }, + removePeer: () async { + Navigator.pop(context); + var peer = await _meetingStore.getPeer( + peerId: peerNode.peerId); + _meetingStore.removePeerFromRoom(peer!); + }, + changeRole: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (_) => ChangeRoleOptionDialog( + peerName: peerNode.name, + getRoleFunction: + _meetingStore.getRoles(), + changeRole: (role, forceChange) { + Navigator.pop(context); + _meetingStore.changeRole( + peer: peerNode, + roleName: role, + forceChange: forceChange); + }, + )); + }, + mute: mutePermission, + unMute: unMutePermission, + removeOthers: removePeerPermission, + roles: changeRolePermission, + ), ], )); }, @@ -114,12 +137,12 @@ class _VideoTileState extends State { child: Stack( children: [ VideoView( - uid :context.read().uid, + uid: context.read().uid, scaleType: widget.scaleType, itemHeight: widget.itemHeight, itemWidth: widget.itemWidth, ), - + DegradeTile( itemHeight: widget.itemHeight, itemWidth: widget.itemWidth, From b597afcc4b97cb848395995d5dd278d90263e59d Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Wed, 1 Jun 2022 22:15:04 +0530 Subject: [PATCH 52/67] raise hand icon filled color --- example/assets/icons/hand.svg | 3 +++ example/assets/icons/hand_state_off.svg | 9 --------- example/assets/icons/hand_state_on.svg | 3 --- example/lib/common/ui/organisms/hand_raise.dart | 4 ++-- .../common/ui/organisms/participant_organism.dart | 9 +++++---- example/lib/meeting/meeting_page.dart | 15 +++++---------- 6 files changed, 15 insertions(+), 28 deletions(-) create mode 100644 example/assets/icons/hand.svg delete mode 100644 example/assets/icons/hand_state_off.svg delete mode 100644 example/assets/icons/hand_state_on.svg diff --git a/example/assets/icons/hand.svg b/example/assets/icons/hand.svg new file mode 100644 index 000000000..3f0b1182b --- /dev/null +++ b/example/assets/icons/hand.svg @@ -0,0 +1,3 @@ + + + diff --git a/example/assets/icons/hand_state_off.svg b/example/assets/icons/hand_state_off.svg deleted file mode 100644 index 3ed0e9895..000000000 --- a/example/assets/icons/hand_state_off.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/example/assets/icons/hand_state_on.svg b/example/assets/icons/hand_state_on.svg deleted file mode 100644 index 340aa4269..000000000 --- a/example/assets/icons/hand_state_on.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/example/lib/common/ui/organisms/hand_raise.dart b/example/lib/common/ui/organisms/hand_raise.dart index 3d073f38c..fb222d991 100644 --- a/example/lib/common/ui/organisms/hand_raise.dart +++ b/example/lib/common/ui/organisms/hand_raise.dart @@ -16,9 +16,9 @@ class HandRaise extends StatelessWidget { child: Padding( padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), child: SvgPicture.asset( - "assets/icons/hand_state_on.svg", + "assets/icons/hand.svg", color: Colors.yellow, - height: 50, + height: 35, ), ), bottom: 5.0, diff --git a/example/lib/common/ui/organisms/participant_organism.dart b/example/lib/common/ui/organisms/participant_organism.dart index 370b0e82a..4ebda3fe6 100644 --- a/example/lib/common/ui/organisms/participant_organism.dart +++ b/example/lib/common/ui/organisms/participant_organism.dart @@ -45,8 +45,9 @@ class _ParticipantOrganismState extends State { width: width / 3, child: Text( peer.name, - style: GoogleFonts.inter(fontSize: 20.0, - color:iconColor, + style: GoogleFonts.inter( + fontSize: 20.0, + color: iconColor, ), maxLines: 1, overflow: TextOverflow.ellipsis, @@ -58,7 +59,7 @@ class _ParticipantOrganismState extends State { Padding( padding: const EdgeInsets.fromLTRB(5, 0, 5, 0), child: SvgPicture.asset( - "assets/icons/hand_state_on.svg", + "assets/icons/hand.svg", color: Colors.yellow, height: 25, )), @@ -104,7 +105,7 @@ class _ParticipantOrganismState extends State { overflow: TextOverflow.clip, maxLines: 1, style: GoogleFonts.inter( - color:Colors.white, + color: Colors.white, fontSize: 18.0, fontWeight: FontWeight.bold), ), diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 0254025b6..e0cfe9584 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -483,7 +483,7 @@ class _MeetingPageState extends State context.read().changeMetadata(); }, icon: SvgPicture.asset( - "assets/icons/hand_state_on.svg", + "assets/icons/hand.svg", color: raisedHand ? Colors.yellow : iconColor, ))); }, @@ -566,15 +566,10 @@ class _MeetingPageState extends State UtilityComponents.showToastWithString( !raisedHand ? "Raised Hand ON" : "Raised Hand OFF"); }, - icon: raisedHand - ? SvgPicture.asset( - 'assets/icons/hand_state_on.svg', - color: Colors.amber.shade300, - ) - : SvgPicture.asset( - 'assets/icons/hand_state_off.svg', - color: iconColor, - ), + icon: SvgPicture.asset( + "assets/icons/hand.svg", + color: raisedHand ? Colors.yellow : iconColor, + ), )); }, ), From 390c1f55f05e34e582562cf573b522482f568cc2 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Thu, 2 Jun 2022 02:44:00 +0530 Subject: [PATCH 53/67] #593 local peer action on tile long press added --- .../lib/common/ui/organisms/audio_tile.dart | 131 ++++++++++------- .../ui/organisms/local_peer_tile_dialog.dart | 118 ++++++++++++++++ ...ions.dart => remote_peer_tile_dialog.dart} | 35 +++-- .../lib/common/ui/organisms/video_tile.dart | 132 +++++++++++------- example/lib/meeting/meeting_page.dart | 8 +- 5 files changed, 304 insertions(+), 120 deletions(-) create mode 100644 example/lib/common/ui/organisms/local_peer_tile_dialog.dart rename example/lib/common/ui/organisms/{change_track_options.dart => remote_peer_tile_dialog.dart} (87%) diff --git a/example/lib/common/ui/organisms/audio_tile.dart b/example/lib/common/ui/organisms/audio_tile.dart index 32bc091fb..a67c8af65 100644 --- a/example/lib/common/ui/organisms/audio_tile.dart +++ b/example/lib/common/ui/organisms/audio_tile.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/audio_level_avatar.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/change_role_options.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/local_peer_tile_dialog.dart'; +import 'package:hmssdk_flutter_example/common/util/utility_components.dart'; import 'package:provider/provider.dart'; // Project imports @@ -15,7 +17,7 @@ import 'package:hmssdk_flutter_example/common/ui/organisms/tile_border.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/rtc_stats_view.dart'; import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; -import 'package:hmssdk_flutter_example/common/ui/organisms/change_track_options.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/remote_peer_tile_dialog.dart'; class AudioTile extends StatelessWidget { final double itemHeight; @@ -40,58 +42,89 @@ class AudioTile extends StatelessWidget { onLongPress: () { var peerTrackNode = context.read(); HMSPeer peerNode = peerTrackNode.peer; - if (!mutePermission || !unMutePermission || !removePeerPermission || !changeRolePermission) - return; + if (!mutePermission || + !unMutePermission || + !removePeerPermission || + !changeRolePermission) return; if (peerTrackNode.peer.peerId != _meetingStore.localPeer!.peerId) showDialog( context: context, - builder: (_) => Column( - children: [ - ChangeTrackOptionDialog( - isAudioMuted: peerTrackNode.audioTrack?.isMute ?? true, - isVideoMuted: peerTrackNode.track == null - ? true - : peerTrackNode.track!.isMute, - peerName: peerNode.name, - changeVideoTrack: (mute, isVideoTrack) { - Navigator.pop(context); - _meetingStore.changeTrackState( - peerTrackNode.track!, mute); - }, - changeAudioTrack: (mute, isAudioTrack) { - Navigator.pop(context); - _meetingStore.changeTrackState( - peerTrackNode.audioTrack!, mute); - }, - removePeer: () async { - Navigator.pop(context); - var peer = await _meetingStore.getPeer( - peerId: peerNode.peerId); - _meetingStore.removePeerFromRoom(peer!); - }, - changeRole: () { - Navigator.pop(context); - showDialog( - context: context, - builder: (_) => ChangeRoleOptionDialog( - peerName: peerNode.name, - getRoleFunction: _meetingStore.getRoles(), - changeRole: (role, forceChange) { - Navigator.pop(context); - _meetingStore.changeRole( - peer: peerNode, - roleName: role, - forceChange: forceChange); - }, - )); - }, - mute: mutePermission, - unMute: unMutePermission, - removeOthers: removePeerPermission, - roles: changeRolePermission, - ), - ], + builder: (_) => RemotePeerTileDialog( + isAudioMuted: peerTrackNode.audioTrack?.isMute ?? true, + isVideoMuted: peerTrackNode.track == null + ? true + : peerTrackNode.track!.isMute, + peerName: peerNode.name, + changeVideoTrack: (mute, isVideoTrack) { + Navigator.pop(context); + _meetingStore.changeTrackState( + peerTrackNode.track!, mute); + }, + changeAudioTrack: (mute, isAudioTrack) { + Navigator.pop(context); + _meetingStore.changeTrackState( + peerTrackNode.audioTrack!, mute); + }, + removePeer: () async { + Navigator.pop(context); + var peer = + await _meetingStore.getPeer(peerId: peerNode.peerId); + _meetingStore.removePeerFromRoom(peer!); + }, + changeRole: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (_) => ChangeRoleOptionDialog( + peerName: peerNode.name, + getRoleFunction: _meetingStore.getRoles(), + changeRole: (role, forceChange) { + Navigator.pop(context); + _meetingStore.changeRole( + peer: peerNode, + roleName: role, + forceChange: forceChange); + }, + )); + }, + mute: mutePermission, + unMute: unMutePermission, + removeOthers: removePeerPermission, + roles: changeRolePermission, )); + else + showDialog( + context: context, + builder: (_) => LocalPeerTileDialog( + isAudioMode: true, + toggleCamera: () { + if (_meetingStore.isVideoOn) _meetingStore.switchCamera(); + }, + peerName: peerNode.name, + changeRole: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (_) => ChangeRoleOptionDialog( + peerName: peerNode.name, + getRoleFunction: _meetingStore.getRoles(), + changeRole: (role, forceChange) { + Navigator.pop(context); + _meetingStore.changeRole( + peer: peerNode, + roleName: role, + forceChange: forceChange); + }, + )); + }, + roles: changeRolePermission, + changeName: () async { + String name = await UtilityComponents.showInputDialog( + context: context, placeholder: "Enter Name"); + if (name.isNotEmpty) { + _meetingStore.changeName(name: name); + } + })); }, child: Container( color: Colors.transparent, diff --git a/example/lib/common/ui/organisms/local_peer_tile_dialog.dart b/example/lib/common/ui/organisms/local_peer_tile_dialog.dart new file mode 100644 index 000000000..0b72596b3 --- /dev/null +++ b/example/lib/common/ui/organisms/local_peer_tile_dialog.dart @@ -0,0 +1,118 @@ +//Package imports +import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:google_fonts/google_fonts.dart'; +import 'package:hmssdk_flutter_example/common/util/app_color.dart'; + +class LocalPeerTileDialog extends StatefulWidget { + final String peerName; + final bool isAudioMode; + final bool roles; + final Function() toggleCamera; + final Function() changeName; + final Function() changeRole; + const LocalPeerTileDialog({ + required this.isAudioMode, + required this.toggleCamera, + required this.peerName, + required this.changeRole, + required this.roles, + required this.changeName, + }); + + @override + _LocalPeerTileDialogState createState() => _LocalPeerTileDialogState(); +} + +class _LocalPeerTileDialogState extends State { + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text( + widget.peerName, + style: GoogleFonts.inter(color: iconColor, fontWeight: FontWeight.bold), + ), + content: Container( + width: double.infinity, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (!widget.isAudioMode) + Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: GestureDetector( + onTap: () { + Navigator.pop(context); + widget.toggleCamera(); + }, + child: Row( + children: [ + SvgPicture.asset( + "assets/icons/camera.svg", + color: iconColor, + ), + SizedBox( + width: 16, + ), + Text( + "Toggle Camera", + style: GoogleFonts.inter(color: iconColor), + ) + ], + ), + ), + ), + Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: GestureDetector( + onTap: () { + Navigator.pop(context); + widget.changeName(); + }, + child: Row( + children: [ + SvgPicture.asset( + "assets/icons/pencil.svg", + color: iconColor, + ), + SizedBox( + width: 16, + ), + Text( + "Change Name", + style: GoogleFonts.inter(color: iconColor), + ) + ], + ), + ), + ), + if (widget.roles) + Padding( + padding: const EdgeInsets.only(bottom: 20.0), + child: GestureDetector( + onTap: () { + widget.changeRole(); + }, + child: Row( + children: [ + SvgPicture.asset( + "assets/icons/role_change.svg", + color: iconColor, + ), + SizedBox( + width: 16, + ), + Text( + "Change Role", + style: GoogleFonts.inter(color: iconColor), + ) + ], + ), + ), + ), + ], + ), + ), + ); + } +} diff --git a/example/lib/common/ui/organisms/change_track_options.dart b/example/lib/common/ui/organisms/remote_peer_tile_dialog.dart similarity index 87% rename from example/lib/common/ui/organisms/change_track_options.dart rename to example/lib/common/ui/organisms/remote_peer_tile_dialog.dart index 496020bfb..b4becfb33 100644 --- a/example/lib/common/ui/organisms/change_track_options.dart +++ b/example/lib/common/ui/organisms/remote_peer_tile_dialog.dart @@ -4,19 +4,19 @@ import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/common/util/app_color.dart'; -class ChangeTrackOptionDialog extends StatefulWidget { +class RemotePeerTileDialog extends StatefulWidget { final String peerName; - final isVideoMuted; - final isAudioMuted; + final bool isVideoMuted; + final bool isAudioMuted; + final bool mute; + final bool unMute; + final bool removeOthers; + final bool roles; final Function(bool, bool) changeVideoTrack; final Function(bool, bool) changeAudioTrack; final Function() removePeer; final Function() changeRole; - final mute; - final unMute; - final removeOthers; - final roles; - const ChangeTrackOptionDialog({ + const RemotePeerTileDialog({ required this.isVideoMuted, required this.isAudioMuted, required this.changeVideoTrack, @@ -31,17 +31,16 @@ class ChangeTrackOptionDialog extends StatefulWidget { }); @override - _ChangeTrackOptionDialogState createState() => - _ChangeTrackOptionDialogState(); + _RemotePeerTileDialogState createState() => _RemotePeerTileDialogState(); } -class _ChangeTrackOptionDialogState extends State { +class _RemotePeerTileDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( title: Text( widget.peerName, - style: GoogleFonts.inter(color: iconColor), + style: GoogleFonts.inter(color: iconColor,fontWeight: FontWeight.bold), ), content: Container( width: double.infinity, @@ -126,9 +125,9 @@ class _ChangeTrackOptionDialogState extends State { child: Row( children: [ SvgPicture.asset( - "assets/icons/peer_remove.svg", - color: iconColor, - ), + "assets/icons/peer_remove.svg", + color: iconColor, + ), SizedBox( width: 16, ), @@ -150,9 +149,9 @@ class _ChangeTrackOptionDialogState extends State { child: Row( children: [ SvgPicture.asset( - "assets/icons/role_change.svg", - color: iconColor, - ), + "assets/icons/role_change.svg", + color: iconColor, + ), SizedBox( width: 16, ), diff --git a/example/lib/common/ui/organisms/video_tile.dart b/example/lib/common/ui/organisms/video_tile.dart index 8838d34d8..f0f61e729 100644 --- a/example/lib/common/ui/organisms/video_tile.dart +++ b/example/lib/common/ui/organisms/video_tile.dart @@ -3,6 +3,8 @@ import 'package:flutter/material.dart'; import 'package:focus_detector/focus_detector.dart'; import 'package:hmssdk_flutter/hmssdk_flutter.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/change_role_options.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/local_peer_tile_dialog.dart'; +import 'package:hmssdk_flutter_example/common/util/utility_components.dart'; import 'package:provider/provider.dart'; // Project imports @@ -17,7 +19,7 @@ import 'package:hmssdk_flutter_example/common/ui/organisms/rtc_stats_view.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/video_view.dart'; import 'package:hmssdk_flutter_example/meeting/meeting_store.dart'; import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; -import 'package:hmssdk_flutter_example/common/ui/organisms/change_track_options.dart'; +import 'package:hmssdk_flutter_example/common/ui/organisms/remote_peer_tile_dialog.dart'; class VideoTile extends StatefulWidget { final double itemHeight; @@ -77,55 +79,87 @@ class _VideoTileState extends State { _meetingStore.localPeer!.peerId) showDialog( context: context, - builder: (_) => Column( - children: [ - ChangeTrackOptionDialog( - isAudioMuted: - peerTrackNode.audioTrack?.isMute ?? true, - isVideoMuted: peerTrackNode.track == null - ? true - : peerTrackNode.track!.isMute, - peerName: peerNode.name, - changeVideoTrack: (mute, isVideoTrack) { - Navigator.pop(context); - _meetingStore.changeTrackState( - peerTrackNode.track!, mute); - }, - changeAudioTrack: (mute, isAudioTrack) { - Navigator.pop(context); - _meetingStore.changeTrackState( - peerTrackNode.audioTrack!, mute); - }, - removePeer: () async { - Navigator.pop(context); - var peer = await _meetingStore.getPeer( - peerId: peerNode.peerId); - _meetingStore.removePeerFromRoom(peer!); - }, - changeRole: () { - Navigator.pop(context); - showDialog( - context: context, - builder: (_) => ChangeRoleOptionDialog( - peerName: peerNode.name, - getRoleFunction: - _meetingStore.getRoles(), - changeRole: (role, forceChange) { - Navigator.pop(context); - _meetingStore.changeRole( - peer: peerNode, - roleName: role, - forceChange: forceChange); - }, - )); - }, - mute: mutePermission, - unMute: unMutePermission, - removeOthers: removePeerPermission, - roles: changeRolePermission, - ), - ], + builder: (_) => RemotePeerTileDialog( + isAudioMuted: + peerTrackNode.audioTrack?.isMute ?? true, + isVideoMuted: peerTrackNode.track == null + ? true + : peerTrackNode.track!.isMute, + peerName: peerNode.name, + changeVideoTrack: (mute, isVideoTrack) { + Navigator.pop(context); + _meetingStore.changeTrackState( + peerTrackNode.track!, mute); + }, + changeAudioTrack: (mute, isAudioTrack) { + Navigator.pop(context); + _meetingStore.changeTrackState( + peerTrackNode.audioTrack!, mute); + }, + removePeer: () async { + Navigator.pop(context); + var peer = await _meetingStore.getPeer( + peerId: peerNode.peerId); + _meetingStore.removePeerFromRoom(peer!); + }, + changeRole: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (_) => ChangeRoleOptionDialog( + peerName: peerNode.name, + getRoleFunction: + _meetingStore.getRoles(), + changeRole: (role, forceChange) { + Navigator.pop(context); + _meetingStore.changeRole( + peer: peerNode, + roleName: role, + forceChange: forceChange); + }, + )); + }, + mute: mutePermission, + unMute: unMutePermission, + removeOthers: removePeerPermission, + roles: changeRolePermission, )); + else + showDialog( + context: context, + builder: (_) => LocalPeerTileDialog( + isAudioMode: false, + toggleCamera: () { + if (_meetingStore.isVideoOn) + _meetingStore.switchCamera(); + }, + peerName: peerNode.name, + changeRole: () { + Navigator.pop(context); + showDialog( + context: context, + builder: (_) => ChangeRoleOptionDialog( + peerName: peerNode.name, + getRoleFunction: _meetingStore.getRoles(), + changeRole: (role, forceChange) { + Navigator.pop(context); + _meetingStore.changeRole( + peer: peerNode, + roleName: role, + forceChange: forceChange); + }, + )); + }, + roles: changeRolePermission, + changeName: () async { + String name = + await UtilityComponents.showInputDialog( + context: context, + placeholder: "Enter Name"); + if (name.isNotEmpty) { + _meetingStore.changeName(name: name); + } + })); }, child: Container( color: Colors.transparent, diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index e0cfe9584..a731b3c38 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -437,7 +437,7 @@ class _MeetingPageState extends State ) : SvgPicture.asset( "assets/icons/cam_state_off.svg", - color: iconColor, + color: data.item2 ? Colors.grey : iconColor, ))); }, ), @@ -567,9 +567,9 @@ class _MeetingPageState extends State !raisedHand ? "Raised Hand ON" : "Raised Hand OFF"); }, icon: SvgPicture.asset( - "assets/icons/hand.svg", - color: raisedHand ? Colors.yellow : iconColor, - ), + "assets/icons/hand.svg", + color: raisedHand ? Colors.yellow : iconColor, + ), )); }, ), From c0aeb4034a53b322123d96cef1a267b89c976651 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 11:44:11 +0530 Subject: [PATCH 54/67] updated ReadMe --- README.md | 94 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index 9354f7b8c..c82d75823 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ - + @@ -16,34 +16,34 @@ Here you will find everything you need to build experiences with video using 100ms iOS/Android SDK. Dive into our SDKs, quick starts, add real-time video, voice, and screen sharing to your web and mobile applications. -📲 Download the Sample iOS app here: https://testflight.apple.com/join/Uhzebmut +📲 Download the Sample iOS app here: -🤖 Download the Sample Android app here: https://appdistribution.firebase.dev/i/b623e5310929ab70 +🤖 Download the Sample Android app here: - ## 🏃‍♀️ How to run the Sample App - - The Example app can be found [here](https://github.com/100mslive/100ms-flutter/tree/main/example). - - 1. In project root, run `flutter pub get` - 2. Change directory to `example` folder & run either `flutter build ios` OR `flutter build apk` - 3. Finally, `flutter run` - ## 🚂 Setup Guide -1. Sign up on https://dashboard.100ms.live/register & visit the Developer tab to access your credentials. +1. Sign up on & visit the Developer tab to access your credentials. 2. Get familiarized with [Tokens & Security here](https://docs.100ms.live/flutter/foundation/security-and-tokens) 3. Complete the steps in [Auth Token Quick Start Guide](https://docs.100ms.live/flutter/guides/token) 4. Get the HMSSDK via [pub.dev](https://pub.dev/packages/hmssdk_flutter). Add the `hmssdk_flutter` to your pubspec.yaml +If you are running Flutter 3.0 or higher, use this branch to add the package: `flutter3.0` + +## 🏃‍♀️ How to run the Sample App + +The Example app can be found [here](https://github.com/100mslive/100ms-flutter/tree/main/example). +1. In project root, run `flutter pub get` +2. Change directory to `example` folder & run either `flutter build ios` OR `flutter build apk` +3. Finally, `flutter run` ## ☝️ Pre-requisites - Support for Android API level 24 or higher - Support for Java 8 -- Support for iOS 10 or higher +- Support for iOS 12 or higher - Xcode 12 or higher ## 📱 Supported Devices @@ -54,7 +54,7 @@ iPhone & iPads with iOS version 10 or higher. ## Android Permissions -Add following permissions in Android AndroidManifest.xml file +Add the following permissions in the Android AndroidManifest.xml file ```xml @@ -78,10 +78,10 @@ Add following permissions in Android AndroidManifest.xml file ``` - ## iOS Permissions Add following permissions in iOS Info.plist file + ```xml NSMicrophoneUsageDescription {YourAppName} wants to use your microphone @@ -93,14 +93,12 @@ Add following permissions in iOS Info.plist file {YourAppName} App wants to use your local network ``` - ## 🧐 Key Concepts - `Room` - A room represents real-time audio, video session, the basic building block of the 100mslive Video SDK - `Track` - A track represents either the audio or video that makes up a stream - `Peer` - A peer represents all participants connected to a room. Peers can be "local" or "remote" -- `Broadcast` - A local peer can send any message/data to all remote peers in the room - +- `Broadcast` - A local peer can send any message/data to all remote peers in the room ## Generating Auth Token @@ -115,27 +113,28 @@ Add following permissions in iOS Info.plist file body: {'room_id': room, 'user_id': user, 'role': Constant.defaultRole}); ``` - after generating token parse it using json. + after generating the token parse it using JSON. ```dart var body = json.decode(response.body); String token = body['token']; ``` - You will need this token later explained below. - + + You will need this token later explained below. + ## ♻️ Setup event listeners -100ms SDK provides callbacks to the client app about any change or update happening in the room after a user has joined by implementing `HMSUpdateListener`. These updates can be used to render the video on screen or to display other info regarding the room. +100ms SDK provides callbacks to the client app about any change or update happening in the room after a user has joined by implementing `HMSUpdateListener`. These updates can be used to render the video on the screen or to display other info regarding the room. ```dart /// 100ms SDK provides callbacks to the client app about any change or update happening in the room after a user has joined by implementing HMSUpdateListener. -/// These updates can be used to render the video on screen or to display other info regarding the room. +/// These updates can be used to render the video on the screen or to display other info regarding the room. abstract class HMSUpdateListener { /// This will be called on a successful JOIN of the room by the user /// - /// This is the point where applications can stop showing its loading state + /// This is the point where applications can stop showing their loading state /// [room]: the room which was joined void onJoin({required HMSRoom room}); @@ -173,13 +172,13 @@ abstract class HMSUpdateListener { /// [message]: the received broadcast message void onMessage({required HMSMessage message}); - /// This is called when someone asks for change or role + /// This is called when someone asks for a change or role /// /// for eg. admin can ask a peer to become host from guest. /// this triggers this call on peer's app void onRoleChangeRequest({required HMSRoleChangeRequest roleChangeRequest}); - /// This is called every 1 second with list of active speakers + /// This is called every 1 second with a list of active speakers /// /// ## A HMSSpeaker object contains - /// - peerId: the peer identifier of HMSPeer who is speaking @@ -203,18 +202,19 @@ abstract class HMSUpdateListener { void onChangeTrackStateRequest({required HMSTrackChangeRequest hmsTrackChangeRequest}); ///when someone kicks you out or when someone ends the room at that time it is triggered - /// [hmsPeerRemovedFromPeer] it consists info about who removed you and why. + /// [hmsPeerRemovedFromPeer] it consists of info about who removed you and why. void onRemovedFromRoom({required HMSPeerRemovedFromPeer hmsPeerRemovedFromPeer}); } ``` -## 🤔 How to listen to Track, Peer and Room updates? +## 🤔 How to listen to Track, Peer and Room updates? + + The HMS SDK sends updates to the application about any change in HMSPeer, HMSTrack or HMSRoom via the callbacks in HMSUpdateListener. + Application need to listen to the corresponding updates in onPeerUpdate, onTrackUpdate or onRoomUpdate - The HMS SDK sends updates to the application about any change in HMSPeer , HMSTrack or HMSRoom via the callbacks in HMSUpdateListener. - Application need to listen to the corresponding updates in onPeerUpdate , onTrackUpdate or onRoomUpdate + The following are the different types of updates that are emitted by the SDK - - The following are the different types of updates that are emitted by the SDK - ```dart HMSPeerUpdate HMSPeerUpdate.peerJoined: A new peer joins the room @@ -242,14 +242,14 @@ HMSRoomUpdate ## 🛤 How to know the type and source of Track? - HMSTrack contain a field called source which denotes the source of the Track. + HMSTrack contains a field called source which denotes the source of the Track. Source can have the following values - regular (normal), screen (for screenshare)and plugin (for plugins) To know the type of track, check the value of type which would be one of the enum values - AUDIO or VIDEO ## 🤝 Provide joining configuration -To join a room created by following the steps described in the above section, clients need to create a `HMSConfig` instance and use that instance to call `join` method of `HMSSDK` +To join a room created by following the steps described in the above section, clients need to create an `HMSConfig` instance and use that instance to call the `join` method of `HMSSDK` ```dart // Create a new HMSConfig @@ -257,8 +257,8 @@ HMSConfig config = HMSConfig(authToken: token, userName: userName); ``` - `token`: follow the above step 1 to generate token. - `userName`: your name using which you want to join the room. + `token`: follow the above step 1 to generate a token. + `userName`: your name using which you want to join the room. ## 🙏 Join a room @@ -314,6 +314,7 @@ HMSTrack ``` ## 🎞 Display a Track + To display a video track, first get the `HMSVideoTrack` & pass it on to `HMSVideoView` using `setVideoTrack` function. Ensure to attach the `HMSVideoView` to your UI hierarchy. ```dart @@ -321,22 +322,25 @@ HMSVideoView(track: videoTrack); ``` ## Change a Role - To change role, you will provide the selected peer and new roleName from roles. If forceChange is true, the system will prompt user for the change. If forceChange is false, user will get a prompt to accept/reject the role. + + To change role, you will provide the selected peer and new roleName from roles. If forceChange is true, the system will prompt the user for the change. If forceChange is false, the user will get a prompt to accept/reject the role. After changeRole is called, HMSUpdateListener's onRoleChangeRequest will be called on selected user's end. + ```dart hmsSDK.changeRole(peer: peer, roleName: roleName, forceChange: true); ``` ## 📨 Chat Messaging -You can send a chat or any other kind of message from local peer to all remote peers in the room. + +You can send a chat or any other kind of message from a local peer to all remote peers in the room. To send a message first create an instance of `HMSMessage` object. Add the information to be sent in the `message` property of `HMSMessage`. -Then use the `void sendBroadcastMessage(message: String)` function on instance of HMSSDK. +Then use the `void sendBroadcastMessage(message: String)` function on the instance of HMSSDK. -When you(the local peer) receives a message from others(any remote peer), ` void onMessage({required HMSMessage message})` function of `HMSUpdateListener` is invoked. +When you(the local peer) receives a message from others(any remote peer), `void onMessage({required HMSMessage message})` function of `HMSUpdateListener` is invoked. ```dart // following is an example implementation of chat messaging @@ -357,25 +361,25 @@ void onMessage({required HMSMessage message}){ 🏃‍♀️ Checkout the sample implementation in the [Example app folder](https://github.com/100mslive/100ms-flutter/tree/main/example). ## 🎞 Preview + You can use our preview feature to unmute/mute audio/video before joining the room. You can implement your own preview listener using this `abstract class HMSPreviewListener` -```dart +```dart abstract class HMSPreviewListener { //you will get all error updates here void onError({required HMSException error}); - //here you will get room instance where you are going to join and your own local tracks to render the video by checking the type of trackKind and then using the + //here you will get a room instance where you are going to join and your own local tracks to render the video by checking the type of trackKind and then using the //above mentioned VideoView widget void onPreview({required HMSRoom room, required List localTracks}); } ``` +📖 Read the Complete Documentation here: -📖 Read the Complete Documentation here: https://docs.100ms.live/flutter/v2/foundation/basics - -📲 Download the Sample iOS app here: https://testflight.apple.com/join/Uhzebmut +📲 Download the Sample iOS app here: -🤖 Download the Sample Android app here: https://appdistribution.firebase.dev/i/b623e5310929ab70 +🤖 Download the Sample Android app here: From 1a18bbebd6d01193854f375858275554678fa240 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 11:49:45 +0530 Subject: [PATCH 55/67] updated ReadMe --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c82d75823..0a038064f 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,9 @@ Here you will find everything you need to build experiences with video using 100 3. Complete the steps in [Auth Token Quick Start Guide](https://docs.100ms.live/flutter/guides/token) -4. Get the HMSSDK via [pub.dev](https://pub.dev/packages/hmssdk_flutter). Add the `hmssdk_flutter` to your pubspec.yaml +4. Get the HMSSDK via [pub.dev](https://pub.dev/packages/hmssdk_flutter). Add the `hmssdk_flutter` to your pubspec.yaml. + + If you are running Flutter 3.0 or higher, use this branch to add the package: `flutter3.0` ## 🏃‍♀️ How to run the Sample App From ea0b3411c63bfe6ed17bbeec93b74f0ef85098de Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 11:51:46 +0530 Subject: [PATCH 56/67] updated ReadMe --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0a038064f..2f21e4777 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,8 @@ Here you will find everything you need to build experiences with video using 100 4. Get the HMSSDK via [pub.dev](https://pub.dev/packages/hmssdk_flutter). Add the `hmssdk_flutter` to your pubspec.yaml. -If you are running Flutter 3.0 or higher, use this branch to add the package: `flutter3.0` + If you are running Flutter 3.0 or higher, use this branch to add the package: `flutter3.0` + ## 🏃‍♀️ How to run the Sample App From f8e667c0c5b0cf1184f13ba3e71b6b382fb972f4 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 11:52:39 +0530 Subject: [PATCH 57/67] updated ReadMe --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 2f21e4777..10420d026 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,6 @@ Here you will find everything you need to build experiences with video using 100 3. Complete the steps in [Auth Token Quick Start Guide](https://docs.100ms.live/flutter/guides/token) 4. Get the HMSSDK via [pub.dev](https://pub.dev/packages/hmssdk_flutter). Add the `hmssdk_flutter` to your pubspec.yaml. - - If you are running Flutter 3.0 or higher, use this branch to add the package: `flutter3.0` From 59413a1dca498ca739be3875143bac5ee62b5397 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 11:53:05 +0530 Subject: [PATCH 58/67] updated ReadMe --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 10420d026..95d4d4c52 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Here you will find everything you need to build experiences with video using 100 3. Complete the steps in [Auth Token Quick Start Guide](https://docs.100ms.live/flutter/guides/token) 4. Get the HMSSDK via [pub.dev](https://pub.dev/packages/hmssdk_flutter). Add the `hmssdk_flutter` to your pubspec.yaml. + If you are running Flutter 3.0 or higher, use this branch to add the package: `flutter3.0` From e7e85e8c9acac873f6b2481ef4e601dc0e1d5545 Mon Sep 17 00:00:00 2001 From: Decoder07 Date: Thu, 2 Jun 2022 12:14:04 +0530 Subject: [PATCH 59/67] Fixed RTMP --- example/lib/meeting/meeting_page.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index a731b3c38..16df42eb8 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -798,8 +798,8 @@ class _MeetingPageState extends State children: [ Text( meetingStore.isRecordingStarted - ? "Recording " - : "Record", + ? "Stop RTMP/Rec" + : "Start RTMP/Rec", style: GoogleFonts.inter( color: meetingStore.isRecordingStarted ? Colors.blue From b1167f51d1ec0d69bb99559266464022a0ccc78d Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Thu, 2 Jun 2022 14:56:25 +0530 Subject: [PATCH 60/67] zoom tile --- example/lib/common/ui/organisms/video_tile.dart | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/example/lib/common/ui/organisms/video_tile.dart b/example/lib/common/ui/organisms/video_tile.dart index f0f61e729..04c58b8e9 100644 --- a/example/lib/common/ui/organisms/video_tile.dart +++ b/example/lib/common/ui/organisms/video_tile.dart @@ -198,7 +198,10 @@ class _VideoTileState extends State { ), ) : Container( - color: Colors.transparent, + decoration: BoxDecoration( + border: Border.all(color: Colors.grey, width: 1.0), + color: Colors.transparent, + borderRadius: BorderRadius.all(Radius.circular(10))), key: key, padding: EdgeInsets.all(2), margin: EdgeInsets.all(2), @@ -209,17 +212,8 @@ class _VideoTileState extends State { VideoView( uid: context.read().uid, scaleType: widget.scaleType, - itemHeight: widget.itemHeight, - itemWidth: widget.itemWidth, ), PeerName(), - Container( - height: widget.itemHeight + 110, - width: widget.itemWidth - 4, - decoration: BoxDecoration( - border: Border.all(color: Colors.grey, width: 1.0), - borderRadius: BorderRadius.all(Radius.circular(10))), - ) ], ), ), From 143662636704f8c11aa950153674ef2a25e32ec7 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Thu, 2 Jun 2022 16:37:37 +0530 Subject: [PATCH 61/67] loading indicator added --- example/assets/icons/hms_icon_loading.png | Bin 0 -> 116925 bytes example/lib/meeting/meeting_page.dart | 27 ++++++++++++++++------ example/lib/preview/preview_page.dart | 18 ++++++++++++--- 3 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 example/assets/icons/hms_icon_loading.png diff --git a/example/assets/icons/hms_icon_loading.png b/example/assets/icons/hms_icon_loading.png new file mode 100644 index 0000000000000000000000000000000000000000..609da786272191fcf8a8f7bc259a4802dab6db2f GIT binary patch literal 116925 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

8Z}N_qIt+xN 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 literal 0 HcmV?d00001 diff --git a/example/lib/meeting/meeting_page.dart b/example/lib/meeting/meeting_page.dart index 16df42eb8..c4269757f 100644 --- a/example/lib/meeting/meeting_page.dart +++ b/example/lib/meeting/meeting_page.dart @@ -59,6 +59,7 @@ class _MeetingPageState extends State bool isRecordingStarted = false; bool isBRB = false; final scrollController = DraggableScrollableController(); + late AnimationController animationController; @override void initState() { @@ -67,6 +68,7 @@ class _MeetingPageState extends State initMeeting(); checkAudioState(); setInitValues(); + initAnimation(); } void initMeeting() async { @@ -88,8 +90,17 @@ class _MeetingPageState extends State context.read().setSettings(); } + void initAnimation() { + animationController = AnimationController( + vsync: this, + duration: new Duration(milliseconds: 5000), + ); + animationController.repeat(); + } + @override void dispose() { + animationController.dispose(); super.dispose(); } @@ -302,8 +313,11 @@ class _MeetingPageState extends State fontSize: 20), ), ), - CircularProgressIndicator( - strokeWidth: 1, + RotationTransition( + child: Image.asset( + "assets/icons/hms_icon_loading.png"), + turns: + animationController, ) ], ), @@ -312,11 +326,10 @@ class _MeetingPageState extends State } if (data.item3 == 0) { return Center( - child: Text( - 'Waiting for others to join!', - style: GoogleFonts.inter( - color: iconColor, - ), + child: RotationTransition( + child: Image.asset( + "assets/icons/hms_icon_loading.png"), + turns: animationController, )); } Size size = MediaQuery.of(context).size; diff --git a/example/lib/preview/preview_page.dart b/example/lib/preview/preview_page.dart index ab19f8653..23ffe11d1 100644 --- a/example/lib/preview/preview_page.dart +++ b/example/lib/preview/preview_page.dart @@ -1,7 +1,6 @@ //Package imports import 'package:connectivity_checker/connectivity_checker.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/svg.dart'; import 'package:google_fonts/google_fonts.dart'; @@ -38,13 +37,21 @@ class PreviewPage extends StatefulWidget { _PreviewPageState createState() => _PreviewPageState(); } -class _PreviewPageState extends State with WidgetsBindingObserver { +class _PreviewPageState extends State + with WidgetsBindingObserver, TickerProviderStateMixin { + late AnimationController animationController; + @override void initState() { WidgetsBinding.instance!.addObserver(this); MultiProvider( providers: [ChangeNotifierProvider(create: (_) => PreviewStore())], ); + animationController = AnimationController( + vsync: this, + duration: new Duration(milliseconds: 5000), + ); + animationController.repeat(); super.initState(); initPreview(); } @@ -61,6 +68,7 @@ class _PreviewPageState extends State with WidgetsBindingObserver { @override void dispose() { + animationController.dispose(); super.dispose(); } @@ -90,7 +98,11 @@ class _PreviewPageState extends State with WidgetsBindingObserver { ) : Align( alignment: Alignment.center, - child: CupertinoActivityIndicator(radius: 50)) + child: RotationTransition( + child: Image.asset( + "assets/icons/hms_icon_loading.png"), + turns: animationController, + )) : Container( height: itemHeight, width: itemWidth, From 51ce9c88bfd3656131f10536cc83dee57df84209 Mon Sep 17 00:00:00 2001 From: govindmaheshwari2 Date: Thu, 2 Jun 2022 17:06:20 +0530 Subject: [PATCH 62/67] system based theme --- example/lib/common/constant.dart | 2 -- example/lib/common/util/app_color.dart | 10 ++++++---- example/lib/main.dart | 16 +++++++++------- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/example/lib/common/constant.dart b/example/lib/common/constant.dart index d458e6aab..2f2f487d8 100644 --- a/example/lib/common/constant.dart +++ b/example/lib/common/constant.dart @@ -21,6 +21,4 @@ class Constant { static String meetingUrl = defaultRoomID; static String meetingCode = ""; static String rtmpUrl = ""; - - static bool isDarkMode = true; } diff --git a/example/lib/common/util/app_color.dart b/example/lib/common/util/app_color.dart index 3646d7755..876d3395d 100644 --- a/example/lib/common/util/app_color.dart +++ b/example/lib/common/util/app_color.dart @@ -1,8 +1,10 @@ import 'package:flutter/material.dart'; -import 'package:hmssdk_flutter_example/common/constant.dart'; -Color iconColor = Constant.isDarkMode ? Colors.white : Colors.black; +Color iconColor = + WidgetsBinding.instance?.window.platformBrightness == Brightness.dark + ? Colors.white + : Colors.black; -void updateColor() { - iconColor = Constant.isDarkMode ? Colors.white : Colors.black; +void updateColor(ThemeMode mode) { + iconColor = mode == ThemeMode.dark ? Colors.white : Colors.black; } diff --git a/example/lib/main.dart b/example/lib/main.dart index f729b0925..135bda5f7 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -45,8 +45,9 @@ class HMSExampleApp extends StatefulWidget { } class _HMSExampleAppState extends State { - ThemeMode _themeMode = ThemeMode.dark; - + ThemeMode _themeMode = ThemeMode.system; + bool isDarkMode = + WidgetsBinding.instance?.window.platformBrightness == Brightness.dark; ThemeData _darkTheme = ThemeData( brightness: Brightness.dark, primaryColor: Color.fromARGB(255, 13, 107, 184), @@ -74,8 +75,8 @@ class _HMSExampleAppState extends State { void changeTheme(ThemeMode themeMode) { setState(() { _themeMode = themeMode; - Constant.isDarkMode = _themeMode == ThemeMode.dark ? true : false; - updateColor(); + isDarkMode = themeMode == ThemeMode.dark; + updateColor(_themeMode); }); } } @@ -167,11 +168,12 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { + bool isDarkMode = HMSExampleApp.of(context).isDarkMode; return WillPopScope( onWillPop: _closeApp, child: Scaffold( appBar: AppBar( - backgroundColor: Constant.isDarkMode ? Colors.black : Colors.white, + backgroundColor: isDarkMode ? Colors.black : Colors.white, elevation: 0, title: Text( '100ms', @@ -180,13 +182,13 @@ class _HomePageState extends State { actions: [ IconButton( onPressed: () { - if (Constant.isDarkMode) { + if (isDarkMode) { HMSExampleApp.of(context).changeTheme(ThemeMode.light); } else { HMSExampleApp.of(context).changeTheme(ThemeMode.dark); } }, - icon: Constant.isDarkMode + icon: isDarkMode ? SvgPicture.asset( 'assets/icons/light_mode.svg', color: iconColor, From c6b5a879e98a5806eef2bbc7916e7cf9c3786a71 Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 17:48:26 +0530 Subject: [PATCH 63/67] =?UTF-8?q?released=20sample=20app=20version=201.1.2?= =?UTF-8?q?2=20(72)=20=F0=9F=8D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- example/android/app/build.gradle | 4 ++-- example/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- example/ios/Runner/Info.plist | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index dea308527..6b41a014e 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -32,8 +32,8 @@ android { applicationId "live.hms.flutter" minSdkVersion 21 targetSdkVersion 32 - versionCode 71 - versionName "1.1.21" + versionCode 72 + versionName "1.1.22" } signingConfigs { diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj index 161de1302..10443ecde 100644 --- a/example/ios/Runner.xcodeproj/project.pbxproj +++ b/example/ios/Runner.xcodeproj/project.pbxproj @@ -384,7 +384,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 71; + CURRENT_PROJECT_VERSION = 72; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; @@ -522,7 +522,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 71; + CURRENT_PROJECT_VERSION = 72; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; @@ -555,7 +555,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 71; + CURRENT_PROJECT_VERSION = 72; DEVELOPMENT_TEAM = 5N85PP82A9; ENABLE_BITCODE = YES; INFOPLIST_FILE = Runner/Info.plist; diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist index afa4242f2..784a84e0d 100644 --- a/example/ios/Runner/Info.plist +++ b/example/ios/Runner/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.1.21 + 1.1.22 CFBundleSignature ???? CFBundleURLTypes @@ -34,7 +34,7 @@ CFBundleVersion - 71 + 72 ITSAppUsesNonExemptEncryption LSApplicationCategoryType From 39a108b08d3337b2cdf962f901aef7469d557e9a Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 17:51:27 +0530 Subject: [PATCH 64/67] dart formatted --- .../ui/organisms/change_role_options.dart | 35 +++++++++--- .../ui/organisms/chat_bottom_sheet.dart | 54 ++++++++++++------ .../lib/common/ui/organisms/degrade_tile.dart | 16 +++--- .../common/ui/organisms/full_screen_view.dart | 9 ++- .../common/ui/organisms/grid_audio_view.dart | 2 +- .../common/ui/organisms/grid_video_view.dart | 9 ++- .../common/ui/organisms/offline_screen.dart | 6 +- .../lib/common/ui/organisms/peer_name.dart | 3 +- .../ui/organisms/remote_peer_tile_dialog.dart | 2 +- .../organisms/role_change_request_dialog.dart | 2 +- .../common/ui/organisms/rtc_stats_view.dart | 56 ++++++++++++++----- .../track_change_request_dialog.dart | 17 +++++- .../organisms/user_name_dialog_organism.dart | 4 +- example/lib/common/util/utility_function.dart | 2 +- example/lib/hls_viewer/hls_viewer.dart | 2 +- .../meeting/meeting_participants_list.dart | 4 +- lib/src/model/hms_update_listener.dart | 1 - 17 files changed, 160 insertions(+), 64 deletions(-) diff --git a/example/lib/common/ui/organisms/change_role_options.dart b/example/lib/common/ui/organisms/change_role_options.dart index 89f295ee1..bd3743cfa 100644 --- a/example/lib/common/ui/organisms/change_role_options.dart +++ b/example/lib/common/ui/organisms/change_role_options.dart @@ -36,7 +36,10 @@ class _ChangeRoleOptionDialogState extends State { @override Widget build(BuildContext context) { return AlertDialog( - title: Text(widget.peerName,style: GoogleFonts.inter(color:iconColor),), + title: Text( + widget.peerName, + style: GoogleFonts.inter(color: iconColor), + ), content: Container( width: double.infinity, child: FutureBuilder>( @@ -55,7 +58,10 @@ class _ChangeRoleOptionDialogState extends State { Row( mainAxisAlignment: MainAxisAlignment.center, children: [ - Text("Role To: ",style: GoogleFonts.inter(color:iconColor),), + Text( + "Role To: ", + style: GoogleFonts.inter(color: iconColor), + ), Flexible( child: DropdownButton2( buttonWidth: MediaQuery.of(context).size.width / 2, @@ -68,7 +74,10 @@ class _ChangeRoleOptionDialogState extends State { }, items: data.data!.map((role) { return DropdownMenuItem( - child: Text(role.name,style: GoogleFonts.inter(color:iconColor),), + child: Text( + role.name, + style: GoogleFonts.inter(color: iconColor), + ), value: role.name, ); }).toList(), @@ -92,7 +101,10 @@ class _ChangeRoleOptionDialogState extends State { SizedBox( width: 16, ), - Text('Force change',style: GoogleFonts.inter(color:iconColor),) + Text( + 'Force change', + style: GoogleFonts.inter(color: iconColor), + ) ], ), ), @@ -108,7 +120,10 @@ class _ChangeRoleOptionDialogState extends State { onPressed: () { Navigator.pop(context); }, - child: Text("Cancel",style: GoogleFonts.inter(),)), + child: Text( + "Cancel", + style: GoogleFonts.inter(), + )), ElevatedButton( onPressed: () { widget.changeRole( @@ -116,14 +131,20 @@ class _ChangeRoleOptionDialogState extends State { (element) => element.name == valueChoose), forceValue); }, - child: Text("Change Role",style: GoogleFonts.inter(),)), + child: Text( + "Change Role", + style: GoogleFonts.inter(), + )), ], ) ], ), ); } - return Text('No roles available',style: GoogleFonts.inter(),); + return Text( + 'No roles available', + style: GoogleFonts.inter(), + ); }, future: widget.getRoleFunction, ), diff --git a/example/lib/common/ui/organisms/chat_bottom_sheet.dart b/example/lib/common/ui/organisms/chat_bottom_sheet.dart index b2361076f..b9027ee1b 100644 --- a/example/lib/common/ui/organisms/chat_bottom_sheet.dart +++ b/example/lib/common/ui/organisms/chat_bottom_sheet.dart @@ -79,8 +79,12 @@ class _ChatWidgetState extends State { items: [ DropdownMenuItem( child: Container( - width: 90, - child: Text("Everyone",style: GoogleFonts.inter(),overflow: TextOverflow.clip,)), + width: 90, + child: Text( + "Everyone", + style: GoogleFonts.inter(), + overflow: TextOverflow.clip, + )), value: "Everyone", ), ...data.item2 @@ -90,7 +94,15 @@ class _ChatWidgetState extends State { child: Container( width: 90, child: Text( - "${peer.name} ${peer.isLocal ? "(You)" : ""}",style: GoogleFonts.inter(color:iconColor),overflow: TextOverflow.clip,), + "${peer.name} ${peer.isLocal ? "(You)" : ""}", + style: GoogleFonts + .inter( + color: + iconColor), + overflow: + TextOverflow + .clip, + ), ), value: peer.peerId, ) @@ -102,10 +114,16 @@ class _ChatWidgetState extends State { .map((role) => DropdownMenuItem( child: Container( - width: 90, - child: Text("${role.name}", - overflow: TextOverflow.clip, - style: GoogleFonts.inter(color:iconColor),)), + width: 90, + child: Text( + "${role.name}", + overflow: + TextOverflow.clip, + style: + GoogleFonts.inter( + color: + iconColor), + )), value: role.name, )) .toList() @@ -140,7 +158,11 @@ class _ChatWidgetState extends State { // if (!_meetingStore.isMeetingStarted) return SizedBox(); if (data.item2 == 0) - return Center(child: Text('No messages',style: GoogleFonts.inter(color:iconColor),)); + return Center( + child: Text( + 'No messages', + style: GoogleFonts.inter(color: iconColor), + )); return ListView( children: List.generate( @@ -158,18 +180,18 @@ class _ChatWidgetState extends State { Expanded( child: Text( data.item1[index].sender?.name ?? "", - style: GoogleFonts.inter( + style: GoogleFonts.inter( fontSize: 14.0, - color:iconColor, + color: iconColor, fontWeight: FontWeight.w600), ), ), Text( formatter .format(data.item1[index].time), - style: GoogleFonts.inter( + style: GoogleFonts.inter( fontSize: 10.0, - color:iconColor, + color: iconColor, fontWeight: FontWeight.w900), ) ], @@ -183,9 +205,9 @@ class _ChatWidgetState extends State { Flexible( child: Text( data.item1[index].message.toString(), - style: GoogleFonts.inter( + style: GoogleFonts.inter( fontSize: 14.0, - color:iconColor, + color: iconColor, fontWeight: FontWeight.w700), ), ), @@ -197,7 +219,7 @@ class _ChatWidgetState extends State { .hmsMessageRecipient! .hmsMessageRecipientType) .toLowerCase(), - style: GoogleFonts.inter( + style: GoogleFonts.inter( fontSize: 14.0, color: Colors.blue, fontWeight: FontWeight.w500), @@ -227,7 +249,7 @@ class _ChatWidgetState extends State { margin: EdgeInsets.only(bottom: 5.0, left: 5.0), child: TextField( autofocus: true, - style: GoogleFonts.inter(color:iconColor), + style: GoogleFonts.inter(color: iconColor), controller: messageTextController, decoration: new InputDecoration( border: InputBorder.none, diff --git a/example/lib/common/ui/organisms/degrade_tile.dart b/example/lib/common/ui/organisms/degrade_tile.dart index 6740d98d5..803b4c65e 100644 --- a/example/lib/common/ui/organisms/degrade_tile.dart +++ b/example/lib/common/ui/organisms/degrade_tile.dart @@ -39,15 +39,15 @@ class _DegradeTileState extends State { child: Stack( children: [ Positioned( - child: Padding( - padding: const EdgeInsets.fromLTRB(5, 5, 0, 0), - child: SvgPicture.asset( - 'assets/icons/degrade.svg', + child: Padding( + padding: const EdgeInsets.fromLTRB(5, 5, 0, 0), + child: SvgPicture.asset( + 'assets/icons/degrade.svg', + ), + ), + top: 10.0, + right: 5.0, ), - ), - top: 10.0, - right: 5.0, - ), AudioLevelAvatar() ], ), diff --git a/example/lib/common/ui/organisms/full_screen_view.dart b/example/lib/common/ui/organisms/full_screen_view.dart index 6829dcd97..e9871b702 100644 --- a/example/lib/common/ui/organisms/full_screen_view.dart +++ b/example/lib/common/ui/organisms/full_screen_view.dart @@ -39,10 +39,15 @@ Widget fullScreenView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/screen_share.svg",color:iconColor,), + SvgPicture.asset( + "assets/icons/screen_share.svg", + color: iconColor, + ), Text( "You are sharing your screen", - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ), ], ), diff --git a/example/lib/common/ui/organisms/grid_audio_view.dart b/example/lib/common/ui/organisms/grid_audio_view.dart index 8e642510b..fb4b0931d 100644 --- a/example/lib/common/ui/organisms/grid_audio_view.dart +++ b/example/lib/common/ui/organisms/grid_audio_view.dart @@ -34,7 +34,7 @@ Widget gridAudioView( } List pattern(int itemCount, Size size) { - double ratio = Utilities.getRatio(size); + double ratio = Utilities.getRatio(size); List tiles = []; int gridView = itemCount ~/ 6; diff --git a/example/lib/common/ui/organisms/grid_video_view.dart b/example/lib/common/ui/organisms/grid_video_view.dart index aeb0617a9..52a8691c1 100644 --- a/example/lib/common/ui/organisms/grid_video_view.dart +++ b/example/lib/common/ui/organisms/grid_video_view.dart @@ -39,10 +39,15 @@ Widget gridVideoView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - SvgPicture.asset("assets/icons/screen_share.svg",color:iconColor,), + SvgPicture.asset( + "assets/icons/screen_share.svg", + color: iconColor, + ), Text( "You are sharing your screen", - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ), ], ), diff --git a/example/lib/common/ui/organisms/offline_screen.dart b/example/lib/common/ui/organisms/offline_screen.dart index 255dc8862..9f2641965 100644 --- a/example/lib/common/ui/organisms/offline_screen.dart +++ b/example/lib/common/ui/organisms/offline_screen.dart @@ -29,8 +29,10 @@ class OfflineWidget extends StatelessWidget { child: Center( child: Text( 'Oops, No internet connection.\n\nReconnecting...', - style: GoogleFonts.inter(color:iconColor, - fontSize: 20, fontWeight: FontWeight.bold), + style: GoogleFonts.inter( + color: iconColor, + fontSize: 20, + fontWeight: FontWeight.bold), ), ), ), diff --git a/example/lib/common/ui/organisms/peer_name.dart b/example/lib/common/ui/organisms/peer_name.dart index 1421bd6d2..6757c71a1 100644 --- a/example/lib/common/ui/organisms/peer_name.dart +++ b/example/lib/common/ui/organisms/peer_name.dart @@ -33,8 +33,7 @@ class _PeerNameState extends State { overflow: TextOverflow.ellipsis, style: GoogleFonts.inter( fontWeight: FontWeight.w500, - color:iconColor, - + color: iconColor, fontSize: 16), ), ), diff --git a/example/lib/common/ui/organisms/remote_peer_tile_dialog.dart b/example/lib/common/ui/organisms/remote_peer_tile_dialog.dart index b4becfb33..4d0174534 100644 --- a/example/lib/common/ui/organisms/remote_peer_tile_dialog.dart +++ b/example/lib/common/ui/organisms/remote_peer_tile_dialog.dart @@ -40,7 +40,7 @@ class _RemotePeerTileDialogState extends State { return AlertDialog( title: Text( widget.peerName, - style: GoogleFonts.inter(color: iconColor,fontWeight: FontWeight.bold), + style: GoogleFonts.inter(color: iconColor, fontWeight: FontWeight.bold), ), content: Container( width: double.infinity, diff --git a/example/lib/common/ui/organisms/role_change_request_dialog.dart b/example/lib/common/ui/organisms/role_change_request_dialog.dart index 80f8843da..bcf7e3ad4 100644 --- a/example/lib/common/ui/organisms/role_change_request_dialog.dart +++ b/example/lib/common/ui/organisms/role_change_request_dialog.dart @@ -31,7 +31,7 @@ class _RoleChangeDialogOrganismState extends State { Text( message, style: GoogleFonts.inter( - color:iconColor, + color: iconColor, ), ), ], diff --git a/example/lib/common/ui/organisms/rtc_stats_view.dart b/example/lib/common/ui/organisms/rtc_stats_view.dart index cb1cd63b9..91a3772cf 100644 --- a/example/lib/common/ui/organisms/rtc_stats_view.dart +++ b/example/lib/common/ui/organisms/rtc_stats_view.dart @@ -50,22 +50,34 @@ class Stats extends StatelessWidget { children: [ Text( "Width\t ${data.item3?.hmsLocalVideoStats?.resolution.width.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ), Text( "Height\t ${data.item3?.hmsLocalVideoStats?.resolution.height.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "FPS\t ${data.item3?.hmsLocalVideoStats?.frameRate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text("Downlink\t ${data.item4 ?? "-1"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "Bitrate(V)\t ${data.item3?.hmsLocalVideoStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "Bitrate(A)\t ${data.item3?.hmsLocalAudioStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), ], ), ); @@ -89,27 +101,43 @@ class Stats extends StatelessWidget { children: [ Text( "Width\t ${data.item3?.hmsRemoteVideoStats?.resolution.width.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "Height\t ${data.item3?.hmsRemoteVideoStats?.resolution.height.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "FPS\t ${data.item3?.hmsRemoteVideoStats?.frameRate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text("Downlink\t ${data.item4 ?? "-1"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "Bitrate(V)\t ${data.item3?.hmsRemoteVideoStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "Bitrate(A)\t ${data.item3?.hmsRemoteAudioStats?.bitrate.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "Jitter(V)\t ${data.item3?.hmsRemoteVideoStats?.jitter.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), Text( "Jitter(A)\t ${data.item3?.hmsRemoteAudioStats?.jitter.toStringAsFixed(2) ?? "0.00"}", - style: GoogleFonts.inter(color:iconColor,)), + style: GoogleFonts.inter( + color: iconColor, + )), ], ), ); diff --git a/example/lib/common/ui/organisms/track_change_request_dialog.dart b/example/lib/common/ui/organisms/track_change_request_dialog.dart index 4e51ff39c..624e7fe29 100644 --- a/example/lib/common/ui/organisms/track_change_request_dialog.dart +++ b/example/lib/common/ui/organisms/track_change_request_dialog.dart @@ -35,19 +35,30 @@ class _RoleChangeDialogOrganismState extends State { child: Column( mainAxisSize: MainAxisSize.min, children: [ - Text(message,style: GoogleFonts.inter(color:iconColor,),), + Text( + message, + style: GoogleFonts.inter( + color: iconColor, + ), + ), ], ), ), actions: [ ElevatedButton( - child: Text('Cancel',style: GoogleFonts.inter(),), + child: Text( + 'Cancel', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context, ''); }, ), ElevatedButton( - child: Text('OK',style: GoogleFonts.inter(),), + child: Text( + 'OK', + style: GoogleFonts.inter(), + ), onPressed: () { Navigator.pop(context, 'OK'); }, diff --git a/example/lib/common/ui/organisms/user_name_dialog_organism.dart b/example/lib/common/ui/organisms/user_name_dialog_organism.dart index 4df8da476..691bdb18a 100644 --- a/example/lib/common/ui/organisms/user_name_dialog_organism.dart +++ b/example/lib/common/ui/organisms/user_name_dialog_organism.dart @@ -29,7 +29,9 @@ class _UserNameDialogOrganismState extends State { borderRadius: BorderRadius.all(Radius.circular(16)), ), hintText: 'Enter your Name', - hintStyle: GoogleFonts.inter(color:iconColor,)), + hintStyle: GoogleFonts.inter( + color: iconColor, + )), ), ], ), diff --git a/example/lib/common/util/utility_function.dart b/example/lib/common/util/utility_function.dart index 327d5483f..756f17ab1 100644 --- a/example/lib/common/util/utility_function.dart +++ b/example/lib/common/util/utility_function.dart @@ -31,6 +31,6 @@ class Utilities { ]; static double getRatio(Size size) { - return (size.height * 0.82) / (size.width); + return (size.height * 0.82) / (size.width); } } diff --git a/example/lib/hls_viewer/hls_viewer.dart b/example/lib/hls_viewer/hls_viewer.dart index 775c025c6..1f13d9a2a 100644 --- a/example/lib/hls_viewer/hls_viewer.dart +++ b/example/lib/hls_viewer/hls_viewer.dart @@ -50,7 +50,7 @@ class _HLSViewerState extends State { ) : Text( "Waiting for the HLS Streaming to start...", - style: GoogleFonts.inter(color:iconColor,fontSize: 20.0), + style: GoogleFonts.inter(color: iconColor, fontSize: 20.0), ), ), ); diff --git a/example/lib/meeting/meeting_participants_list.dart b/example/lib/meeting/meeting_participants_list.dart index 6b6fdda02..d8d5fcc98 100644 --- a/example/lib/meeting/meeting_participants_list.dart +++ b/example/lib/meeting/meeting_participants_list.dart @@ -59,7 +59,9 @@ class _ParticipantsListState extends State { } else { return Text( "No Participants", - style: GoogleFonts.inter(color:iconColor,), + style: GoogleFonts.inter( + color: iconColor, + ), ); } }), diff --git a/lib/src/model/hms_update_listener.dart b/lib/src/model/hms_update_listener.dart index 54629c2dc..c96f8b0c3 100644 --- a/lib/src/model/hms_update_listener.dart +++ b/lib/src/model/hms_update_listener.dart @@ -93,5 +93,4 @@ abstract class HMSUpdateListener { ///- Paramter hmsPeerRemovedFromPeer - it consists info about who removed you and why. void onRemovedFromRoom( {required HMSPeerRemovedFromPeer hmsPeerRemovedFromPeer}); - } From 3df3673c5c2c91517a2260bfa3b79aaccaf349ab Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 17:57:26 +0530 Subject: [PATCH 65/67] applied dart fixes --- example/lib/common/ui/organisms/degrade_tile.dart | 2 -- example/lib/meeting/meeting_store.dart | 1 - lib/src/model/platform_method_response.dart | 1 - 3 files changed, 4 deletions(-) diff --git a/example/lib/common/ui/organisms/degrade_tile.dart b/example/lib/common/ui/organisms/degrade_tile.dart index 803b4c65e..a1dbc2f65 100644 --- a/example/lib/common/ui/organisms/degrade_tile.dart +++ b/example/lib/common/ui/organisms/degrade_tile.dart @@ -1,12 +1,10 @@ //package imports import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; -import 'package:google_fonts/google_fonts.dart'; import 'package:hmssdk_flutter_example/common/ui/organisms/audio_level_avatar.dart'; import 'package:provider/provider.dart'; //Package imports -import 'package:hmssdk_flutter_example/common/util/utility_function.dart'; import 'package:hmssdk_flutter_example/meeting/peer_track_node.dart'; class DegradeTile extends StatefulWidget { diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 270a3997e..99f78d4e1 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -1,6 +1,5 @@ //Package imports import 'package:firebase_crashlytics/firebase_crashlytics.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:hmssdk_flutter_example/enum/meeting_mode.dart'; diff --git a/lib/src/model/platform_method_response.dart b/lib/src/model/platform_method_response.dart index 406e84aed..8ab0785af 100644 --- a/lib/src/model/platform_method_response.dart +++ b/lib/src/model/platform_method_response.dart @@ -2,7 +2,6 @@ import 'package:hmssdk_flutter/hmssdk_flutter.dart'; import 'package:hmssdk_flutter/src/enum/hms_logs_update_listener.dart'; import 'package:hmssdk_flutter/src/enum/hms_network_update_listener_method.dart'; -import 'package:hmssdk_flutter/src/enum/hms_stats_listener_method.dart'; ///PlatformMethodResponse contains all the responses sent back from the platform /// From 572d660e446545e69cc36b7dc72747b51985003a Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 17:57:58 +0530 Subject: [PATCH 66/67] updated TODOs --- example/lib/meeting/hms_sdk_interactor.dart | 3 --- example/lib/meeting/meeting_store.dart | 26 ++------------------- example/lib/meeting/peer_track_node.dart | 1 - lib/src/model/hms_peer.dart | 2 -- lib/src/model/hms_remote_peer.dart | 2 -- 5 files changed, 2 insertions(+), 32 deletions(-) diff --git a/example/lib/meeting/hms_sdk_interactor.dart b/example/lib/meeting/hms_sdk_interactor.dart index 417cedf27..f3582c35f 100644 --- a/example/lib/meeting/hms_sdk_interactor.dart +++ b/example/lib/meeting/hms_sdk_interactor.dart @@ -183,7 +183,6 @@ class HMSSDKInteractor { } Future isVideoMute(HMSPeer? peer) async { - // TODO: add permission checks in exmaple app UI return await hmsSDK.isVideoMute(peer: peer); } @@ -201,12 +200,10 @@ class HMSSDKInteractor { } void unMuteAll() { - // TODO: add permission checks in exmaple app UI hmsSDK.unMuteAll(); } void setPlayBackAllowed(bool allow) { - // TODO: add permission checks in exmaple app UI hmsSDK.setPlayBackAllowed(allow: allow); } diff --git a/example/lib/meeting/meeting_store.dart b/example/lib/meeting/meeting_store.dart index 99f78d4e1..03c8438d8 100644 --- a/example/lib/meeting/meeting_store.dart +++ b/example/lib/meeting/meeting_store.dart @@ -171,12 +171,10 @@ class MeetingStore extends ChangeNotifier } Future isAudioMute(HMSPeer? peer) async { - // TODO: add permission checks in exmaple app UI return await _hmsSDKInteractor.isAudioMute(peer); } Future isVideoMute(HMSPeer? peer) async { - // TODO: add permission checks in exmaple app UI return await _hmsSDKInteractor.isVideoMute(peer); } @@ -953,7 +951,6 @@ class MeetingStore extends ChangeNotifier notifyListeners(); break; case HMSActionResultListenerMethod.changeTrackState: - // TODO: Handle this case. showToast("Track State Changed"); break; case HMSActionResultListenerMethod.changeMetadata: @@ -967,11 +964,9 @@ class MeetingStore extends ChangeNotifier // TODO: Handle this case. break; case HMSActionResultListenerMethod.acceptChangeRole: - // TODO: Handle this case. showToast("Accept role change successful"); break; case HMSActionResultListenerMethod.changeRole: - // TODO: Handle this case. showToast("Change role successful"); break; case HMSActionResultListenerMethod.changeTrackStateForRole: @@ -982,7 +977,6 @@ class MeetingStore extends ChangeNotifier break; case HMSActionResultListenerMethod.startRtmpOrRecording: showToast("RTMP start successful"); - //TODO: HmsException?.code == 400(To see what this means) break; case HMSActionResultListenerMethod.stopRtmpAndRecording: @@ -1037,14 +1031,11 @@ class MeetingStore extends ChangeNotifier hasHlsStarted = true; showToast("HLS Streaming Started"); notifyListeners(); - // TODO: Handle this case. break; case HMSActionResultListenerMethod.hlsStreamingStopped: hasHlsStarted = false; showToast("HLS Streaming Stopped"); notifyListeners(); - - // TODO: Handle this case. break; case HMSActionResultListenerMethod.startScreenShare: @@ -1069,30 +1060,24 @@ class MeetingStore extends ChangeNotifier FirebaseCrashlytics.instance.log(hmsException.toString()); switch (methodType) { case HMSActionResultListenerMethod.leave: - // TODO: Handle this case. showToast("Leave Operation failed"); break; case HMSActionResultListenerMethod.changeTrackState: - // TODO: Handle this case. showToast("Change Track state failed"); break; case HMSActionResultListenerMethod.changeMetadata: // TODO: Handle this case. break; case HMSActionResultListenerMethod.endRoom: - // TODO: Handle this case. showToast("End room failed"); break; case HMSActionResultListenerMethod.removePeer: - // TODO: Handle this case. showToast("Remove peer failed"); break; case HMSActionResultListenerMethod.acceptChangeRole: - // TODO: Handle this case. showToast("Accept change role failed"); break; case HMSActionResultListenerMethod.changeRole: - // TODO: Handle this case. showToast("Change role failed"); break; case HMSActionResultListenerMethod.changeTrackStateForRole: @@ -1105,13 +1090,9 @@ class MeetingStore extends ChangeNotifier showToast("Start RTMP Streaming failed"); break; case HMSActionResultListenerMethod.stopRtmpAndRecording: - // TODO: Handle this case. showToast("Stop RTMP Streaming failed"); break; - case HMSActionResultListenerMethod.unknown: - break; case HMSActionResultListenerMethod.changeName: - // TODO: Handle this case. showToast("Name change failed"); break; case HMSActionResultListenerMethod.sendBroadcastMessage: @@ -1124,24 +1105,21 @@ class MeetingStore extends ChangeNotifier // TODO: Handle this case. break; case HMSActionResultListenerMethod.hlsStreamingStarted: - // TODO: Handle this case. showToast("Start HLS failed"); break; case HMSActionResultListenerMethod.hlsStreamingStopped: - // TODO: Handle this case. showToast("Stop HLS failed"); - break; - case HMSActionResultListenerMethod.startScreenShare: isScreenShareActive(); showToast("Start screenshare failed"); break; - case HMSActionResultListenerMethod.stopScreenShare: isScreenShareActive(); showToast("Stop screenshare failed"); break; + case HMSActionResultListenerMethod.unknown: + break; } } diff --git a/example/lib/meeting/peer_track_node.dart b/example/lib/meeting/peer_track_node.dart index 75628696d..da8c5dd2f 100644 --- a/example/lib/meeting/peer_track_node.dart +++ b/example/lib/meeting/peer_track_node.dart @@ -42,7 +42,6 @@ class PeerTrackNode extends ChangeNotifier { @override bool operator ==(Object other) { - // TODO: implement == return super == other; } } diff --git a/lib/src/model/hms_peer.dart b/lib/src/model/hms_peer.dart index bc9a46962..0f853fafd 100644 --- a/lib/src/model/hms_peer.dart +++ b/lib/src/model/hms_peer.dart @@ -98,8 +98,6 @@ class HMSPeer { return peer; } - // TODO: add HMSRemotePeer class - static List fromListOfMap(List peersMap) { List peers = peersMap.map((e) => HMSPeer.fromMap(e)).toList(); return peers; diff --git a/lib/src/model/hms_remote_peer.dart b/lib/src/model/hms_remote_peer.dart index 7bece5f4e..1d39d06b5 100644 --- a/lib/src/model/hms_remote_peer.dart +++ b/lib/src/model/hms_remote_peer.dart @@ -81,8 +81,6 @@ class HMSRemotePeer extends HMSPeer { return peer; } - // TODO: add HMSRemotePeer class - static List fromListOfMap(List peersMap) { List peers = peersMap.map((e) => HMSPeer.fromMap(e)).toList(); return peers; From beef4506e2f5d9fcc1228afccf501252ab31165a Mon Sep 17 00:00:00 2001 From: Yogesh Singh Date: Thu, 2 Jun 2022 18:22:09 +0530 Subject: [PATCH 67/67] updated Changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16116a026..6d197a048 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## 0.7.2 - 2022-06-02 + +- Segregated RTC Stats update notifications from `HMSUpdateListener` into `HMSStatsListener` +- Removed `room_peer_count_updated` from `HMSRoomUpdate` enum +- Added `sessionId` to the `HMSRoom` class +- Updated to Native Android SDK 2.3.9 & Native iOS SDK 0.3.1 + ## 0.7.1 - 2022-05-20 - Added RTC Stats Listener which provides info about local & remote peer's audio/video quality