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

Web implementation #47

Open
wants to merge 3 commits into
base: master
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
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,8 @@
## 1.0.0+1

- iOS Build Issue fixed for real devices
- Some Minor Improvements
- Some Minor Improvements

## 1.0.0+2

- iOS Start meeting issue fixed
16 changes: 16 additions & 0 deletions example/lib/generated_plugin_registrant.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// Generated file. Do not edit.
//

// ignore_for_file: directives_ordering
// ignore_for_file: lines_longer_than_80_chars

import 'package:flutter_zoom_sdk/flutter_zoom_web.dart';

import 'package:flutter_web_plugins/flutter_web_plugins.dart';

// ignore: public_member_api_docs
void registerPlugins(Registrar registrar) {
ZoomViewWeb.registerWith(registrar);
registrar.registerMessageHandler();
}
223 changes: 221 additions & 2 deletions example/lib/meeting_screen.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
import 'dart:async';
import 'dart:convert';
import 'dart:html' hide Platform;
import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_zoom_sdk/flutter_zoom_web.dart';
import 'package:flutter_zoom_sdk/zoom_options.dart';
import 'package:flutter_zoom_sdk/zoom_view.dart';
import 'package:crypto/crypto.dart';

class MeetingWidget extends StatefulWidget {
@override
Expand Down Expand Up @@ -59,7 +64,13 @@ class _MeetingWidgetState extends State<MeetingWidget> {
primary: Colors.blue, // background
onPrimary: Colors.white, // foreground
),
onPressed: () => joinMeeting(context),
onPressed: () => {
if (kIsWeb) {
joinMeetingWeb(context)
}else{
joinMeeting(context)
}
},
child: Text('Join'),
);
},
Expand All @@ -75,7 +86,13 @@ class _MeetingWidgetState extends State<MeetingWidget> {
primary: Colors.blue, // background
onPrimary: Colors.white, // foreground
),
onPressed: () => startMeeting(context),
onPressed: () => {
if (kIsWeb) {
startMeetingWeb(context)
}else{
startMeeting(context)
}
},
child: Text('Start Meeting'),
);
},
Expand Down Expand Up @@ -104,6 +121,8 @@ class _MeetingWidgetState extends State<MeetingWidget> {
);
}



//API KEY & SECRET is required for below methods to work
//Join Meeting With Meeting ID & Password
joinMeeting(BuildContext context) {
Expand Down Expand Up @@ -304,4 +323,204 @@ class _MeetingWidgetState extends State<MeetingWidget> {
});

}

// WEB Example

//API KEY & SECRET is required for below methods to work
//Join Meeting With Meeting ID & Password For Web Only ----- JWT is required for web to work
//To get jwt credentials go to this link https://marketplace.zoom.us/develop/create and under Jwt click create to get jwt credentials
joinMeetingWeb(BuildContext context) {
if(meetingIdController.text.isNotEmpty && meetingPasswordController.text.isNotEmpty){
ZoomOptions zoomOptions = new ZoomOptions(
domain: "zoom.us",
appKey: "LAyezanZSziuhe8Yxt5IQQ", //API KEY FROM ZOOM - Jwt API Key
appSecret: "iSFZ47c5mZ2U7GcpwrL4PutzQbcxXNagdSxQ", //API SECRET FROM ZOOM - Jwt API Secret
language: "en-US", // Optional - For Web
showMeetingHeader: true, // Optional - For Web
disableInvite: false, // Optional - For Web
disableCallOut: false, // Optional - For Web
disableRecord: false, // Optional - For Web
disableJoinAudio: false, // Optional - For Web
audioPanelAlwaysOpen: false, // Optional - For Web
isSupportAV: true, // Optional - For Web
isSupportChat: true, // Optional - For Web
isSupportQA: true, // Optional - For Web
isSupportCC: true, // Optional - For Web
isSupportPolling: true, // Optional - For Web
isSupportBreakout: true, // Optional - For Web
screenShare: true, // Optional - For Web
rwcBackup: '', // Optional - For Web
videoDrag: true, // Optional - For Web
sharingMode: 'both', // Optional - For Web
videoHeader: true, // Optional - For Web
isLockBottom: true, // Optional - For Web
isSupportNonverbal: true, // Optional - For Web
isShowJoiningErrorDialog: true, // Optional - For Web
disablePreview: false, // Optional - For Web
disableCORP: true, // Optional - For Web
inviteUrlFormat: '', // Optional - For Web
disableVOIP: false, // Optional - For Web
disableReport: false, // Optional - For Web
meetingInfo: const [
// Optional - For Web
'topic',
'host',
'mn',
'pwd',
'telPwd',
'invite',
'participant',
'dc',
'enctype',
'report'
]
);
var meetingOptions = new ZoomMeetingOptions(
userId: 'EvilRAT Technologies', //pass username for join meeting only --- Any name eg:- EVILRATT.
meetingId: meetingIdController.text, //pass meeting id for join meeting only
meetingPassword: meetingPasswordController.text, //pass meeting password for join meeting only
);

var zoom = ZoomViewWeb();
zoom.initZoom(zoomOptions).then((results) {
if(results[0] == 0) {
var zr = window.document.getElementById("zmmtg-root");
querySelector('body')?.append(zr!);
zoom.onMeetingStatus().listen((status) {
print("[Meeting Status Stream] : " + status[0] + " - " + status[1]);
if(status[0] == "MEETING_STATUS_INMEETING"){
zoom.meetinDetails().then((meetingDetailsResult) {
print("[MeetingDetailsResult] :- " + meetingDetailsResult.toString());
});
}
});
final signature = zoom.generateSignature(zoomOptions.appKey.toString(), zoomOptions.appSecret.toString(), meetingIdController.text, 0);
meetingOptions.jwtAPIKey = zoomOptions.appKey.toString();
meetingOptions.jwtSignature = signature;
zoom.joinMeeting(meetingOptions).then((joinMeetingResult) {
print("[Meeting Status Polling] : " + joinMeetingResult.toString());
timer = Timer.periodic(new Duration(seconds: 2), (timer) {
zoom.meetingStatus(meetingOptions.meetingId!)
.then((status) {
print("[Meeting Status Polling] : " + status[0] + " - " + status[1]);
});
});
});
}
}).catchError((error) {
print("[Error Generated] : " + error);
});
}else{
if(meetingIdController.text.isEmpty){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Enter a valid meeting id to continue."),
));
}
else if(meetingPasswordController.text.isEmpty){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Enter a meeting password to start."),
));
}
}

}


//Start Meeting With Meeting ID and Passcode ----- Jwt Credentials is required
//To get jwt credentials go to this link https://marketplace.zoom.us/develop/create and under Jwt click create to get jwt credentials
startMeetingWeb(BuildContext context) {
if(meetingIdController.text.isNotEmpty && meetingPasswordController.text.isNotEmpty){
ZoomOptions zoomOptions = new ZoomOptions(
domain: "zoom.us",
appKey: "LAyezanZSziuhe8Yxt5IQQ", //API KEY FROM ZOOM - Jwt API Key
appSecret: "iSFZ47c5mZ2U7GcpwrL4PutzQbcxXNagdSxQ", //API SECRET FROM ZOOM - Jwt API Secret
language: "en-US", // Optional - For Web
showMeetingHeader: true, // Optional - For Web
disableInvite: false, // Optional - For Web
disableCallOut: false, // Optional - For Web
disableRecord: false, // Optional - For Web
disableJoinAudio: false, // Optional - For Web
audioPanelAlwaysOpen: false, // Optional - For Web
isSupportAV: true, // Optional - For Web
isSupportChat: true, // Optional - For Web
isSupportQA: true, // Optional - For Web
isSupportCC: true, // Optional - For Web
isSupportPolling: true, // Optional - For Web
isSupportBreakout: true, // Optional - For Web
screenShare: true, // Optional - For Web
rwcBackup: '', // Optional - For Web
videoDrag: true, // Optional - For Web
sharingMode: 'both', // Optional - For Web
videoHeader: true, // Optional - For Web
isLockBottom: true, // Optional - For Web
isSupportNonverbal: true, // Optional - For Web
isShowJoiningErrorDialog: true, // Optional - For Web
disablePreview: false, // Optional - For Web
disableCORP: true, // Optional - For Web
inviteUrlFormat: '', // Optional - For Web
disableVOIP: false, // Optional - For Web
disableReport: false, // Optional - For Web
meetingInfo: const [
// Optional - For Web
'topic',
'host',
'mn',
'pwd',
'telPwd',
'invite',
'participant',
'dc',
'enctype',
'report'
]
);
var meetingOptions = new ZoomMeetingOptions(
userId: 'EvilRAT Technologies', //pass host email for zoom
meetingId: meetingIdController.text, //Personal meeting id for start meeting required
meetingPassword: meetingPasswordController.text, //Personal meeting passcode for start meeting required
//To get personal meeting id and passcode follow https://zoom.us/meeting#/ and novigate to Personal Room tab
);

var zoom = ZoomViewWeb();
zoom.initZoom(zoomOptions).then((results) {
if(results[0] == 0) {
var zr = window.document.getElementById("zmmtg-root");
querySelector('body')?.append(zr!);
zoom.onMeetingStatus().listen((status) {
print("[Meeting Status Stream] : " + status[0] + " - " + status[1]);
if(status[0] == "MEETING_STATUS_INMEETING"){
zoom.meetinDetails().then((meetingDetailsResult) {
print("[MeetingDetailsResult] :- " + meetingDetailsResult.toString());
});
}
});
final signature = zoom.generateSignature(zoomOptions.appKey.toString(), zoomOptions.appSecret.toString(), meetingIdController.text, 1);
meetingOptions.jwtAPIKey = zoomOptions.appKey.toString();
meetingOptions.jwtSignature = signature;
zoom.startMeeting(meetingOptions).then((startMeetingResult) {
print("[Meeting Status Polling] : " + startMeetingResult[0] + " - " + startMeetingResult[1]);
timer = Timer.periodic(new Duration(seconds: 2), (timer) {
zoom.meetingStatus(meetingOptions.meetingId!)
.then((status) {
print("[Meeting Status Polling] : " + status[0] + " - " + status[1]);
});
});
});
}
}).catchError((error) {
print("[Error Generated] : " + error);
});
}else{
if(meetingIdController.text.isEmpty){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Enter a valid personal meeting id to continue."),
));
}
else if(meetingPasswordController.text.isEmpty){
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Enter a meeting passcode to start."),
));
}
}
}
}
19 changes: 19 additions & 0 deletions example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
crypto:
dependency: transitive
description:
name: crypto
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
cupertino_icons:
dependency: "direct main"
description:
Expand All @@ -67,13 +74,25 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_web_plugins:
dependency: transitive
description: flutter
source: sdk
version: "0.0.0"
flutter_zoom_sdk:
dependency: "direct main"
description:
path: ".."
relative: true
source: path
version: "1.0.0+1"
js:
dependency: transitive
description:
name: js
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
matcher:
dependency: transitive
description:
Expand Down
27 changes: 27 additions & 0 deletions example/test/widget_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility that Flutter provides. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.

import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';

import 'package:flutter_zoom_sdk_example/main.dart';

void main() {
testWidgets('Verify Platform version', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(const MyApp());

// Verify that platform version is retrieved.
expect(
find.byWidgetPredicate(
(Widget widget) => widget is Text &&
widget.data!.startsWith('Running on:'),
),
findsOneWidget,
);
});
}
Binary file added example/web/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/web/icons/Icon-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/web/icons/Icon-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/web/icons/Icon-maskable-192.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added example/web/icons/Icon-maskable-512.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading