diff --git a/client/packages/lowcoder-design/src/components/Section.tsx b/client/packages/lowcoder-design/src/components/Section.tsx
index feae5402a..a0c18134f 100644
--- a/client/packages/lowcoder-design/src/components/Section.tsx
+++ b/client/packages/lowcoder-design/src/components/Section.tsx
@@ -142,4 +142,5 @@ export const sectionNames = {
validation: trans("prop.validation"),
layout: trans("prop.layout"),
style: trans("prop.style"),
+ meetings : trans("prop.meetings"),
};
diff --git a/client/packages/lowcoder-design/src/i18n/design/locales/en.ts b/client/packages/lowcoder-design/src/i18n/design/locales/en.ts
index 0082f6f98..59e045b55 100644
--- a/client/packages/lowcoder-design/src/i18n/design/locales/en.ts
+++ b/client/packages/lowcoder-design/src/i18n/design/locales/en.ts
@@ -23,6 +23,7 @@ export const en = {
validation: "Validation",
layout: "Layout",
style: "Style",
+ meetings : "Meeting Settings",
},
passwordInput: {
label: "Password:",
diff --git a/client/packages/lowcoder/src/comps/comps/meetingComp/controlButton.tsx b/client/packages/lowcoder/src/comps/comps/meetingComp/controlButton.tsx
index d3ad399a5..b6034a6db 100644
--- a/client/packages/lowcoder/src/comps/comps/meetingComp/controlButton.tsx
+++ b/client/packages/lowcoder/src/comps/comps/meetingComp/controlButton.tsx
@@ -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 () {
{children.style.getPropertyView()}
+ {children.aspectRatio.propertyView({
+ label: "Video Aspect Ratio",
+ })}
>
))
diff --git a/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx b/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx
index 427feabb3..49a5f2cbb 100644
--- a/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx
@@ -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,7 +106,16 @@ 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;
@@ -111,20 +123,6 @@ 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([]),
usersScreenShared: stateComp([]),
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([]),
};
let MTComp = (function () {
@@ -269,34 +265,29 @@ let MTComp = (function () {
});
const [rtmMessages, setRtmMessages] = useState([]);
const [localUserSpeaking, setLocalUserSpeaking] = useState(false);
- const [localUserVideo, setLocalUserVideo] =
- useState();
+ const [localUserVideo, setLocalUserVideo] = useState();
const [userJoined, setUserJoined] = useState();
const [userLeft, setUserLeft] = useState();
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) => (
<>
- {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"),
})}
+
+ {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"),
+ })}
+
{children.onEvent.getPropertyView()}
@@ -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")),
]);
diff --git a/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx b/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx
index 2218ba0c3..5fbc372b7 100644
--- a/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx
+++ b/client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx
@@ -151,10 +151,7 @@ export const meetingStreamChildren = {
style: ButtonStyleControl,
viewRef: RefControl,
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"),
};
diff --git a/client/packages/lowcoder/src/i18n/locales/en.ts b/client/packages/lowcoder/src/i18n/locales/en.ts
index 7f20f9c9e..40138fb17 100644
--- a/client/packages/lowcoder/src/i18n/locales/en.ts
+++ b/client/packages/lowcoder/src/i18n/locales/en.ts
@@ -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,11 +1480,10 @@ 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",
@@ -1486,6 +1491,8 @@ export const en = {
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: