fix: voip code breaking from 0.28

have not tested it but should mostly be fine, rewrite should get in someday anyway :p
This commit is contained in:
td 2024-04-30 18:19:10 +05:30
parent 57f0962921
commit 4095560412
No known key found for this signature in database
GPG key ID: 62A30523D4D6CE28
10 changed files with 124 additions and 115 deletions

View file

@ -1269,25 +1269,12 @@ class ChatController extends State<ChatPageWithRoom>
);
if (callType == null) return;
final success = await showFutureLoadingDialog(
context: context,
future: () =>
Matrix.of(context).voipPlugin!.voip.requestTurnServerCredentials(),
);
if (success.result != null) {
final voipPlugin = Matrix.of(context).voipPlugin;
try {
await voipPlugin!.voip.inviteToCall(room.id, callType);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.toLocalizedString(context))),
);
}
} else {
await showOkAlertDialog(
context: context,
title: L10n.of(context)!.unavailable,
okLabel: L10n.of(context)!.next,
final voipPlugin = Matrix.of(context).voipPlugin;
try {
await voipPlugin!.voip.inviteToCall(room, callType);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.toLocalizedString(context))),
);
}
}

View file

@ -145,7 +145,7 @@ class _SpaceViewState extends State<SpaceView> {
icon: Icons.send_outlined,
),
if (spaceChild != null &&
(activeSpace?.canChangeStateEvent(EventTypes.spaceChild) ?? false))
(activeSpace?.canChangeStateEvent(EventTypes.SpaceChild) ?? false))
SheetAction(
key: SpaceChildContextAction.removeFromSpace,
label: L10n.of(context)!.removeFromSpace,
@ -474,7 +474,7 @@ class _SpaceViewState extends State<SpaceView> {
onTap: () => _onJoinSpaceChild(spaceChild),
),
if (activeSpace?.canChangeStateEvent(
EventTypes.spaceChild,
EventTypes.SpaceChild,
) ==
true)
Material(

View file

@ -25,13 +25,14 @@ import 'package:flutter/services.dart';
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart' hide VideoRenderer;
import 'package:just_audio/just_audio.dart';
import 'package:matrix/matrix.dart';
import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/utils/voip/video_renderer.dart';
import 'package:fluffychat/widgets/avatar.dart';
import 'pip/pip_view.dart';
@ -75,19 +76,13 @@ class _StreamView extends StatelessWidget {
child: Stack(
alignment: Alignment.center,
children: <Widget>[
if (videoMuted)
Container(
color: Colors.transparent,
),
if (!videoMuted)
RTCVideoView(
// yes, it must explicitly be casted even though I do not feel
// comfortable with it...
wrappedStream.renderer as RTCVideoRenderer,
mirror: mirrored,
objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
),
if (videoMuted)
VideoRenderer(
wrappedStream,
mirror: mirrored,
fit: RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
),
if (videoMuted) ...[
Container(color: Colors.black54),
Positioned(
child: Avatar(
mxContent: avatarUrl,
@ -98,6 +93,7 @@ class _StreamView extends StatelessWidget {
// matrixClient: matrixClient,
),
),
],
if (!isScreenSharing)
Positioned(
left: 4.0,
@ -159,8 +155,6 @@ class MyCallingPage extends State<Calling> {
return null;
}
bool get speakerOn => call.speakerOn;
bool get isMicrophoneMuted => call.isMicrophoneMuted;
bool get isLocalVideoMuted => call.isLocalVideoMuted;
@ -175,9 +169,6 @@ class MyCallingPage extends State<Calling> {
bool get connected => call.state == CallState.kConnected;
bool get mirrored => call.facingMode == 'user';
List<WrappedMediaStream> get streams => call.streams;
double? _localVideoHeight;
double? _localVideoWidth;
EdgeInsetsGeometry? _localVideoMargin;
@ -205,12 +196,12 @@ class MyCallingPage extends State<Calling> {
final call = this.call;
call.onCallStateChanged.stream.listen(_handleCallState);
call.onCallEventChanged.stream.listen((event) {
if (event == CallEvent.kFeedsChanged) {
if (event == CallStateChange.kFeedsChanged) {
setState(() {
call.tryRemoveStopedStreams();
});
} else if (event == CallEvent.kLocalHoldUnhold ||
event == CallEvent.kRemoteHoldUnhold) {
} else if (event == CallStateChange.kLocalHoldUnhold ||
event == CallStateChange.kRemoteHoldUnhold) {
setState(() {});
Logs().i(
'Call hold event: local ${call.localHold}, remote ${call.remoteOnHold}',
@ -286,7 +277,7 @@ class MyCallingPage extends State<Calling> {
if (call.isRinging) {
call.reject();
} else {
call.hangup();
call.hangup(reason: CallErrorCode.userHangup);
}
});
}
@ -341,11 +332,6 @@ class MyCallingPage extends State<Calling> {
await Helper.switchCamera(
call.localUserMediaStream!.stream!.getVideoTracks()[0],
);
if (PlatformInfos.isMobile) {
call.facingMode == 'user'
? call.facingMode = 'environment'
: call.facingMode = 'user';
}
}
setState(() {});
}
@ -450,16 +436,10 @@ class MyCallingPage extends State<Calling> {
hangupButton,
];
case CallState.kFledgling:
// TODO: Handle this case.
break;
case CallState.kWaitLocalMedia:
// TODO: Handle this case.
break;
case CallState.kCreateOffer:
// TODO: Handle this case.
break;
case CallState.kEnding:
case null:
// TODO: Handle this case.
break;
}
return <Widget>[];

View file

@ -299,7 +299,7 @@ class UserBottomSheetView extends StatelessWidget {
BorderRadius.circular(AppConfig.borderRadius / 2),
color: Theme.of(context).colorScheme.onInverseSurface,
child: DropdownButton<int>(
onChanged: user.canChangePowerLevel ||
onChanged: user.canChangeUserPowerLevel ||
// Workaround until https://github.com/famedly/matrix-dart-sdk/pull/1765
(user.room.canChangePowerLevel &&
user.id == user.room.client.userID)

View file

@ -8,8 +8,6 @@ import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:fluffychat/utils/voip_plugin.dart';
class CallKeeper {
CallKeeper(this.callKeepManager, this.call) {
call.onCallStateChanged.stream.listen(_handleCallState);
@ -40,31 +38,14 @@ class CallKeeper {
case CallState.kEnded:
callKeepManager.hangup(call.callId);
break;
/* TODO:
case CallState.kMuted:
callKeepManager.setMutedCall(uuid, true);
break;
case CallState.kHeld:
callKeepManager.setOnHold(uuid, true);
break;
*/
case CallState.kFledgling:
// TODO: Handle this case.
break;
case CallState.kInviteSent:
// TODO: Handle this case.
break;
case CallState.kWaitLocalMedia:
// TODO: Handle this case.
break;
case CallState.kCreateOffer:
// TODO: Handle this case.
break;
case CallState.kCreateAnswer:
// TODO: Handle this case.
break;
case CallState.kRinging:
// TODO: Handle this case.
case CallState.kEnding:
break;
}
}
@ -84,7 +65,6 @@ class CallKeepManager {
static final CallKeepManager _instance = CallKeepManager._internal();
late FlutterCallkeep _callKeep;
VoipPlugin? _voipPlugin;
String get appName => 'FluffyChat';
@ -130,7 +110,7 @@ class CallKeepManager {
});
call.onCallEventChanged.stream.listen(
(event) {
if (event == CallEvent.kLocalHoldUnhold) {
if (event == CallStateChange.kLocalHoldUnhold) {
Logs().i(
'Call hold event: local ${call.localHold}, remote ${call.remoteOnHold}',
);
@ -170,10 +150,7 @@ class CallKeepManager {
Future<void> initialize() async {
_callKeep.on(CallKeepPerformAnswerCallAction(), answerCall);
_callKeep.on(CallKeepDidPerformDTMFAction(), didPerformDTMFAction);
_callKeep.on(
CallKeepDidReceiveStartCallAction(),
didReceiveStartCallAction,
);
_callKeep.on(CallKeepDidToggleHoldAction(), didToggleHoldCallAction);
_callKeep.on(
CallKeepDidPerformSetMutedCallAction(),
@ -313,7 +290,7 @@ class CallKeepManager {
Future<void> endCall(CallKeepPerformEndCallAction event) async {
final keeper = calls[event.callUUID];
keeper?.call.hangup();
keeper?.call.hangup(reason: CallErrorCode.userHangup);
removeCall(event.callUUID);
}
@ -322,25 +299,6 @@ class CallKeepManager {
keeper.call.sendDTMF(event.digits!);
}
Future<void> didReceiveStartCallAction(
CallKeepDidReceiveStartCallAction event,
) async {
if (event.handle == null) {
// @TODO: sometime we receive `didReceiveStartCallAction` with handle` undefined`
return;
}
final callUUID = event.callUUID!;
if (event.callUUID == null) {
final call =
await _voipPlugin!.voip.inviteToCall(event.handle!, CallType.kVideo);
addCall(callUUID, CallKeeper(this, call));
}
await _callKeep.startCall(callUUID, event.handle!, event.handle!);
Timer(const Duration(seconds: 1), () {
_callKeep.setCurrentCallActive(callUUID);
});
}
Future<void> didPerformSetMutedCallAction(
CallKeepDidPerformSetMutedCallAction event,
) async {

View file

@ -0,0 +1,86 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import 'package:matrix/matrix.dart';
class VideoRenderer extends StatefulWidget {
final WrappedMediaStream? stream;
final bool mirror;
final RTCVideoViewObjectFit fit;
const VideoRenderer(
this.stream, {
this.mirror = false,
this.fit = RTCVideoViewObjectFit.RTCVideoViewObjectFitContain,
super.key,
});
@override
State<StatefulWidget> createState() => _VideoRendererState();
}
class _VideoRendererState extends State<VideoRenderer> {
RTCVideoRenderer? _renderer;
bool _rendererReady = false;
MediaStream? get mediaStream => widget.stream?.stream;
StreamSubscription? _streamChangeSubscription;
Future<RTCVideoRenderer> _initializeRenderer() async {
_renderer ??= RTCVideoRenderer();
await _renderer!.initialize();
_renderer!.srcObject = mediaStream;
return _renderer!;
}
void disposeRenderer() {
try {
_renderer?.srcObject = null;
_renderer?.dispose();
_renderer = null;
// ignore: empty_catches
} catch (e) {}
}
@override
void initState() {
_streamChangeSubscription =
widget.stream?.onStreamChanged.stream.listen((stream) {
setState(() {
_renderer?.srcObject = stream;
});
});
setupRenderer();
super.initState();
}
Future<void> setupRenderer() async {
await _initializeRenderer();
setState(() => _rendererReady = true);
}
@override
void dispose() {
_streamChangeSubscription?.cancel();
disposeRenderer();
super.dispose();
}
@override
Widget build(BuildContext context) => !_rendererReady
? Container()
: Builder(
key: widget.key,
builder: (ctx) {
return RTCVideoView(
_renderer!,
mirror: widget.mirror,
filterQuality: FilterQuality.medium,
objectFit: widget.fit,
placeholderBuilder: (_) =>
Container(color: Colors.white.withOpacity(0.18)),
);
},
);
}

View file

@ -90,11 +90,6 @@ class VoipPlugin with WidgetsBindingObserver implements WebRTCDelegate {
]) =>
webrtc_impl.createPeerConnection(configuration, constraints);
@override
VideoRenderer createRenderer() {
return webrtc_impl.RTCVideoRenderer();
}
Future<bool> get hasCallingAccount async =>
kIsWeb ? false : await CallKeepManager().hasPhoneAccountEnabled;
@ -179,12 +174,12 @@ class VoipPlugin with WidgetsBindingObserver implements WebRTCDelegate {
}
@override
Future<void> handleGroupCallEnded(GroupCall groupCall) async {
Future<void> handleGroupCallEnded(GroupCallSession groupCall) async {
// TODO: implement handleGroupCallEnded
}
@override
Future<void> handleNewGroupCall(GroupCall groupCall) async {
Future<void> handleNewGroupCall(GroupCallSession groupCall) async {
// TODO: implement handleNewGroupCall
}
@ -197,4 +192,8 @@ class VoipPlugin with WidgetsBindingObserver implements WebRTCDelegate {
Future<void> handleMissedCall(CallSession session) async {
// TODO: implement handleMissedCall
}
@override
// TODO: implement keyProvider
EncryptionKeyProvider? get keyProvider => throw UnimplementedError();
}

View file

@ -1210,10 +1210,10 @@ packages:
dependency: "direct main"
description:
name: matrix
sha256: "36c7e13d5d7420898f2597d6f5f0611a9da8114a0fde11f41b9e54cd1140b05f"
sha256: "32c21a2ac2c221ce887b00a87f965bd8df1a3a4ba8794bbe86be8b56214051fb"
url: "https://pub.dev"
source: hosted
version: "0.27.0"
version: "0.28.1"
meta:
dependency: transitive
description:

View file

@ -64,7 +64,7 @@ dependencies:
keyboard_shortcuts: ^0.1.4
latlong2: ^0.9.1
linkify: ^5.0.0
matrix: ^0.27.0
matrix: ^0.28.1
native_imaging: ^0.1.0
package_info_plus: ^6.0.0
pasteboard: ^0.2.0

View file

@ -1,7 +1,6 @@
// ignore_for_file: depend_on_referenced_packages
import 'package:matrix/encryption/utils/key_verification.dart';
import 'package:matrix/fake_matrix_api.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/flutter_hive_collections_database.dart';