Skip to content

Commit c02d325

Browse files
authoredNov 21, 2023
Merge pull request #513 from lowcoder-org/agora-integrationn
Agora integrationn - Split into Video and Screen share Stream
·
v2.4.102.2.0
2 parents 480a4a2 + 39bbd15 commit c02d325

File tree

13 files changed

+565
-46
lines changed

13 files changed

+565
-46
lines changed
 
Lines changed: 20 additions & 1 deletion
Loading
Lines changed: 13 additions & 1 deletion
Loading
Lines changed: 20 additions & 1 deletion
Loading
Lines changed: 23 additions & 1 deletion
Loading
Lines changed: 10 additions & 3 deletions
Loading

‎client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingControllerComp.tsx

Lines changed: 78 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import { useUserViewMode } from "util/hooks";
4141
import { isNumeric } from "util/stringUtils";
4242
import { NameConfig, withExposingConfigs } from "../../generators/withExposing";
4343

44-
import { v4 as uuidv4 } from 'uuid';
44+
import { v4 as uuidv4 } from "uuid";
4545

4646
// import axios from "axios";
4747

@@ -147,6 +147,7 @@ const shareScreen = async (sharing: boolean) => {
147147
try {
148148
if (sharing === false) {
149149
await client.unpublish(screenShareStream);
150+
screenShareStream.close();
150151
await client.publish(videoTrack);
151152
videoTrack.play(userId + "");
152153
} else {
@@ -165,11 +166,16 @@ const shareScreen = async (sharing: boolean) => {
165166
}
166167
};
167168
const leaveChannel = async () => {
169+
//stops local sharing video
170+
screenShareStream.close();
171+
172+
//stops local video streaming and puts off the camera
168173
if (videoTrack) {
169174
await client.unpublish(videoTrack);
170175
await turnOnCamera(false);
171176
}
172177

178+
//mutes and stops locla audio stream
173179
if (audioTrack) {
174180
await turnOnMicrophone(false);
175181
}
@@ -183,12 +189,12 @@ const publishVideo = async (
183189
rtmToken: string,
184190
rtcToken: string
185191
) => {
186-
// initializing the Agora Meeting Client
187-
await turnOnCamera(true);
188-
await client.join(appId, channel, rtcToken, userId);
189-
await client.publish(videoTrack);
190-
// initializing the Agora RTM Client
191-
await rtmInit(appId, userId, rtmToken, channel);
192+
// initializing the Agora Meeting Client
193+
await turnOnCamera(true);
194+
await client.join(appId, channel, rtcToken, userId);
195+
await client.publish(videoTrack);
196+
// initializing the Agora RTM Client
197+
await rtmInit(appId, userId, rtmToken, channel);
192198
};
193199

194200
const sendMessageRtm = (message: any) => {
@@ -231,8 +237,14 @@ export const meetingControllerChildren = {
231237
participants: stateComp<JSONValue>([]),
232238
usersScreenShared: stateComp<JSONValue>([]),
233239
localUser: jsonObjectExposingStateControl(""),
234-
localUserID : withDefault(stringStateControl(trans("meeting.localUserID")), uuidv4() + ""),
235-
meetingName: withDefault(stringStateControl(trans("meeting.meetingName")), uuidv4() + ""),
240+
localUserID: withDefault(
241+
stringStateControl(trans("meeting.localUserID")),
242+
uuidv4() + ""
243+
),
244+
meetingName: withDefault(
245+
stringStateControl(trans("meeting.meetingName")),
246+
uuidv4() + ""
247+
),
236248
rtmToken: stringStateControl(trans("meeting.rtmToken")),
237249
rtcToken: stringStateControl(trans("meeting.rtcToken")),
238250
messages: stateComp<JSONValue>([]),
@@ -265,7 +277,8 @@ let MTComp = (function () {
265277
});
266278
const [rtmMessages, setRtmMessages] = useState<any>([]);
267279
const [localUserSpeaking, setLocalUserSpeaking] = useState<any>(false);
268-
const [localUserVideo, setLocalUserVideo] = useState<IAgoraRTCRemoteUser>();
280+
const [localUserVideo, setLocalUserVideo] =
281+
useState<IAgoraRTCRemoteUser>();
269282
const [userJoined, setUserJoined] = useState<IAgoraRTCRemoteUser>();
270283
const [userLeft, setUserLeft] = useState<IAgoraRTCRemoteUser>();
271284

@@ -323,6 +336,8 @@ let MTComp = (function () {
323336
}
324337
}, [userLeft]);
325338

339+
console.log("sharing", props.sharing);
340+
326341
useEffect(() => {
327342
if (updateVolume.userid) {
328343
let prevUsers: [] = props.participants as [];
@@ -342,6 +357,28 @@ let MTComp = (function () {
342357
}
343358
}, [updateVolume]);
344359

360+
useEffect(() => {
361+
let prevUsers: [] = props.participants as [];
362+
const updatedItems = prevUsers.map((userInfo: any) => {
363+
if (userInfo.user === localUserVideo?.uid) {
364+
return { ...userInfo, streamingSharing: props.sharing.value };
365+
}
366+
return userInfo;
367+
});
368+
dispatch(
369+
changeChildAction("participants", getData(updatedItems).data, false)
370+
);
371+
372+
let localObject = {
373+
user: userId + "",
374+
audiostatus: props.audioControl.value,
375+
streamingVideo: props.videoControl.value,
376+
streamingSharing: props.sharing.value,
377+
speaking: localUserSpeaking,
378+
};
379+
props.localUser.onChange(localObject);
380+
}, [props.sharing.value]);
381+
345382
useEffect(() => {
346383
let prevUsers: [] = props.participants as [];
347384
const updatedItems = prevUsers.map((userInfo: any) => {
@@ -383,37 +420,52 @@ let MTComp = (function () {
383420
if (prevMessages.length >= 500) {
384421
prevMessages.pop(); // Remove the oldest message
385422
}
386-
return [...prevMessages, {"peermessage" : JSON.parse(message.text + ""), "from" : peerId}];
423+
return [
424+
...prevMessages,
425+
{ peermessage: JSON.parse(message.text + ""), from: peerId },
426+
];
387427
});
388428
});
389-
429+
390430
rtmChannelResponse.on("ChannelMessage", function (message, memberId) {
391431
setRtmMessages((prevMessages: any[]) => {
392432
// Check if the messages array exceeds the maximum limit
393433
if (prevMessages.length >= 500) {
394434
prevMessages.pop(); // Remove the oldest message
395435
}
396-
return [...prevMessages, {"channelmessage" : JSON.parse(message.text + ""), "from" : memberId}];
436+
return [
437+
...prevMessages,
438+
{
439+
channelmessage: JSON.parse(message.text + ""),
440+
from: memberId,
441+
},
442+
];
397443
});
398-
399-
dispatch(changeChildAction("messages", getData(rtmMessages).data, false));
444+
445+
dispatch(
446+
changeChildAction("messages", getData(rtmMessages).data, false)
447+
);
400448
});
401449
}
402450
}, [rtmChannelResponse]);
403-
404451

405452
useEffect(() => {
406453
if (client) {
454+
//Enable Agora to send audio bytes
407455
client.enableAudioVolumeIndicator();
456+
//user activity listeners
408457
client.on("user-joined", (user: IAgoraRTCRemoteUser) => {
409458
setUserJoined(user);
410459
});
411460
client.on("user-left", (user: IAgoraRTCRemoteUser, reason: any) => {
412461
setUserLeft(user);
413462
});
463+
464+
//listen to user speaking,
414465
client.on("volume-indicator", (volumeInfos: any) => {
415466
if (volumeInfos.length === 0) return;
416467
volumeInfos.map((volumeInfo: any) => {
468+
//when the volume is above 30, user is probably speaking
417469
const speaking = volumeInfo.level >= 30;
418470
if (
419471
volumeInfo.uid === userId &&
@@ -534,8 +586,8 @@ let MTComp = (function () {
534586
})}
535587
</Section>
536588
<Section name={sectionNames.meetings}>
537-
{children.appId.propertyView({
538-
label: trans("meeting.appid")
589+
{children.appId.propertyView({
590+
label: trans("meeting.appid"),
539591
})}
540592
{children.meetingName.propertyView({
541593
label: trans("meeting.meetingName"),
@@ -646,7 +698,10 @@ MTComp = withMethodExposing(MTComp, [
646698
},
647699
execute: async (comp, values) => {
648700
if (comp.children.meetingActive.getView().value) return;
649-
userId = comp.children.localUserID.getView().value === "" ? uuidv4() : comp.children.localUserID.getView().value;
701+
userId =
702+
comp.children.localUserID.getView().value === ""
703+
? uuidv4()
704+
: comp.children.localUserID.getView().value;
650705
comp.children.localUser.change({
651706
user: userId + "",
652707
audiostatus: false,
@@ -669,7 +724,9 @@ MTComp = withMethodExposing(MTComp, [
669724
comp.children.videoControl.change(true);
670725
await publishVideo(
671726
comp.children.appId.getView(),
672-
comp.children.meetingName.getView().value === "" ? uuidv4() : comp.children.meetingName.getView().value,
727+
comp.children.meetingName.getView().value === ""
728+
? uuidv4()
729+
: comp.children.meetingName.getView().value,
673730
comp.children.rtmToken.getView().value,
674731
comp.children.rtcToken.getView().value
675732
);
@@ -790,7 +847,7 @@ export const VideoMeetingControllerComp = withExposingConfigs(MTComp, [
790847
new NameConfig("meetingActive", trans("meeting.meetingActive")),
791848
new NameConfig("meetingName", trans("meeting.meetingName")),
792849
new NameConfig("localUserID", trans("meeting.localUserID")),
793-
new NameConfig("messages", trans("meeting.messages")),
850+
new NameConfig("messages", trans("meeting.messages")),
794851
new NameConfig("rtmToken", trans("meeting.rtmToken")),
795852
new NameConfig("rtcToken", trans("meeting.rtcToken")),
796853
]);

‎client/packages/lowcoder/src/comps/comps/meetingComp/videoMeetingStreamComp.tsx

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,6 @@ const typeOptions = [
137137

138138
export const meetingStreamChildren = {
139139
autoHeight: withDefault(AutoHeightControl, "fixed"),
140-
shareScreen: withDefault(BoolShareVideoControl, false),
141140
profilePadding: withDefault(StringControl, "0px"),
142141
profileBorderRadius: withDefault(StringControl, "0px"),
143142
videoAspectRatio: withDefault(StringControl, "1 / 1"),
@@ -236,6 +235,9 @@ let VideoCompBuilder = (function (props) {
236235
}
237236
}, [props.userId.value]);
238237

238+
console.log(props.userId);
239+
240+
239241
return (
240242
<EditorContext.Consumer>
241243
{(editorState) => (
@@ -264,7 +266,7 @@ let VideoCompBuilder = (function (props) {
264266
borderRadius: props.style.radius,
265267
width: "auto",
266268
}}
267-
id={props.shareScreen ? "share-screen" : userId}
269+
id={userId}
268270
></VideoContainer>
269271
) : (
270272
<></>
@@ -300,9 +302,6 @@ let VideoCompBuilder = (function (props) {
300302
<Section name={sectionNames.basic}>
301303
{children.userId.propertyView({ label: trans("meeting.videoId") })}
302304
{children.autoHeight.getPropertyView()}
303-
{children.shareScreen.propertyView({
304-
label: trans("meeting.shareScreen"),
305-
})}
306305
{children.profileImageUrl.propertyView({
307306
label: trans("meeting.profileImageUrl"),
308307
placeholder: "https://via.placeholder.com/120",
Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
import { BoolCodeControl } from "comps/controls/codeControl";
2+
import { dropdownControl } from "comps/controls/dropdownControl";
3+
// import { IconControl } from "comps/controls/iconControl";
4+
import { CompNameContext, EditorContext, EditorState } from "comps/editorState";
5+
import { withDefault } from "comps/generators";
6+
import { UICompBuilder } from "comps/generators/uiCompBuilder";
7+
import ReactResizeDetector from "react-resize-detector";
8+
// import _ from "lodash";
9+
import {
10+
CommonBlueLabel,
11+
controlItem,
12+
Dropdown,
13+
Section,
14+
sectionNames,
15+
} from "lowcoder-design";
16+
import { trans } from "i18n";
17+
18+
import styled, { css } from "styled-components";
19+
import {
20+
CommonNameConfig,
21+
NameConfig,
22+
withExposingConfigs,
23+
} from "../../generators/withExposing";
24+
import { IForm } from "../formComp/formDataConstants";
25+
import { SimpleNameComp } from "../simpleNameComp";
26+
import { ButtonStyleControl } from "./videobuttonCompConstants";
27+
import { RefControl } from "comps/controls/refControl";
28+
import { useEffect, useRef, useState } from "react";
29+
30+
import { AutoHeightControl } from "comps/controls/autoHeightControl";
31+
import { client } from "./videoMeetingControllerComp";
32+
33+
import { IAgoraRTCRemoteUser } from "agora-rtc-sdk-ng";
34+
35+
import {
36+
MeetingEventHandlerControl,
37+
StringControl,
38+
StringStateControl,
39+
hiddenPropertyView,
40+
stringExposingStateControl,
41+
} from "@lowcoder-ee/index.sdk";
42+
import { BoolShareVideoControl } from "./meetingControlerUtils";
43+
44+
const FormLabel = styled(CommonBlueLabel)`
45+
font-size: 13px;
46+
margin-right: 4px;
47+
`;
48+
49+
function getFormOptions(editorState: EditorState) {
50+
return editorState
51+
.uiCompInfoList()
52+
.filter((info) => info.type === "form")
53+
.map((info) => ({
54+
label: info.name,
55+
value: info.name,
56+
}));
57+
}
58+
59+
const VideoContainer = styled.video`
60+
height: 100%;
61+
width: 100%;
62+
display: flex;
63+
align-items: center;
64+
justify-content: space-around;
65+
`;
66+
67+
function getForm(editorState: EditorState, formName: string) {
68+
const comp = editorState?.getUICompByName(formName);
69+
if (comp && comp.children.compType.getView() === "form") {
70+
return comp.children.comp as unknown as IForm;
71+
}
72+
}
73+
74+
function getFormEventHandlerPropertyView(
75+
editorState: EditorState,
76+
formName: string
77+
) {
78+
const form = getForm(editorState, formName);
79+
if (!form) {
80+
return undefined;
81+
}
82+
83+
return (
84+
<CompNameContext.Provider value={formName}>
85+
{form.onEventPropertyView(
86+
<>
87+
<FormLabel
88+
onClick={() =>
89+
editorState.setSelectedCompNames(
90+
new Set([formName]),
91+
"rightPanel"
92+
)
93+
}
94+
>
95+
{formName}
96+
</FormLabel>
97+
{trans("button.formButtonEvent")}
98+
</>
99+
)}
100+
</CompNameContext.Provider>
101+
);
102+
}
103+
104+
class SelectFormControl extends SimpleNameComp {
105+
override getPropertyView() {
106+
const label = trans("button.formToSubmit");
107+
return controlItem(
108+
{ filterText: label },
109+
<EditorContext.Consumer>
110+
{(editorState) => (
111+
<>
112+
<Dropdown
113+
label={label}
114+
value={this.value}
115+
options={getFormOptions(editorState)}
116+
onChange={(value) => this.dispatchChangeValueAction(value)}
117+
allowClear={true}
118+
/>
119+
{getFormEventHandlerPropertyView(editorState, this.value)}
120+
</>
121+
)}
122+
</EditorContext.Consumer>
123+
);
124+
}
125+
}
126+
127+
const typeOptions = [
128+
{
129+
label: trans("button.default"),
130+
value: "",
131+
},
132+
{
133+
label: trans("button.submit"),
134+
value: "submit",
135+
},
136+
] as const;
137+
138+
export const meetingStreamChildren = {
139+
autoHeight: withDefault(AutoHeightControl, "fixed"),
140+
profilePadding: withDefault(StringControl, "0px"),
141+
profileBorderRadius: withDefault(StringControl, "0px"),
142+
videoAspectRatio: withDefault(StringControl, "1 / 1"),
143+
type: dropdownControl(typeOptions, ""),
144+
onEvent: MeetingEventHandlerControl,
145+
disabled: BoolCodeControl,
146+
loading: BoolCodeControl,
147+
form: SelectFormControl,
148+
// prefixIcon: IconControl,
149+
// suffixIcon: IconControl,
150+
style: ButtonStyleControl,
151+
viewRef: RefControl<HTMLElement>,
152+
userId: stringExposingStateControl(""),
153+
profileImageUrl: withDefault(
154+
StringStateControl,
155+
"https://api.dicebear.com/7.x/fun-emoji/svg?seed=Peanut&radius=50&backgroundColor=transparent&randomizeIds=true&eyes=wink,sleepClose"
156+
),
157+
noVideoText: stringExposingStateControl("No Video"),
158+
};
159+
160+
let SharingCompBuilder = (function (props) {
161+
return new UICompBuilder(meetingStreamChildren, (props) => {
162+
const videoRef = useRef<HTMLVideoElement>(null);
163+
const conRef = useRef<HTMLDivElement>(null);
164+
const [userId, setUserId] = useState();
165+
const [userName, setUsername] = useState("");
166+
const [showVideoSharing, setVideoSharing] = useState(true);
167+
168+
useEffect(() => {
169+
if (props.userId.value !== "") {
170+
let userData = JSON.parse(props.userId?.value);
171+
client.on(
172+
"user-published",
173+
async (user: IAgoraRTCRemoteUser, mediaType: "video" | "audio") => {
174+
if (mediaType === "video") {
175+
const remoteTrack = await client.subscribe(user, mediaType);
176+
let userId = user.uid + "";
177+
if (
178+
user.hasVideo &&
179+
user.uid + "" !== userData.user &&
180+
userData.user !== ""
181+
) {
182+
props.onEvent("videoOn");
183+
}
184+
const element = document.getElementById(userId);
185+
186+
if (element) {
187+
remoteTrack.play(userId);
188+
}
189+
}
190+
if (mediaType === "audio") {
191+
const remoteTrack = await client.subscribe(user, mediaType);
192+
if (
193+
user.hasAudio &&
194+
user.uid + "" !== userData.user &&
195+
userData.user !== ""
196+
) {
197+
userData.audiostatus = user.hasVideo;
198+
199+
props.onEvent("audioUnmuted");
200+
}
201+
remoteTrack.play();
202+
}
203+
}
204+
);
205+
client.on(
206+
"user-unpublished",
207+
(user: IAgoraRTCRemoteUser, mediaType: "video" | "audio") => {
208+
console.log("user-unpublished");
209+
210+
if (mediaType === "audio") {
211+
if (
212+
!user.hasAudio &&
213+
user.uid + "" !== userData.user &&
214+
userData.user !== ""
215+
) {
216+
userData.audiostatus = user.hasVideo;
217+
props.onEvent("audioMuted");
218+
}
219+
}
220+
if (mediaType === "video") {
221+
if (videoRef.current && videoRef.current?.id === user.uid + "") {
222+
videoRef.current.srcObject = null;
223+
}
224+
if (
225+
!user.hasVideo &&
226+
user.uid + "" !== userData.user &&
227+
userData.user !== ""
228+
) {
229+
props.onEvent("videoOff");
230+
}
231+
}
232+
}
233+
);
234+
235+
setUserId(userData.user);
236+
setUsername(userData.userName);
237+
setVideoSharing(userData.streamingSharing);
238+
}
239+
}, [props.userId.value]);
240+
241+
return (
242+
<EditorContext.Consumer>
243+
{(editorState) => (
244+
<ReactResizeDetector>
245+
<div
246+
ref={conRef}
247+
style={{
248+
display: "flex",
249+
alignItems: "center",
250+
height: "100%",
251+
overflow: "hidden",
252+
borderRadius: props.style.radius,
253+
aspectRatio: props.videoAspectRatio,
254+
backgroundColor: props.style.background,
255+
padding: props.style.padding,
256+
margin: props.style.margin,
257+
}}
258+
>
259+
{userId ? (
260+
<VideoContainer
261+
onClick={() => props.onEvent("videoClicked")}
262+
ref={videoRef}
263+
style={{
264+
display: `${showVideoSharing ? "flex" : "none"}`,
265+
aspectRatio: props.videoAspectRatio,
266+
borderRadius: props.style.radius,
267+
width: "auto",
268+
}}
269+
id="share-screen"
270+
></VideoContainer>
271+
) : (
272+
<></>
273+
)}
274+
<div
275+
style={{
276+
flexDirection: "column",
277+
alignItems: "center",
278+
display: `${!showVideoSharing || userId ? "flex" : "none"}`,
279+
margin: "0 auto",
280+
padding: props.profilePadding,
281+
}}
282+
>
283+
<img
284+
alt=""
285+
style={{
286+
borderRadius: props.profileBorderRadius,
287+
width: "100%",
288+
overflow: "hidden",
289+
}}
290+
src={props.profileImageUrl.value}
291+
/>
292+
<p style={{ margin: "0" }}>{userName ?? ""}</p>
293+
</div>
294+
</div>
295+
</ReactResizeDetector>
296+
)}
297+
</EditorContext.Consumer>
298+
);
299+
})
300+
.setPropertyViewFn((children) => (
301+
<>
302+
<Section name={sectionNames.basic}>
303+
{children.userId.propertyView({ label: trans("meeting.videoId") })}
304+
{children.autoHeight.getPropertyView()}
305+
{children.profileImageUrl.propertyView({
306+
label: trans("meeting.profileImageUrl"),
307+
placeholder: "https://via.placeholder.com/120",
308+
})}
309+
</Section>
310+
311+
<Section name={sectionNames.interaction}>
312+
{children.onEvent.getPropertyView()}
313+
</Section>
314+
<Section name={sectionNames.layout}>
315+
{hiddenPropertyView(children)}
316+
</Section>
317+
<Section name={sectionNames.style}>
318+
{children.profilePadding.propertyView({
319+
label: "Profile Image Padding",
320+
})}
321+
{children.profileBorderRadius.propertyView({
322+
label: "Profile Image Border Radius",
323+
})}
324+
{children.videoAspectRatio.propertyView({
325+
label: "Video Aspect Ratio",
326+
})}
327+
{children.style.getPropertyView()}
328+
</Section>
329+
</>
330+
))
331+
.build();
332+
})();
333+
334+
SharingCompBuilder = class extends SharingCompBuilder {
335+
override autoHeight(): boolean {
336+
return this.children.autoHeight.getView();
337+
}
338+
};
339+
340+
export const VideoSharingStreamComp = withExposingConfigs(SharingCompBuilder, [
341+
new NameConfig("loading", trans("button.loadingDesc")),
342+
new NameConfig("profileImageUrl", trans("meeting.profileImageUrl")),
343+
344+
...CommonNameConfig,
345+
]);

‎client/packages/lowcoder/src/comps/index.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ import { ResponsiveLayoutComp } from "./comps/responsiveLayout";
142142
import { VideoMeetingStreamComp } from "./comps/meetingComp/videoMeetingStreamComp";
143143
import { ControlButton } from "./comps/meetingComp/controlButton";
144144
import { VideoMeetingControllerComp } from "./comps/meetingComp/videoMeetingControllerComp";
145+
import { VideoSharingStreamComp } from "./comps/meetingComp/videoSharingStreamComp";
145146

146147
type Registry = {
147148
[key in UICompType]?: UICompManifest;
@@ -560,7 +561,17 @@ const uiCompMap: Registry = {
560561
},
561562
defaultDataFn: defaultContainerData,
562563
},
563-
564+
//ADDED BY FRED
565+
sharingcomponent: {
566+
name: trans("meeting.sharingCompName"),
567+
enName: "Sharing",
568+
description: trans("meeting.sharingCompName"),
569+
categories: ["meeting"],
570+
icon: VideoCompIcon,
571+
keywords: trans("meeting.meetingCompKeywords"),
572+
comp: VideoSharingStreamComp,
573+
withoutLoading: true,
574+
},
564575
videocomponent: {
565576
name: trans("meeting.videoCompName"),
566577
enName: "Video",
@@ -581,6 +592,7 @@ const uiCompMap: Registry = {
581592
comp: ControlButton,
582593
withoutLoading: true,
583594
},
595+
//END
584596
tabbedContainer: {
585597
name: trans("uiComp.tabbedContainerCompName"),
586598
enName: "Tabbed Container",
@@ -931,7 +943,7 @@ const uiCompMap: Registry = {
931943
layoutInfo: {
932944
w: 13,
933945
h: 55,
934-
}
946+
},
935947
},
936948
mention: {
937949
name: trans("uiComp.mentionCompName"),

‎client/packages/lowcoder/src/comps/uiCompRegistry.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export type UICompType =
5858
| "chart"
5959
| "meeting"
6060
| "videocomponent"
61+
| "sharingcomponent"
6162
| "controlButton"
6263
| "imageEditor"
6364
| "calendar"

‎client/packages/lowcoder/src/i18n/locales/en.ts

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,7 @@ export const en = {
861861
audioCompDesc: "Audio component",
862862
audioCompKeywords: "",
863863
videoCompName: "Video",
864+
sharingCompName: "Sharing",
864865
videoCompDesc: "Video component",
865866
videoCompKeywords: "",
866867
drawerCompName: "Drawer",
@@ -1466,8 +1467,8 @@ export const en = {
14661467
meetingName: "Meeting Name",
14671468
localUserID: "Host User Id",
14681469
userName: "Host User Name",
1469-
rtmToken : "Agora RTM Token",
1470-
rtcToken : "Agora RTC Token",
1470+
rtmToken: "Agora RTM Token",
1471+
rtcToken: "Agora RTC Token",
14711472
videoCompText: "No video Text",
14721473
profileImageUrl: "Profile Image Url",
14731474
right: "Right",
@@ -1484,18 +1485,21 @@ export const en = {
14841485
actionBtnDesc: "Action Button",
14851486
broadCast: "BroadCast Messages",
14861487
title: "Meeting Title",
1487-
meetingCompName: "Meeting Controller",
1488-
videoCompName: "Video Stream",
1489-
videoSharingCompName: "Screen Sharing",
1490-
meetingControlCompName: "Controls Buttons",
1491-
meetingCompDesc: "Meeting component",
1492-
meetingCompControls: "Meeting control",
1493-
meetingCompKeywords: "",
1488+
//ADDED BY FRED
1489+
meetingCompName: "Agora Meeting Controller",
1490+
sharingCompName: "Screen share Stream",
1491+
videoCompName: "Camera Stream",
1492+
videoSharingCompName: "Screen share Stream",
1493+
meetingControlCompName: "Control Button",
1494+
meetingCompDesc: "Meeting Component",
1495+
meetingCompControls: "Meeting Control",
1496+
meetingCompKeywords: "Agora Meeting, Web Meeting, Collaboration",
1497+
//END
14941498
iconSize: "Icon Size",
14951499
userId: "userId",
14961500
roomId: "roomId",
1497-
meetingActive : "Ongoing Meeting",
1498-
messages : "Broadcasted Messages",
1501+
meetingActive: "Ongoing Meeting",
1502+
messages: "Broadcasted Messages",
14991503
},
15001504
settings: {
15011505
title: "Settings",
@@ -1844,6 +1848,8 @@ export const en = {
18441848
preloadLibsEmpty: "No JavaScript libraries were added",
18451849
preloadLibsAddBtn: "Add a library",
18461850
saveSuccess: "Saved successfully",
1851+
AuthOrgTitle: "Workspace welcome Screen",
1852+
AuthOrgDescrition: "The URL for your users to Sign in to the current workspace.",
18471853
},
18481854
branding: {
18491855
title: "Branding",

‎client/packages/lowcoder/src/pages/editor/editorConstants.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ export const CompStateIcon: {
8888
meeting: <LeftMeeting />,
8989
mermaid: <LeftChart />,
9090
videocomponent: <LeftMeeting />,
91+
sharingcomponent: <LeftMeeting />,
9192
controlButton: <LeftButton />,
9293
tabbedContainer: <LeftContainer />,
9394
modal: <LeftModal />,

‎client/packages/lowcoder/src/pages/setting/idSource/list.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { messageInstance, AddIcon } from "lowcoder-design";
3434
import { currentOrgAdmin } from "../../../util/permissionUtils";
3535
import CreateModal from "./createModal";
3636
import _ from "lodash";
37+
import { HelpText } from "components/HelpText";
3738

3839
export const IdSourceList = (props: any) => {
3940
const user = useSelector(getUser);
@@ -44,6 +45,18 @@ export const IdSourceList = (props: any) => {
4445
const [modalVisible, setModalVisible] = useState(false);
4546
const enableEnterpriseLogin = useSelector(selectSystemConfig)?.featureFlag?.enableEnterpriseLogin;
4647

48+
let protocol = window.location.protocol;
49+
const port = window.location.port;
50+
let currentDomain = window.location.hostname;
51+
52+
// Show port only if it is not a standard port
53+
if (port && port !== '80' && port !== '443') {
54+
currentDomain += `:${port}`;
55+
}
56+
57+
const redirectUrl = encodeURIComponent(`${protocol}//${currentDomain}/apps`);
58+
const loginUrl = `${protocol}//${currentDomain}/org/${currentOrgId}/auth/login?redirectUrl=${encodeURIComponent(redirectUrl)}`;
59+
4760
useEffect(() => {
4861
if (!currentOrgId) {
4962
return;
@@ -154,6 +167,11 @@ export const IdSourceList = (props: any) => {
154167
)}
155168
/>
156169
</TableStyled>
170+
171+
<div style={{ marginTop: 20, marginLeft: 12 }} className="section-title">{trans("advanced.AuthOrgTitle")}</div>
172+
<HelpText style={{ marginBottom: 12, marginLeft: 12 }}>{trans("advanced.AuthOrgDescrition") + ": "}</HelpText>
173+
<HelpText style={{ marginBottom: 12, marginLeft: 12 }}><a href={loginUrl} target="blank">{loginUrl}</a></HelpText>
174+
157175
</Level1SettingPageContentWithList>
158176
<CreateModal
159177
modalVisible={modalVisible}
@@ -167,3 +185,4 @@ export const IdSourceList = (props: any) => {
167185
</>
168186
);
169187
};
188+

0 commit comments

Comments
 (0)
Please sign in to comment.