Compare commits
No commits in common. "3585941ccb8e96b75c2b9f7ce08f00f975ef6bcd" and "61dbf9290997d4db57c5f9d1bd3ed20e3e3a9a0b" have entirely different histories.
3585941ccb
...
61dbf92909
@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:livekit_client/livekit_client.dart';
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
import 'package:livekit_noise_filter/livekit_noise_filter.dart';
|
|
||||||
import 'package:permission_handler/permission_handler.dart';
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:surface/providers/sn_network.dart';
|
import 'package:surface/providers/sn_network.dart';
|
||||||
@ -132,14 +131,10 @@ class ChatCallProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
void initRoom() {
|
void initRoom() {
|
||||||
initHardware();
|
initHardware();
|
||||||
final timeout = const Duration(seconds: 60);
|
|
||||||
_room = Room(
|
_room = Room(
|
||||||
roomOptions: RoomOptions(
|
roomOptions: const RoomOptions(
|
||||||
dynacast: true,
|
dynacast: true,
|
||||||
adaptiveStream: true,
|
adaptiveStream: true,
|
||||||
defaultAudioCaptureOptions: AudioCaptureOptions(
|
|
||||||
processor: LiveKitNoiseFilter(),
|
|
||||||
),
|
|
||||||
defaultAudioPublishOptions: AudioPublishOptions(
|
defaultAudioPublishOptions: AudioPublishOptions(
|
||||||
name: 'call_voice',
|
name: 'call_voice',
|
||||||
stream: 'call_stream',
|
stream: 'call_stream',
|
||||||
@ -159,16 +154,6 @@ class ChatCallProvider extends ChangeNotifier {
|
|||||||
params: VideoParametersPresets.h1080_169,
|
params: VideoParametersPresets.h1080_169,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
connectOptions: ConnectOptions(
|
|
||||||
autoSubscribe: true,
|
|
||||||
timeouts: Timeouts(
|
|
||||||
connection: timeout,
|
|
||||||
debounce: timeout,
|
|
||||||
publish: timeout,
|
|
||||||
peerConnection: timeout,
|
|
||||||
iceRestart: timeout,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
_listener = _room.createListener();
|
_listener = _room.createListener();
|
||||||
WakelockPlus.enable();
|
WakelockPlus.enable();
|
||||||
|
@ -32,7 +32,7 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMeetLayout() {
|
Widget _buildListLayout() {
|
||||||
final call = context.read<ChatCallProvider>();
|
final call = context.read<ChatCallProvider>();
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
@ -41,7 +41,9 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
|
|||||||
Theme.of(context).colorScheme.surfaceContainer.withOpacity(0.75),
|
Theme.of(context).colorScheme.surfaceContainer.withOpacity(0.75),
|
||||||
child: call.focusTrack != null
|
child: call.focusTrack != null
|
||||||
? InteractiveParticipantWidget(
|
? InteractiveParticipantWidget(
|
||||||
|
isFixedAvatar: false,
|
||||||
participant: call.focusTrack!,
|
participant: call.focusTrack!,
|
||||||
|
onTap: () {},
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
@ -60,18 +62,23 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
|
|||||||
return Container();
|
return Container();
|
||||||
}
|
}
|
||||||
|
|
||||||
return SizedBox(
|
return Padding(
|
||||||
height: 128,
|
padding: const EdgeInsets.only(top: 8, left: 8),
|
||||||
width: 128,
|
child: ClipRRect(
|
||||||
child: InteractiveParticipantWidget(
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
participant: track,
|
child: InteractiveParticipantWidget(
|
||||||
avatarSize: 32,
|
isFixedAvatar: true,
|
||||||
onTap: () {
|
width: 120,
|
||||||
if (track.participant.sid !=
|
height: 120,
|
||||||
call.focusTrack?.participant.sid) {
|
color: Theme.of(context).cardColor,
|
||||||
call.setFocusTrack(track);
|
participant: track,
|
||||||
}
|
onTap: () {
|
||||||
},
|
if (track.participant.sid !=
|
||||||
|
call.focusTrack?.participant.sid) {
|
||||||
|
call.setFocusTrack(track);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@ -82,26 +89,50 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildListLayout() {
|
Widget _buildGridLayout() {
|
||||||
final call = context.read<ChatCallProvider>();
|
final call = context.read<ChatCallProvider>();
|
||||||
|
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
builder: (context, constraints) {
|
double screenWidth = constraints.maxWidth;
|
||||||
return ListView.builder(
|
double screenHeight = constraints.maxHeight;
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
itemCount: math.max(0, call.participantTracks.length),
|
int columns = (math.sqrt(call.participantTracks.length)).ceil();
|
||||||
itemBuilder: (BuildContext context, int index) {
|
int rows = (call.participantTracks.length / columns).ceil();
|
||||||
final track = call.participantTracks[index];
|
|
||||||
return InteractiveParticipantWidget(
|
double tileWidth = screenWidth / columns;
|
||||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
double tileHeight = screenHeight / rows;
|
||||||
isList: true,
|
|
||||||
avatarSize: 24,
|
return StyledWidget(GridView.builder(
|
||||||
participant: track,
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
);
|
crossAxisCount: columns,
|
||||||
},
|
childAspectRatio: tileWidth / tileHeight,
|
||||||
);
|
crossAxisSpacing: 8,
|
||||||
},
|
mainAxisSpacing: 8,
|
||||||
);
|
),
|
||||||
|
itemCount: math.max(0, call.participantTracks.length),
|
||||||
|
itemBuilder: (BuildContext context, int index) {
|
||||||
|
final track = call.participantTracks[index];
|
||||||
|
return Card(
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
child: InteractiveParticipantWidget(
|
||||||
|
color: Theme.of(context)
|
||||||
|
.colorScheme
|
||||||
|
.surfaceContainerHigh
|
||||||
|
.withOpacity(0.75),
|
||||||
|
participant: track,
|
||||||
|
onTap: () {
|
||||||
|
if (track.participant.sid !=
|
||||||
|
call.focusTrack?.participant.sid) {
|
||||||
|
call.setFocusTrack(track);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)).padding(all: 8);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -145,129 +176,131 @@ class _CallRoomScreenState extends State<CallRoomScreen> {
|
|||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: Column(
|
body: GestureDetector(
|
||||||
children: [
|
behavior: HitTestBehavior.translucent,
|
||||||
SizedBox(
|
child: Column(
|
||||||
width: MediaQuery.of(context).size.width,
|
children: [
|
||||||
height: 64,
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Builder(builder: (context) {
|
|
||||||
final call = context.read<ChatCallProvider>();
|
|
||||||
final connectionQuality =
|
|
||||||
call.room.localParticipant?.connectionQuality ??
|
|
||||||
livekit.ConnectionQuality.unknown;
|
|
||||||
return Expanded(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
call.channel?.name ?? 'unknown'.tr(),
|
|
||||||
style: const TextStyle(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Gap(6),
|
|
||||||
Text(call.lastDuration.toString())
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
{
|
|
||||||
livekit.ConnectionState.disconnected:
|
|
||||||
'callStatusDisconnected'.tr(),
|
|
||||||
livekit.ConnectionState.connected:
|
|
||||||
'callStatusConnected'.tr(),
|
|
||||||
livekit.ConnectionState.connecting:
|
|
||||||
'callStatusConnecting'.tr(),
|
|
||||||
livekit.ConnectionState.reconnecting:
|
|
||||||
'callStatusReconnecting'.tr(),
|
|
||||||
}[call.room.connectionState]!,
|
|
||||||
),
|
|
||||||
const Gap(6),
|
|
||||||
if (connectionQuality !=
|
|
||||||
livekit.ConnectionQuality.unknown)
|
|
||||||
Icon(
|
|
||||||
{
|
|
||||||
livekit.ConnectionQuality.excellent:
|
|
||||||
Icons.signal_cellular_alt,
|
|
||||||
livekit.ConnectionQuality.good:
|
|
||||||
Icons.signal_cellular_alt_2_bar,
|
|
||||||
livekit.ConnectionQuality.poor:
|
|
||||||
Icons.signal_cellular_alt_1_bar,
|
|
||||||
}[connectionQuality],
|
|
||||||
color: {
|
|
||||||
livekit.ConnectionQuality.excellent:
|
|
||||||
Colors.green,
|
|
||||||
livekit.ConnectionQuality.good:
|
|
||||||
Colors.orange,
|
|
||||||
livekit.ConnectionQuality.poor:
|
|
||||||
Colors.red,
|
|
||||||
}[connectionQuality],
|
|
||||||
size: 16,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
height: 12,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
color: Colors.white,
|
|
||||||
strokeWidth: 2,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
),
|
|
||||||
).padding(all: 3),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: _layoutMode == 0
|
|
||||||
? const Icon(Icons.view_list)
|
|
||||||
: const Icon(Icons.grid_view),
|
|
||||||
onPressed: () {
|
|
||||||
_switchLayout();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(left: 20, right: 16),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Material(
|
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerLow,
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) {
|
|
||||||
switch (_layoutMode) {
|
|
||||||
case 1:
|
|
||||||
return _buildListLayout();
|
|
||||||
default:
|
|
||||||
return _buildMeetLayout();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (call.room.localParticipant != null)
|
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: MediaQuery.of(context).size.width,
|
width: MediaQuery.of(context).size.width,
|
||||||
child: ControlsWidget(
|
height: 64,
|
||||||
call.room,
|
child: Row(
|
||||||
call.room.localParticipant!,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Builder(builder: (context) {
|
||||||
|
final call = context.read<ChatCallProvider>();
|
||||||
|
final connectionQuality =
|
||||||
|
call.room.localParticipant?.connectionQuality ??
|
||||||
|
livekit.ConnectionQuality.unknown;
|
||||||
|
return Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
call.channel?.name ?? 'unknown'.tr(),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(6),
|
||||||
|
Text(call.lastDuration.toString())
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
{
|
||||||
|
livekit.ConnectionState.disconnected:
|
||||||
|
'callStatusDisconnected'.tr(),
|
||||||
|
livekit.ConnectionState.connected:
|
||||||
|
'callStatusConnected'.tr(),
|
||||||
|
livekit.ConnectionState.connecting:
|
||||||
|
'callStatusConnecting'.tr(),
|
||||||
|
livekit.ConnectionState.reconnecting:
|
||||||
|
'callStatusReconnecting'.tr(),
|
||||||
|
}[call.room.connectionState]!,
|
||||||
|
),
|
||||||
|
const Gap(6),
|
||||||
|
if (connectionQuality !=
|
||||||
|
livekit.ConnectionQuality.unknown)
|
||||||
|
Icon(
|
||||||
|
{
|
||||||
|
livekit.ConnectionQuality.excellent:
|
||||||
|
Icons.signal_cellular_alt,
|
||||||
|
livekit.ConnectionQuality.good:
|
||||||
|
Icons.signal_cellular_alt_2_bar,
|
||||||
|
livekit.ConnectionQuality.poor:
|
||||||
|
Icons.signal_cellular_alt_1_bar,
|
||||||
|
}[connectionQuality],
|
||||||
|
color: {
|
||||||
|
livekit.ConnectionQuality.excellent:
|
||||||
|
Colors.green,
|
||||||
|
livekit.ConnectionQuality.good:
|
||||||
|
Colors.orange,
|
||||||
|
livekit.ConnectionQuality.poor:
|
||||||
|
Colors.red,
|
||||||
|
}[connectionQuality],
|
||||||
|
size: 16,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
height: 12,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Colors.white,
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
|
).padding(all: 3),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: _layoutMode == 0
|
||||||
|
? const Icon(Icons.view_list)
|
||||||
|
: const Icon(Icons.grid_view),
|
||||||
|
onPressed: () {
|
||||||
|
_switchLayout();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(left: 20, right: 16),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Material(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
switch (_layoutMode) {
|
||||||
|
case 1:
|
||||||
|
return _buildGridLayout();
|
||||||
|
default:
|
||||||
|
return _buildListLayout();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Gap(MediaQuery.of(context).padding.bottom),
|
if (call.room.localParticipant != null)
|
||||||
],
|
SizedBox(
|
||||||
|
width: MediaQuery.of(context).size.width,
|
||||||
|
child: ControlsWidget(
|
||||||
|
call.room,
|
||||||
|
call.room.localParticipant!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -54,15 +54,11 @@ class AccountImage extends StatelessWidget {
|
|||||||
))
|
))
|
||||||
.center(),
|
.center(),
|
||||||
)
|
)
|
||||||
: UniversalImage(
|
: AutoResizeUniversalImage(
|
||||||
sn.getAttachmentUrl(url),
|
sn.getAttachmentUrl(url),
|
||||||
filterQuality: filterQuality,
|
filterQuality: filterQuality,
|
||||||
key: Key('attachment-${content.hashCode}'),
|
key: Key('attachment-${content.hashCode}'),
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
width: (radius != null ? radius! : 20) * 2,
|
|
||||||
height: (radius != null ? radius! : 20) * 2,
|
|
||||||
cacheWidth: (radius != null ? radius! : 20) * 2,
|
|
||||||
cacheHeight: (radius != null ? radius! : 20) * 2,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -8,12 +8,12 @@ import 'package:surface/widgets/account/account_image.dart';
|
|||||||
class NoContentWidget extends StatefulWidget {
|
class NoContentWidget extends StatefulWidget {
|
||||||
final SnAccount? userinfo;
|
final SnAccount? userinfo;
|
||||||
final bool isSpeaking;
|
final bool isSpeaking;
|
||||||
final double? avatarSize;
|
final bool isFixed;
|
||||||
|
|
||||||
const NoContentWidget({
|
const NoContentWidget({
|
||||||
super.key,
|
super.key,
|
||||||
this.userinfo,
|
this.userinfo,
|
||||||
this.avatarSize,
|
this.isFixed = false,
|
||||||
required this.isSpeaking,
|
required this.isSpeaking,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -45,35 +45,41 @@ class _NoContentWidgetState extends State<NoContentWidget>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final double radius = widget.avatarSize ??
|
final double radius = widget.isFixed
|
||||||
math.min(
|
? 32
|
||||||
MediaQuery.of(context).size.width * 0.1,
|
: math.min(
|
||||||
MediaQuery.of(context).size.height * 0.1,
|
MediaQuery.of(context).size.width * 0.1,
|
||||||
);
|
MediaQuery.of(context).size.height * 0.1,
|
||||||
|
);
|
||||||
|
|
||||||
return Animate(
|
return Container(
|
||||||
autoPlay: false,
|
alignment: Alignment.center,
|
||||||
controller: _animationController,
|
child: Center(
|
||||||
effects: [
|
child: Animate(
|
||||||
CustomEffect(
|
autoPlay: false,
|
||||||
begin: widget.isSpeaking ? 2 : 0,
|
controller: _animationController,
|
||||||
end: 8,
|
effects: [
|
||||||
curve: Curves.easeInOut,
|
CustomEffect(
|
||||||
duration: 1250.ms,
|
begin: widget.isSpeaking ? 2 : 0,
|
||||||
builder: (context, value, child) => Container(
|
end: 8,
|
||||||
decoration: BoxDecoration(
|
curve: Curves.easeInOut,
|
||||||
borderRadius: BorderRadius.all(Radius.circular(radius + 8)),
|
duration: 1250.ms,
|
||||||
border: value > 0
|
builder: (context, value, child) => Container(
|
||||||
? Border.all(color: Colors.green, width: value)
|
decoration: BoxDecoration(
|
||||||
: null,
|
borderRadius: BorderRadius.all(Radius.circular(radius + 8)),
|
||||||
),
|
border: value > 0
|
||||||
child: child,
|
? Border.all(color: Colors.green, width: value)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
child: AccountImage(
|
||||||
|
content: widget.userinfo?.avatar,
|
||||||
|
radius: radius,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
|
||||||
child: AccountImage(
|
|
||||||
content: widget.userinfo?.avatar,
|
|
||||||
radius: radius,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,7 @@ import 'dart:convert';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
import 'package:flutter_webrtc/flutter_webrtc.dart';
|
||||||
import 'package:gap/gap.dart';
|
|
||||||
import 'package:livekit_client/livekit_client.dart';
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
|
||||||
import 'package:surface/types/account.dart';
|
import 'package:surface/types/account.dart';
|
||||||
import 'package:surface/types/chat.dart';
|
import 'package:surface/types/chat.dart';
|
||||||
import 'package:surface/widgets/chat/call/call_no_content.dart';
|
import 'package:surface/widgets/chat/call/call_no_content.dart';
|
||||||
@ -13,32 +11,23 @@ import 'package:surface/widgets/chat/call/call_participant_menu.dart';
|
|||||||
import 'package:surface/widgets/chat/call/call_participant_stats.dart';
|
import 'package:surface/widgets/chat/call/call_participant_stats.dart';
|
||||||
|
|
||||||
abstract class ParticipantWidget extends StatefulWidget {
|
abstract class ParticipantWidget extends StatefulWidget {
|
||||||
static ParticipantWidget widgetFor(
|
static ParticipantWidget widgetFor(ParticipantTrack participantTrack,
|
||||||
ParticipantTrack participantTrack, {
|
{bool isFixed = false, bool showStatsLayer = false}) {
|
||||||
double? avatarSize,
|
|
||||||
EdgeInsets? padding,
|
|
||||||
bool showStatsLayer = false,
|
|
||||||
bool isList = false,
|
|
||||||
}) {
|
|
||||||
if (participantTrack.participant is LocalParticipant) {
|
if (participantTrack.participant is LocalParticipant) {
|
||||||
return LocalParticipantWidget(
|
return LocalParticipantWidget(
|
||||||
participantTrack.participant as LocalParticipant,
|
participantTrack.participant as LocalParticipant,
|
||||||
participantTrack.videoTrack,
|
participantTrack.videoTrack,
|
||||||
avatarSize,
|
isFixed,
|
||||||
participantTrack.isScreenShare,
|
participantTrack.isScreenShare,
|
||||||
showStatsLayer,
|
showStatsLayer,
|
||||||
isList,
|
|
||||||
padding,
|
|
||||||
);
|
);
|
||||||
} else if (participantTrack.participant is RemoteParticipant) {
|
} else if (participantTrack.participant is RemoteParticipant) {
|
||||||
return RemoteParticipantWidget(
|
return RemoteParticipantWidget(
|
||||||
participantTrack.participant as RemoteParticipant,
|
participantTrack.participant as RemoteParticipant,
|
||||||
participantTrack.videoTrack,
|
participantTrack.videoTrack,
|
||||||
avatarSize,
|
isFixed,
|
||||||
participantTrack.isScreenShare,
|
participantTrack.isScreenShare,
|
||||||
showStatsLayer,
|
showStatsLayer,
|
||||||
isList,
|
|
||||||
padding,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
throw UnimplementedError('Unknown participant type');
|
throw UnimplementedError('Unknown participant type');
|
||||||
@ -47,10 +36,8 @@ abstract class ParticipantWidget extends StatefulWidget {
|
|||||||
abstract final Participant participant;
|
abstract final Participant participant;
|
||||||
abstract final VideoTrack? videoTrack;
|
abstract final VideoTrack? videoTrack;
|
||||||
abstract final bool isScreenShare;
|
abstract final bool isScreenShare;
|
||||||
abstract final double? avatarSize;
|
abstract final bool isFixed;
|
||||||
abstract final bool showStatsLayer;
|
abstract final bool showStatsLayer;
|
||||||
abstract final bool isList;
|
|
||||||
abstract final EdgeInsets? padding;
|
|
||||||
final VideoQuality quality;
|
final VideoQuality quality;
|
||||||
|
|
||||||
const ParticipantWidget({
|
const ParticipantWidget({
|
||||||
@ -65,24 +52,18 @@ class LocalParticipantWidget extends ParticipantWidget {
|
|||||||
@override
|
@override
|
||||||
final VideoTrack? videoTrack;
|
final VideoTrack? videoTrack;
|
||||||
@override
|
@override
|
||||||
final double? avatarSize;
|
final bool isFixed;
|
||||||
@override
|
@override
|
||||||
final bool isScreenShare;
|
final bool isScreenShare;
|
||||||
@override
|
@override
|
||||||
final bool showStatsLayer;
|
final bool showStatsLayer;
|
||||||
@override
|
|
||||||
final bool isList;
|
|
||||||
@override
|
|
||||||
final EdgeInsets? padding;
|
|
||||||
|
|
||||||
const LocalParticipantWidget(
|
const LocalParticipantWidget(
|
||||||
this.participant,
|
this.participant,
|
||||||
this.videoTrack,
|
this.videoTrack,
|
||||||
this.avatarSize,
|
this.isFixed,
|
||||||
this.isScreenShare,
|
this.isScreenShare,
|
||||||
this.showStatsLayer,
|
this.showStatsLayer, {
|
||||||
this.isList,
|
|
||||||
this.padding, {
|
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -96,24 +77,18 @@ class RemoteParticipantWidget extends ParticipantWidget {
|
|||||||
@override
|
@override
|
||||||
final VideoTrack? videoTrack;
|
final VideoTrack? videoTrack;
|
||||||
@override
|
@override
|
||||||
final double? avatarSize;
|
final bool isFixed;
|
||||||
@override
|
@override
|
||||||
final bool isScreenShare;
|
final bool isScreenShare;
|
||||||
@override
|
@override
|
||||||
final bool showStatsLayer;
|
final bool showStatsLayer;
|
||||||
@override
|
|
||||||
final bool isList;
|
|
||||||
@override
|
|
||||||
final EdgeInsets? padding;
|
|
||||||
|
|
||||||
const RemoteParticipantWidget(
|
const RemoteParticipantWidget(
|
||||||
this.participant,
|
this.participant,
|
||||||
this.videoTrack,
|
this.videoTrack,
|
||||||
this.avatarSize,
|
this.isFixed,
|
||||||
this.isScreenShare,
|
this.isScreenShare,
|
||||||
this.showStatsLayer,
|
this.showStatsLayer, {
|
||||||
this.isList,
|
|
||||||
this.padding, {
|
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -161,82 +136,19 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext ctx) {
|
||||||
if (widget.isList) {
|
|
||||||
return Padding(
|
|
||||||
padding: widget.padding ?? EdgeInsets.zero,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
SizedBox(
|
|
||||||
width: (widget.avatarSize ?? 32) * 2,
|
|
||||||
height: (widget.avatarSize ?? 32) * 2,
|
|
||||||
child: Center(
|
|
||||||
child: NoContentWidget(
|
|
||||||
userinfo: _userinfoMetadata,
|
|
||||||
avatarSize: widget.avatarSize,
|
|
||||||
isSpeaking: widget.participant.isSpeaking,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Gap(8),
|
|
||||||
Expanded(
|
|
||||||
child: SizedBox(
|
|
||||||
height: (widget.avatarSize ?? 32) * 2,
|
|
||||||
child: ParticipantInfoWidget(
|
|
||||||
isList: true,
|
|
||||||
title: widget.participant.name.isNotEmpty
|
|
||||||
? widget.participant.name
|
|
||||||
: widget.participant.identity,
|
|
||||||
audioAvailable: _firstAudioPublication?.muted == false &&
|
|
||||||
_firstAudioPublication?.subscribed == true,
|
|
||||||
connectionQuality: widget.participant.connectionQuality,
|
|
||||||
isScreenShare: widget.isScreenShare,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (_activeVideoTrack != null && !_activeVideoTrack!.muted)
|
|
||||||
ClipRRect(
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 16 / 9,
|
|
||||||
child: Material(
|
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.surfaceContainer
|
|
||||||
.withOpacity(0.75),
|
|
||||||
child: VideoTrackRenderer(
|
|
||||||
_activeVideoTrack!,
|
|
||||||
fit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).padding(top: 8),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
if (_activeVideoTrack != null && !_activeVideoTrack!.muted)
|
_activeVideoTrack != null && !_activeVideoTrack!.muted
|
||||||
VideoTrackRenderer(
|
? VideoTrackRenderer(
|
||||||
_activeVideoTrack!,
|
_activeVideoTrack!,
|
||||||
fit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
|
fit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
|
||||||
)
|
)
|
||||||
else
|
: NoContentWidget(
|
||||||
Center(
|
userinfo: _userinfoMetadata,
|
||||||
child: NoContentWidget(
|
isFixed: widget.isFixed,
|
||||||
userinfo: _userinfoMetadata,
|
isSpeaking: widget.participant.isSpeaking,
|
||||||
avatarSize: widget.avatarSize,
|
),
|
||||||
isSpeaking: widget.participant.isSpeaking,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (widget.showStatsLayer)
|
if (widget.showStatsLayer)
|
||||||
Positioned(
|
Positioned(
|
||||||
top: 30,
|
top: 30,
|
||||||
@ -287,51 +199,44 @@ class _RemoteParticipantWidgetState
|
|||||||
}
|
}
|
||||||
|
|
||||||
class InteractiveParticipantWidget extends StatelessWidget {
|
class InteractiveParticipantWidget extends StatelessWidget {
|
||||||
final double? avatarSize;
|
final double? width;
|
||||||
final bool isList;
|
final double? height;
|
||||||
|
final Color? color;
|
||||||
|
final bool isFixedAvatar;
|
||||||
final ParticipantTrack participant;
|
final ParticipantTrack participant;
|
||||||
final Function? onTap;
|
final Function() onTap;
|
||||||
final EdgeInsets? padding;
|
|
||||||
|
|
||||||
const InteractiveParticipantWidget({
|
const InteractiveParticipantWidget({
|
||||||
super.key,
|
super.key,
|
||||||
this.avatarSize,
|
this.width,
|
||||||
this.isList = false,
|
this.height,
|
||||||
this.padding,
|
this.color,
|
||||||
|
this.isFixedAvatar = false,
|
||||||
required this.participant,
|
required this.participant,
|
||||||
this.onTap,
|
required this.onTap,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Material(
|
return GestureDetector(
|
||||||
color: Colors.transparent,
|
child: Container(
|
||||||
child: InkWell(
|
width: width,
|
||||||
onTap: onTap != null
|
height: height,
|
||||||
? () {
|
color: color,
|
||||||
onTap?.call();
|
child: ParticipantWidget.widgetFor(participant, isFixed: isFixedAvatar),
|
||||||
}
|
|
||||||
: null,
|
|
||||||
onLongPress: () {
|
|
||||||
if (participant.participant is LocalParticipant) return;
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => ParticipantMenu(
|
|
||||||
participant: participant.participant as RemoteParticipant,
|
|
||||||
videoTrack: participant.videoTrack,
|
|
||||||
isScreenShare: participant.isScreenShare,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
child: ParticipantWidget.widgetFor(
|
|
||||||
participant,
|
|
||||||
avatarSize: avatarSize,
|
|
||||||
isList: isList,
|
|
||||||
padding: padding,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ class ParticipantInfoWidget extends StatelessWidget {
|
|||||||
final bool audioAvailable;
|
final bool audioAvailable;
|
||||||
final ConnectionQuality connectionQuality;
|
final ConnectionQuality connectionQuality;
|
||||||
final bool isScreenShare;
|
final bool isScreenShare;
|
||||||
final bool isList;
|
|
||||||
|
|
||||||
const ParticipantInfoWidget({
|
const ParticipantInfoWidget({
|
||||||
super.key,
|
super.key,
|
||||||
@ -17,124 +16,64 @@ class ParticipantInfoWidget extends StatelessWidget {
|
|||||||
this.audioAvailable = true,
|
this.audioAvailable = true,
|
||||||
this.connectionQuality = ConnectionQuality.unknown,
|
this.connectionQuality = ConnectionQuality.unknown,
|
||||||
this.isScreenShare = false,
|
this.isScreenShare = false,
|
||||||
this.isList = false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) => Container(
|
||||||
if (isList) {
|
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.75),
|
||||||
return Column(
|
padding: const EdgeInsets.symmetric(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
vertical: 7,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
horizontal: 10,
|
||||||
children: [
|
),
|
||||||
if (title != null)
|
child: Row(
|
||||||
Text(
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
title!,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
overflow: TextOverflow.ellipsis,
|
children: [
|
||||||
style: const TextStyle(
|
if (title != null)
|
||||||
color: Colors.white,
|
Flexible(
|
||||||
fontWeight: FontWeight.bold,
|
child: Text(
|
||||||
),
|
title!,
|
||||||
).padding(left: 2),
|
overflow: TextOverflow.ellipsis,
|
||||||
Row(
|
style: const TextStyle(color: Colors.white),
|
||||||
children: [
|
|
||||||
isScreenShare
|
|
||||||
? const Icon(
|
|
||||||
Symbols.monitor,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 16,
|
|
||||||
)
|
|
||||||
: Icon(
|
|
||||||
audioAvailable ? Symbols.mic : Symbols.mic_off,
|
|
||||||
color: audioAvailable ? Colors.white : Colors.red,
|
|
||||||
size: 16,
|
|
||||||
),
|
|
||||||
const Gap(3),
|
|
||||||
if (connectionQuality != ConnectionQuality.unknown)
|
|
||||||
Icon(
|
|
||||||
{
|
|
||||||
ConnectionQuality.excellent: Symbols.signal_cellular_alt,
|
|
||||||
ConnectionQuality.good: Symbols.signal_cellular_alt_2_bar,
|
|
||||||
ConnectionQuality.poor: Symbols.signal_cellular_alt_1_bar,
|
|
||||||
}[connectionQuality],
|
|
||||||
color: {
|
|
||||||
ConnectionQuality.excellent: Colors.green,
|
|
||||||
ConnectionQuality.good: Colors.orange,
|
|
||||||
ConnectionQuality.poor: Colors.red,
|
|
||||||
}[connectionQuality],
|
|
||||||
size: 16,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
height: 12,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
color: Colors.white,
|
|
||||||
strokeWidth: 2,
|
|
||||||
),
|
|
||||||
).padding(all: 3),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.75),
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 7,
|
|
||||||
horizontal: 10,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
if (title != null)
|
|
||||||
Flexible(
|
|
||||||
child: Text(
|
|
||||||
title!,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: const TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Gap(5),
|
|
||||||
isScreenShare
|
|
||||||
? const Icon(
|
|
||||||
Symbols.monitor,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 16,
|
|
||||||
)
|
|
||||||
: Icon(
|
|
||||||
audioAvailable ? Symbols.mic : Symbols.mic_off,
|
|
||||||
color: audioAvailable ? Colors.white : Colors.red,
|
|
||||||
size: 16,
|
|
||||||
),
|
),
|
||||||
const Gap(3),
|
|
||||||
if (connectionQuality != ConnectionQuality.unknown)
|
|
||||||
Icon(
|
|
||||||
{
|
|
||||||
ConnectionQuality.excellent: Symbols.signal_cellular_alt,
|
|
||||||
ConnectionQuality.good: Symbols.signal_cellular_alt_2_bar,
|
|
||||||
ConnectionQuality.poor: Symbols.signal_cellular_alt_1_bar,
|
|
||||||
}[connectionQuality],
|
|
||||||
color: {
|
|
||||||
ConnectionQuality.excellent: Colors.green,
|
|
||||||
ConnectionQuality.good: Colors.orange,
|
|
||||||
ConnectionQuality.poor: Colors.red,
|
|
||||||
}[connectionQuality],
|
|
||||||
size: 16,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
const SizedBox(
|
|
||||||
width: 12,
|
|
||||||
height: 12,
|
|
||||||
child: CircularProgressIndicator(
|
|
||||||
color: Colors.white,
|
|
||||||
strokeWidth: 2,
|
|
||||||
),
|
),
|
||||||
).padding(all: 3),
|
const Gap(5),
|
||||||
],
|
isScreenShare
|
||||||
),
|
? const Icon(
|
||||||
);
|
Symbols.monitor,
|
||||||
}
|
color: Colors.white,
|
||||||
|
size: 16,
|
||||||
|
)
|
||||||
|
: Icon(
|
||||||
|
audioAvailable ? Symbols.mic : Symbols.mic_off,
|
||||||
|
color: audioAvailable ? Colors.white : Colors.red,
|
||||||
|
size: 16,
|
||||||
|
),
|
||||||
|
const Gap(3),
|
||||||
|
if (connectionQuality != ConnectionQuality.unknown)
|
||||||
|
Icon(
|
||||||
|
{
|
||||||
|
ConnectionQuality.excellent: Symbols.signal_cellular_alt,
|
||||||
|
ConnectionQuality.good: Symbols.signal_cellular_alt_2_bar,
|
||||||
|
ConnectionQuality.poor: Symbols.signal_cellular_alt_1_bar,
|
||||||
|
}[connectionQuality],
|
||||||
|
color: {
|
||||||
|
ConnectionQuality.excellent: Colors.green,
|
||||||
|
ConnectionQuality.good: Colors.orange,
|
||||||
|
ConnectionQuality.poor: Colors.red,
|
||||||
|
}[connectionQuality],
|
||||||
|
size: 16,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
const SizedBox(
|
||||||
|
width: 12,
|
||||||
|
height: 12,
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Colors.white,
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
|
).padding(all: 3),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ import gal
|
|||||||
import hotkey_manager_macos
|
import hotkey_manager_macos
|
||||||
import in_app_review
|
import in_app_review
|
||||||
import livekit_client
|
import livekit_client
|
||||||
import livekit_noise_filter
|
|
||||||
import local_notifier
|
import local_notifier
|
||||||
import media_kit_libs_macos_video
|
import media_kit_libs_macos_video
|
||||||
import media_kit_video
|
import media_kit_video
|
||||||
@ -61,7 +60,6 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin"))
|
HotkeyManagerMacosPlugin.register(with: registry.registrar(forPlugin: "HotkeyManagerMacosPlugin"))
|
||||||
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
|
InAppReviewPlugin.register(with: registry.registrar(forPlugin: "InAppReviewPlugin"))
|
||||||
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
|
LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin"))
|
||||||
LiveKitKrispNoiseFilterPlugin.register(with: registry.registrar(forPlugin: "LiveKitKrispNoiseFilterPlugin"))
|
|
||||||
LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin"))
|
LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin"))
|
||||||
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin"))
|
||||||
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin"))
|
||||||
|
@ -152,11 +152,6 @@ PODS:
|
|||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- WebRTC-SDK (= 125.6422.06)
|
- WebRTC-SDK (= 125.6422.06)
|
||||||
- livekit_noise_filter (0.0.1):
|
|
||||||
- flutter_webrtc
|
|
||||||
- FlutterMacOS
|
|
||||||
- LiveKitKrispNoiseFilter (= 0.0.7)
|
|
||||||
- LiveKitKrispNoiseFilter (0.0.7)
|
|
||||||
- local_notifier (0.1.0):
|
- local_notifier (0.1.0):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- media_kit_libs_macos_video (1.0.4):
|
- media_kit_libs_macos_video (1.0.4):
|
||||||
@ -242,7 +237,6 @@ DEPENDENCIES:
|
|||||||
- hotkey_manager_macos (from `Flutter/ephemeral/.symlinks/plugins/hotkey_manager_macos/macos`)
|
- hotkey_manager_macos (from `Flutter/ephemeral/.symlinks/plugins/hotkey_manager_macos/macos`)
|
||||||
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
|
- in_app_review (from `Flutter/ephemeral/.symlinks/plugins/in_app_review/macos`)
|
||||||
- livekit_client (from `Flutter/ephemeral/.symlinks/plugins/livekit_client/macos`)
|
- livekit_client (from `Flutter/ephemeral/.symlinks/plugins/livekit_client/macos`)
|
||||||
- livekit_noise_filter (from `Flutter/ephemeral/.symlinks/plugins/livekit_noise_filter/macos`)
|
|
||||||
- local_notifier (from `Flutter/ephemeral/.symlinks/plugins/local_notifier/macos`)
|
- local_notifier (from `Flutter/ephemeral/.symlinks/plugins/local_notifier/macos`)
|
||||||
- media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`)
|
- media_kit_libs_macos_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_libs_macos_video/macos`)
|
||||||
- media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`)
|
- media_kit_video (from `Flutter/ephemeral/.symlinks/plugins/media_kit_video/macos`)
|
||||||
@ -271,7 +265,6 @@ SPEC REPOS:
|
|||||||
- GoogleDataTransport
|
- GoogleDataTransport
|
||||||
- GoogleUtilities
|
- GoogleUtilities
|
||||||
- HotKey
|
- HotKey
|
||||||
- LiveKitKrispNoiseFilter
|
|
||||||
- nanopb
|
- nanopb
|
||||||
- OrderedSet
|
- OrderedSet
|
||||||
- PromisesObjC
|
- PromisesObjC
|
||||||
@ -322,8 +315,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/in_app_review/macos
|
||||||
livekit_client:
|
livekit_client:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/livekit_client/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/livekit_client/macos
|
||||||
livekit_noise_filter:
|
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/livekit_noise_filter/macos
|
|
||||||
local_notifier:
|
local_notifier:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/local_notifier/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/local_notifier/macos
|
||||||
media_kit_libs_macos_video:
|
media_kit_libs_macos_video:
|
||||||
@ -387,8 +378,6 @@ SPEC CHECKSUMS:
|
|||||||
hotkey_manager_macos: a4317849af96d2430fa89944d3c58977ca089fbe
|
hotkey_manager_macos: a4317849af96d2430fa89944d3c58977ca089fbe
|
||||||
in_app_review: 0599bccaed5e02f6bed2b0d30d16f86b63ed8638
|
in_app_review: 0599bccaed5e02f6bed2b0d30d16f86b63ed8638
|
||||||
livekit_client: 35690bf9861be6325a6f7d11bb38d50c7c9fed80
|
livekit_client: 35690bf9861be6325a6f7d11bb38d50c7c9fed80
|
||||||
livekit_noise_filter: c5710c0871ef3621b48c0b44d3c3ff938ba414b2
|
|
||||||
LiveKitKrispNoiseFilter: efe418ceca28163ace0ff222bd2cc02384645d84
|
|
||||||
local_notifier: ebf072651e35ae5e47280ad52e2707375cb2ae4e
|
local_notifier: ebf072651e35ae5e47280ad52e2707375cb2ae4e
|
||||||
media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65
|
media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65
|
||||||
media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758
|
media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758
|
||||||
|
@ -1381,14 +1381,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.1"
|
||||||
livekit_noise_filter:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: livekit_noise_filter
|
|
||||||
sha256: "398bfd1cc63ada9dee9fd7ea415e2fc1e51e091a6d217aad3649b882c35c7fcb"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.0"
|
|
||||||
local_notifier:
|
local_notifier:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -144,7 +144,6 @@ dependencies:
|
|||||||
latlong2: ^0.9.1
|
latlong2: ^0.9.1
|
||||||
crypto: ^3.0.6
|
crypto: ^3.0.6
|
||||||
audioplayers: ^6.4.0
|
audioplayers: ^6.4.0
|
||||||
livekit_noise_filter: ^0.1.0
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user