Implement jitsi

This commit is contained in:
Christian Pauly 2020-04-08 17:43:07 +02:00
commit f721045d00
7 changed files with 145 additions and 22 deletions

View file

@ -6,6 +6,7 @@ import 'package:fluffychat/utils/app_route.dart';
import 'package:fluffychat/views/chat_details.dart';
import 'package:fluffychat/views/chat_list.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'dialogs/simple_dialogs.dart';
import 'matrix.dart';
@ -29,6 +30,18 @@ class _ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
super.dispose();
}
void startCallAction(BuildContext context) async {
final url =
'${Matrix.of(context).jitsiInstance}${Uri.encodeComponent(widget.room.id.localpart)}';
final success = await Matrix.of(context)
.tryRequestWithLoadingDialog(widget.room.sendEvent({
'msgtype': Matrix.callNamespace,
'body': url,
}));
if (success == false) return;
await launch(url);
}
@override
Widget build(BuildContext context) {
notificationChangeSub ??= Matrix.of(context)
@ -49,6 +62,10 @@ class _ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
value: "unmute",
child: Text(I18n.of(context).unmuteChat),
),
PopupMenuItem<String>(
value: "call",
child: Text(I18n.of(context).videoCall),
),
PopupMenuItem<String>(
value: "leave",
child: Text(I18n.of(context).leave),
@ -86,6 +103,9 @@ class _ChatSettingsPopupMenuState extends State<ChatSettingsPopupMenu> {
await Matrix.of(context).tryRequestWithLoadingDialog(
widget.room.setPushRuleState(PushRuleState.notify));
break;
case "call":
startCallAction(context);
break;
case "details":
await Navigator.of(context).push(
AppRoute.defaultRoute(

View file

@ -26,6 +26,7 @@ class SimpleDialogs {
content: TextField(
controller: controller,
autofocus: true,
autocorrect: false,
onSubmitted: (s) {
input = s;
Navigator.of(context).pop();

View file

@ -10,6 +10,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:localstorage/localstorage.dart';
import 'package:path_provider/path_provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../i18n/i18n.dart';
import '../utils/app_route.dart';
@ -18,8 +19,11 @@ import '../utils/event_extension.dart';
import '../utils/famedlysdk_store.dart';
import '../utils/room_extension.dart';
import '../views/chat.dart';
import 'avatar.dart';
class Matrix extends StatefulWidget {
static const String callNamespace = 'chat.fluffy.jitsi_call';
final Widget child;
final String clientName;
@ -52,6 +56,8 @@ class MatrixState extends State<Matrix> {
String activeRoomId;
File wallpaper;
String jitsiInstance = 'https://meet.jit.si/';
void clean() async {
if (!kIsWeb) return;
@ -343,12 +349,73 @@ class MatrixState extends State<Matrix> {
};
StreamSubscription onRoomKeyRequestSub;
StreamSubscription onJitsiCallSub;
void onJitsiCall(EventUpdate eventUpdate) {
final event = Event.fromJson(
eventUpdate.content, client.getRoomById(eventUpdate.roomID));
if (DateTime.now().millisecondsSinceEpoch -
event.time.millisecondsSinceEpoch >
1000 * 60 * 5) {
return;
}
final senderName = event.sender.calcDisplayname();
final senderAvatar = event.sender.avatarUrl;
showDialog(
context: context,
builder: (context) => AlertDialog(
title: ListTile(
contentPadding: EdgeInsets.all(0),
leading: Avatar(senderAvatar, senderName),
title: Text(
senderName,
style: TextStyle(fontSize: 18),
),
subtitle:
event.room.isDirectChat ? null : Text(event.room.displayname),
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Divider(),
Row(
children: <Widget>[
Spacer(),
FloatingActionButton(
backgroundColor: Colors.red,
child: Icon(Icons.phone_missed),
onPressed: () => Navigator.of(context).pop(),
),
Spacer(),
FloatingActionButton(
backgroundColor: Colors.green,
child: Icon(Icons.phone),
onPressed: () {
Navigator.of(context).pop();
launch(event.body);
},
),
Spacer(),
],
),
],
),
),
);
return;
}
@override
void initState() {
if (widget.client == null) {
debugPrint("[Matrix] Init matrix client");
client = Client(widget.clientName, debug: false);
onJitsiCallSub ??= client.onEvent.stream
.where((e) =>
e.eventType == 'm.room.message' &&
e.content['content']['msgtype'] == Matrix.callNamespace &&
e.content['sender'] != client.userID)
.listen(onJitsiCall);
onRoomKeyRequestSub ??=
client.onRoomKeyRequest.stream.listen((RoomKeyRequest request) async {
final Room room = request.room;
@ -368,6 +435,9 @@ class MatrixState extends State<Matrix> {
client = widget.client;
}
if (client.storeAPI != null) {
client.storeAPI
.getItem("chat.fluffy.jitsi_instance")
.then((final instance) => jitsiInstance = instance ?? jitsiInstance);
client.storeAPI.getItem("chat.fluffy.wallpaper").then((final path) async {
if (path == null) return;
final file = File(path);
@ -382,6 +452,7 @@ class MatrixState extends State<Matrix> {
@override
void dispose() {
onRoomKeyRequestSub?.cancel();
onJitsiCallSub?.cancel();
super.dispose();
}

View file

@ -99,6 +99,19 @@ class MessageContent extends StatelessWidget {
case MessageTypes.Notice:
case MessageTypes.Emote:
default:
if (event.content['msgtype'] == Matrix.callNamespace) {
return RaisedButton(
color: Theme.of(context).backgroundColor,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(Icons.phone),
Text(I18n.of(context).videoCall),
],
),
onPressed: () => launch(event.body),
);
}
return LinkText(
text: event.getLocalizedBody(context, hideReply: true),
textStyle: TextStyle(