Compare commits

..

No commits in common. "4238ea6fdc1d009d0a64578cfd42522e5eaa5bce" and "7e8993fbd2b388626bbedcdfb9151aae80cc6301" have entirely different histories.

3 changed files with 116 additions and 204 deletions

View File

@ -21,8 +21,6 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
Timer? _timer; Timer? _timer;
String _currentDuration = '00:00:00'; String _currentDuration = '00:00:00';
int _layoutMode = 0;
bool _showControls = true; bool _showControls = true;
CancelableOperation? _hideControlsOperation; CancelableOperation? _hideControlsOperation;
@ -56,14 +54,6 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
}); });
} }
void _switchLayout() {
if (_layoutMode < 1) {
setState(() => _layoutMode++);
} else {
setState(() => _layoutMode = 0);
}
}
void _toggleControls() { void _toggleControls() {
if (_showControls) { if (_showControls) {
setState(() => _showControls = false); setState(() => _showControls = false);
@ -85,107 +75,6 @@ class _CallScreenState extends State<CallScreen> 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 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);
}
},
),
),
);
},
),
),
),
],
);
}
Widget _buildGridLayout() {
final ChatCallProvider call = Get.find();
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();
double tileWidth = screenWidth / columns;
double tileHeight = screenHeight / rows;
return GridView.builder(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: columns,
childAspectRatio: tileWidth / tileHeight,
),
itemCount: math.max(0, call.participantTracks.length),
itemBuilder: (BuildContext context, int index) {
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);
}
},
),
),
);
},
);
}
);
}
@override @override
void initState() { void initState() {
Get.find<ChatCallProvider>().setupRoom(); Get.find<ChatCallProvider>().setupRoom();
@ -235,53 +124,78 @@ class _CallScreenState extends State<CallScreen> with TickerProviderStateMixin {
child: GestureDetector( child: GestureDetector(
behavior: HitTestBehavior.translucent, behavior: HitTestBehavior.translucent,
child: Obx( child: Obx(
() => Column( () => Stack(
children: [ children: [
SizeTransition( Column(
sizeFactor: _controlsAnimation, children: [
axis: Axis.vertical, Expanded(
child: SizedBox( child: Container(
width: MediaQuery.of(context).size.width, color: Theme.of(context).colorScheme.surfaceContainer,
height: 64, child: provider.focusTrack.value != null
child: Row( ? InteractiveParticipantWidget(
children: [ isFixed: false,
const Expanded(child: SizedBox()), participant: provider.focusTrack.value!,
IconButton( onTap: () {},
icon: _layoutMode == 0 )
? const Icon(Icons.view_list) : const SizedBox(),
: const Icon(Icons.grid_view),
onPressed: () {
_switchLayout();
},
),
],
).paddingSymmetric(horizontal: 10),
),
),
Expanded(
child: Builder(
builder: (context) {
switch (_layoutMode) {
case 1:
return _buildGridLayout();
default:
return _buildListLayout();
}
},
),
),
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!,
),
),
),
],
),
Positioned(
left: 0,
right: 0,
top: 0,
child: SizedBox(
height: 128,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount:
math.max(0, provider.participantTracks.length),
itemBuilder: (BuildContext context, int index) {
final track = provider.participantTracks[index];
if (track.participant.sid ==
provider.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 !=
provider
.focusTrack.value?.participant.sid) {
provider.changeFocusTrack(track);
}
},
),
),
);
},
),
), ),
),
], ],
), ),
), ),

View File

@ -217,25 +217,28 @@ class InteractiveParticipantWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return GestureDetector( return Material(
child: Container( color: Colors.transparent,
width: width, child: GestureDetector(
height: height, child: Container(
color: color, width: width,
child: ParticipantWidget.widgetFor(participant, isFixed: isFixed), height: height,
color: color,
child: ParticipantWidget.widgetFor(participant, isFixed: isFixed),
),
onTap: () => onTap(),
onLongPress: () {
if (participant.participant is LocalParticipant) return;
showModalBottomSheet(
context: context,
builder: (context) => ParticipantMenu(
participant: participant.participant as RemoteParticipant,
videoTrack: participant.videoTrack,
isScreenShare: participant.isScreenShare,
),
);
},
), ),
onTap: () => onTap(),
onLongPress: () {
if (participant.participant is LocalParticipant) return;
showModalBottomSheet(
context: context,
builder: (context) => ParticipantMenu(
participant: participant.participant as RemoteParticipant,
videoTrack: participant.videoTrack,
isScreenShare: participant.isScreenShare,
),
);
},
); );
} }
} }

View File

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:livekit_client/livekit_client.dart'; import 'package:livekit_client/livekit_client.dart';
class ParticipantInfoWidget extends StatelessWidget { class ParticipantInfoWidget extends StatelessWidget {
@ -35,42 +34,38 @@ class ParticipantInfoWidget extends StatelessWidget {
style: const TextStyle(color: Colors.white), style: const TextStyle(color: Colors.white),
), ),
), ),
const SizedBox(width: 5),
isScreenShare isScreenShare
? const Icon( ? const Padding(
Icons.monitor, padding: EdgeInsets.only(left: 5),
color: Colors.white, child: Icon(
size: 16, Icons.monitor,
color: Colors.white,
size: 16,
),
) )
: Icon( : Padding(
audioAvailable ? Icons.mic : Icons.mic_off, padding: const EdgeInsets.only(left: 5),
color: audioAvailable ? Colors.white : Colors.red, child: Icon(
size: 16, audioAvailable ? Icons.mic : Icons.mic_off,
color: audioAvailable ? Colors.white : Colors.red,
size: 16,
),
), ),
const SizedBox(width: 3),
if (connectionQuality != ConnectionQuality.unknown) if (connectionQuality != ConnectionQuality.unknown)
Icon( Padding(
{ padding: const EdgeInsets.only(left: 5),
ConnectionQuality.excellent: Icons.signal_cellular_alt, child: Icon(
ConnectionQuality.good: Icons.signal_cellular_alt_2_bar, connectionQuality == ConnectionQuality.poor
ConnectionQuality.poor: Icons.signal_cellular_alt_1_bar, ? Icons.wifi_off_outlined
}[connectionQuality], : Icons.wifi,
color: { color: {
ConnectionQuality.excellent: Colors.green, ConnectionQuality.excellent: Colors.green,
ConnectionQuality.good: Colors.orange, ConnectionQuality.good: Colors.orange,
ConnectionQuality.poor: Colors.red, ConnectionQuality.poor: Colors.red,
}[connectionQuality], }[connectionQuality],
size: 16, size: 16,
)
else
const SizedBox(
width: 12,
height: 12,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
), ),
).paddingAll(3), ),
], ],
), ),
); );