example app design update & show active speaker

This commit is contained in:
Hiroshi Horie
2021-10-25 02:08:26 +09:00
parent 6d4f32233f
commit d065c2eb97
11 changed files with 314 additions and 160 deletions
+64 -46
View File
@@ -151,56 +151,74 @@ class _ControlsWidgetState extends State<ControlsWidget> {
final videoPub = participant.videoTracks.firstOrNull;
final videoEnabled = videoPub != null && !videoPub.muted;
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
IconButton(
onPressed: _unpublishAll,
icon: const Icon(EvaIcons.closeCircleOutline),
),
if (canMute)
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 15,
horizontal: 15,
),
child: Wrap(
alignment: WrapAlignment.center,
spacing: 5,
runSpacing: 5,
children: [
IconButton(
onPressed: _muteAudio,
icon: const Icon(EvaIcons.mic),
)
else
IconButton(
onPressed: _unmuteAudio,
icon: const Icon(EvaIcons.micOff),
onPressed: _unpublishAll,
icon: const Icon(EvaIcons.closeCircleOutline),
tooltip: 'Unpublish all',
),
if (videoEnabled)
if (canMute)
IconButton(
onPressed: _muteAudio,
icon: const Icon(EvaIcons.mic),
tooltip: 'mute audio',
)
else
IconButton(
onPressed: _unmuteAudio,
icon: const Icon(EvaIcons.micOff),
tooltip: 'un-mute audio',
),
if (videoEnabled)
IconButton(
onPressed: _muteVideo,
icon: const Icon(EvaIcons.video),
tooltip: 'mute video',
)
else
IconButton(
onPressed: _unmuteVideo,
icon: const Icon(EvaIcons.videoOff),
tooltip: 'un-mute video',
),
IconButton(
onPressed: _muteVideo,
icon: const Icon(EvaIcons.video),
)
else
IconButton(
onPressed: _unmuteVideo,
icon: const Icon(EvaIcons.videoOff),
icon: Icon(position == CameraPosition.back
? EvaIcons.camera
: EvaIcons.person),
onPressed: () => _toggleCamera(),
tooltip: 'toggle camera',
),
IconButton(
icon: Icon(position == CameraPosition.back
? EvaIcons.camera
: EvaIcons.person),
onPressed: () => _toggleCamera(),
),
IconButton(
icon: const Icon(EvaIcons.monitor),
onPressed: () => _shareScreen(),
),
IconButton(
onPressed: _onTapDisconnect,
icon: const Icon(EvaIcons.closeCircle),
),
IconButton(
onPressed: _onTapSendData,
icon: const Icon(EvaIcons.paperPlane),
),
IconButton(
onPressed: _onTapReconnect,
icon: const Icon(EvaIcons.refresh),
),
],
IconButton(
icon: const Icon(EvaIcons.monitor),
onPressed: () => _shareScreen(),
tooltip: 'share screen (experimental)',
),
IconButton(
onPressed: _onTapDisconnect,
icon: const Icon(EvaIcons.closeCircle),
tooltip: 'disconnect',
),
IconButton(
onPressed: _onTapSendData,
icon: const Icon(EvaIcons.paperPlane),
tooltip: 'send demo data',
),
IconButton(
onPressed: _onTapReconnect,
icon: const Icon(EvaIcons.refresh),
tooltip: 're-connect',
),
],
),
);
}
}
+3 -1
View File
@@ -2,6 +2,8 @@ import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'package:livekit_example/theme.dart';
class NoVideoWidget extends StatelessWidget {
//
const NoVideoWidget({Key? key}) : super(key: key);
@@ -12,7 +14,7 @@ class NoVideoWidget extends StatelessWidget {
child: LayoutBuilder(
builder: (ctx, constraints) => Icon(
EvaIcons.videoOffOutline,
color: Theme.of(ctx).colorScheme.secondary,
color: LKColors.lkBlue,
size: math.min(constraints.maxHeight, constraints.maxWidth) * 0.3,
),
),
+12 -1
View File
@@ -3,6 +3,7 @@ import 'package:eva_icons_flutter/eva_icons_flutter.dart';
import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:livekit_client/livekit_client.dart';
import 'package:livekit_example/theme.dart';
import 'no_video.dart';
import 'participant_info.dart';
@@ -64,7 +65,17 @@ class _ParticipantWidgetState extends State<ParticipantWidget> {
@override
Widget build(BuildContext ctx) => Container(
color: Theme.of(ctx).cardColor,
foregroundDecoration: BoxDecoration(
border: widget.participant.isSpeaking
? Border.all(
width: 5,
color: LKColors.lkBlue,
)
: null,
),
decoration: BoxDecoration(
color: Theme.of(ctx).cardColor,
),
child: Stack(
children: [
// Video
+48
View File
@@ -0,0 +1,48 @@
import 'package:flutter/material.dart';
class LKTextField extends StatelessWidget {
final String label;
final TextEditingController? ctrl;
const LKTextField({
required this.label,
this.ctrl,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) => Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text(
label,
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Container(
padding: const EdgeInsets.symmetric(
vertical: 15,
horizontal: 15,
),
decoration: BoxDecoration(
border: Border.all(
width: 1,
color: Colors.white.withOpacity(.3),
),
borderRadius: BorderRadius.circular(8),
),
child: TextField(
controller: ctrl,
decoration: const InputDecoration.collapsed(
hintText: '',
),
keyboardType: TextInputType.url,
),
),
],
);
}