From 61b870864a10286fde3f838a0d6d8d171a897402 Mon Sep 17 00:00:00 2001 From: cloudwebrtc Date: Fri, 25 Oct 2024 23:07:12 +0800 Subject: [PATCH] chore: Optimize layout for mobile. --- example/lib/main.dart | 26 ++++++++++++++----- lib/livekit_components.dart | 1 + lib/src/context/chat_context.dart | 9 ++----- lib/src/ui/layout/garousel_ayout.dart | 8 +++--- lib/src/ui/layout/grid_layout.dart | 6 ++++- lib/src/ui/prejoin/prejoin.dart | 8 ++++-- lib/src/ui/widgets/room/clear_pin_button.dart | 26 +++++++++++++++++++ lib/src/ui/widgets/room/control_bar.dart | 3 +-- lib/src/ui/widgets/track/focus_toggle.dart | 14 +++++++--- 9 files changed, 76 insertions(+), 25 deletions(-) create mode 100644 lib/src/ui/widgets/room/clear_pin_button.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 03f9218..c436cbb 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -70,6 +70,14 @@ class MyHomePage extends StatelessWidget { builder: (context, roomCtx) { var deviceScreenType = getDeviceType(MediaQuery.of(context).size); return Scaffold( + appBar: AppBar( + title: const Text('LiveKit Components', + style: TextStyle(color: Colors.white)), + actions: [ + /// show clear pin button + if (roomCtx.connected) const ClearPinButton(), + ], + ), body: Stack( children: [ !roomCtx.connected && !roomCtx.connecting @@ -97,7 +105,7 @@ class MyHomePage extends StatelessWidget { onSend: (message) => chatCtx.sendMessage(message), onClose: () { - chatCtx.disableChat(); + chatCtx.toggleChat(false); }, ); }, @@ -105,8 +113,7 @@ class MyHomePage extends StatelessWidget { ) : Expanded( flex: 5, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, + child: Stack( children: [ Expanded( /// show participant loop @@ -152,8 +159,8 @@ class MyHomePage extends StatelessWidget { /// track stats at the bottom right const Positioned( - bottom: 30, - right: 0, + top: 8, + left: 0, child: TrackStatsWidget(), ), @@ -167,7 +174,12 @@ class MyHomePage extends StatelessWidget { ), /// show control bar at the bottom - const ControlBar(), + const Positioned( + bottom: 30, + left: 0, + right: 0, + child: ControlBar(), + ), ], ), ), @@ -187,7 +199,7 @@ class MyHomePage extends StatelessWidget { onSend: (message) => chatCtx.sendMessage(message), onClose: () { - chatCtx.disableChat(); + chatCtx.toggleChat(false); }, ); }, diff --git a/lib/livekit_components.dart b/lib/livekit_components.dart index a0d60e0..c517f67 100644 --- a/lib/livekit_components.dart +++ b/lib/livekit_components.dart @@ -49,6 +49,7 @@ export 'src/ui/widgets/room/microphone_select_button.dart'; export 'src/ui/widgets/room/control_bar.dart'; export 'src/ui/widgets/room/disconnect_button.dart'; export 'src/ui/widgets/room/screenshare_toggle.dart'; +export 'src/ui/widgets/room/clear_pin_button.dart'; export 'src/ui/widgets/track/focus_toggle.dart'; export 'src/ui/widgets/track/no_track_widget.dart'; diff --git a/lib/src/context/chat_context.dart b/lib/src/context/chat_context.dart index 5a0822f..bc6f979 100644 --- a/lib/src/context/chat_context.dart +++ b/lib/src/context/chat_context.dart @@ -99,13 +99,8 @@ mixin ChatContextMixin on ChangeNotifier { bool _chatEnabled = false; bool get isChatEnabled => _chatEnabled; - void enableChat() { - _chatEnabled = true; - notifyListeners(); - } - - void disableChat() { - _chatEnabled = false; + void toggleChat(bool enabled) { + _chatEnabled = enabled; notifyListeners(); } } diff --git a/lib/src/ui/layout/garousel_ayout.dart b/lib/src/ui/layout/garousel_ayout.dart index f5b5d08..daa0e48 100644 --- a/lib/src/ui/layout/garousel_ayout.dart +++ b/lib/src/ui/layout/garousel_ayout.dart @@ -29,13 +29,15 @@ class CarouselLayoutBuilder implements ParticipantLayoutBuilder { } var deviceScreenType = getDeviceType(MediaQuery.of(context).size); - if (deviceScreenType == DeviceScreenType.mobile) { + var orientation = MediaQuery.of(context).orientation; + var isMobile = deviceScreenType == DeviceScreenType.mobile; + if (isMobile && orientation == Orientation.portrait) { return Column( mainAxisAlignment: MainAxisAlignment.start, children: [ if (children.length > 1) SizedBox( - height: 80, + height: 120, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: math.max(0, otherWidgets.length), @@ -56,7 +58,7 @@ class CarouselLayoutBuilder implements ParticipantLayoutBuilder { children: [ if (children.length > 1) SizedBox( - width: 180, + width: isMobile && orientation == Orientation.landscape ? 120 : 180, child: ListView.builder( scrollDirection: Axis.vertical, itemCount: math.max(0, otherWidgets.length), diff --git a/lib/src/ui/layout/grid_layout.dart b/lib/src/ui/layout/grid_layout.dart index 6ee0438..8e3edec 100644 --- a/lib/src/ui/layout/grid_layout.dart +++ b/lib/src/ui/layout/grid_layout.dart @@ -11,8 +11,12 @@ class GridLayoutBuilder implements ParticipantLayoutBuilder { Widget build( BuildContext context, List children, List? pinned) { var deviceScreenType = getDeviceType(MediaQuery.of(context).size); + var orientation = MediaQuery.of(context).orientation; return GridView.count( - crossAxisCount: deviceScreenType == DeviceScreenType.mobile ? 2 : 4, + crossAxisCount: deviceScreenType == DeviceScreenType.mobile && + orientation == Orientation.portrait + ? 2 + : 4, childAspectRatio: 1.5, children: [ if (pinned != null) ...pinned, diff --git a/lib/src/ui/prejoin/prejoin.dart b/lib/src/ui/prejoin/prejoin.dart index 2184659..e99ba2d 100644 --- a/lib/src/ui/prejoin/prejoin.dart +++ b/lib/src/ui/prejoin/prejoin.dart @@ -75,8 +75,12 @@ class Prejoin extends StatelessWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - MicrophoneSelectButton(), - CameraSelectButton(), + MicrophoneSelectButton( + showLabels: true, + ), + CameraSelectButton( + showLabels: true, + ), ], )), ), diff --git a/lib/src/ui/widgets/room/clear_pin_button.dart b/lib/src/ui/widgets/room/clear_pin_button.dart new file mode 100644 index 0000000..4befa19 --- /dev/null +++ b/lib/src/ui/widgets/room/clear_pin_button.dart @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; + +import 'package:provider/provider.dart'; + +import '../../../context/room_context.dart'; + +class ClearPinButton extends StatelessWidget { + const ClearPinButton({ + super.key, + }); + + @override + Widget build(BuildContext context) { + final roomCtx = context.read(); + return Padding( + padding: const EdgeInsets.all(2), + child: IconButton( + icon: Icon(Icons.grid_view), + color: Colors.white70, + onPressed: () { + roomCtx.clearPinnedTracks(); + }, + ), + ); + } +} diff --git a/lib/src/ui/widgets/room/control_bar.dart b/lib/src/ui/widgets/room/control_bar.dart index e0eb074..0352b49 100644 --- a/lib/src/ui/widgets/room/control_bar.dart +++ b/lib/src/ui/widgets/room/control_bar.dart @@ -106,8 +106,7 @@ class ControlBar extends StatelessWidget { ChatToggle( builder: (context, roomCtx, isChatEnabled) => ChatToggleWidget( isChatOpen: roomCtx.isChatEnabled, - toggleChat: (enabled) => - enabled ? roomCtx.enableChat() : roomCtx.disableChat(), + toggleChat: (enabled) => roomCtx.toggleChat(enabled), showLabel: showLabels, ), ), diff --git a/lib/src/ui/widgets/track/focus_toggle.dart b/lib/src/ui/widgets/track/focus_toggle.dart index e7c4d23..b2c7a1f 100644 --- a/lib/src/ui/widgets/track/focus_toggle.dart +++ b/lib/src/ui/widgets/track/focus_toggle.dart @@ -9,8 +9,11 @@ import '../../../debug/logger.dart'; class FocusToggle extends StatelessWidget { const FocusToggle({ super.key, + this.showBackToGridView = false, }); + final bool showBackToGridView; + @override Widget build(BuildContext context) { final roomCtx = context.read(); @@ -20,19 +23,24 @@ class FocusToggle extends StatelessWidget { if (trackCtx == null) { return const SizedBox(); } - var showBackToGridView = + var shouldShowBackToGridView = roomCtx.pinnedTracks.contains(sid) && sid == roomCtx.pinnedTracks.first; + if (shouldShowBackToGridView && !showBackToGridView) { + return const SizedBox(); + } + return Padding( padding: const EdgeInsets.all(2), child: IconButton( - icon: Icon(showBackToGridView ? Icons.grid_view : Icons.open_in_full), + icon: Icon( + shouldShowBackToGridView ? Icons.grid_view : Icons.open_in_full), color: Colors.white70, onPressed: () { if (sid == null) { return; } - if (showBackToGridView) { + if (shouldShowBackToGridView) { roomCtx.clearPinnedTracks(); } else { roomCtx.pinningTrack(sid);