@dialtribe/react-sdk 0.1.0-alpha.11 → 0.1.0-alpha.12
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/README.md +11 -11
- package/dist/{broadcast-player-DnnXgWin.d.mts → dialtribe-player-Rc9kfQiX.d.mts} +87 -87
- package/dist/{broadcast-player-DnnXgWin.d.ts → dialtribe-player-Rc9kfQiX.d.ts} +87 -87
- package/dist/dialtribe-player.d.mts +3 -0
- package/dist/dialtribe-player.d.ts +3 -0
- package/dist/{broadcast-player.js → dialtribe-player.js} +105 -108
- package/dist/dialtribe-player.js.map +1 -0
- package/dist/{broadcast-player.mjs → dialtribe-player.mjs} +100 -103
- package/dist/dialtribe-player.mjs.map +1 -0
- package/dist/{broadcast-streamer.d.ts → dialtribe-streamer.d.mts} +203 -32
- package/dist/{broadcast-streamer.d.mts → dialtribe-streamer.d.ts} +203 -32
- package/dist/{broadcast-streamer.js → dialtribe-streamer.js} +386 -257
- package/dist/dialtribe-streamer.js.map +1 -0
- package/dist/{broadcast-streamer.mjs → dialtribe-streamer.mjs} +276 -150
- package/dist/dialtribe-streamer.mjs.map +1 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +382 -253
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +273 -147
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +9 -9
- package/dist/broadcast-player.d.mts +0 -3
- package/dist/broadcast-player.d.ts +0 -3
- package/dist/broadcast-player.js.map +0 -1
- package/dist/broadcast-player.mjs.map +0 -1
- package/dist/broadcast-streamer.js.map +0 -1
- package/dist/broadcast-streamer.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var jsxRuntime = require('react/jsx-runtime');
|
|
4
|
-
var
|
|
4
|
+
var React2 = require('react');
|
|
5
5
|
var ReactPlayer = require('react-player');
|
|
6
|
+
var reactDom = require('react-dom');
|
|
6
7
|
|
|
7
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
9
|
|
|
10
|
+
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
9
11
|
var ReactPlayer__default = /*#__PURE__*/_interopDefault(ReactPlayer);
|
|
10
12
|
|
|
11
13
|
// src/components/HelloWorld.tsx
|
|
@@ -27,17 +29,17 @@ function HelloWorld({ name = "World" }) {
|
|
|
27
29
|
/* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "14px" }, children: "@dialtribe/react-sdk is working correctly" })
|
|
28
30
|
] });
|
|
29
31
|
}
|
|
30
|
-
var
|
|
31
|
-
function
|
|
32
|
+
var DialtribeContext = React2.createContext(null);
|
|
33
|
+
function DialtribeProvider({
|
|
32
34
|
sessionToken: initialToken,
|
|
33
35
|
onTokenRefresh,
|
|
34
36
|
onTokenExpired,
|
|
35
37
|
apiBaseUrl,
|
|
36
38
|
children
|
|
37
39
|
}) {
|
|
38
|
-
const [sessionToken, setSessionTokenState] =
|
|
39
|
-
const [isExpired, setIsExpired] =
|
|
40
|
-
const setSessionToken =
|
|
40
|
+
const [sessionToken, setSessionTokenState] = React2.useState(initialToken);
|
|
41
|
+
const [isExpired, setIsExpired] = React2.useState(false);
|
|
42
|
+
const setSessionToken = React2.useCallback(
|
|
41
43
|
(newToken, expiresAt) => {
|
|
42
44
|
setSessionTokenState(newToken);
|
|
43
45
|
setIsExpired(false);
|
|
@@ -47,11 +49,11 @@ function DialTribeProvider({
|
|
|
47
49
|
},
|
|
48
50
|
[onTokenRefresh]
|
|
49
51
|
);
|
|
50
|
-
const markExpired =
|
|
52
|
+
const markExpired = React2.useCallback(() => {
|
|
51
53
|
setIsExpired(true);
|
|
52
54
|
onTokenExpired?.();
|
|
53
55
|
}, [onTokenExpired]);
|
|
54
|
-
|
|
56
|
+
React2.useEffect(() => {
|
|
55
57
|
if (initialToken !== sessionToken) {
|
|
56
58
|
setSessionTokenState(initialToken);
|
|
57
59
|
setIsExpired(false);
|
|
@@ -64,22 +66,22 @@ function DialTribeProvider({
|
|
|
64
66
|
markExpired,
|
|
65
67
|
apiBaseUrl
|
|
66
68
|
};
|
|
67
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
69
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DialtribeContext.Provider, { value, children });
|
|
68
70
|
}
|
|
69
|
-
function
|
|
70
|
-
const context =
|
|
71
|
+
function useDialtribe() {
|
|
72
|
+
const context = React2.useContext(DialtribeContext);
|
|
71
73
|
if (!context) {
|
|
72
74
|
throw new Error(
|
|
73
|
-
'
|
|
75
|
+
'useDialtribe must be used within a DialtribeProvider. Wrap your app with <DialtribeProvider sessionToken="sess_xxx">...</DialtribeProvider>'
|
|
74
76
|
);
|
|
75
77
|
}
|
|
76
78
|
return context;
|
|
77
79
|
}
|
|
78
|
-
function
|
|
79
|
-
return
|
|
80
|
+
function useDialtribeOptional() {
|
|
81
|
+
return React2.useContext(DialtribeContext);
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
// src/client/
|
|
84
|
+
// src/client/DialtribeClient.ts
|
|
83
85
|
function getDefaultApiBaseUrl() {
|
|
84
86
|
if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_DIALTRIBE_API_URL) {
|
|
85
87
|
return process.env.NEXT_PUBLIC_DIALTRIBE_API_URL;
|
|
@@ -99,13 +101,13 @@ function getEndpoints(baseUrl = DIALTRIBE_API_BASE) {
|
|
|
99
101
|
};
|
|
100
102
|
}
|
|
101
103
|
var ENDPOINTS = getEndpoints();
|
|
102
|
-
var
|
|
104
|
+
var DialtribeClient = class {
|
|
103
105
|
constructor(config) {
|
|
104
106
|
this.config = config;
|
|
105
107
|
this.endpoints = config.apiBaseUrl ? getEndpoints(config.apiBaseUrl) : ENDPOINTS;
|
|
106
108
|
}
|
|
107
109
|
/**
|
|
108
|
-
* Make an authenticated request to
|
|
110
|
+
* Make an authenticated request to Dialtribe API
|
|
109
111
|
*
|
|
110
112
|
* Automatically:
|
|
111
113
|
* - Adds Authorization header with session token
|
|
@@ -257,18 +259,18 @@ function AudioWaveform({
|
|
|
257
259
|
isPlaying = false,
|
|
258
260
|
isLive = false
|
|
259
261
|
}) {
|
|
260
|
-
const canvasRef =
|
|
261
|
-
const animationFrameRef =
|
|
262
|
-
const [setupError, setSetupError] =
|
|
263
|
-
const isPlayingRef =
|
|
264
|
-
const isLiveRef =
|
|
265
|
-
|
|
262
|
+
const canvasRef = React2.useRef(null);
|
|
263
|
+
const animationFrameRef = React2.useRef(void 0);
|
|
264
|
+
const [setupError, setSetupError] = React2.useState(false);
|
|
265
|
+
const isPlayingRef = React2.useRef(isPlaying);
|
|
266
|
+
const isLiveRef = React2.useRef(isLive);
|
|
267
|
+
React2.useEffect(() => {
|
|
266
268
|
isPlayingRef.current = isPlaying;
|
|
267
269
|
}, [isPlaying]);
|
|
268
|
-
|
|
270
|
+
React2.useEffect(() => {
|
|
269
271
|
isLiveRef.current = isLive;
|
|
270
272
|
}, [isLive]);
|
|
271
|
-
|
|
273
|
+
React2.useEffect(() => {
|
|
272
274
|
const canvas = canvasRef.current;
|
|
273
275
|
if (!canvas) return;
|
|
274
276
|
const ctx = canvas.getContext("2d");
|
|
@@ -770,7 +772,7 @@ function getErrorMessage(error) {
|
|
|
770
772
|
}
|
|
771
773
|
return "Unable to play media. Please try refreshing the page or contact support if the problem persists.";
|
|
772
774
|
}
|
|
773
|
-
function
|
|
775
|
+
function DialtribePlayer({
|
|
774
776
|
broadcast,
|
|
775
777
|
appId,
|
|
776
778
|
contentId,
|
|
@@ -781,18 +783,18 @@ function BroadcastPlayer({
|
|
|
781
783
|
className = "",
|
|
782
784
|
enableKeyboardShortcuts = false
|
|
783
785
|
}) {
|
|
784
|
-
const { sessionToken, setSessionToken, markExpired, apiBaseUrl } =
|
|
785
|
-
const clientRef =
|
|
786
|
+
const { sessionToken, setSessionToken, markExpired, apiBaseUrl } = useDialtribe();
|
|
787
|
+
const clientRef = React2.useRef(null);
|
|
786
788
|
if (!clientRef.current && sessionToken) {
|
|
787
|
-
clientRef.current = new
|
|
789
|
+
clientRef.current = new DialtribeClient({
|
|
788
790
|
sessionToken,
|
|
789
791
|
apiBaseUrl,
|
|
790
792
|
onTokenRefresh: (newToken, expiresAt) => {
|
|
791
|
-
debug.log(`[
|
|
793
|
+
debug.log(`[DialtribeClient] Token refreshed, expires at ${expiresAt}`);
|
|
792
794
|
setSessionToken(newToken, expiresAt);
|
|
793
795
|
},
|
|
794
796
|
onTokenExpired: () => {
|
|
795
|
-
debug.error("[
|
|
797
|
+
debug.error("[DialtribeClient] Token expired");
|
|
796
798
|
markExpired();
|
|
797
799
|
}
|
|
798
800
|
});
|
|
@@ -800,35 +802,35 @@ function BroadcastPlayer({
|
|
|
800
802
|
clientRef.current.setSessionToken(sessionToken);
|
|
801
803
|
}
|
|
802
804
|
const client = clientRef.current;
|
|
803
|
-
const playerRef =
|
|
804
|
-
const transcriptContainerRef =
|
|
805
|
-
const activeWordRef =
|
|
806
|
-
const [audioElement, setAudioElement] =
|
|
807
|
-
const [playing, setPlaying] =
|
|
808
|
-
const [played, setPlayed] =
|
|
809
|
-
const [duration, setDuration] =
|
|
810
|
-
const [volume, setVolume] =
|
|
811
|
-
const [muted, setMuted] =
|
|
812
|
-
const [seeking, setSeeking] =
|
|
813
|
-
const [hasError, setHasError] =
|
|
814
|
-
const [errorMessage, setErrorMessage] =
|
|
815
|
-
const [hasEnded, setHasEnded] =
|
|
816
|
-
const [hasStreamEnded, setHasStreamEnded] =
|
|
817
|
-
const [showTranscript, setShowTranscript] =
|
|
818
|
-
const [transcriptData, setTranscriptData] =
|
|
819
|
-
const [currentTime, setCurrentTime] =
|
|
820
|
-
const [isLoadingTranscript, setIsLoadingTranscript] =
|
|
821
|
-
const [isLoadingVideo, setIsLoadingVideo] =
|
|
822
|
-
const [autoScrollEnabled, setAutoScrollEnabled] =
|
|
823
|
-
const isScrollingProgrammatically =
|
|
824
|
-
const lastActiveWordIndex =
|
|
825
|
-
const [showClipCreator, setShowClipCreator] =
|
|
826
|
-
const initialPlaybackTypeRef =
|
|
827
|
-
const [currentPlaybackInfo, setCurrentPlaybackInfo] =
|
|
828
|
-
const [urlExpiresAt, setUrlExpiresAt] =
|
|
829
|
-
const isRefreshingUrl =
|
|
830
|
-
const [audienceId, setAudienceId] =
|
|
831
|
-
const [sessionId] =
|
|
805
|
+
const playerRef = React2.useRef(null);
|
|
806
|
+
const transcriptContainerRef = React2.useRef(null);
|
|
807
|
+
const activeWordRef = React2.useRef(null);
|
|
808
|
+
const [audioElement, setAudioElement] = React2.useState(null);
|
|
809
|
+
const [playing, setPlaying] = React2.useState(false);
|
|
810
|
+
const [played, setPlayed] = React2.useState(0);
|
|
811
|
+
const [duration, setDuration] = React2.useState(0);
|
|
812
|
+
const [volume, setVolume] = React2.useState(1);
|
|
813
|
+
const [muted, setMuted] = React2.useState(false);
|
|
814
|
+
const [seeking, setSeeking] = React2.useState(false);
|
|
815
|
+
const [hasError, setHasError] = React2.useState(false);
|
|
816
|
+
const [errorMessage, setErrorMessage] = React2.useState("");
|
|
817
|
+
const [hasEnded, setHasEnded] = React2.useState(false);
|
|
818
|
+
const [hasStreamEnded, setHasStreamEnded] = React2.useState(false);
|
|
819
|
+
const [showTranscript, setShowTranscript] = React2.useState(false);
|
|
820
|
+
const [transcriptData, setTranscriptData] = React2.useState(null);
|
|
821
|
+
const [currentTime, setCurrentTime] = React2.useState(0);
|
|
822
|
+
const [isLoadingTranscript, setIsLoadingTranscript] = React2.useState(false);
|
|
823
|
+
const [isLoadingVideo, setIsLoadingVideo] = React2.useState(true);
|
|
824
|
+
const [autoScrollEnabled, setAutoScrollEnabled] = React2.useState(true);
|
|
825
|
+
const isScrollingProgrammatically = React2.useRef(false);
|
|
826
|
+
const lastActiveWordIndex = React2.useRef(-1);
|
|
827
|
+
const [showClipCreator, setShowClipCreator] = React2.useState(false);
|
|
828
|
+
const initialPlaybackTypeRef = React2.useRef(null);
|
|
829
|
+
const [currentPlaybackInfo, setCurrentPlaybackInfo] = React2.useState(null);
|
|
830
|
+
const [urlExpiresAt, setUrlExpiresAt] = React2.useState(null);
|
|
831
|
+
const isRefreshingUrl = React2.useRef(false);
|
|
832
|
+
const [audienceId, setAudienceId] = React2.useState(null);
|
|
833
|
+
const [sessionId] = React2.useState(() => {
|
|
832
834
|
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
|
833
835
|
return crypto.randomUUID();
|
|
834
836
|
}
|
|
@@ -838,9 +840,9 @@ function BroadcastPlayer({
|
|
|
838
840
|
return v.toString(16);
|
|
839
841
|
});
|
|
840
842
|
});
|
|
841
|
-
const heartbeatIntervalRef =
|
|
842
|
-
const hasInitializedSession =
|
|
843
|
-
const refreshPresignedUrl =
|
|
843
|
+
const heartbeatIntervalRef = React2.useRef(null);
|
|
844
|
+
const hasInitializedSession = React2.useRef(false);
|
|
845
|
+
const refreshPresignedUrl = React2.useCallback(
|
|
844
846
|
async (fileType) => {
|
|
845
847
|
if (!broadcast.hash || isRefreshingUrl.current || !client) {
|
|
846
848
|
debug.log("[URL Refresh] Skipping refresh - no hash, already refreshing, or no client");
|
|
@@ -891,7 +893,7 @@ function BroadcastPlayer({
|
|
|
891
893
|
if (width < 1024) return "tablet";
|
|
892
894
|
return "desktop";
|
|
893
895
|
};
|
|
894
|
-
const initializeTrackingSession =
|
|
896
|
+
const initializeTrackingSession = React2.useCallback(async () => {
|
|
895
897
|
if (!contentId || !appId || !client) return;
|
|
896
898
|
if (currentPlaybackInfo?.type === "hls" && broadcast.broadcastStatus === 1) return;
|
|
897
899
|
if (hasInitializedSession.current) return;
|
|
@@ -926,7 +928,7 @@ function BroadcastPlayer({
|
|
|
926
928
|
}
|
|
927
929
|
}
|
|
928
930
|
}, [contentId, appId, broadcast.id, broadcast.broadcastStatus, foreignId, foreignTier, sessionId, currentPlaybackInfo?.type, audioElement, client, onError]);
|
|
929
|
-
const sendTrackingPing =
|
|
931
|
+
const sendTrackingPing = React2.useCallback(
|
|
930
932
|
async (eventType) => {
|
|
931
933
|
if (!audienceId || !sessionId || !client) return;
|
|
932
934
|
try {
|
|
@@ -964,7 +966,7 @@ function BroadcastPlayer({
|
|
|
964
966
|
}
|
|
965
967
|
return null;
|
|
966
968
|
};
|
|
967
|
-
|
|
969
|
+
React2.useEffect(() => {
|
|
968
970
|
if (!currentPlaybackInfo) {
|
|
969
971
|
const info = getPlaybackInfo();
|
|
970
972
|
setCurrentPlaybackInfo(info);
|
|
@@ -980,12 +982,12 @@ function BroadcastPlayer({
|
|
|
980
982
|
}
|
|
981
983
|
}
|
|
982
984
|
}, [currentPlaybackInfo]);
|
|
983
|
-
|
|
985
|
+
React2.useEffect(() => {
|
|
984
986
|
if (currentPlaybackInfo?.url) {
|
|
985
987
|
setIsLoadingVideo(true);
|
|
986
988
|
}
|
|
987
989
|
}, [currentPlaybackInfo?.url]);
|
|
988
|
-
|
|
990
|
+
React2.useEffect(() => {
|
|
989
991
|
if (!urlExpiresAt || !currentPlaybackInfo?.type) return;
|
|
990
992
|
const checkExpiration = () => {
|
|
991
993
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -1004,7 +1006,7 @@ function BroadcastPlayer({
|
|
|
1004
1006
|
clearInterval(interval);
|
|
1005
1007
|
};
|
|
1006
1008
|
}, [urlExpiresAt, currentPlaybackInfo?.type, refreshPresignedUrl]);
|
|
1007
|
-
|
|
1009
|
+
React2.useEffect(() => {
|
|
1008
1010
|
if (initialPlaybackTypeRef.current === "hls" && currentPlaybackInfo?.type === "hls" && broadcast.broadcastStatus !== 1 && broadcast.recordingMp3Url && broadcast.hash && parseInt(broadcast.mp3Size || "0") > 0) {
|
|
1009
1011
|
const secureUrl = buildPlaybackUrl(broadcast.id, broadcast.hash);
|
|
1010
1012
|
setCurrentPlaybackInfo({ url: secureUrl, type: "mp3" });
|
|
@@ -1040,22 +1042,22 @@ function BroadcastPlayer({
|
|
|
1040
1042
|
setHasEnded(true);
|
|
1041
1043
|
}
|
|
1042
1044
|
};
|
|
1043
|
-
|
|
1045
|
+
React2.useEffect(() => {
|
|
1044
1046
|
if (broadcast.durationSeconds && broadcast.durationSeconds > 0) {
|
|
1045
1047
|
setDuration(broadcast.durationSeconds);
|
|
1046
1048
|
}
|
|
1047
1049
|
}, [broadcast.durationSeconds]);
|
|
1048
|
-
|
|
1050
|
+
React2.useEffect(() => {
|
|
1049
1051
|
if (isLiveStream && !playing) {
|
|
1050
1052
|
setPlaying(true);
|
|
1051
1053
|
}
|
|
1052
1054
|
}, [isLiveStream, playing]);
|
|
1053
|
-
|
|
1055
|
+
React2.useEffect(() => {
|
|
1054
1056
|
if (currentPlaybackInfo && audioElement && !hasInitializedSession.current) {
|
|
1055
1057
|
initializeTrackingSession();
|
|
1056
1058
|
}
|
|
1057
1059
|
}, [currentPlaybackInfo, audioElement, initializeTrackingSession]);
|
|
1058
|
-
|
|
1060
|
+
React2.useEffect(() => {
|
|
1059
1061
|
if (playing && audienceId) {
|
|
1060
1062
|
sendTrackingPing(1);
|
|
1061
1063
|
heartbeatIntervalRef.current = setInterval(() => {
|
|
@@ -1075,7 +1077,7 @@ function BroadcastPlayer({
|
|
|
1075
1077
|
}
|
|
1076
1078
|
}
|
|
1077
1079
|
}, [playing, audienceId, sendTrackingPing]);
|
|
1078
|
-
|
|
1080
|
+
React2.useEffect(() => {
|
|
1079
1081
|
return () => {
|
|
1080
1082
|
if (audienceId && sessionId && sessionToken) {
|
|
1081
1083
|
const payload = {
|
|
@@ -1100,7 +1102,7 @@ function BroadcastPlayer({
|
|
|
1100
1102
|
}
|
|
1101
1103
|
};
|
|
1102
1104
|
}, [audienceId, sessionId, sessionToken, audioElement, duration]);
|
|
1103
|
-
|
|
1105
|
+
React2.useEffect(() => {
|
|
1104
1106
|
if (broadcast.transcriptUrl && broadcast.transcriptStatus === 2 && !transcriptData) {
|
|
1105
1107
|
setIsLoadingTranscript(true);
|
|
1106
1108
|
fetch(broadcast.transcriptUrl).then((res) => {
|
|
@@ -1131,7 +1133,7 @@ function BroadcastPlayer({
|
|
|
1131
1133
|
});
|
|
1132
1134
|
}
|
|
1133
1135
|
}, [broadcast.transcriptUrl, broadcast.transcriptStatus, transcriptData]);
|
|
1134
|
-
|
|
1136
|
+
React2.useEffect(() => {
|
|
1135
1137
|
if (!audioElement) return;
|
|
1136
1138
|
const handleTimeUpdate2 = () => {
|
|
1137
1139
|
setCurrentTime(audioElement.currentTime);
|
|
@@ -1139,7 +1141,7 @@ function BroadcastPlayer({
|
|
|
1139
1141
|
audioElement.addEventListener("timeupdate", handleTimeUpdate2);
|
|
1140
1142
|
return () => audioElement.removeEventListener("timeupdate", handleTimeUpdate2);
|
|
1141
1143
|
}, [audioElement]);
|
|
1142
|
-
|
|
1144
|
+
React2.useEffect(() => {
|
|
1143
1145
|
if (showTranscript && autoScrollEnabled && activeWordRef.current && transcriptContainerRef.current) {
|
|
1144
1146
|
const container = transcriptContainerRef.current;
|
|
1145
1147
|
const activeWord = activeWordRef.current;
|
|
@@ -1154,7 +1156,7 @@ function BroadcastPlayer({
|
|
|
1154
1156
|
}
|
|
1155
1157
|
}
|
|
1156
1158
|
}, [currentTime, showTranscript, autoScrollEnabled]);
|
|
1157
|
-
|
|
1159
|
+
React2.useEffect(() => {
|
|
1158
1160
|
if (!showTranscript || !transcriptContainerRef.current) return;
|
|
1159
1161
|
const container = transcriptContainerRef.current;
|
|
1160
1162
|
const handleScroll = () => {
|
|
@@ -1237,10 +1239,10 @@ function BroadcastPlayer({
|
|
|
1237
1239
|
setAudioElement(internalPlayer);
|
|
1238
1240
|
}
|
|
1239
1241
|
} catch (error) {
|
|
1240
|
-
debug.error("[
|
|
1242
|
+
debug.error("[DialtribePlayer] Error getting internal player:", error);
|
|
1241
1243
|
}
|
|
1242
1244
|
};
|
|
1243
|
-
|
|
1245
|
+
React2.useEffect(() => {
|
|
1244
1246
|
const findAudioElement = () => {
|
|
1245
1247
|
const videoElements = document.querySelectorAll("video, audio");
|
|
1246
1248
|
if (videoElements.length > 0) {
|
|
@@ -1260,7 +1262,7 @@ function BroadcastPlayer({
|
|
|
1260
1262
|
return () => timeouts.forEach(clearTimeout);
|
|
1261
1263
|
}
|
|
1262
1264
|
}, [playbackUrl]);
|
|
1263
|
-
|
|
1265
|
+
React2.useEffect(() => {
|
|
1264
1266
|
if (playing && !audioElement) {
|
|
1265
1267
|
const videoElements = document.querySelectorAll("video, audio");
|
|
1266
1268
|
if (videoElements.length > 0) {
|
|
@@ -1339,7 +1341,7 @@ function BroadcastPlayer({
|
|
|
1339
1341
|
onError(error);
|
|
1340
1342
|
}
|
|
1341
1343
|
};
|
|
1342
|
-
const handleRetry =
|
|
1344
|
+
const handleRetry = React2.useCallback(() => {
|
|
1343
1345
|
setHasError(false);
|
|
1344
1346
|
setErrorMessage("");
|
|
1345
1347
|
setIsLoadingVideo(true);
|
|
@@ -1362,7 +1364,7 @@ function BroadcastPlayer({
|
|
|
1362
1364
|
}
|
|
1363
1365
|
}
|
|
1364
1366
|
};
|
|
1365
|
-
|
|
1367
|
+
React2.useEffect(() => {
|
|
1366
1368
|
if (!enableKeyboardShortcuts) return;
|
|
1367
1369
|
const seekBy = (seconds) => {
|
|
1368
1370
|
if (!audioElement || duration <= 0) return;
|
|
@@ -1445,7 +1447,7 @@ function BroadcastPlayer({
|
|
|
1445
1447
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center p-8", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { variant: "white", text: "Loading..." }) });
|
|
1446
1448
|
}
|
|
1447
1449
|
const hasTranscript = broadcast.transcriptStatus === 2 && transcriptData && (transcriptData.segments && transcriptData.segments.some((s) => s.words && s.words.length > 0) || transcriptData.words && transcriptData.words.length > 0);
|
|
1448
|
-
|
|
1450
|
+
const playerContent = /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bg-black rounded-lg shadow-2xl w-full max-h-full flex flex-col overflow-hidden ${className}`, children: [
|
|
1449
1451
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-zinc-900/50 backdrop-blur-sm border-b border-zinc-800 px-3 sm:px-4 md:px-6 py-2 sm:py-3 md:py-4 flex justify-between items-center rounded-t-lg shrink-0", children: [
|
|
1450
1452
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1451
1453
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-white", children: broadcast.streamKeyRecord?.foreignName || "Broadcast" }),
|
|
@@ -1977,90 +1979,9 @@ function BroadcastPlayer({
|
|
|
1977
1979
|
}
|
|
1978
1980
|
` })
|
|
1979
1981
|
] });
|
|
1982
|
+
return playerContent;
|
|
1980
1983
|
}
|
|
1981
|
-
|
|
1982
|
-
broadcast,
|
|
1983
|
-
isOpen,
|
|
1984
|
-
onClose,
|
|
1985
|
-
appId,
|
|
1986
|
-
contentId,
|
|
1987
|
-
foreignId,
|
|
1988
|
-
foreignTier,
|
|
1989
|
-
renderClipCreator,
|
|
1990
|
-
className,
|
|
1991
|
-
enableKeyboardShortcuts = false
|
|
1992
|
-
}) {
|
|
1993
|
-
const closeButtonRef = react.useRef(null);
|
|
1994
|
-
const previousActiveElement = react.useRef(null);
|
|
1995
|
-
react.useEffect(() => {
|
|
1996
|
-
if (!isOpen) return;
|
|
1997
|
-
previousActiveElement.current = document.activeElement;
|
|
1998
|
-
setTimeout(() => {
|
|
1999
|
-
closeButtonRef.current?.focus();
|
|
2000
|
-
}, 100);
|
|
2001
|
-
return () => {
|
|
2002
|
-
if (previousActiveElement.current) {
|
|
2003
|
-
previousActiveElement.current.focus();
|
|
2004
|
-
}
|
|
2005
|
-
};
|
|
2006
|
-
}, [isOpen]);
|
|
2007
|
-
react.useEffect(() => {
|
|
2008
|
-
if (!isOpen) return;
|
|
2009
|
-
const handleKeyDown = (e) => {
|
|
2010
|
-
if (e.key === "Escape") {
|
|
2011
|
-
onClose();
|
|
2012
|
-
}
|
|
2013
|
-
};
|
|
2014
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
2015
|
-
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
2016
|
-
}, [isOpen, onClose]);
|
|
2017
|
-
if (!isOpen) return null;
|
|
2018
|
-
const handleBackdropClick = (e) => {
|
|
2019
|
-
if (e.target === e.currentTarget) {
|
|
2020
|
-
onClose();
|
|
2021
|
-
}
|
|
2022
|
-
};
|
|
2023
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2024
|
-
"div",
|
|
2025
|
-
{
|
|
2026
|
-
className: "fixed inset-0 bg-black/70 backdrop-blur-xl flex items-center justify-center z-50 p-2 sm:p-4",
|
|
2027
|
-
onClick: handleBackdropClick,
|
|
2028
|
-
role: "dialog",
|
|
2029
|
-
"aria-modal": "true",
|
|
2030
|
-
"aria-label": "Broadcast player",
|
|
2031
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full max-w-7xl max-h-[95vh] sm:max-h-[90vh] overflow-hidden", children: [
|
|
2032
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2033
|
-
"button",
|
|
2034
|
-
{
|
|
2035
|
-
ref: closeButtonRef,
|
|
2036
|
-
onClick: onClose,
|
|
2037
|
-
className: "absolute top-2 right-2 sm:top-4 sm:right-4 z-10 text-gray-400 hover:text-white text-2xl leading-none transition-colors w-8 h-8 flex items-center justify-center bg-black/50 rounded-full",
|
|
2038
|
-
title: "Close (ESC)",
|
|
2039
|
-
"aria-label": "Close player",
|
|
2040
|
-
children: "\xD7"
|
|
2041
|
-
}
|
|
2042
|
-
),
|
|
2043
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2044
|
-
BroadcastPlayer,
|
|
2045
|
-
{
|
|
2046
|
-
broadcast,
|
|
2047
|
-
appId,
|
|
2048
|
-
contentId,
|
|
2049
|
-
foreignId,
|
|
2050
|
-
foreignTier,
|
|
2051
|
-
renderClipCreator,
|
|
2052
|
-
className,
|
|
2053
|
-
enableKeyboardShortcuts,
|
|
2054
|
-
onError: (error) => {
|
|
2055
|
-
debug.error("[BroadcastPlayerModal] Player error:", error);
|
|
2056
|
-
}
|
|
2057
|
-
}
|
|
2058
|
-
)
|
|
2059
|
-
] })
|
|
2060
|
-
}
|
|
2061
|
-
);
|
|
2062
|
-
}
|
|
2063
|
-
var BroadcastPlayerErrorBoundary = class extends react.Component {
|
|
1984
|
+
var DialtribePlayerErrorBoundary = class extends React2.Component {
|
|
2064
1985
|
constructor(props) {
|
|
2065
1986
|
super(props);
|
|
2066
1987
|
this.handleReset = () => {
|
|
@@ -2186,6 +2107,84 @@ var BroadcastPlayerErrorBoundary = class extends react.Component {
|
|
|
2186
2107
|
return this.props.children;
|
|
2187
2108
|
}
|
|
2188
2109
|
};
|
|
2110
|
+
var overlayStyles = {
|
|
2111
|
+
modal: {
|
|
2112
|
+
backdrop: "bg-black/70 backdrop-blur-xl p-2 sm:p-4",
|
|
2113
|
+
container: "max-w-7xl max-h-[95vh] sm:max-h-[90vh]"
|
|
2114
|
+
},
|
|
2115
|
+
fullscreen: {
|
|
2116
|
+
backdrop: "bg-black",
|
|
2117
|
+
container: "h-full"
|
|
2118
|
+
}
|
|
2119
|
+
};
|
|
2120
|
+
function DialtribeOverlay({
|
|
2121
|
+
isOpen,
|
|
2122
|
+
onClose,
|
|
2123
|
+
mode = "modal",
|
|
2124
|
+
children,
|
|
2125
|
+
ariaLabel = "Dialog",
|
|
2126
|
+
showCloseButton = true,
|
|
2127
|
+
closeOnBackdropClick = true,
|
|
2128
|
+
closeOnEsc = true
|
|
2129
|
+
}) {
|
|
2130
|
+
const closeButtonRef = React2.useRef(null);
|
|
2131
|
+
const previousActiveElement = React2.useRef(null);
|
|
2132
|
+
React2.useEffect(() => {
|
|
2133
|
+
if (!isOpen) return;
|
|
2134
|
+
previousActiveElement.current = document.activeElement;
|
|
2135
|
+
setTimeout(() => {
|
|
2136
|
+
closeButtonRef.current?.focus();
|
|
2137
|
+
}, 100);
|
|
2138
|
+
return () => {
|
|
2139
|
+
if (previousActiveElement.current) {
|
|
2140
|
+
previousActiveElement.current.focus();
|
|
2141
|
+
}
|
|
2142
|
+
};
|
|
2143
|
+
}, [isOpen]);
|
|
2144
|
+
React2.useEffect(() => {
|
|
2145
|
+
if (!isOpen || !closeOnEsc) return;
|
|
2146
|
+
const handleKeyDown = (e) => {
|
|
2147
|
+
if (e.key === "Escape") {
|
|
2148
|
+
onClose();
|
|
2149
|
+
}
|
|
2150
|
+
};
|
|
2151
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
2152
|
+
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
2153
|
+
}, [isOpen, onClose, closeOnEsc]);
|
|
2154
|
+
if (!isOpen) {
|
|
2155
|
+
return null;
|
|
2156
|
+
}
|
|
2157
|
+
const handleBackdropClick = (e) => {
|
|
2158
|
+
if (closeOnBackdropClick && e.target === e.currentTarget) {
|
|
2159
|
+
onClose();
|
|
2160
|
+
}
|
|
2161
|
+
};
|
|
2162
|
+
const styles = overlayStyles[mode];
|
|
2163
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
2164
|
+
"div",
|
|
2165
|
+
{
|
|
2166
|
+
className: `fixed inset-0 flex items-center justify-center z-50 ${styles.backdrop}`,
|
|
2167
|
+
onClick: handleBackdropClick,
|
|
2168
|
+
role: "dialog",
|
|
2169
|
+
"aria-modal": "true",
|
|
2170
|
+
"aria-label": ariaLabel,
|
|
2171
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative w-full overflow-hidden ${styles.container}`, children: [
|
|
2172
|
+
showCloseButton && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2173
|
+
"button",
|
|
2174
|
+
{
|
|
2175
|
+
ref: closeButtonRef,
|
|
2176
|
+
onClick: onClose,
|
|
2177
|
+
className: "absolute top-2 right-2 sm:top-4 sm:right-4 z-10 text-gray-400 hover:text-white text-2xl leading-none transition-colors w-8 h-8 flex items-center justify-center bg-black/50 rounded-full",
|
|
2178
|
+
title: "Close (ESC)",
|
|
2179
|
+
"aria-label": "Close",
|
|
2180
|
+
children: "\xD7"
|
|
2181
|
+
}
|
|
2182
|
+
),
|
|
2183
|
+
children
|
|
2184
|
+
] })
|
|
2185
|
+
}
|
|
2186
|
+
);
|
|
2187
|
+
}
|
|
2189
2188
|
|
|
2190
2189
|
// src/utils/media-constraints.ts
|
|
2191
2190
|
function getMediaConstraints(options) {
|
|
@@ -2561,8 +2560,8 @@ function StreamKeyDisplay({
|
|
|
2561
2560
|
layout = "vertical",
|
|
2562
2561
|
darkMode = false
|
|
2563
2562
|
}) {
|
|
2564
|
-
const [isRevealed, setIsRevealed] =
|
|
2565
|
-
const [copySuccess, setCopySuccess] =
|
|
2563
|
+
const [isRevealed, setIsRevealed] = React2.useState(false);
|
|
2564
|
+
const [copySuccess, setCopySuccess] = React2.useState(false);
|
|
2566
2565
|
const obscureStreamKey = (key) => {
|
|
2567
2566
|
if (key.length <= 12) {
|
|
2568
2567
|
return "\u2022".repeat(key.length);
|
|
@@ -2670,9 +2669,9 @@ function StreamingControls({
|
|
|
2670
2669
|
onAudioDeviceChange,
|
|
2671
2670
|
mediaStream
|
|
2672
2671
|
}) {
|
|
2673
|
-
const [duration, setDuration] =
|
|
2674
|
-
const [showSettings, setShowSettings] =
|
|
2675
|
-
|
|
2672
|
+
const [duration, setDuration] = React2.useState(0);
|
|
2673
|
+
const [showSettings, setShowSettings] = React2.useState(false);
|
|
2674
|
+
React2.useEffect(() => {
|
|
2676
2675
|
if (state !== "live" || !startTime) return;
|
|
2677
2676
|
const interval = setInterval(() => {
|
|
2678
2677
|
const elapsed = Math.floor((Date.now() - startTime.getTime()) / 1e3);
|
|
@@ -3005,8 +3004,8 @@ function StreamingControls({
|
|
|
3005
3004
|
] });
|
|
3006
3005
|
}
|
|
3007
3006
|
function StreamKeyInput({ onSubmit, inline = false }) {
|
|
3008
|
-
const [streamKey, setStreamKey] =
|
|
3009
|
-
const [error, setError] =
|
|
3007
|
+
const [streamKey, setStreamKey] = React2.useState("");
|
|
3008
|
+
const [error, setError] = React2.useState("");
|
|
3010
3009
|
const containerClass = inline ? "dialtribe-stream-key-input flex items-center justify-center h-full w-full p-4 overflow-auto" : "dialtribe-stream-key-input flex items-center justify-center min-h-screen p-4";
|
|
3011
3010
|
const validateStreamKey = (key) => {
|
|
3012
3011
|
const pattern = /^[abvw][a-zA-Z0-9]+_.+$/;
|
|
@@ -3072,7 +3071,7 @@ function StreamKeyInput({ onSubmit, inline = false }) {
|
|
|
3072
3071
|
] })
|
|
3073
3072
|
] }) });
|
|
3074
3073
|
}
|
|
3075
|
-
function
|
|
3074
|
+
function DialtribeStreamer({
|
|
3076
3075
|
sessionToken: propSessionToken,
|
|
3077
3076
|
streamKey: initialStreamKey,
|
|
3078
3077
|
onDone,
|
|
@@ -3081,35 +3080,35 @@ function BroadcastStreamer({
|
|
|
3081
3080
|
apiBaseUrl = DIALTRIBE_API_BASE,
|
|
3082
3081
|
inline = false
|
|
3083
3082
|
}) {
|
|
3084
|
-
const containerClass = inline ? "dialtribe-
|
|
3085
|
-
const centeredContainerClass = inline ? "dialtribe-
|
|
3086
|
-
const dialTribeContext =
|
|
3083
|
+
const containerClass = inline ? "dialtribe-dialtribe-streamer h-full w-full bg-black relative" : "dialtribe-dialtribe-streamer min-h-screen bg-black";
|
|
3084
|
+
const centeredContainerClass = inline ? "dialtribe-dialtribe-streamer flex items-center justify-center h-full w-full p-4 bg-black relative" : "dialtribe-dialtribe-streamer flex items-center justify-center min-h-screen p-4 bg-black";
|
|
3085
|
+
const dialTribeContext = useDialtribeOptional();
|
|
3087
3086
|
const sessionToken = propSessionToken ?? dialTribeContext?.sessionToken ?? null;
|
|
3088
|
-
const [streamKey, setStreamKey] =
|
|
3089
|
-
const [state, setState] =
|
|
3090
|
-
|
|
3087
|
+
const [streamKey, setStreamKey] = React2.useState(initialStreamKey || null);
|
|
3088
|
+
const [state, setState] = React2.useState("idle");
|
|
3089
|
+
React2.useEffect(() => {
|
|
3091
3090
|
if (initialStreamKey && initialStreamKey !== streamKey) {
|
|
3092
3091
|
setStreamKey(initialStreamKey);
|
|
3093
3092
|
}
|
|
3094
3093
|
}, [initialStreamKey]);
|
|
3095
|
-
const [error, setError] =
|
|
3096
|
-
const [mediaStream, setMediaStream] =
|
|
3097
|
-
const [streamer, setStreamer] =
|
|
3098
|
-
const [bytesSent, setBytesSent] =
|
|
3099
|
-
const [startTime, setStartTime] =
|
|
3100
|
-
const [isMuted, setIsMuted] =
|
|
3101
|
-
const [isVideoEnabled, setIsVideoEnabled] =
|
|
3102
|
-
const [facingMode, setFacingMode] =
|
|
3103
|
-
const [showStopConfirm, setShowStopConfirm] =
|
|
3104
|
-
const [showCloseConfirm, setShowCloseConfirm] =
|
|
3105
|
-
const [hasMultipleCameras, setHasMultipleCameras] =
|
|
3106
|
-
const [videoDevices, setVideoDevices] =
|
|
3107
|
-
const [audioDevices, setAudioDevices] =
|
|
3108
|
-
const [selectedVideoDeviceId, setSelectedVideoDeviceId] =
|
|
3109
|
-
const [selectedAudioDeviceId, setSelectedAudioDeviceId] =
|
|
3110
|
-
const videoRef =
|
|
3111
|
-
const streamerRef =
|
|
3112
|
-
const mediaStreamRef =
|
|
3094
|
+
const [error, setError] = React2.useState(null);
|
|
3095
|
+
const [mediaStream, setMediaStream] = React2.useState(null);
|
|
3096
|
+
const [streamer, setStreamer] = React2.useState(null);
|
|
3097
|
+
const [bytesSent, setBytesSent] = React2.useState(0);
|
|
3098
|
+
const [startTime, setStartTime] = React2.useState(null);
|
|
3099
|
+
const [isMuted, setIsMuted] = React2.useState(false);
|
|
3100
|
+
const [isVideoEnabled, setIsVideoEnabled] = React2.useState(true);
|
|
3101
|
+
const [facingMode, setFacingMode] = React2.useState("user");
|
|
3102
|
+
const [showStopConfirm, setShowStopConfirm] = React2.useState(false);
|
|
3103
|
+
const [showCloseConfirm, setShowCloseConfirm] = React2.useState(false);
|
|
3104
|
+
const [hasMultipleCameras, setHasMultipleCameras] = React2.useState(false);
|
|
3105
|
+
const [videoDevices, setVideoDevices] = React2.useState([]);
|
|
3106
|
+
const [audioDevices, setAudioDevices] = React2.useState([]);
|
|
3107
|
+
const [selectedVideoDeviceId, setSelectedVideoDeviceId] = React2.useState();
|
|
3108
|
+
const [selectedAudioDeviceId, setSelectedAudioDeviceId] = React2.useState();
|
|
3109
|
+
const videoRef = React2.useRef(null);
|
|
3110
|
+
const streamerRef = React2.useRef(null);
|
|
3111
|
+
const mediaStreamRef = React2.useRef(null);
|
|
3113
3112
|
const isVideoKey = streamKey ? streamKey.startsWith("v") || streamKey.startsWith("w") : false;
|
|
3114
3113
|
const handleStreamKeySubmit = (key) => {
|
|
3115
3114
|
setStreamKey(key);
|
|
@@ -3119,7 +3118,7 @@ function BroadcastStreamer({
|
|
|
3119
3118
|
setStreamKey(key);
|
|
3120
3119
|
onStreamKeyChange?.(key);
|
|
3121
3120
|
};
|
|
3122
|
-
|
|
3121
|
+
React2.useEffect(() => {
|
|
3123
3122
|
if (!streamKey) return;
|
|
3124
3123
|
const compat = checkBrowserCompatibility();
|
|
3125
3124
|
if (!compat.compatible) {
|
|
@@ -3157,13 +3156,13 @@ function BroadcastStreamer({
|
|
|
3157
3156
|
setHasMultipleCameras(false);
|
|
3158
3157
|
}
|
|
3159
3158
|
};
|
|
3160
|
-
|
|
3159
|
+
React2.useEffect(() => {
|
|
3161
3160
|
streamerRef.current = streamer;
|
|
3162
3161
|
}, [streamer]);
|
|
3163
|
-
|
|
3162
|
+
React2.useEffect(() => {
|
|
3164
3163
|
mediaStreamRef.current = mediaStream;
|
|
3165
3164
|
}, [mediaStream]);
|
|
3166
|
-
|
|
3165
|
+
React2.useEffect(() => {
|
|
3167
3166
|
return () => {
|
|
3168
3167
|
if (streamerRef.current) {
|
|
3169
3168
|
streamerRef.current.stop();
|
|
@@ -3173,7 +3172,7 @@ function BroadcastStreamer({
|
|
|
3173
3172
|
}
|
|
3174
3173
|
};
|
|
3175
3174
|
}, []);
|
|
3176
|
-
|
|
3175
|
+
React2.useEffect(() => {
|
|
3177
3176
|
if (state === "live") {
|
|
3178
3177
|
const handleBeforeUnload = (e) => {
|
|
3179
3178
|
e.preventDefault();
|
|
@@ -3184,7 +3183,7 @@ function BroadcastStreamer({
|
|
|
3184
3183
|
return () => window.removeEventListener("beforeunload", handleBeforeUnload);
|
|
3185
3184
|
}
|
|
3186
3185
|
}, [state]);
|
|
3187
|
-
|
|
3186
|
+
React2.useEffect(() => {
|
|
3188
3187
|
if (videoRef.current && mediaStream) {
|
|
3189
3188
|
videoRef.current.srcObject = mediaStream;
|
|
3190
3189
|
}
|
|
@@ -3467,36 +3466,9 @@ function BroadcastStreamer({
|
|
|
3467
3466
|
}
|
|
3468
3467
|
};
|
|
3469
3468
|
if (!sessionToken) {
|
|
3470
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: centeredContainerClass, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "
|
|
3471
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16
|
|
3472
|
-
|
|
3473
|
-
{
|
|
3474
|
-
className: "w-8 h-8 text-red-600 dark:text-red-400",
|
|
3475
|
-
fill: "none",
|
|
3476
|
-
stroke: "currentColor",
|
|
3477
|
-
viewBox: "0 0 24 24",
|
|
3478
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3479
|
-
"path",
|
|
3480
|
-
{
|
|
3481
|
-
strokeLinecap: "round",
|
|
3482
|
-
strokeLinejoin: "round",
|
|
3483
|
-
strokeWidth: 2,
|
|
3484
|
-
d: "M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"
|
|
3485
|
-
}
|
|
3486
|
-
)
|
|
3487
|
-
}
|
|
3488
|
-
) }),
|
|
3489
|
-
/* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-bold text-black dark:text-white mb-2", children: "Authentication Required" }),
|
|
3490
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 dark:text-gray-400 mb-4", children: "A session token is required to use the broadcast streamer." }),
|
|
3491
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 dark:text-gray-500 mb-6", children: "Wrap your app with DialTribeProvider or pass a sessionToken prop." }),
|
|
3492
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3493
|
-
"button",
|
|
3494
|
-
{
|
|
3495
|
-
onClick: handleDone,
|
|
3496
|
-
className: "w-full px-6 py-2 bg-gray-100 dark:bg-zinc-800 hover:bg-gray-200 dark:hover:bg-zinc-700 text-black dark:text-white font-medium rounded-lg transition-colors",
|
|
3497
|
-
children: "Close"
|
|
3498
|
-
}
|
|
3499
|
-
)
|
|
3469
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: centeredContainerClass, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
3470
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-16 h-16 border-4 border-gray-700 border-t-blue-600 rounded-full animate-spin mx-auto mb-4" }),
|
|
3471
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-white text-lg", children: "Connecting..." })
|
|
3500
3472
|
] }) });
|
|
3501
3473
|
}
|
|
3502
3474
|
if (!streamKey) {
|
|
@@ -3675,7 +3647,7 @@ function BroadcastStreamer({
|
|
|
3675
3647
|
] });
|
|
3676
3648
|
}
|
|
3677
3649
|
|
|
3678
|
-
// src/utils/
|
|
3650
|
+
// src/utils/dialtribe-popup.ts
|
|
3679
3651
|
function calculatePopupDimensions() {
|
|
3680
3652
|
const screenWidth = window.screen.width;
|
|
3681
3653
|
const screenHeight = window.screen.height;
|
|
@@ -3693,26 +3665,22 @@ function calculatePopupDimensions() {
|
|
|
3693
3665
|
const top = Math.floor((screenHeight - height) / 2);
|
|
3694
3666
|
return { width, height, left, top };
|
|
3695
3667
|
}
|
|
3696
|
-
function
|
|
3668
|
+
function openDialtribeStreamerPopup(options) {
|
|
3697
3669
|
const {
|
|
3698
3670
|
sessionToken,
|
|
3699
3671
|
streamKey,
|
|
3672
|
+
streamerUrl,
|
|
3700
3673
|
appId,
|
|
3701
|
-
|
|
3702
|
-
additionalParams,
|
|
3703
|
-
baseUrl = "/broadcasts/new"
|
|
3674
|
+
additionalParams
|
|
3704
3675
|
} = options;
|
|
3705
3676
|
const { width, height, left, top } = calculatePopupDimensions();
|
|
3706
3677
|
const params = new URLSearchParams();
|
|
3707
|
-
if (mode) {
|
|
3708
|
-
params.append("mode", mode);
|
|
3709
|
-
}
|
|
3710
3678
|
if (additionalParams) {
|
|
3711
3679
|
Object.entries(additionalParams).forEach(([key, value]) => {
|
|
3712
3680
|
params.append(key, value);
|
|
3713
3681
|
});
|
|
3714
3682
|
}
|
|
3715
|
-
const url = `${
|
|
3683
|
+
const url = `${streamerUrl}${params.toString() ? `?${params.toString()}` : ""}`;
|
|
3716
3684
|
const popup = window.open(
|
|
3717
3685
|
url,
|
|
3718
3686
|
"_blank",
|
|
@@ -3742,18 +3710,177 @@ function openBroadcastStreamerPopup(options) {
|
|
|
3742
3710
|
setTimeout(sendMessage, 500);
|
|
3743
3711
|
return popup;
|
|
3744
3712
|
}
|
|
3745
|
-
var openBroadcastPopup =
|
|
3713
|
+
var openBroadcastPopup = openDialtribeStreamerPopup;
|
|
3714
|
+
function useDialtribeStreamerPopup() {
|
|
3715
|
+
const [sessionToken, setSessionToken] = React2.useState(null);
|
|
3716
|
+
const [streamKey, setStreamKey] = React2.useState(null);
|
|
3717
|
+
const [apiBaseUrl, setApiBaseUrl] = React2.useState("");
|
|
3718
|
+
const receivedDataRef = React2.useRef(false);
|
|
3719
|
+
React2.useEffect(() => {
|
|
3720
|
+
const handleMessage = (event) => {
|
|
3721
|
+
if (event.data?.type !== "STREAM_KEY") return;
|
|
3722
|
+
const { sessionToken: token, streamKey: key, apiBaseUrl: url } = event.data;
|
|
3723
|
+
if (token && key) {
|
|
3724
|
+
receivedDataRef.current = true;
|
|
3725
|
+
setSessionToken(token);
|
|
3726
|
+
setStreamKey(key);
|
|
3727
|
+
if (url) {
|
|
3728
|
+
setApiBaseUrl(url);
|
|
3729
|
+
}
|
|
3730
|
+
} else if (key) {
|
|
3731
|
+
receivedDataRef.current = true;
|
|
3732
|
+
setStreamKey(key);
|
|
3733
|
+
}
|
|
3734
|
+
};
|
|
3735
|
+
window.addEventListener("message", handleMessage);
|
|
3736
|
+
const requestCredentials = () => {
|
|
3737
|
+
if (window.opener && !receivedDataRef.current) {
|
|
3738
|
+
window.opener.postMessage({ type: "POPUP_READY" }, "*");
|
|
3739
|
+
}
|
|
3740
|
+
};
|
|
3741
|
+
requestCredentials();
|
|
3742
|
+
const pollInterval = setInterval(() => {
|
|
3743
|
+
if (!receivedDataRef.current) {
|
|
3744
|
+
requestCredentials();
|
|
3745
|
+
} else {
|
|
3746
|
+
clearInterval(pollInterval);
|
|
3747
|
+
}
|
|
3748
|
+
}, 200);
|
|
3749
|
+
const timeout = setTimeout(() => {
|
|
3750
|
+
clearInterval(pollInterval);
|
|
3751
|
+
}, 1e4);
|
|
3752
|
+
return () => {
|
|
3753
|
+
window.removeEventListener("message", handleMessage);
|
|
3754
|
+
clearInterval(pollInterval);
|
|
3755
|
+
clearTimeout(timeout);
|
|
3756
|
+
};
|
|
3757
|
+
}, []);
|
|
3758
|
+
return {
|
|
3759
|
+
sessionToken,
|
|
3760
|
+
streamKey,
|
|
3761
|
+
apiBaseUrl,
|
|
3762
|
+
setStreamKey,
|
|
3763
|
+
isReady: receivedDataRef.current
|
|
3764
|
+
};
|
|
3765
|
+
}
|
|
3766
|
+
function useDialtribeStreamerLauncher(options) {
|
|
3767
|
+
const {
|
|
3768
|
+
sessionToken,
|
|
3769
|
+
streamKey,
|
|
3770
|
+
streamerUrl,
|
|
3771
|
+
apiBaseUrl,
|
|
3772
|
+
fallback = "fullscreen",
|
|
3773
|
+
onPopupBlocked,
|
|
3774
|
+
onDone,
|
|
3775
|
+
onStreamKeyChange
|
|
3776
|
+
} = options;
|
|
3777
|
+
const [showFallback, setShowFallback] = React2.useState(false);
|
|
3778
|
+
const [wasBlocked, setWasBlocked] = React2.useState(false);
|
|
3779
|
+
const popupRef = React2.useRef(null);
|
|
3780
|
+
const sessionTokenRef = React2.useRef(sessionToken);
|
|
3781
|
+
const streamKeyRef = React2.useRef(streamKey);
|
|
3782
|
+
const apiBaseUrlRef = React2.useRef(apiBaseUrl);
|
|
3783
|
+
React2.useEffect(() => {
|
|
3784
|
+
sessionTokenRef.current = sessionToken;
|
|
3785
|
+
}, [sessionToken]);
|
|
3786
|
+
React2.useEffect(() => {
|
|
3787
|
+
streamKeyRef.current = streamKey;
|
|
3788
|
+
}, [streamKey]);
|
|
3789
|
+
React2.useEffect(() => {
|
|
3790
|
+
apiBaseUrlRef.current = apiBaseUrl;
|
|
3791
|
+
}, [apiBaseUrl]);
|
|
3792
|
+
React2.useEffect(() => {
|
|
3793
|
+
const handleMessage = (event) => {
|
|
3794
|
+
if (event.data?.type === "POPUP_READY" && popupRef.current) {
|
|
3795
|
+
popupRef.current.postMessage(
|
|
3796
|
+
{
|
|
3797
|
+
type: "STREAM_KEY",
|
|
3798
|
+
sessionToken: sessionTokenRef.current,
|
|
3799
|
+
streamKey: streamKeyRef.current,
|
|
3800
|
+
apiBaseUrl: apiBaseUrlRef.current
|
|
3801
|
+
},
|
|
3802
|
+
"*"
|
|
3803
|
+
);
|
|
3804
|
+
}
|
|
3805
|
+
};
|
|
3806
|
+
window.addEventListener("message", handleMessage);
|
|
3807
|
+
return () => window.removeEventListener("message", handleMessage);
|
|
3808
|
+
}, []);
|
|
3809
|
+
const launch = React2.useCallback(() => {
|
|
3810
|
+
if (!sessionToken) {
|
|
3811
|
+
console.warn("Cannot launch streamer: no session token");
|
|
3812
|
+
return;
|
|
3813
|
+
}
|
|
3814
|
+
setWasBlocked(false);
|
|
3815
|
+
const popup = openDialtribeStreamerPopup({
|
|
3816
|
+
sessionToken,
|
|
3817
|
+
streamKey,
|
|
3818
|
+
streamerUrl
|
|
3819
|
+
});
|
|
3820
|
+
if (popup) {
|
|
3821
|
+
popupRef.current = popup;
|
|
3822
|
+
return;
|
|
3823
|
+
}
|
|
3824
|
+
setWasBlocked(true);
|
|
3825
|
+
onPopupBlocked?.();
|
|
3826
|
+
switch (fallback) {
|
|
3827
|
+
case "fullscreen":
|
|
3828
|
+
setShowFallback(true);
|
|
3829
|
+
break;
|
|
3830
|
+
case "newTab":
|
|
3831
|
+
window.open(streamerUrl, "_blank");
|
|
3832
|
+
break;
|
|
3833
|
+
}
|
|
3834
|
+
}, [sessionToken, streamKey, streamerUrl, fallback, onPopupBlocked]);
|
|
3835
|
+
const closeFallback = React2.useCallback(() => {
|
|
3836
|
+
setShowFallback(false);
|
|
3837
|
+
onDone?.();
|
|
3838
|
+
}, [onDone]);
|
|
3839
|
+
const Fallback = React2.useCallback(() => {
|
|
3840
|
+
if (fallback !== "fullscreen" || !showFallback) {
|
|
3841
|
+
return null;
|
|
3842
|
+
}
|
|
3843
|
+
if (typeof document === "undefined") {
|
|
3844
|
+
return null;
|
|
3845
|
+
}
|
|
3846
|
+
const streamerElement = React2__default.default.createElement(DialtribeStreamer, {
|
|
3847
|
+
sessionToken: sessionToken || void 0,
|
|
3848
|
+
streamKey: streamKey || void 0,
|
|
3849
|
+
apiBaseUrl,
|
|
3850
|
+
onDone: closeFallback,
|
|
3851
|
+
onStreamKeyChange
|
|
3852
|
+
});
|
|
3853
|
+
const overlayElement = React2__default.default.createElement(
|
|
3854
|
+
DialtribeOverlay,
|
|
3855
|
+
{
|
|
3856
|
+
mode: "fullscreen",
|
|
3857
|
+
isOpen: true,
|
|
3858
|
+
onClose: closeFallback,
|
|
3859
|
+
children: streamerElement
|
|
3860
|
+
}
|
|
3861
|
+
);
|
|
3862
|
+
return reactDom.createPortal(overlayElement, document.body);
|
|
3863
|
+
}, [fallback, showFallback, closeFallback, sessionToken, streamKey, apiBaseUrl, onStreamKeyChange]);
|
|
3864
|
+
return {
|
|
3865
|
+
launch,
|
|
3866
|
+
Fallback,
|
|
3867
|
+
showFallback,
|
|
3868
|
+
closeFallback,
|
|
3869
|
+
popupRef: popupRef.current,
|
|
3870
|
+
wasBlocked
|
|
3871
|
+
};
|
|
3872
|
+
}
|
|
3746
3873
|
|
|
3747
3874
|
exports.AudioWaveform = AudioWaveform;
|
|
3748
|
-
exports.BroadcastPlayer = BroadcastPlayer;
|
|
3749
|
-
exports.BroadcastPlayerErrorBoundary = BroadcastPlayerErrorBoundary;
|
|
3750
|
-
exports.BroadcastPlayerModal = BroadcastPlayerModal;
|
|
3751
|
-
exports.BroadcastStreamer = BroadcastStreamer;
|
|
3752
3875
|
exports.CDN_DOMAIN = CDN_DOMAIN;
|
|
3753
3876
|
exports.DEFAULT_ENCODER_SERVER_URL = DEFAULT_ENCODER_SERVER_URL;
|
|
3754
3877
|
exports.DIALTRIBE_API_BASE = DIALTRIBE_API_BASE;
|
|
3755
|
-
exports.
|
|
3756
|
-
exports.
|
|
3878
|
+
exports.DialtribeClient = DialtribeClient;
|
|
3879
|
+
exports.DialtribeOverlay = DialtribeOverlay;
|
|
3880
|
+
exports.DialtribePlayer = DialtribePlayer;
|
|
3881
|
+
exports.DialtribePlayerErrorBoundary = DialtribePlayerErrorBoundary;
|
|
3882
|
+
exports.DialtribeProvider = DialtribeProvider;
|
|
3883
|
+
exports.DialtribeStreamer = DialtribeStreamer;
|
|
3757
3884
|
exports.ENDPOINTS = ENDPOINTS;
|
|
3758
3885
|
exports.HTTP_STATUS = HTTP_STATUS;
|
|
3759
3886
|
exports.HelloWorld = HelloWorld;
|
|
@@ -3771,7 +3898,9 @@ exports.formatTime = formatTime;
|
|
|
3771
3898
|
exports.getMediaConstraints = getMediaConstraints;
|
|
3772
3899
|
exports.getMediaRecorderOptions = getMediaRecorderOptions;
|
|
3773
3900
|
exports.openBroadcastPopup = openBroadcastPopup;
|
|
3774
|
-
exports.
|
|
3775
|
-
exports.
|
|
3901
|
+
exports.openDialtribeStreamerPopup = openDialtribeStreamerPopup;
|
|
3902
|
+
exports.useDialtribe = useDialtribe;
|
|
3903
|
+
exports.useDialtribeStreamerLauncher = useDialtribeStreamerLauncher;
|
|
3904
|
+
exports.useDialtribeStreamerPopup = useDialtribeStreamerPopup;
|
|
3776
3905
|
//# sourceMappingURL=index.js.map
|
|
3777
3906
|
//# sourceMappingURL=index.js.map
|