From 0ad4854443664f7e2edc190343bf00f52ef0e5f6 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Fri, 2 Aug 2024 21:12:37 +0800 Subject: [PATCH] :lipstick: Grid view in call --- ios/Podfile.lock | 4 +- lib/screens/channel/call/call.dart | 221 ++++++++++---------- lib/widgets/chat/call/call_participant.dart | 6 +- pubspec.lock | 28 +-- 4 files changed, 132 insertions(+), 127 deletions(-) diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 9da6c6f..97735cb 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -113,7 +113,7 @@ PODS: - TOCropViewController (~> 2.7.4) - image_picker_ios (0.0.1): - Flutter - - livekit_client (2.2.2): + - livekit_client (2.2.3): - Flutter - WebRTC-SDK (= 125.6422.04) - media_kit_libs_ios_video (1.0.4): @@ -295,7 +295,7 @@ SPEC CHECKSUMS: GoogleUtilities: ea963c370a38a8069cc5f7ba4ca849a60b6d7d15 image_cropper: 37d40f62177c101ff4c164906d259ea2c3aa70cf image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 - livekit_client: c767049a635d5b6d43de3273dca3c439b8a6e970 + livekit_client: bad83a7776a41abc42e1f26d903eeac9164c8a9f media_kit_libs_ios_video: a5fe24bc7875ccd6378a0978c13185e1344651c1 media_kit_native_event_loop: e6b2ab20cf0746eb1c33be961fcf79667304fa2a media_kit_video: 5da63f157170e5bf303bf85453b7ef6971218a2e diff --git a/lib/screens/channel/call/call.dart b/lib/screens/channel/call/call.dart index d1d934d..9e2d263 100644 --- a/lib/screens/channel/call/call.dart +++ b/lib/screens/channel/call/call.dart @@ -87,75 +87,77 @@ class _CallScreenState extends State with TickerProviderStateMixin { Widget _buildListLayout() { final ChatCallProvider call = Get.find(); - return Stack( - children: [ - Container( - color: Theme.of(context).colorScheme.surfaceContainer, - child: call.focusTrack.value != null - ? InteractiveParticipantWidget( - isFixed: false, - participant: call.focusTrack.value!, - onTap: () {}, - ) - : const SizedBox(), - ), - Positioned( - left: 0, - right: 0, - top: 0, - child: SizedBox( - height: 128, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: math.max(0, call.participantTracks.length), - itemBuilder: (BuildContext context, int index) { - final track = call.participantTracks[index]; - if (track.participant.sid == - call.focusTrack.value?.participant.sid) { - return Container(); - } + return Obx( + () => Stack( + children: [ + Container( + color: Theme.of(context).colorScheme.surfaceContainer, + child: call.focusTrack.value != null + ? InteractiveParticipantWidget( + isFixedAvatar: false, + participant: call.focusTrack.value!, + onTap: () {}, + ) + : const SizedBox(), + ), + Positioned( + left: 0, + right: 0, + top: 0, + child: SizedBox( + height: 128, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: math.max(0, call.participantTracks.length), + itemBuilder: (BuildContext context, int index) { + final track = call.participantTracks[index]; + if (track.participant.sid == + call.focusTrack.value?.participant.sid) { + return Container(); + } - return Padding( - padding: const EdgeInsets.only(top: 8, left: 8), - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(8)), - child: InteractiveParticipantWidget( - isFixed: true, - width: 120, - height: 120, - color: Theme.of(context).cardColor, - participant: track, - onTap: () { - if (track.participant.sid != - call.focusTrack.value?.participant.sid) { - call.changeFocusTrack(track); - } - }, + return Padding( + padding: const EdgeInsets.only(top: 8, left: 8), + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(8)), + child: InteractiveParticipantWidget( + isFixedAvatar: true, + width: 120, + height: 120, + color: Theme.of(context).cardColor, + participant: track, + onTap: () { + if (track.participant.sid != + call.focusTrack.value?.participant.sid) { + call.changeFocusTrack(track); + } + }, + ), ), - ), - ); - }, + ); + }, + ), ), ), - ), - ], + ], + ), ); } Widget _buildGridLayout() { final ChatCallProvider call = Get.find(); - return LayoutBuilder( - builder: (context, constraints) { - double screenWidth = constraints.maxWidth; - double screenHeight = constraints.maxHeight; + return LayoutBuilder(builder: (context, constraints) { + double screenWidth = constraints.maxWidth; + double screenHeight = constraints.maxHeight; - int columns = (math.sqrt(call.participantTracks.length)).ceil(); - int rows = (call.participantTracks.length / columns).ceil(); + int columns = (math.sqrt(call.participantTracks.length)).ceil(); + int rows = (call.participantTracks.length / columns).ceil(); - double tileWidth = screenWidth / columns; - double tileHeight = screenHeight / rows; + double tileWidth = screenWidth / columns; + double tileHeight = screenHeight / rows; - return GridView.builder( + return Obx( + () => GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: columns, childAspectRatio: tileWidth / tileHeight, @@ -165,25 +167,26 @@ class _CallScreenState extends State with TickerProviderStateMixin { final track = call.participantTracks[index]; return Padding( padding: const EdgeInsets.all(16), - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(8)), - child: InteractiveParticipantWidget( - isFixed: true, - color: Theme.of(context).colorScheme.surfaceContainerLow, - participant: track, - onTap: () { - if (track.participant.sid != - call.focusTrack.value?.participant.sid) { - call.changeFocusTrack(track); - } - }, + child: Card( + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(8)), + child: InteractiveParticipantWidget( + color: Theme.of(context).colorScheme.surfaceContainerHigh, + participant: track, + onTap: () { + if (track.participant.sid != + call.focusTrack.value?.participant.sid) { + call.changeFocusTrack(track); + } + }, + ), ), ), ); }, - ); - } - ); + ), + ); + }); } @override @@ -234,31 +237,33 @@ class _CallScreenState extends State with TickerProviderStateMixin { body: SafeArea( child: GestureDetector( behavior: HitTestBehavior.translucent, - child: Obx( - () => Column( - children: [ - SizeTransition( - sizeFactor: _controlsAnimation, - axis: Axis.vertical, - child: SizedBox( - width: MediaQuery.of(context).size.width, - height: 64, - child: Row( - children: [ - const Expanded(child: SizedBox()), - IconButton( - icon: _layoutMode == 0 - ? const Icon(Icons.view_list) - : const Icon(Icons.grid_view), - onPressed: () { - _switchLayout(); - }, - ), - ], - ).paddingSymmetric(horizontal: 10), - ), + child: Column( + children: [ + SizeTransition( + sizeFactor: _controlsAnimation, + axis: Axis.vertical, + child: SizedBox( + width: MediaQuery.of(context).size.width, + height: 64, + child: Row( + children: [ + const Expanded(child: SizedBox()), + IconButton( + icon: _layoutMode == 0 + ? const Icon(Icons.view_list) + : const Icon(Icons.grid_view), + onPressed: () { + _switchLayout(); + }, + ), + ], + ).paddingSymmetric(horizontal: 10), ), - Expanded( + ), + Expanded( + child: Material( + color: Theme.of(context).colorScheme.surfaceContainerLow, + elevation: 2, child: Builder( builder: (context) { switch (_layoutMode) { @@ -270,20 +275,20 @@ class _CallScreenState extends State with TickerProviderStateMixin { }, ), ), - if (provider.room.localParticipant != null) - SizeTransition( - sizeFactor: _controlsAnimation, - axis: Axis.vertical, - child: SizedBox( - width: MediaQuery.of(context).size.width, - child: ControlsWidget( - provider.room, - provider.room.localParticipant!, - ), + ), + if (provider.room.localParticipant != null) + SizeTransition( + sizeFactor: _controlsAnimation, + axis: Axis.vertical, + child: SizedBox( + width: MediaQuery.of(context).size.width, + child: ControlsWidget( + provider.room, + provider.room.localParticipant!, ), ), - ], - ), + ), + ], ), onTap: () { _toggleControls(); diff --git a/lib/widgets/chat/call/call_participant.dart b/lib/widgets/chat/call/call_participant.dart index 476a66d..8b43a20 100644 --- a/lib/widgets/chat/call/call_participant.dart +++ b/lib/widgets/chat/call/call_participant.dart @@ -201,7 +201,7 @@ class InteractiveParticipantWidget extends StatelessWidget { final double? width; final double? height; final Color? color; - final bool isFixed; + final bool isFixedAvatar; final ParticipantTrack participant; final Function() onTap; @@ -210,7 +210,7 @@ class InteractiveParticipantWidget extends StatelessWidget { this.width, this.height, this.color, - this.isFixed = false, + this.isFixedAvatar = false, required this.participant, required this.onTap, }); @@ -222,7 +222,7 @@ class InteractiveParticipantWidget extends StatelessWidget { width: width, height: height, color: color, - child: ParticipantWidget.widgetFor(participant, isFixed: isFixed), + child: ParticipantWidget.widgetFor(participant, isFixed: isFixedAvatar), ), onTap: () => onTap(), onLongPress: () { diff --git a/pubspec.lock b/pubspec.lock index 2324e5b..d3b2f2f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -261,10 +261,10 @@ packages: dependency: transitive description: name: cross_file - sha256: "55d7b444feb71301ef6b8838dbc1ae02e63dd48c8773f3810ff53bb1e2945b32" + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" url: "https://pub.dev" source: hosted - version: "0.3.4+1" + version: "0.3.4+2" crypto: dependency: "direct main" description: @@ -684,10 +684,10 @@ packages: dependency: "direct main" description: name: flutter_webrtc - sha256: d305793e6737c59a81c45b18484e1f985710827704eeb9092573387efcbae272 + sha256: f46bd76cef6e8d787dc707d0c591f0e89c912a2970c7b5e68a55b9cca1bdde4c url: "https://pub.dev" source: hosted - version: "0.11.5" + version: "0.11.6" font_awesome_flutter: dependency: "direct main" description: @@ -732,10 +732,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "39dd52168d6c59984454183148dc3a5776960c61083adfc708cc79a7b3ce1ba8" + sha256: d380de0355788c5c784fe9f81b43fc833b903991c25ecc4e2a416a67faefa722 url: "https://pub.dev" source: hosted - version: "14.2.1" + version: "14.2.2" graphs: dependency: transitive description: @@ -820,10 +820,10 @@ packages: dependency: transitive description: name: image_picker_for_web - sha256: "5d6eb13048cd47b60dbf1a5495424dea226c5faf3950e20bf8120a58efb5b5f3" + sha256: "65d94623e15372c5c51bebbcb820848d7bcb323836e12dfdba60b5d3a8b39e50" url: "https://pub.dev" source: hosted - version: "3.0.4" + version: "3.0.5" image_picker_ios: dependency: transitive description: @@ -948,10 +948,10 @@ packages: dependency: "direct main" description: name: livekit_client - sha256: e6b1e8a3cdcae95f7e62c0371590648444bac245fce3a1bcfb4ec05889ad82f3 + sha256: be2a3375851a6147d5de94a870edd6e831ab8d3d793e3563ba1ff1b05490b3de url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" logging: dependency: transitive description: @@ -1524,10 +1524,10 @@ packages: dependency: transitive description: name: shared_preferences_web - sha256: "3a293170d4d9403c3254ee05b84e62e8a9b3c5808ebd17de6a33fe9ea6457936" + sha256: "59dc807b94d29d52ddbb1b3c0d3b9d0a67fc535a64e62a5542c8db0513fcb6c2" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.4.1" shared_preferences_windows: dependency: transitive description: @@ -1809,10 +1809,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "8d9e750d8c9338601e709cd0885f95825086bd8b642547f26bda435aade95d8a" + sha256: a36e2d7981122fa185006b216eb6b5b97ede3f9a54b7a511bc966971ab98d049 url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" url_launcher_windows: dependency: transitive description: