Skip to content

Dev > Main - Agora Meeting Token Handling #507

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

Merged
merged 6 commits into from
Nov 19, 2023
Merged
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
1 change: 1 addition & 0 deletions client/packages/lowcoder-design/src/components/Section.tsx
Original file line number Diff line number Diff line change
@@ -142,4 +142,5 @@ export const sectionNames = {
validation: trans("prop.validation"),
layout: trans("prop.layout"),
style: trans("prop.style"),
meetings : trans("prop.meetings"),
};
Original file line number Diff line number Diff line change
@@ -23,6 +23,7 @@ export const en = {
validation: "Validation",
layout: "Layout",
style: "Style",
meetings : "Meeting Settings",
},
passwordInput: {
label: "Password:",
Original file line number Diff line number Diff line change
@@ -179,6 +179,7 @@ let ButtonTmpComp = (function () {
iconSize: withDefault(StringControl, "20px"),
type: dropdownControl(typeOptions, ""),
autoHeight: withDefault(AutoHeightControl, "fixed"),
aspectRatio: withDefault(StringControl, "1 / 1"),
onEvent: ButtonEventHandlerControl,
disabled: BoolCodeControl,
loading: BoolCodeControl,
@@ -244,8 +245,16 @@ let ButtonTmpComp = (function () {
loading={props.loading}
style={
props.autoHeight
? { width: "100%", height: "100%" }
: undefined
? {
width: "100%",
height: "100%",
aspectRatio: props.aspectRatio,
borderRadius: props.style.radius,
}
: {
aspectRatio: props.aspectRatio,
borderRadius: props.style.radius,
}
}
disabled={
props.disabled ||
@@ -304,6 +313,9 @@ let ButtonTmpComp = (function () {
</Section>
<Section name={sectionNames.style}>
{children.style.getPropertyView()}
{children.aspectRatio.propertyView({
label: "Video Aspect Ratio",
})}
</Section>
</>
))
Original file line number Diff line number Diff line change
@@ -41,7 +41,10 @@ import { useUserViewMode } from "util/hooks";
import { isNumeric } from "util/stringUtils";
import { NameConfig, withExposingConfigs } from "../../generators/withExposing";

import axios from "axios";
import { v4 as uuidv4 } from 'uuid';

// import axios from "axios";

import AgoraRTC, {
ICameraVideoTrack,
IMicrophoneAudioTrack,
@@ -51,7 +54,7 @@ import AgoraRTC, {
ILocalVideoTrack,
} from "agora-rtc-sdk-ng";

import { JSONValue } from "@lowcoder-ee/index.sdk";
import { JSONValue, NumberControl } from "@lowcoder-ee/index.sdk";
import { getData } from "../listViewComp/listViewUtils";
import AgoraRTM, { RtmChannel, RtmClient } from "agora-rtm-sdk";

@@ -103,28 +106,23 @@ export const client: IAgoraRTCClient = AgoraRTC.createClient({
mode: "rtc",
codec: "vp8",
});
AgoraRTC.setLogLevel(3);

AgoraRTC.setLogLevel(4);

/*
0: DEBUG. Output all API logs.
1: INFO. Output logs of the INFO, WARNING and ERROR level.
2: WARNING. Output logs of the WARNING and ERROR level.
3: ERROR. Output logs of the ERROR level.
4: NONE. Do not output any log.
*/

let audioTrack: IMicrophoneAudioTrack;
let videoTrack: ICameraVideoTrack;
let screenShareStream: ILocalVideoTrack;
let userId: UID | null | undefined;
let rtmChannelResponse: RtmChannel;
let rtmClient: RtmClient;
const agoraTokenUrl = `https://sandbox.wiggolive.com/token/rtc`;

const generateToken = async (
appId: any,
certificate: any,
channelName: any
) => {
let response = await axios.post(agoraTokenUrl, {
appId,
certificate,
channelName,
});
return response.data;
};

const turnOnCamera = async (flag?: boolean) => {
if (videoTrack) {
@@ -147,7 +145,7 @@ const turnOnMicrophone = async (flag?: boolean) => {
};
const shareScreen = async (sharing: boolean) => {
try {
if (sharing == false) {
if (sharing === false) {
await client.unpublish(screenShareStream);
await client.publish(videoTrack);
videoTrack.play(userId + "");
@@ -179,23 +177,18 @@ const leaveChannel = async () => {
await rtmChannelResponse.leave();
};

const hostChanged = (users: any) => {};

const publishVideo = async (
appId: string,
channel: any,
height: any,
certifiCateKey: string
channel: string,
rtmToken: string,
rtcToken: string
) => {
let token = null;
if (certifiCateKey) {
token = await generateToken(appId, certifiCateKey, channel);
}
await turnOnCamera(true);
await client.join(appId, channel, token, userId);
await client.publish(videoTrack);

await rtmInit(appId, userId, channel);
// initializing the Agora Meeting Client
await turnOnCamera(true);
await client.join(appId, channel, rtcToken, userId);
await client.publish(videoTrack);
// initializing the Agora RTM Client
await rtmInit(appId, userId, rtmToken, channel);
};

const sendMessageRtm = (message: any) => {
@@ -206,10 +199,11 @@ const sendPeerMessageRtm = (message: any, toId: string) => {
rtmClient.sendMessageToPeer({ text: JSON.stringify(message) }, toId);
};

const rtmInit = async (appId: any, uid: any, channel: any) => {
const rtmInit = async (appId: any, uid: any, token: any, channel: any) => {
rtmClient = AgoraRTM.createInstance(appId);
let options = {
uid: String(uid),
token: token ? token : null,
};
await rtmClient.login(options);

@@ -237,8 +231,10 @@ export const meetingControllerChildren = {
participants: stateComp<JSONValue>([]),
usersScreenShared: stateComp<JSONValue>([]),
localUser: jsonObjectExposingStateControl(""),
meetingName: stringStateControl("meetingName"),
certifiCateKey: stringStateControl(""),
localUserID : withDefault(stringStateControl(trans("meeting.localUserID")), uuidv4() + ""),
meetingName: withDefault(stringStateControl(trans("meeting.meetingName")), uuidv4() + ""),
rtmToken: stringStateControl(trans("meeting.rtmToken")),
rtcToken: stringStateControl(trans("meeting.rtcToken")),
messages: stateComp<JSONValue>([]),
};
let MTComp = (function () {
@@ -269,34 +265,29 @@ let MTComp = (function () {
});
const [rtmMessages, setRtmMessages] = useState<any>([]);
const [localUserSpeaking, setLocalUserSpeaking] = useState<any>(false);
const [localUserVideo, setLocalUserVideo] =
useState<IAgoraRTCRemoteUser>();
const [localUserVideo, setLocalUserVideo] = useState<IAgoraRTCRemoteUser>();
const [userJoined, setUserJoined] = useState<IAgoraRTCRemoteUser>();
const [userLeft, setUserLeft] = useState<IAgoraRTCRemoteUser>();

useEffect(() => {
if (userJoined) {
let prevUsers: any[] = props.participants as [];
let userData = {
user: userJoined.uid,
host: false,
audiostatus: userJoined.hasAudio,
streamingVideo: true,
};
setUserIds((userIds: any) => [...userIds, userData]);
if (userIds.length == 0) {
userData.host = true;
} else {
userData.host = false;
}
dispatch(
changeChildAction(
"participants",
removeDuplicates(getData([...userIds, userData]).data, "user"),
removeDuplicates(getData([...prevUsers, userData]).data, "user"),
false
)
);
}
}, [userJoined]);

function removeDuplicates(arr: any, prop: any) {
const uniqueObjects = [];
const seenValues = new Set();
@@ -320,7 +311,6 @@ let MTComp = (function () {
let hostExists = newUsers.filter((f: any) => f.host === true);
if (hostExists.length == 0 && newUsers.length > 0) {
newUsers[0].host = true;
hostChanged(newUsers);
}
setUserIds(newUsers);
dispatch(
@@ -432,8 +422,6 @@ let MTComp = (function () {
client.on(
"user-unpublished",
(user: IAgoraRTCRemoteUser, mediaType: "video" | "audio") => {
console.log("user-unpublished");

setLocalUserVideo(user);
}
);
@@ -507,15 +495,6 @@ let MTComp = (function () {
.setPropertyViewFn((children) => (
<>
<Section name={sectionNames.basic}>
{children.appId.propertyView({ label: trans("meeting.appid") })}
{children.certifiCateKey.propertyView({
label: trans("meeting.certifiCateKey"),
})}

{children.meetingName.propertyView({
label: trans("meeting.meetingName"),
})}

{children.placement.propertyView({
label: trans("drawer.placement"),
radioButton: true,
@@ -541,6 +520,23 @@ let MTComp = (function () {
label: trans("prop.showMask"),
})}
</Section>
<Section name={sectionNames.meetings}>
{children.appId.propertyView({
label: trans("meeting.appid")
})}
{children.meetingName.propertyView({
label: trans("meeting.meetingName"),
})}
{children.localUserID.propertyView({
label: trans("meeting.localUserID"),
})}
{children.rtmToken.propertyView({
label: trans("meeting.rtmToken"),
})}
{children.rtcToken.propertyView({
label: trans("meeting.rtcToken"),
})}
</Section>
<Section name={sectionNames.interaction}>
{children.onEvent.getPropertyView()}
</Section>
@@ -636,7 +632,8 @@ MTComp = withMethodExposing(MTComp, [
params: [],
},
execute: async (comp, values) => {
userId = Math.floor(100000 + Math.random() * 900000);
if (comp.children.meetingActive.getView().value) return;
userId = comp.children.localUserID.getView().value === "" ? uuidv4() : comp.children.localUserID.getView().value;
comp.children.localUser.change({
user: userId + "",
audiostatus: false,
@@ -659,11 +656,9 @@ MTComp = withMethodExposing(MTComp, [
comp.children.videoControl.change(true);
await publishVideo(
comp.children.appId.getView(),
comp.children.meetingName.getView().value == ""
? "_meetingId"
: comp.children.meetingName.getView().value,
comp.children,
comp.children.certifiCateKey.getView().value
comp.children.meetingName.getView().value === "" ? uuidv4() : comp.children.meetingName.getView().value,
comp.children.rtmToken.getView().value,
comp.children.rtcToken.getView().value
);
comp.children.meetingActive.change(true);
},
@@ -677,9 +672,9 @@ MTComp = withMethodExposing(MTComp, [
execute: async (comp, values) => {
if (!comp.children.meetingActive.getView().value) return;
let otherData =
values != undefined && values[1] !== undefined ? values[1] : "";
values !== undefined && values[1] !== undefined ? values[1] : "";
let toUsers: any =
values != undefined && values[0] !== undefined ? values[0] : "";
values !== undefined && values[0] !== undefined ? values[0] : "";

let message: any = {
time: Date.now(),
@@ -711,7 +706,7 @@ MTComp = withMethodExposing(MTComp, [
{
method: {
name: "setUserName",
description: trans("meeting.meetingName"),
description: trans("meeting.userName"),
params: [],
},
execute: async (comp, values) => {
@@ -720,6 +715,28 @@ MTComp = withMethodExposing(MTComp, [
comp.children.localUser.change({ ...userLocal, userName: userName });
},
},
{
method: {
name: "setRTCToken",
description: trans("meeting.rtcToken"),
params: [],
},
execute: async (comp, values) => {
let rtcToken: any = values[0];
comp.children.rtcToken.change(rtcToken);
},
},
{
method: {
name: "setRTMToken",
description: trans("meeting.rtmToken"),
params: [],
},
execute: async (comp, values) => {
let rtmToken: any = values[0];
comp.children.rtmToken.change(rtmToken);
},
},
{
method: {
name: "endMeeting",
@@ -758,7 +775,10 @@ export const VideoMeetingControllerComp = withExposingConfigs(MTComp, [
new NameConfig("appId", trans("meeting.appid")),
new NameConfig("localUser", trans("meeting.host")),
new NameConfig("participants", trans("meeting.participants")),
new NameConfig("meetingActive", trans("meeting.meetingName")),
new NameConfig("meetingActive", trans("meeting.meetingActive")),
new NameConfig("meetingName", trans("meeting.meetingName")),
new NameConfig("messages", trans("meeting.meetingName")),
new NameConfig("localUserID", trans("meeting.localUserID")),
new NameConfig("messages", trans("meeting.messages")),
new NameConfig("rtmToken", trans("meeting.rtmToken")),
new NameConfig("rtcToken", trans("meeting.rtcToken")),
]);
Original file line number Diff line number Diff line change
@@ -151,10 +151,7 @@ export const meetingStreamChildren = {
style: ButtonStyleControl,
viewRef: RefControl<HTMLElement>,
userId: stringExposingStateControl(""),
profileImageUrl: withDefault(
StringStateControl,
"https://via.placeholder.com/120"
),
profileImageUrl: withDefault(StringStateControl, "https://api.dicebear.com/7.x/fun-emoji/svg?seed=Peanut&radius=50&backgroundColor=transparent&randomizeIds=true&eyes=wink,sleepClose"),
noVideoText: stringExposingStateControl("No Video"),
};

29 changes: 18 additions & 11 deletions client/packages/lowcoder/src/i18n/locales/en.ts
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@ import table from "./componentDocExtra/table.md?url";

export const en = {
productName: "Lowcoder",
productDesc: "Create software applications for your Company and your Customers with minimal coding experience. Lowcoder is the best Retool, Appsmith or Tooljet Alternative.",
productDesc:
"Create software applications for your Company and your Customers with minimal coding experience. Lowcoder is the best Retool, Appsmith or Tooljet Alternative.",
notSupportedBrowser:
"Your current browser may have compatibility issues. For a better user experience, it is recommended to use the latest version of the Chrome browser.",
create: "Create",
@@ -1441,6 +1442,7 @@ export const en = {
height: "Drawer height",
},
meeting: {
logLevel: "Agora SDK Log Level",
placement: "Meeting placement",
meeting: "Meeting Settings",
cameraView: "Camera View",
@@ -1454,17 +1456,21 @@ export const en = {
videoOn: "Video On",
size: "Size",
top: "Top",
host: "Host",
participants: "Participants",
shareScreen: "Share Screen",
appid: "Application Id",
host: "Host of the Meetingroom",
participants: "Participants of the Meetingroom",
shareScreen: "Local Screenshare",
appid: "Agora Application Id",
meetingName: "Meeting Name",
localUserID: "Host User Id",
userName: "Host User Name",
rtmToken : "Agora RTM Token",
rtcToken : "Agora RTC Token",
videoCompText: "No video Text",
profileImageUrl: "Profile Image Url",
right: "Right",
bottom: "Bottom",
videoId: "Video Id",
audioStatus: "audio status",
videoId: "Video Stream Id",
audioStatus: "Audio status",
left: "Left",
widthTooltip: "Number or percentage, e.g. 520, 60%",
heightTooltip: "Number, e.g. 378",
@@ -1474,18 +1480,19 @@ export const en = {
height: "Drawer height",
actionBtnDesc: "Action Button",
broadCast: "BroadCast Messages",
certifiCateKey: "certifiCate Key",
title: "Meeting title",
title: "Meeting Title",
meetingCompName: "Meeting Controller",
videoCompName: "Video Stream",
videoSharingCompName: "Video Sharing",
videoSharingCompName: "Screen Sharing",
meetingControlCompName: "Controls Buttons",
meetingCompDesc: "Meeting component",
meetingCompControls: "Meeting control",
meetingCompKeywords: "",
iconSize: "Icon Size",
userId: "userId",
roomId: "roomId",
meetingActive : "Ongoing Meeting",
messages : "Broadcasted Messages",
},
settings: {
title: "Settings",
@@ -2094,7 +2101,7 @@ export const en = {
resetSuccessDesc:
"Password reset succeeded. The new password is: {password}",
copyPassword: "Copy password",
poweredByLowcoder: "Powered by Lowcoder.cloud"
poweredByLowcoder: "Powered by Lowcoder.cloud",
},
preLoad: {
jsLibraryHelpText: