Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add the possibility to control PiP programmatically #94

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class JitsiMeetPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
"sendChatMessage" -> sendChatMessage(call, result)
"closeChat" -> closeChat(call, result)
"retrieveParticipantsInfo" -> retrieveParticipantsInfo(call, result)
"enterPiP" -> enterPiP(call, result)
else -> result.notImplemented()
}
}
Expand Down Expand Up @@ -193,4 +194,10 @@ class JitsiMeetPlugin: FlutterPlugin, MethodCallHandler, ActivityAware {
LocalBroadcastManager.getInstance(activity!!.applicationContext).sendBroadcast(retrieveParticipantsInfoIntent)
result.success("Successfully retrieved participants info")
}

private fun enterPiP(call: MethodCall, result: Result) {
val enterPiPIntent = Intent("org.jitsi.meet.ENTER_PICTURE_IN_PICTURE");
LocalBroadcastManager.getInstance(activity!!.applicationContext).sendBroadcast(enterPiPIntent)
result.success("Successfully entered PiP")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,49 +58,57 @@ class WrapperJitsiMeetActivity : JitsiMeetActivity() {
for (eventType in BroadcastEvent.Type.values()) {
intentFilter.addAction(eventType.action)
}
intentFilter.addAction("org.jitsi.meet.ENTER_PICTURE_IN_PICTURE")
LocalBroadcastManager.getInstance(this)
.registerReceiver(this.broadcastReceiver, intentFilter)
}

private fun onBroadcastReceived(intent: Intent?) {
if (intent != null) {
val event = BroadcastEvent(intent)
val data = event.data
when (event.type!!) {
BroadcastEvent.Type.CONFERENCE_JOINED -> eventStreamHandler.conferenceJoined(data)
BroadcastEvent.Type.CONFERENCE_TERMINATED -> eventStreamHandler.conferenceTerminated(
data
)

BroadcastEvent.Type.CONFERENCE_WILL_JOIN -> eventStreamHandler.conferenceWillJoin(
data
)

BroadcastEvent.Type.PARTICIPANT_JOINED -> eventStreamHandler.participantJoined(data)
BroadcastEvent.Type.PARTICIPANT_LEFT -> eventStreamHandler.participantLeft(data)
BroadcastEvent.Type.AUDIO_MUTED_CHANGED -> eventStreamHandler.audioMutedChanged(data)
BroadcastEvent.Type.VIDEO_MUTED_CHANGED -> eventStreamHandler.videoMutedChanged(data)
BroadcastEvent.Type.ENDPOINT_TEXT_MESSAGE_RECEIVED -> eventStreamHandler.endpointTextMessageReceived(
data
)

BroadcastEvent.Type.SCREEN_SHARE_TOGGLED -> eventStreamHandler.screenShareToggled(
data
)

BroadcastEvent.Type.CHAT_MESSAGE_RECEIVED -> eventStreamHandler.chatMessageReceived(
data
)

BroadcastEvent.Type.CHAT_TOGGLED -> eventStreamHandler.chatToggled(data)
BroadcastEvent.Type.PARTICIPANTS_INFO_RETRIEVED -> eventStreamHandler.participantsInfoRetrieved(
data
)

BroadcastEvent.Type.READY_TO_CLOSE -> eventStreamHandler.readyToClose()

BroadcastEvent.Type.CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED -> eventStreamHandler.customOverflowMenuButtonPressed(data)
else -> {}
if (intent.action == "org.jitsi.meet.ENTER_PICTURE_IN_PICTURE") {
enterPiP()
} else {
val event = BroadcastEvent(intent)
val data = event.data
when (event.type.action!!) {
BroadcastEvent.Type.CONFERENCE_JOINED.action -> eventStreamHandler.conferenceJoined(data)
BroadcastEvent.Type.CONFERENCE_TERMINATED.action -> eventStreamHandler.conferenceTerminated(
data
)

BroadcastEvent.Type.CONFERENCE_WILL_JOIN.action -> eventStreamHandler.conferenceWillJoin(
data
)

BroadcastEvent.Type.PARTICIPANT_JOINED.action -> eventStreamHandler.participantJoined(data)
BroadcastEvent.Type.PARTICIPANT_LEFT.action -> eventStreamHandler.participantLeft(data)
BroadcastEvent.Type.AUDIO_MUTED_CHANGED.action -> eventStreamHandler.audioMutedChanged(data)
BroadcastEvent.Type.VIDEO_MUTED_CHANGED.action -> eventStreamHandler.videoMutedChanged(data)
BroadcastEvent.Type.ENDPOINT_TEXT_MESSAGE_RECEIVED.action -> eventStreamHandler.endpointTextMessageReceived(
data
)

BroadcastEvent.Type.SCREEN_SHARE_TOGGLED.action -> eventStreamHandler.screenShareToggled(
data
)

BroadcastEvent.Type.CHAT_MESSAGE_RECEIVED.action -> eventStreamHandler.chatMessageReceived(
data
)

BroadcastEvent.Type.CHAT_TOGGLED.action -> eventStreamHandler.chatToggled(data)
BroadcastEvent.Type.PARTICIPANTS_INFO_RETRIEVED.action -> eventStreamHandler.participantsInfoRetrieved(
data
)

BroadcastEvent.Type.READY_TO_CLOSE.action -> eventStreamHandler.readyToClose()

BroadcastEvent.Type.CUSTOM_OVERFLOW_MENU_BUTTON_PRESSED.action -> eventStreamHandler.customOverflowMenuButtonPressed(
data
)

else -> {}
}
}
}
}
Expand All @@ -109,4 +117,8 @@ class WrapperJitsiMeetActivity : JitsiMeetActivity() {
LocalBroadcastManager.getInstance(this).unregisterReceiver(this.broadcastReceiver)
super.onDestroy()
}

fun enterPiP() {
jitsiView?.enterPictureInPicture()
}
}
8 changes: 8 additions & 0 deletions ios/Classes/JitsiMeetPlugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ public class JitsiMeetPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
case "retrieveParticipantsInfo":
retrieveParticipantsInfo(call, result: result)
return
case "enterPiP":
enterPiP(call, result: result)
return
default:
result(FlutterMethodNotImplemented)
}
Expand Down Expand Up @@ -166,6 +169,11 @@ public class JitsiMeetPlugin: NSObject, FlutterPlugin, FlutterStreamHandler {
result("Successfully retrieved participants info")
}

private func enterPiP(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
jitsiMeetViewController?.enterPicture(inPicture: [:])
result("Successfully entered Picture in Picture")
}

public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
eventSink = events
return nil
Expand Down
9 changes: 7 additions & 2 deletions lib/src/jitsi_meet.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'jitsi_meet_platform_interface.dart';
import 'jitsi_meet_event_listener.dart';
import 'jitsi_meet_conference_options.dart';
import 'jitsi_meet_event_listener.dart';
import 'jitsi_meet_platform_interface.dart';
import 'method_response.dart';

/// The entry point for the sdk. It is used to launch the meeting screen,
Expand Down Expand Up @@ -76,4 +76,9 @@ class JitsiMeet {
Future<MethodResponse> retrieveParticipantsInfo() async {
return await JitsiMeetPlatform.instance.retrieveParticipantsInfo();
}

/// Enters Picture in Picture mode.
Future<MethodResponse> enterPiP() async {
return await JitsiMeetPlatform.instance.enterPiP();
}
}
20 changes: 20 additions & 0 deletions lib/src/jitsi_meet_method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,26 @@ class MethodChannelJitsiMeet extends JitsiMeetPlatform {
});
}

/// Enters Picture-in-Picture mode.
@override
Future<MethodResponse> enterPiP() async {
return await methodChannel
.invokeMethod<String>('enterPiP')
.then(
(message) => MethodResponse(
isSuccess: true,
message: message,
),
)
.catchError(
(error) => MethodResponse(
isSuccess: false,
message: error.toString(),
error: error,
),
);
}

void _initialize() {
eventChannel.receiveBroadcastStream().listen((message) {
final data = message['data'];
Expand Down
9 changes: 7 additions & 2 deletions lib/src/jitsi_meet_platform_interface.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import 'package:plugin_platform_interface/plugin_platform_interface.dart';

import 'jitsi_meet_method_channel.dart';
import 'jitsi_meet_event_listener.dart';
import 'jitsi_meet_conference_options.dart';
import 'jitsi_meet_event_listener.dart';
import 'jitsi_meet_method_channel.dart';
import 'method_response.dart';

abstract class JitsiMeetPlatform extends PlatformInterface {
Expand Down Expand Up @@ -96,4 +96,9 @@ abstract class JitsiMeetPlatform extends PlatformInterface {
throw UnimplementedError(
'retrieveParticipantsInfo() has not been implemented.');
}

/// Enters Picture-in-Picture mode.
Future<MethodResponse> enterPiP() async {
throw UnimplementedError('enterPiP() has not been implemented.');
}
}
11 changes: 8 additions & 3 deletions test/jitsi_meet_test.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:jitsi_meet_flutter_sdk/src/jitsi_meet.dart';
import 'package:jitsi_meet_flutter_sdk/src/jitsi_meet_platform_interface.dart';
import 'package:jitsi_meet_flutter_sdk/src/jitsi_meet_method_channel.dart';
import 'package:jitsi_meet_flutter_sdk/src/jitsi_meet_event_listener.dart';
import 'package:jitsi_meet_flutter_sdk/src/jitsi_meet_conference_options.dart';
import 'package:jitsi_meet_flutter_sdk/src/jitsi_meet_event_listener.dart';
import 'package:jitsi_meet_flutter_sdk/src/jitsi_meet_method_channel.dart';
import 'package:jitsi_meet_flutter_sdk/src/jitsi_meet_platform_interface.dart';
import 'package:jitsi_meet_flutter_sdk/src/method_response.dart';
import 'package:plugin_platform_interface/plugin_platform_interface.dart';

Expand Down Expand Up @@ -75,6 +75,11 @@ class MockJitsiMeetPlatform
// TODO: implement retrieveParticipantsInfo
throw UnimplementedError();
}

@override
Future<MethodResponse> enterPiP() {
throw UnimplementedError();
}
}

void main() {
Expand Down