@dialtribe/react-sdk 0.1.0-alpha.5 → 0.1.0-alpha.7
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/dist/broadcast-player.d.mts +49 -18
- package/dist/broadcast-player.d.ts +49 -18
- package/dist/broadcast-player.js +47 -34
- package/dist/broadcast-player.js.map +1 -1
- package/dist/broadcast-player.mjs +47 -34
- package/dist/broadcast-player.mjs.map +1 -1
- package/dist/index.js +47 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +47 -34
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ function DialTribeProvider({
|
|
|
32
32
|
sessionToken: initialToken,
|
|
33
33
|
onTokenRefresh,
|
|
34
34
|
onTokenExpired,
|
|
35
|
+
apiBaseUrl,
|
|
35
36
|
children
|
|
36
37
|
}) {
|
|
37
38
|
const [sessionToken, setSessionTokenState] = react.useState(initialToken);
|
|
@@ -60,7 +61,8 @@ function DialTribeProvider({
|
|
|
60
61
|
sessionToken,
|
|
61
62
|
setSessionToken,
|
|
62
63
|
isExpired,
|
|
63
|
-
markExpired
|
|
64
|
+
markExpired,
|
|
65
|
+
apiBaseUrl
|
|
64
66
|
};
|
|
65
67
|
return /* @__PURE__ */ jsxRuntime.jsx(DialTribeContext.Provider, { value, children });
|
|
66
68
|
}
|
|
@@ -75,18 +77,28 @@ function useDialTribe() {
|
|
|
75
77
|
}
|
|
76
78
|
|
|
77
79
|
// src/client/DialTribeClient.ts
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
function getDefaultApiBaseUrl() {
|
|
81
|
+
if (typeof process !== "undefined" && process.env?.NEXT_PUBLIC_DIALTRIBE_API_URL) {
|
|
82
|
+
return process.env.NEXT_PUBLIC_DIALTRIBE_API_URL;
|
|
83
|
+
}
|
|
84
|
+
return "https://dialtribe.com/api/public/v1";
|
|
85
|
+
}
|
|
86
|
+
var DIALTRIBE_API_BASE = getDefaultApiBaseUrl();
|
|
87
|
+
function getEndpoints(baseUrl = DIALTRIBE_API_BASE) {
|
|
88
|
+
return {
|
|
89
|
+
broadcasts: `${baseUrl}/broadcasts`,
|
|
90
|
+
broadcast: (id) => `${baseUrl}/broadcasts/${id}`,
|
|
91
|
+
contentPlay: `${baseUrl}/content/play`,
|
|
92
|
+
presignedUrl: `${baseUrl}/media/presigned-url`,
|
|
93
|
+
sessionStart: `${baseUrl}/session/start`,
|
|
94
|
+
sessionPing: `${baseUrl}/session/ping`
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
var ENDPOINTS = getEndpoints();
|
|
87
98
|
var DialTribeClient = class {
|
|
88
99
|
constructor(config) {
|
|
89
100
|
this.config = config;
|
|
101
|
+
this.endpoints = config.apiBaseUrl ? getEndpoints(config.apiBaseUrl) : ENDPOINTS;
|
|
90
102
|
}
|
|
91
103
|
/**
|
|
92
104
|
* Make an authenticated request to DialTribe API
|
|
@@ -133,7 +145,7 @@ var DialTribeClient = class {
|
|
|
133
145
|
if (params?.broadcastStatus) searchParams.set("broadcastStatus", params.broadcastStatus.toString());
|
|
134
146
|
if (params?.search) searchParams.set("search", params.search);
|
|
135
147
|
if (params?.includeDeleted) searchParams.set("includeDeleted", "true");
|
|
136
|
-
const url = `${
|
|
148
|
+
const url = `${this.endpoints.broadcasts}${searchParams.toString() ? `?${searchParams}` : ""}`;
|
|
137
149
|
const response = await this.fetch(url);
|
|
138
150
|
if (!response.ok) {
|
|
139
151
|
throw new Error(`Failed to fetch broadcasts: ${response.status} ${response.statusText}`);
|
|
@@ -144,7 +156,7 @@ var DialTribeClient = class {
|
|
|
144
156
|
* Get a single broadcast by ID
|
|
145
157
|
*/
|
|
146
158
|
async getBroadcast(id) {
|
|
147
|
-
const response = await this.fetch(
|
|
159
|
+
const response = await this.fetch(this.endpoints.broadcast(id));
|
|
148
160
|
if (!response.ok) {
|
|
149
161
|
if (response.status === 404) {
|
|
150
162
|
throw new Error("Broadcast not found");
|
|
@@ -166,7 +178,7 @@ var DialTribeClient = class {
|
|
|
166
178
|
});
|
|
167
179
|
if (params.hash) searchParams.set("hash", params.hash);
|
|
168
180
|
if (params.action) searchParams.set("action", params.action);
|
|
169
|
-
const url = `${
|
|
181
|
+
const url = `${this.endpoints.contentPlay}?${searchParams}`;
|
|
170
182
|
const response = await this.fetch(url, {
|
|
171
183
|
redirect: "manual"
|
|
172
184
|
// Don't follow redirect, we want the URL
|
|
@@ -190,7 +202,7 @@ var DialTribeClient = class {
|
|
|
190
202
|
hash: params.hash,
|
|
191
203
|
fileType: params.fileType
|
|
192
204
|
});
|
|
193
|
-
const url = `${
|
|
205
|
+
const url = `${this.endpoints.presignedUrl}?${searchParams}`;
|
|
194
206
|
const response = await this.fetch(url);
|
|
195
207
|
if (!response.ok) {
|
|
196
208
|
throw new Error(`Failed to refresh URL: ${response.status} ${response.statusText}`);
|
|
@@ -203,7 +215,7 @@ var DialTribeClient = class {
|
|
|
203
215
|
* @returns audienceId and optional resumePosition
|
|
204
216
|
*/
|
|
205
217
|
async startSession(params) {
|
|
206
|
-
const response = await this.fetch(
|
|
218
|
+
const response = await this.fetch(this.endpoints.sessionStart, {
|
|
207
219
|
method: "POST",
|
|
208
220
|
body: JSON.stringify(params)
|
|
209
221
|
});
|
|
@@ -222,7 +234,7 @@ var DialTribeClient = class {
|
|
|
222
234
|
* - 3: UNMOUNT
|
|
223
235
|
*/
|
|
224
236
|
async sendSessionPing(params) {
|
|
225
|
-
const response = await this.fetch(
|
|
237
|
+
const response = await this.fetch(this.endpoints.sessionPing, {
|
|
226
238
|
method: "POST",
|
|
227
239
|
body: JSON.stringify(params)
|
|
228
240
|
});
|
|
@@ -765,11 +777,12 @@ function BroadcastPlayer({
|
|
|
765
777
|
className = "",
|
|
766
778
|
enableKeyboardShortcuts = false
|
|
767
779
|
}) {
|
|
768
|
-
const { sessionToken, setSessionToken, markExpired } = useDialTribe();
|
|
780
|
+
const { sessionToken, setSessionToken, markExpired, apiBaseUrl } = useDialTribe();
|
|
769
781
|
const clientRef = react.useRef(null);
|
|
770
782
|
if (!clientRef.current && sessionToken) {
|
|
771
783
|
clientRef.current = new DialTribeClient({
|
|
772
784
|
sessionToken,
|
|
785
|
+
apiBaseUrl,
|
|
773
786
|
onTokenRefresh: (newToken, expiresAt) => {
|
|
774
787
|
debug.log(`[DialTribeClient] Token refreshed, expires at ${expiresAt}`);
|
|
775
788
|
setSessionToken(newToken, expiresAt);
|
|
@@ -1428,8 +1441,8 @@ function BroadcastPlayer({
|
|
|
1428
1441
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center p-8", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { variant: "white", text: "Loading..." }) });
|
|
1429
1442
|
}
|
|
1430
1443
|
const hasTranscript = broadcast.transcriptStatus === 2 && transcriptData && (transcriptData.segments && transcriptData.segments.some((s) => s.words && s.words.length > 0) || transcriptData.words && transcriptData.words.length > 0);
|
|
1431
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bg-black rounded-lg shadow-2xl w-full h-full flex flex-col ${className}`, children: [
|
|
1432
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-zinc-900/50 backdrop-blur-sm border-b border-zinc-800 px-4 md:px-6 py-3 md:py-4 flex justify-between items-center rounded-t-lg shrink-0", children: [
|
|
1444
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `bg-black rounded-lg shadow-2xl w-full max-h-full flex flex-col overflow-hidden ${className}`, children: [
|
|
1445
|
+
/* @__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: [
|
|
1433
1446
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1434
1447
|
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold text-white", children: broadcast.streamKeyRecord?.foreignName || "Broadcast" }),
|
|
1435
1448
|
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-400", children: [
|
|
@@ -1457,8 +1470,8 @@ function BroadcastPlayer({
|
|
|
1457
1470
|
}
|
|
1458
1471
|
) })
|
|
1459
1472
|
] }),
|
|
1460
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-1 overflow-hidden", children: [
|
|
1461
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 flex flex-col overflow-hidden", children: [
|
|
1473
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col md:flex-row flex-1 min-h-0 overflow-hidden", children: [
|
|
1474
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "shrink-0 md:shrink md:flex-1 flex flex-col overflow-hidden", children: [
|
|
1462
1475
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: `relative ${isAudioOnly ? "bg-linear-to-br from-zinc-900 via-zinc-800 to-zinc-900 flex items-stretch" : "bg-black"}`, children: [
|
|
1463
1476
|
isAudioOnly ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative cursor-pointer w-full flex flex-col", onClick: handleVideoClick, children: !hasError ? /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full h-full relative", children: [
|
|
1464
1477
|
/* @__PURE__ */ jsxRuntime.jsx(AudioWaveform, { audioElement, isPlaying: isLiveStream ? true : playing, isLive: isLiveStream }),
|
|
@@ -1740,7 +1753,7 @@ function BroadcastPlayer({
|
|
|
1740
1753
|
] })
|
|
1741
1754
|
] }))
|
|
1742
1755
|
] }),
|
|
1743
|
-
showTranscript && hasTranscript && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "w-full md:w-96 bg-zinc-900 border-l border-zinc-800 flex flex-col overflow-hidden", children: [
|
|
1756
|
+
showTranscript && hasTranscript && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex-1 md:flex-none min-h-0 w-full md:w-96 bg-zinc-900 border-t md:border-t-0 border-l border-zinc-800 flex flex-col overflow-hidden", children: [
|
|
1744
1757
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 py-3 border-b border-zinc-800 bg-zinc-900/50 shrink-0", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
1745
1758
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1746
1759
|
/* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5 text-green-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" }) }),
|
|
@@ -1769,7 +1782,7 @@ function BroadcastPlayer({
|
|
|
1769
1782
|
]
|
|
1770
1783
|
}
|
|
1771
1784
|
) }),
|
|
1772
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: transcriptContainerRef, className: "flex-1 overflow-y-auto px-4 py-4 text-gray-300 leading-relaxed", children: isLoadingTranscript ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-6 border-2 border-gray-600 border-t-blue-500 rounded-full animate-spin" }) }) : transcriptData?.segments && transcriptData.segments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: (() => {
|
|
1785
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: transcriptContainerRef, className: "flex-1 min-h-0 overflow-y-auto px-4 py-4 text-gray-300 leading-relaxed", children: isLoadingTranscript ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-6 w-6 border-2 border-gray-600 border-t-blue-500 rounded-full animate-spin" }) }) : transcriptData?.segments && transcriptData.segments.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: (() => {
|
|
1773
1786
|
const filteredSegments = transcriptData.segments.filter((s) => s.words && s.words.length > 0);
|
|
1774
1787
|
let globalWordIndex = 0;
|
|
1775
1788
|
const wordMap = /* @__PURE__ */ new Map();
|
|
@@ -1929,14 +1942,12 @@ function BroadcastPlayerModal({
|
|
|
1929
1942
|
}) {
|
|
1930
1943
|
const closeButtonRef = react.useRef(null);
|
|
1931
1944
|
const previousActiveElement = react.useRef(null);
|
|
1932
|
-
if (!isOpen) return null;
|
|
1933
1945
|
react.useEffect(() => {
|
|
1934
|
-
if (isOpen)
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
}
|
|
1946
|
+
if (!isOpen) return;
|
|
1947
|
+
previousActiveElement.current = document.activeElement;
|
|
1948
|
+
setTimeout(() => {
|
|
1949
|
+
closeButtonRef.current?.focus();
|
|
1950
|
+
}, 100);
|
|
1940
1951
|
return () => {
|
|
1941
1952
|
if (previousActiveElement.current) {
|
|
1942
1953
|
previousActiveElement.current.focus();
|
|
@@ -1944,6 +1955,7 @@ function BroadcastPlayerModal({
|
|
|
1944
1955
|
};
|
|
1945
1956
|
}, [isOpen]);
|
|
1946
1957
|
react.useEffect(() => {
|
|
1958
|
+
if (!isOpen) return;
|
|
1947
1959
|
const handleKeyDown = (e) => {
|
|
1948
1960
|
if (e.key === "Escape") {
|
|
1949
1961
|
onClose();
|
|
@@ -1951,7 +1963,8 @@ function BroadcastPlayerModal({
|
|
|
1951
1963
|
};
|
|
1952
1964
|
document.addEventListener("keydown", handleKeyDown);
|
|
1953
1965
|
return () => document.removeEventListener("keydown", handleKeyDown);
|
|
1954
|
-
}, [onClose]);
|
|
1966
|
+
}, [isOpen, onClose]);
|
|
1967
|
+
if (!isOpen) return null;
|
|
1955
1968
|
const handleBackdropClick = (e) => {
|
|
1956
1969
|
if (e.target === e.currentTarget) {
|
|
1957
1970
|
onClose();
|
|
@@ -1960,18 +1973,18 @@ function BroadcastPlayerModal({
|
|
|
1960
1973
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1961
1974
|
"div",
|
|
1962
1975
|
{
|
|
1963
|
-
className: "fixed inset-0 bg-black/70 backdrop-blur-xl flex items-center justify-center z-50 p-4",
|
|
1976
|
+
className: "fixed inset-0 bg-black/70 backdrop-blur-xl flex items-center justify-center z-50 p-2 sm:p-4",
|
|
1964
1977
|
onClick: handleBackdropClick,
|
|
1965
1978
|
role: "dialog",
|
|
1966
1979
|
"aria-modal": "true",
|
|
1967
1980
|
"aria-label": "Broadcast player",
|
|
1968
|
-
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full
|
|
1981
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full max-w-7xl max-h-[95vh] sm:max-h-[90vh] overflow-hidden", children: [
|
|
1969
1982
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1970
1983
|
"button",
|
|
1971
1984
|
{
|
|
1972
1985
|
ref: closeButtonRef,
|
|
1973
1986
|
onClick: onClose,
|
|
1974
|
-
className: "absolute top-4 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",
|
|
1987
|
+
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",
|
|
1975
1988
|
title: "Close (ESC)",
|
|
1976
1989
|
"aria-label": "Close player",
|
|
1977
1990
|
children: "\xD7"
|