agora-appbuilder-core 4.1.19-beta.4 → 4.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/bridge/rtc/webNg/RtcEngine.ts +320 -83
- package/template/customization-api/atoms.ts +0 -2
- package/template/customization-api/customEvents.ts +1 -4
- package/template/customization-api/index.ts +0 -1
- package/template/customization-api/typeDefinition.ts +1 -6
- package/template/defaultConfig.js +2 -2
- package/template/src/components/Controls.tsx +3 -1
- package/template/src/components/CustomSidePanel.tsx +13 -13
- package/template/src/components/RTMConfigure.tsx +0 -13
- package/template/src/components/livestream/LiveStreamContext.tsx +6 -2
- package/template/src/components/participants/UserActionMenuOptions.tsx +2 -29
- package/template/src/pages/Create.tsx +19 -31
- package/template/src/pages/video-call/ActionSheet.native.tsx +0 -2
- package/template/src/pages/video-call/ActionSheet.tsx +0 -2
- package/template/src/pages/video-call/ActionSheetHandle.tsx +0 -1
- package/template/src/pages/video-call/SidePanelHeader.tsx +1 -3
- package/template/src/pages/video-call/VideoCallScreen.tsx +0 -3
- package/template/src/pages/video-call/VideoRenderer.tsx +0 -4
- package/template/src/subComponents/LocalEndCall.tsx +1 -1
- package/template/src/subComponents/ScreenShareNotice.tsx +1 -1
- package/template/src/subComponents/SidePanelHeader.tsx +2 -16
- package/template/src/subComponents/recording/__tests__/recordingJourney.test.ts +25 -0
- package/template/src/subComponents/recording/__tests__/recordingLayoutResponse.test.ts +56 -0
- package/template/src/subComponents/recording/recordingJourney.ts +12 -0
- package/template/src/subComponents/recording/recordingLayoutResponse.ts +67 -0
- package/template/src/subComponents/recording/useRecording.tsx +28 -12
- package/template/src/subComponents/recording/useRecordingLayoutQuery.tsx +35 -45
- package/template/src/subComponents/screenshare/ScreenshareButton.tsx +1 -1
- package/template/src/subComponents/screenshare/ScreenshareConfigure.tsx +483 -31
- package/template/src/subComponents/screenshare/__tests__/screenshareJourney.test.ts +63 -0
- package/template/src/subComponents/screenshare/screenshareJourney.ts +43 -0
- package/template/src/subComponents/screenshare/useScreenshare.tsx +18 -2
- package/template/customization-api/ai-agent.ts +0 -4
package/package.json
CHANGED
|
@@ -45,6 +45,7 @@ import {
|
|
|
45
45
|
type ScreenEncoderConfigurationPreset,
|
|
46
46
|
type VideoEncoderConfiguration,
|
|
47
47
|
} from '../../../src/app-state/useVideoQuality';
|
|
48
|
+
import {getScreenshareReleaseOrigin} from '../../../src/subComponents/screenshare/screenshareJourney';
|
|
48
49
|
|
|
49
50
|
interface MediaDeviceInfo {
|
|
50
51
|
readonly deviceId: string;
|
|
@@ -54,6 +55,21 @@ interface MediaDeviceInfo {
|
|
|
54
55
|
|
|
55
56
|
type callbackType = (uid?: UID) => void;
|
|
56
57
|
|
|
58
|
+
const getScreenshareErrorDetails = (error: unknown) => {
|
|
59
|
+
const sdkError = error as {
|
|
60
|
+
code?: string | number;
|
|
61
|
+
name?: string;
|
|
62
|
+
message?: string;
|
|
63
|
+
};
|
|
64
|
+
return {
|
|
65
|
+
sdkErrorCode: sdkError?.code,
|
|
66
|
+
sdkErrorName: sdkError?.name,
|
|
67
|
+
sdkErrorMessage:
|
|
68
|
+
sdkError?.message ||
|
|
69
|
+
(error instanceof Error ? error.message : String(error)),
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
57
73
|
declare global {
|
|
58
74
|
interface Window {
|
|
59
75
|
engine: RtcEngine;
|
|
@@ -237,6 +253,13 @@ export default class RtcEngine {
|
|
|
237
253
|
public screenStream: ScreenStream = {};
|
|
238
254
|
public remoteStreams = new Map<UID, RemoteStream>();
|
|
239
255
|
private inScreenshare: Boolean = false;
|
|
256
|
+
private isScreenshareCleanupInProgress = false;
|
|
257
|
+
private activeScreenshareJourneyContext: {
|
|
258
|
+
screenshareSessionId?: string;
|
|
259
|
+
recordingActive?: boolean;
|
|
260
|
+
screenShareUid?: UID;
|
|
261
|
+
stopActorUid?: UID;
|
|
262
|
+
} | null = null;
|
|
240
263
|
private videoProfile:
|
|
241
264
|
| VideoEncoderConfigurationPreset
|
|
242
265
|
| VideoEncoderConfiguration;
|
|
@@ -1466,13 +1489,13 @@ export default class RtcEngine {
|
|
|
1466
1489
|
this.client.setEncryptionConfig(
|
|
1467
1490
|
mode,
|
|
1468
1491
|
config.encryptionKey,
|
|
1469
|
-
config.encryptionMode === 1? null:config.encryptionKdfSalt,
|
|
1492
|
+
config.encryptionMode === 1 ? null : config.encryptionKdfSalt,
|
|
1470
1493
|
true, // encryptDataStream
|
|
1471
1494
|
),
|
|
1472
1495
|
this.screenClient.setEncryptionConfig(
|
|
1473
1496
|
mode,
|
|
1474
1497
|
config.encryptionKey,
|
|
1475
|
-
config.encryptionMode === 1? null:config.encryptionKdfSalt,
|
|
1498
|
+
config.encryptionMode === 1 ? null : config.encryptionKdfSalt,
|
|
1476
1499
|
true, // encryptDataStream
|
|
1477
1500
|
),
|
|
1478
1501
|
]);
|
|
@@ -1518,14 +1541,75 @@ export default class RtcEngine {
|
|
|
1518
1541
|
// this.client.removeAllListeners(eventName);
|
|
1519
1542
|
// }
|
|
1520
1543
|
|
|
1521
|
-
async release(
|
|
1544
|
+
async release(
|
|
1545
|
+
requestedStopOrigin?: 'end_call_cleanup' | 'page_unload',
|
|
1546
|
+
): Promise<void> {
|
|
1547
|
+
const stopOrigin = getScreenshareReleaseOrigin(
|
|
1548
|
+
requestedStopOrigin,
|
|
1549
|
+
typeof document !== 'undefined' ? document.visibilityState : undefined,
|
|
1550
|
+
);
|
|
1522
1551
|
if (this.inScreenshare) {
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1552
|
+
const screenshareAttemptId = `release-${Date.now()}`;
|
|
1553
|
+
const journeyData = {
|
|
1554
|
+
action: 'stop',
|
|
1555
|
+
stage: 'release',
|
|
1556
|
+
outcome: 'started',
|
|
1557
|
+
screenshareAttemptId,
|
|
1558
|
+
screenshareSessionId:
|
|
1559
|
+
this.activeScreenshareJourneyContext?.screenshareSessionId ||
|
|
1560
|
+
'unknown-session',
|
|
1561
|
+
recordingActive:
|
|
1562
|
+
this.activeScreenshareJourneyContext?.recordingActive || false,
|
|
1563
|
+
screenShareUid:
|
|
1564
|
+
this.activeScreenshareJourneyContext?.screenShareUid ||
|
|
1565
|
+
this.screenClient.uid,
|
|
1566
|
+
stopOrigin,
|
|
1567
|
+
stopActorUid:
|
|
1568
|
+
this.activeScreenshareJourneyContext?.stopActorUid || undefined,
|
|
1569
|
+
};
|
|
1570
|
+
logger.log(
|
|
1571
|
+
LogSource.AgoraSDK,
|
|
1572
|
+
'API',
|
|
1573
|
+
`[SCREENSHARE_JOURNEY] screen share stop release cleanup calling screenClient.leave from ${stopOrigin}`,
|
|
1574
|
+
journeyData,
|
|
1526
1575
|
);
|
|
1527
|
-
|
|
1528
|
-
|
|
1576
|
+
try {
|
|
1577
|
+
(this.eventsMap.get('onUserOffline') as callbackType)(
|
|
1578
|
+
{},
|
|
1579
|
+
this.screenClient.uid,
|
|
1580
|
+
);
|
|
1581
|
+
this.screenStream.audio?.stop();
|
|
1582
|
+
this.screenStream.video?.stop();
|
|
1583
|
+
this.screenStream.audio?.close();
|
|
1584
|
+
this.screenStream.video?.close();
|
|
1585
|
+
await this.screenClient.leave();
|
|
1586
|
+
this.inScreenshare = false;
|
|
1587
|
+
(this.eventsMap.get('onScreenshareStopped') as callbackType)(
|
|
1588
|
+
stopOrigin,
|
|
1589
|
+
screenshareAttemptId,
|
|
1590
|
+
journeyData.screenshareSessionId,
|
|
1591
|
+
journeyData.stopActorUid,
|
|
1592
|
+
);
|
|
1593
|
+
logger.log(
|
|
1594
|
+
LogSource.AgoraSDK,
|
|
1595
|
+
'API',
|
|
1596
|
+
`[SCREENSHARE_JOURNEY] screen share stop release cleanup completed successfully from ${stopOrigin}`,
|
|
1597
|
+
{...journeyData, outcome: 'success'},
|
|
1598
|
+
);
|
|
1599
|
+
} catch (error) {
|
|
1600
|
+
logger.error(
|
|
1601
|
+
LogSource.AgoraSDK,
|
|
1602
|
+
'API',
|
|
1603
|
+
`[SCREENSHARE_JOURNEY] screen share stop release cleanup failed from ${stopOrigin}`,
|
|
1604
|
+
{
|
|
1605
|
+
...journeyData,
|
|
1606
|
+
outcome: 'failure',
|
|
1607
|
+
...getScreenshareErrorDetails(error),
|
|
1608
|
+
},
|
|
1609
|
+
);
|
|
1610
|
+
} finally {
|
|
1611
|
+
this.activeScreenshareJourneyContext = null;
|
|
1612
|
+
}
|
|
1529
1613
|
}
|
|
1530
1614
|
this.eventsMap.forEach((callback, event, map) => {
|
|
1531
1615
|
this.client.off(event, callback);
|
|
@@ -1587,17 +1671,110 @@ export default class RtcEngine {
|
|
|
1587
1671
|
encoderConfig: this.screenShareProfile,
|
|
1588
1672
|
},
|
|
1589
1673
|
audio: 'enable' | 'disable' | 'auto' = 'auto',
|
|
1674
|
+
journeyContext: {
|
|
1675
|
+
action?: 'start' | 'stop';
|
|
1676
|
+
screenshareAttemptId?: string;
|
|
1677
|
+
screenshareSessionId?: string;
|
|
1678
|
+
recordingActive?: boolean;
|
|
1679
|
+
screenShareUid?: UID;
|
|
1680
|
+
stopOrigin?: string;
|
|
1681
|
+
stopActorUid?: UID;
|
|
1682
|
+
} = {},
|
|
1590
1683
|
): Promise<void> {
|
|
1684
|
+
const journeyData = {
|
|
1685
|
+
action: journeyContext.action || (this.inScreenshare ? 'stop' : 'start'),
|
|
1686
|
+
screenshareAttemptId:
|
|
1687
|
+
journeyContext.screenshareAttemptId || 'rtc-unknown-attempt',
|
|
1688
|
+
screenshareSessionId:
|
|
1689
|
+
journeyContext.screenshareSessionId || 'unknown-session',
|
|
1690
|
+
recordingActive: journeyContext.recordingActive || false,
|
|
1691
|
+
screenShareUid: journeyContext.screenShareUid || optionalUid,
|
|
1692
|
+
stopOrigin: journeyContext.stopOrigin || 'unknown',
|
|
1693
|
+
stopActorUid: journeyContext.stopActorUid,
|
|
1694
|
+
};
|
|
1591
1695
|
const config: ScreenVideoTrackInitConfig = {
|
|
1592
1696
|
...screenShareConfig,
|
|
1593
1697
|
encoderConfig: this.screenShareProfile,
|
|
1594
1698
|
};
|
|
1699
|
+
let joined = false;
|
|
1700
|
+
let cleanupCompleted = false;
|
|
1701
|
+
const cleanupScreenshare = async (
|
|
1702
|
+
stopOrigin: string,
|
|
1703
|
+
notifyScreenshareStopped: boolean,
|
|
1704
|
+
screenshareAttemptId = journeyData.screenshareAttemptId,
|
|
1705
|
+
) => {
|
|
1706
|
+
const cleanupJourneyData = notifyScreenshareStopped
|
|
1707
|
+
? {
|
|
1708
|
+
...journeyData,
|
|
1709
|
+
action: 'stop',
|
|
1710
|
+
screenshareAttemptId,
|
|
1711
|
+
stopOrigin,
|
|
1712
|
+
}
|
|
1713
|
+
: journeyData;
|
|
1714
|
+
if (this.isScreenshareCleanupInProgress || cleanupCompleted) {
|
|
1715
|
+
logger.log(
|
|
1716
|
+
LogSource.AgoraSDK,
|
|
1717
|
+
'API',
|
|
1718
|
+
`[SCREENSHARE_JOURNEY] screen share ${cleanupJourneyData.action} cleanup skipped because cleanup is already running or completed`,
|
|
1719
|
+
{
|
|
1720
|
+
...cleanupJourneyData,
|
|
1721
|
+
stage: 'cleanup',
|
|
1722
|
+
outcome: 'skipped',
|
|
1723
|
+
stopOrigin,
|
|
1724
|
+
},
|
|
1725
|
+
);
|
|
1726
|
+
return;
|
|
1727
|
+
}
|
|
1728
|
+
this.isScreenshareCleanupInProgress = true;
|
|
1729
|
+
try {
|
|
1730
|
+
if (joined || this.inScreenshare) {
|
|
1731
|
+
(this.eventsMap.get('onUserOffline') as callbackType)(
|
|
1732
|
+
{},
|
|
1733
|
+
this.screenClient.uid,
|
|
1734
|
+
);
|
|
1735
|
+
}
|
|
1736
|
+
this.screenStream.audio?.stop();
|
|
1737
|
+
this.screenStream.video?.stop();
|
|
1738
|
+
this.screenStream.audio?.close();
|
|
1739
|
+
this.screenStream.video?.close();
|
|
1740
|
+
if (joined || this.inScreenshare) {
|
|
1741
|
+
await this.screenClient.leave();
|
|
1742
|
+
}
|
|
1743
|
+
this.screenStream = {};
|
|
1744
|
+
this.inScreenshare = false;
|
|
1745
|
+
this.activeScreenshareJourneyContext = null;
|
|
1746
|
+
if (notifyScreenshareStopped) {
|
|
1747
|
+
(this.eventsMap.get('onScreenshareStopped') as callbackType)(
|
|
1748
|
+
stopOrigin,
|
|
1749
|
+
screenshareAttemptId,
|
|
1750
|
+
cleanupJourneyData.screenshareSessionId,
|
|
1751
|
+
cleanupJourneyData.stopActorUid,
|
|
1752
|
+
);
|
|
1753
|
+
}
|
|
1754
|
+
logger.log(
|
|
1755
|
+
LogSource.AgoraSDK,
|
|
1756
|
+
'API',
|
|
1757
|
+
`[SCREENSHARE_JOURNEY] screen share ${cleanupJourneyData.action} RTC cleanup completed`,
|
|
1758
|
+
{
|
|
1759
|
+
...cleanupJourneyData,
|
|
1760
|
+
stage: 'cleanup',
|
|
1761
|
+
outcome: 'success',
|
|
1762
|
+
stopOrigin,
|
|
1763
|
+
},
|
|
1764
|
+
);
|
|
1765
|
+
cleanupCompleted = true;
|
|
1766
|
+
} finally {
|
|
1767
|
+
this.isScreenshareCleanupInProgress = false;
|
|
1768
|
+
}
|
|
1769
|
+
};
|
|
1595
1770
|
if (!this.inScreenshare) {
|
|
1771
|
+
let stage = 'encryption';
|
|
1596
1772
|
try {
|
|
1597
1773
|
logger.debug(
|
|
1598
1774
|
LogSource.AgoraSDK,
|
|
1599
1775
|
'Log',
|
|
1600
|
-
'
|
|
1776
|
+
'[SCREENSHARE_JOURNEY] screen share start entered RTC engine',
|
|
1777
|
+
{...journeyData, stage: 'rtc_start', outcome: 'started'},
|
|
1601
1778
|
);
|
|
1602
1779
|
if (encryption && encryption.screenKey && encryption.mode) {
|
|
1603
1780
|
let mode: EncryptionMode;
|
|
@@ -1611,7 +1788,8 @@ export default class RtcEngine {
|
|
|
1611
1788
|
logger.log(
|
|
1612
1789
|
LogSource.AgoraSDK,
|
|
1613
1790
|
'Log',
|
|
1614
|
-
'
|
|
1791
|
+
'[SCREENSHARE_JOURNEY] screen share start configuring RTC screen-client encryption',
|
|
1792
|
+
{...journeyData, stage, outcome: 'started'},
|
|
1615
1793
|
);
|
|
1616
1794
|
await this.screenClient.setEncryptionConfig(
|
|
1617
1795
|
mode,
|
|
@@ -1619,21 +1797,44 @@ export default class RtcEngine {
|
|
|
1619
1797
|
encryption.salt,
|
|
1620
1798
|
true, // encryptDataStream
|
|
1621
1799
|
);
|
|
1800
|
+
logger.log(
|
|
1801
|
+
LogSource.AgoraSDK,
|
|
1802
|
+
'Log',
|
|
1803
|
+
'[SCREENSHARE_JOURNEY] screen share start RTC screen-client encryption configured successfully',
|
|
1804
|
+
{...journeyData, stage, outcome: 'success'},
|
|
1805
|
+
);
|
|
1622
1806
|
} catch (e) {
|
|
1623
1807
|
logger.error(
|
|
1624
1808
|
LogSource.AgoraSDK,
|
|
1625
1809
|
'Log',
|
|
1626
|
-
'
|
|
1627
|
-
|
|
1810
|
+
'[SCREENSHARE_JOURNEY] screen share start RTC screen-client encryption configuration failed',
|
|
1811
|
+
{
|
|
1812
|
+
...journeyData,
|
|
1813
|
+
stage,
|
|
1814
|
+
outcome: 'failure',
|
|
1815
|
+
...getScreenshareErrorDetails(e),
|
|
1816
|
+
},
|
|
1628
1817
|
);
|
|
1818
|
+
throw e;
|
|
1629
1819
|
}
|
|
1820
|
+
} else {
|
|
1821
|
+
logger.log(
|
|
1822
|
+
LogSource.AgoraSDK,
|
|
1823
|
+
'Log',
|
|
1824
|
+
'[SCREENSHARE_JOURNEY] screen share start RTC screen-client encryption skipped because encryption is not configured',
|
|
1825
|
+
{...journeyData, stage, outcome: 'skipped'},
|
|
1826
|
+
);
|
|
1630
1827
|
}
|
|
1631
1828
|
|
|
1829
|
+
stage = 'create_screen_video_track';
|
|
1632
1830
|
logger.log(
|
|
1633
1831
|
LogSource.AgoraSDK,
|
|
1634
1832
|
'API',
|
|
1635
|
-
'
|
|
1833
|
+
'[SCREENSHARE_JOURNEY] screen share start calling AgoraRTC.createScreenVideoTrack',
|
|
1636
1834
|
{
|
|
1835
|
+
...journeyData,
|
|
1836
|
+
stage,
|
|
1837
|
+
outcome: 'started',
|
|
1637
1838
|
config,
|
|
1638
1839
|
},
|
|
1639
1840
|
);
|
|
@@ -1641,98 +1842,134 @@ export default class RtcEngine {
|
|
|
1641
1842
|
config,
|
|
1642
1843
|
audio,
|
|
1643
1844
|
);
|
|
1845
|
+
const isSingleScreenTrack = this.isSingleTrack(screenTracks);
|
|
1644
1846
|
logger.log(
|
|
1645
1847
|
LogSource.AgoraSDK,
|
|
1646
1848
|
'API',
|
|
1647
|
-
'
|
|
1849
|
+
'[SCREENSHARE_JOURNEY] screen share start AgoraRTC.createScreenVideoTrack completed successfully',
|
|
1648
1850
|
{
|
|
1649
|
-
|
|
1851
|
+
...journeyData,
|
|
1852
|
+
stage,
|
|
1853
|
+
outcome: 'success',
|
|
1854
|
+
hasVideoTrack: Boolean(
|
|
1855
|
+
isSingleScreenTrack ? screenTracks : screenTracks[0],
|
|
1856
|
+
),
|
|
1857
|
+
hasAudioTrack: Boolean(
|
|
1858
|
+
isSingleScreenTrack ? false : screenTracks[1],
|
|
1859
|
+
),
|
|
1650
1860
|
},
|
|
1651
1861
|
);
|
|
1652
|
-
if (
|
|
1862
|
+
if (isSingleScreenTrack) {
|
|
1653
1863
|
this.screenStream.video = screenTracks;
|
|
1654
1864
|
} else {
|
|
1655
1865
|
this.screenStream.video = screenTracks[0];
|
|
1656
1866
|
this.screenStream.audio = screenTracks[1];
|
|
1657
1867
|
}
|
|
1868
|
+
stage = 'rtc_join';
|
|
1869
|
+
logger.log(
|
|
1870
|
+
LogSource.AgoraSDK,
|
|
1871
|
+
'API',
|
|
1872
|
+
'[SCREENSHARE_JOURNEY] screen share start calling screenClient.join',
|
|
1873
|
+
{...journeyData, stage, outcome: 'started', channelName, optionalUid},
|
|
1874
|
+
);
|
|
1875
|
+
await this.screenClient.join(
|
|
1876
|
+
this.appId,
|
|
1877
|
+
channelName,
|
|
1878
|
+
token || null,
|
|
1879
|
+
optionalUid || null,
|
|
1880
|
+
);
|
|
1881
|
+
joined = true;
|
|
1882
|
+
this.inScreenshare = true;
|
|
1883
|
+
logger.log(
|
|
1884
|
+
LogSource.AgoraSDK,
|
|
1885
|
+
'API',
|
|
1886
|
+
'[SCREENSHARE_JOURNEY] screen share start screenClient.join completed successfully',
|
|
1887
|
+
{...journeyData, stage, outcome: 'success'},
|
|
1888
|
+
);
|
|
1889
|
+
stage = 'rtc_publish';
|
|
1890
|
+
logger.log(
|
|
1891
|
+
LogSource.AgoraSDK,
|
|
1892
|
+
'API',
|
|
1893
|
+
'[SCREENSHARE_JOURNEY] screen share start calling screenClient.publish',
|
|
1894
|
+
{...journeyData, stage, outcome: 'started'},
|
|
1895
|
+
);
|
|
1896
|
+
await this.screenClient.publish(
|
|
1897
|
+
this.screenStream.audio
|
|
1898
|
+
? [this.screenStream.video, this.screenStream.audio]
|
|
1899
|
+
: this.screenStream.video,
|
|
1900
|
+
);
|
|
1901
|
+
logger.log(
|
|
1902
|
+
LogSource.AgoraSDK,
|
|
1903
|
+
'API',
|
|
1904
|
+
'[SCREENSHARE_JOURNEY] screen share start screenClient.publish completed successfully',
|
|
1905
|
+
{...journeyData, stage, outcome: 'success'},
|
|
1906
|
+
);
|
|
1907
|
+
this.activeScreenshareJourneyContext = {
|
|
1908
|
+
screenshareSessionId: journeyData.screenshareSessionId,
|
|
1909
|
+
recordingActive: journeyData.recordingActive,
|
|
1910
|
+
screenShareUid: journeyData.screenShareUid,
|
|
1911
|
+
stopActorUid: journeyData.stopActorUid,
|
|
1912
|
+
};
|
|
1913
|
+
this.screenStream.video.on('track-ended', async () => {
|
|
1914
|
+
const nativeStopAttemptId = `${
|
|
1915
|
+
journeyData.screenshareAttemptId
|
|
1916
|
+
}-native-${Date.now()}`;
|
|
1917
|
+
const mediaTrack = this.screenStream.video?.getMediaStreamTrack?.();
|
|
1918
|
+
logger.log(
|
|
1919
|
+
LogSource.AgoraSDK,
|
|
1920
|
+
'API',
|
|
1921
|
+
'[SCREENSHARE_JOURNEY] screen share stop detected from browser native control through video track-ended',
|
|
1922
|
+
{
|
|
1923
|
+
...journeyData,
|
|
1924
|
+
action: 'stop',
|
|
1925
|
+
screenshareAttemptId: nativeStopAttemptId,
|
|
1926
|
+
stage: 'track_ended',
|
|
1927
|
+
outcome: 'started',
|
|
1928
|
+
stopOrigin: 'browser_native_control',
|
|
1929
|
+
mediaTrack: mediaTrack
|
|
1930
|
+
? {
|
|
1931
|
+
readyState: mediaTrack.readyState,
|
|
1932
|
+
enabled: mediaTrack.enabled,
|
|
1933
|
+
muted: mediaTrack.muted,
|
|
1934
|
+
label: mediaTrack.label,
|
|
1935
|
+
settings: mediaTrack.getSettings?.(),
|
|
1936
|
+
}
|
|
1937
|
+
: null,
|
|
1938
|
+
},
|
|
1939
|
+
);
|
|
1940
|
+
await cleanupScreenshare(
|
|
1941
|
+
'browser_native_control',
|
|
1942
|
+
true,
|
|
1943
|
+
nativeStopAttemptId,
|
|
1944
|
+
);
|
|
1945
|
+
});
|
|
1658
1946
|
} catch (e) {
|
|
1659
1947
|
logger.error(
|
|
1660
1948
|
LogSource.AgoraSDK,
|
|
1661
1949
|
'API',
|
|
1662
|
-
|
|
1663
|
-
|
|
1950
|
+
`[SCREENSHARE_JOURNEY] screen share start failed inside RTC engine at ${stage}`,
|
|
1951
|
+
{
|
|
1952
|
+
...journeyData,
|
|
1953
|
+
stage,
|
|
1954
|
+
outcome: 'failure',
|
|
1955
|
+
joined,
|
|
1956
|
+
...getScreenshareErrorDetails(e),
|
|
1957
|
+
},
|
|
1664
1958
|
);
|
|
1959
|
+
if (joined || this.screenStream.video || this.screenStream.audio) {
|
|
1960
|
+
await cleanupScreenshare('startup_failure', false);
|
|
1961
|
+
}
|
|
1665
1962
|
throw e;
|
|
1666
1963
|
}
|
|
1667
|
-
|
|
1668
|
-
logger.log(
|
|
1669
|
-
LogSource.AgoraSDK,
|
|
1670
|
-
'API',
|
|
1671
|
-
'RTC [join] joining channel of screenclient',
|
|
1672
|
-
{
|
|
1673
|
-
appId: this.appId,
|
|
1674
|
-
channelName,
|
|
1675
|
-
token,
|
|
1676
|
-
optionalUid,
|
|
1677
|
-
},
|
|
1678
|
-
);
|
|
1679
|
-
await this.screenClient.join(
|
|
1680
|
-
this.appId,
|
|
1681
|
-
channelName,
|
|
1682
|
-
token || null,
|
|
1683
|
-
optionalUid || null,
|
|
1684
|
-
);
|
|
1685
|
-
logger.log(
|
|
1686
|
-
LogSource.AgoraSDK,
|
|
1687
|
-
'API',
|
|
1688
|
-
'RTC [join] joined channel successfully',
|
|
1689
|
-
);
|
|
1690
|
-
this.inScreenshare = true;
|
|
1691
|
-
logger.log(
|
|
1692
|
-
LogSource.AgoraSDK,
|
|
1693
|
-
'API',
|
|
1694
|
-
'RTC [publish] trying to publish screen tracks',
|
|
1695
|
-
);
|
|
1696
|
-
await this.screenClient.publish(
|
|
1697
|
-
this.screenStream.audio
|
|
1698
|
-
? [this.screenStream.video, this.screenStream.audio]
|
|
1699
|
-
: this.screenStream.video,
|
|
1700
|
-
);
|
|
1964
|
+
} else {
|
|
1701
1965
|
logger.log(
|
|
1702
1966
|
LogSource.AgoraSDK,
|
|
1703
1967
|
'API',
|
|
1704
|
-
|
|
1968
|
+
`[SCREENSHARE_JOURNEY] screen share stop entered RTC engine from ${journeyData.stopOrigin}`,
|
|
1969
|
+
{...journeyData, stage: 'rtc_stop', outcome: 'started'},
|
|
1705
1970
|
);
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
{},
|
|
1709
|
-
this.screenClient.uid,
|
|
1710
|
-
);
|
|
1711
|
-
|
|
1712
|
-
this.screenClient.leave();
|
|
1713
|
-
|
|
1714
|
-
this.screenStream.audio?.close();
|
|
1715
|
-
this.screenStream.video?.close();
|
|
1716
|
-
this.screenStream = {};
|
|
1717
|
-
|
|
1718
|
-
(this.eventsMap.get('onScreenshareStopped') as callbackType)();
|
|
1719
|
-
this.inScreenshare = false;
|
|
1720
|
-
});
|
|
1721
|
-
} else {
|
|
1722
|
-
(this.eventsMap.get('onUserOffline') as callbackType)(
|
|
1723
|
-
{},
|
|
1724
|
-
this.screenClient.uid,
|
|
1725
|
-
);
|
|
1726
|
-
this.screenClient.leave();
|
|
1727
|
-
(this.eventsMap.get('onScreenshareStopped') as callbackType)();
|
|
1728
|
-
try {
|
|
1729
|
-
this.screenStream.audio?.close();
|
|
1730
|
-
this.screenStream.video?.close();
|
|
1731
|
-
this.screenStream = {};
|
|
1732
|
-
} catch (err) {
|
|
1733
|
-
throw err;
|
|
1734
|
-
}
|
|
1735
|
-
this.inScreenshare = false;
|
|
1971
|
+
await cleanupScreenshare(journeyData.stopOrigin, true);
|
|
1972
|
+
this.activeScreenshareJourneyContext = null;
|
|
1736
1973
|
}
|
|
1737
1974
|
}
|
|
1738
1975
|
}
|
|
@@ -8,5 +8,3 @@ export {default as TertiaryButton} from '../src/atoms/TertiaryButton';
|
|
|
8
8
|
export {default as ActionMenu} from '../src/atoms/ActionMenu';
|
|
9
9
|
export {default as IconButton} from '../src/atoms/IconButton';
|
|
10
10
|
export {default as Dropdown} from '../src/atoms/Dropdown';
|
|
11
|
-
export {default as Popup} from '../src/atoms/Popup';
|
|
12
|
-
export {default as Tooltip} from '../src/atoms/Tooltip';
|
|
@@ -5,13 +5,10 @@ import {
|
|
|
5
5
|
PersistanceLevel,
|
|
6
6
|
EventCallback,
|
|
7
7
|
} from '../src/rtm-events-api';
|
|
8
|
-
import LocalEventEmitter, {
|
|
9
|
-
LocalEventsEnum,
|
|
10
|
-
} from '../src/rtm-events-api/LocalEvents';
|
|
11
8
|
|
|
12
9
|
// 2. Initialize with source "fpe"
|
|
13
10
|
const customEvents = new Events(EventSource.fpe);
|
|
14
11
|
|
|
15
12
|
// 3. export
|
|
16
|
-
export {customEvents, PersistanceLevel
|
|
13
|
+
export {customEvents, PersistanceLevel};
|
|
17
14
|
export type {EventCallback};
|
|
@@ -53,7 +53,6 @@ export interface SidePanelItem {
|
|
|
53
53
|
name: string;
|
|
54
54
|
title: string;
|
|
55
55
|
component: React.ComponentType;
|
|
56
|
-
headerRightSlot?: React.ReactNode;
|
|
57
56
|
onClose?: () => void;
|
|
58
57
|
}
|
|
59
58
|
|
|
@@ -75,10 +74,6 @@ export type CustomLogger = (
|
|
|
75
74
|
export interface CustomAgentInterfaceProps {
|
|
76
75
|
connectionState: AIAgentState;
|
|
77
76
|
}
|
|
78
|
-
export interface CreateInterface extends BeforeAndAfterInterface {
|
|
79
|
-
headerRightSlot?: React.ComponentType;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
77
|
export interface VideoCallInterface extends BeforeAndAfterInterface {
|
|
83
78
|
// commented for v1 release
|
|
84
79
|
topToolBar?: ToolbarType;
|
|
@@ -114,7 +109,7 @@ export type ComponentsInterface = {
|
|
|
114
109
|
precall?: PreCallInterface;
|
|
115
110
|
preferenceWrapper?: React.ComponentType;
|
|
116
111
|
//precall?: React.ComponentType;
|
|
117
|
-
create?: React.ComponentType
|
|
112
|
+
create?: React.ComponentType;
|
|
118
113
|
//share?: React.ComponentType;
|
|
119
114
|
//join?: React.ComponentType;
|
|
120
115
|
videoCall?: VideoCallInterface;
|
|
@@ -77,8 +77,8 @@ const DefaultConfig = {
|
|
|
77
77
|
CHAT_ORG_NAME: "",
|
|
78
78
|
CHAT_APP_NAME: "",
|
|
79
79
|
CHAT_URL: "",
|
|
80
|
-
CLI_VERSION: "3.1.
|
|
81
|
-
CORE_VERSION: "4.1.
|
|
80
|
+
CLI_VERSION: "3.1.20",
|
|
81
|
+
CORE_VERSION: "4.1.20",
|
|
82
82
|
DISABLE_LANDSCAPE_MODE: false,
|
|
83
83
|
STT_AUTO_START: false,
|
|
84
84
|
CLOUD_RECORDING_AUTO_START: false,
|
|
@@ -719,7 +719,9 @@ const MoreButton = (props: {fields: ToolbarMoreButtonDefaultFields}) => {
|
|
|
719
719
|
title: screenShareButton(isScreenshareActive),
|
|
720
720
|
onPress: () => {
|
|
721
721
|
setActionMenuVisible(false);
|
|
722
|
-
isScreenshareActive
|
|
722
|
+
isScreenshareActive
|
|
723
|
+
? stopScreenshare('mobile_action_menu')
|
|
724
|
+
: startScreenshare();
|
|
723
725
|
},
|
|
724
726
|
});
|
|
725
727
|
}
|
|
@@ -10,18 +10,23 @@
|
|
|
10
10
|
*********************************************
|
|
11
11
|
*/
|
|
12
12
|
import React from 'react';
|
|
13
|
-
import {View, StyleSheet, ScrollView} from 'react-native';
|
|
13
|
+
import {View, Text, StyleSheet, ScrollView} from 'react-native';
|
|
14
14
|
import {isMobileUA, isWebInternal, useIsSmall} from '../utils/common';
|
|
15
15
|
import CommonStyles from './CommonStyles';
|
|
16
|
-
import
|
|
17
|
-
|
|
16
|
+
import SidePanelHeader, {
|
|
17
|
+
SidePanelStyles,
|
|
18
|
+
} from '../subComponents/SidePanelHeader';
|
|
18
19
|
import {useLayout} from '../utils/useLayout';
|
|
19
20
|
import {getGridLayoutName} from '../pages/video-call/DefaultLayouts';
|
|
21
|
+
import useCaptionWidth from '../subComponents/caption/useCaptionWidth';
|
|
22
|
+
import {useSidePanel} from '../utils/useSidePanel';
|
|
23
|
+
import {SidePanelType} from '../subComponents/SidePanelEnum';
|
|
24
|
+
import {CustomSidePanelHeader} from '../pages/video-call/SidePanelHeader';
|
|
25
|
+
|
|
20
26
|
export interface CustomSidePanelViewInterface {
|
|
21
27
|
name: string;
|
|
22
28
|
title?: string;
|
|
23
29
|
content: React.ComponentType;
|
|
24
|
-
headerRightSlot?: React.ReactNode;
|
|
25
30
|
onClose?: () => void;
|
|
26
31
|
showHeader?: boolean;
|
|
27
32
|
}
|
|
@@ -32,12 +37,12 @@ const CustomSidePanelView = (props: CustomSidePanelViewInterface) => {
|
|
|
32
37
|
showHeader = true,
|
|
33
38
|
name,
|
|
34
39
|
title,
|
|
35
|
-
headerRightSlot,
|
|
36
40
|
onClose,
|
|
37
41
|
} = props;
|
|
42
|
+
const {currentLayout} = useLayout();
|
|
38
43
|
const {transcriptHeight} = useCaptionWidth();
|
|
44
|
+
const {setSidePanel} = useSidePanel();
|
|
39
45
|
const isSmall = useIsSmall();
|
|
40
|
-
const {currentLayout} = useLayout();
|
|
41
46
|
|
|
42
47
|
return (
|
|
43
48
|
<View
|
|
@@ -52,18 +57,13 @@ const CustomSidePanelView = (props: CustomSidePanelViewInterface) => {
|
|
|
52
57
|
: // desktop maximized
|
|
53
58
|
CommonStyles.sidePanelContainerWeb,
|
|
54
59
|
isWebInternal() && !isSmall() && currentLayout === getGridLayoutName()
|
|
55
|
-
? {
|
|
60
|
+
? {marginVertical: 4}
|
|
56
61
|
: {},
|
|
57
62
|
//@ts-ignore
|
|
58
63
|
transcriptHeight && !isMobileUA() && {height: transcriptHeight},
|
|
59
64
|
]}>
|
|
60
65
|
{showHeader && (
|
|
61
|
-
<CustomSidePanelHeader
|
|
62
|
-
name={name}
|
|
63
|
-
title={title}
|
|
64
|
-
headerRightSlot={headerRightSlot}
|
|
65
|
-
onClose={onClose}
|
|
66
|
-
/>
|
|
66
|
+
<CustomSidePanelHeader name={name} title={title} onClose={onClose} />
|
|
67
67
|
)}
|
|
68
68
|
<ScrollView contentContainerStyle={[style.bodyContainer]}>
|
|
69
69
|
{CustomSidePanelContent ? <CustomSidePanelContent /> : <></>}
|