@optifye/dashboard-core 4.2.7 → 4.2.8
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/index.d.mts +77 -21
- package/dist/index.d.ts +77 -21
- package/dist/index.js +531 -366
- package/dist/index.mjs +528 -366
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,8 +7,8 @@ var dateFnsTz = require('date-fns-tz');
|
|
|
7
7
|
var dateFns = require('date-fns');
|
|
8
8
|
var mixpanel = require('mixpanel-browser');
|
|
9
9
|
var supabaseJs = require('@supabase/supabase-js');
|
|
10
|
-
var useSWR = require('swr');
|
|
11
10
|
var Hls2 = require('hls.js');
|
|
11
|
+
var useSWR = require('swr');
|
|
12
12
|
var motionUtils = require('motion-utils');
|
|
13
13
|
var motionDom = require('motion-dom');
|
|
14
14
|
var recharts = require('recharts');
|
|
@@ -46,8 +46,8 @@ function _interopNamespace(e) {
|
|
|
46
46
|
|
|
47
47
|
var React14__namespace = /*#__PURE__*/_interopNamespace(React14);
|
|
48
48
|
var mixpanel__default = /*#__PURE__*/_interopDefault(mixpanel);
|
|
49
|
-
var useSWR__default = /*#__PURE__*/_interopDefault(useSWR);
|
|
50
49
|
var Hls2__default = /*#__PURE__*/_interopDefault(Hls2);
|
|
50
|
+
var useSWR__default = /*#__PURE__*/_interopDefault(useSWR);
|
|
51
51
|
var html2canvas__default = /*#__PURE__*/_interopDefault(html2canvas);
|
|
52
52
|
var jsPDF__default = /*#__PURE__*/_interopDefault(jsPDF);
|
|
53
53
|
var SelectPrimitive__namespace = /*#__PURE__*/_interopNamespace(SelectPrimitive);
|
|
@@ -154,6 +154,12 @@ var DEFAULT_ANALYTICS_CONFIG = {
|
|
|
154
154
|
var DEFAULT_AUTH_CONFIG = {
|
|
155
155
|
// Defaults related to auth providers, redirects etc.
|
|
156
156
|
};
|
|
157
|
+
var DEFAULT_VIDEO_CONFIG = {
|
|
158
|
+
canvasConfig: {
|
|
159
|
+
fps: 30,
|
|
160
|
+
useRAF: true
|
|
161
|
+
}
|
|
162
|
+
};
|
|
157
163
|
var LINE_1_UUID = "910a224b-0abc-459a-babb-4c899824cfe7";
|
|
158
164
|
var DEFAULT_CONFIG = {
|
|
159
165
|
apiBaseUrl: void 0,
|
|
@@ -167,7 +173,8 @@ var DEFAULT_CONFIG = {
|
|
|
167
173
|
// Add entity config here
|
|
168
174
|
shiftConfig: DEFAULT_SHIFT_CONFIG,
|
|
169
175
|
workspaceConfig: DEFAULT_WORKSPACE_CONFIG,
|
|
170
|
-
endpoints: DEFAULT_ENDPOINTS_CONFIG
|
|
176
|
+
endpoints: DEFAULT_ENDPOINTS_CONFIG,
|
|
177
|
+
videoConfig: DEFAULT_VIDEO_CONFIG
|
|
171
178
|
};
|
|
172
179
|
|
|
173
180
|
// src/lib/utils/config.ts
|
|
@@ -299,6 +306,10 @@ function useCustomConfig() {
|
|
|
299
306
|
const { customConfig } = useDashboardConfig();
|
|
300
307
|
return customConfig ?? {};
|
|
301
308
|
}
|
|
309
|
+
function useVideoConfig() {
|
|
310
|
+
const { videoConfig } = useDashboardConfig();
|
|
311
|
+
return videoConfig ?? DEFAULT_VIDEO_CONFIG;
|
|
312
|
+
}
|
|
302
313
|
|
|
303
314
|
// src/lib/internal/supabaseClientInstance.ts
|
|
304
315
|
var supabaseInstance = null;
|
|
@@ -4247,6 +4258,351 @@ var useWorkspaceOperators = (workspaceId, options) => {
|
|
|
4247
4258
|
refetch: fetchData
|
|
4248
4259
|
};
|
|
4249
4260
|
};
|
|
4261
|
+
|
|
4262
|
+
// src/lib/utils/dashboardReload.ts
|
|
4263
|
+
var createThrottledReload = (interval = 5e3) => {
|
|
4264
|
+
let last = 0;
|
|
4265
|
+
let queued = false;
|
|
4266
|
+
const doReload = () => {
|
|
4267
|
+
if (typeof window !== "undefined") {
|
|
4268
|
+
window.location.reload();
|
|
4269
|
+
}
|
|
4270
|
+
};
|
|
4271
|
+
return () => {
|
|
4272
|
+
const now2 = Date.now();
|
|
4273
|
+
if (now2 - last >= interval) {
|
|
4274
|
+
last = now2;
|
|
4275
|
+
doReload();
|
|
4276
|
+
} else if (!queued) {
|
|
4277
|
+
queued = true;
|
|
4278
|
+
setTimeout(() => {
|
|
4279
|
+
queued = false;
|
|
4280
|
+
last = Date.now();
|
|
4281
|
+
doReload();
|
|
4282
|
+
}, interval - (now2 - last));
|
|
4283
|
+
}
|
|
4284
|
+
};
|
|
4285
|
+
};
|
|
4286
|
+
var throttledReloadDashboard = createThrottledReload(5e3);
|
|
4287
|
+
|
|
4288
|
+
// src/lib/hooks/useHlsStream.ts
|
|
4289
|
+
var HLS_CONFIG = {
|
|
4290
|
+
maxBufferLength: 8,
|
|
4291
|
+
maxMaxBufferLength: 15,
|
|
4292
|
+
lowLatencyMode: false,
|
|
4293
|
+
enableWorker: true,
|
|
4294
|
+
// Retry + timeout tuned for quick recovery
|
|
4295
|
+
manifestLoadingMaxRetry: 4,
|
|
4296
|
+
levelLoadingMaxRetry: 3,
|
|
4297
|
+
fragLoadingMaxRetry: 4,
|
|
4298
|
+
manifestLoadingRetryDelay: 500,
|
|
4299
|
+
levelLoadingRetryDelay: 500,
|
|
4300
|
+
fragLoadingRetryDelay: 500,
|
|
4301
|
+
manifestLoadingTimeOut: 1e4,
|
|
4302
|
+
levelLoadingTimeOut: 8e3,
|
|
4303
|
+
fragLoadingTimeOut: 1e4,
|
|
4304
|
+
liveSyncDurationCount: 2
|
|
4305
|
+
// Follow live edge aggressively
|
|
4306
|
+
};
|
|
4307
|
+
function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
4308
|
+
const [restartKey, setRestartKey] = React14.useState(0);
|
|
4309
|
+
const hlsRef = React14.useRef(null);
|
|
4310
|
+
const stallCheckIntervalRef = React14.useRef(null);
|
|
4311
|
+
const noProgressTimerRef = React14.useRef(null);
|
|
4312
|
+
const lastTimeUpdateRef = React14.useRef(0);
|
|
4313
|
+
const softRestartCountRef = React14.useRef(0);
|
|
4314
|
+
const isNativeHlsRef = React14.useRef(false);
|
|
4315
|
+
const waitingTimerRef = React14.useRef(null);
|
|
4316
|
+
const cleanup = () => {
|
|
4317
|
+
if (stallCheckIntervalRef.current) {
|
|
4318
|
+
clearInterval(stallCheckIntervalRef.current);
|
|
4319
|
+
stallCheckIntervalRef.current = null;
|
|
4320
|
+
}
|
|
4321
|
+
if (noProgressTimerRef.current) {
|
|
4322
|
+
clearTimeout(noProgressTimerRef.current);
|
|
4323
|
+
noProgressTimerRef.current = null;
|
|
4324
|
+
}
|
|
4325
|
+
if (waitingTimerRef.current) {
|
|
4326
|
+
clearTimeout(waitingTimerRef.current);
|
|
4327
|
+
waitingTimerRef.current = null;
|
|
4328
|
+
}
|
|
4329
|
+
if (hlsRef.current) {
|
|
4330
|
+
hlsRef.current.destroy();
|
|
4331
|
+
hlsRef.current = null;
|
|
4332
|
+
}
|
|
4333
|
+
const video = videoRef.current;
|
|
4334
|
+
if (video) {
|
|
4335
|
+
video.pause();
|
|
4336
|
+
video.removeAttribute("src");
|
|
4337
|
+
video.load();
|
|
4338
|
+
video.removeEventListener("waiting", handleWaiting);
|
|
4339
|
+
video.removeEventListener("timeupdate", handleTimeUpdate);
|
|
4340
|
+
video.removeEventListener("error", handleNativeError);
|
|
4341
|
+
}
|
|
4342
|
+
lastTimeUpdateRef.current = 0;
|
|
4343
|
+
softRestartCountRef.current = 0;
|
|
4344
|
+
};
|
|
4345
|
+
const seekToLiveEdge = () => {
|
|
4346
|
+
const hls = hlsRef.current;
|
|
4347
|
+
const video = videoRef.current;
|
|
4348
|
+
if (!hls || !video) return;
|
|
4349
|
+
if (hls.liveSyncPosition !== null && hls.liveSyncPosition !== void 0) {
|
|
4350
|
+
video.currentTime = hls.liveSyncPosition;
|
|
4351
|
+
} else if (hls.levels?.[hls.currentLevel]?.details) {
|
|
4352
|
+
const levelDetails = hls.levels[hls.currentLevel].details;
|
|
4353
|
+
if (levelDetails && levelDetails.edge !== void 0) {
|
|
4354
|
+
video.currentTime = Math.max(0, levelDetails.edge - 5);
|
|
4355
|
+
}
|
|
4356
|
+
}
|
|
4357
|
+
};
|
|
4358
|
+
const softRestart = (reason) => {
|
|
4359
|
+
console.warn(`[HLS] Soft restart: ${reason}`);
|
|
4360
|
+
const hls = hlsRef.current;
|
|
4361
|
+
if (!hls) return;
|
|
4362
|
+
try {
|
|
4363
|
+
hls.stopLoad();
|
|
4364
|
+
hls.startLoad(-1);
|
|
4365
|
+
seekToLiveEdge();
|
|
4366
|
+
softRestartCountRef.current++;
|
|
4367
|
+
if (softRestartCountRef.current >= 5) {
|
|
4368
|
+
hardRestart(`${reason} (escalated after ${softRestartCountRef.current} soft restarts)`);
|
|
4369
|
+
}
|
|
4370
|
+
} catch (error) {
|
|
4371
|
+
console.error("[HLS] Soft restart failed:", error);
|
|
4372
|
+
hardRestart(`${reason} (soft restart error)`);
|
|
4373
|
+
}
|
|
4374
|
+
};
|
|
4375
|
+
const hardRestart = (reason) => {
|
|
4376
|
+
console.warn(`[HLS] Hard restart: ${reason}`);
|
|
4377
|
+
cleanup();
|
|
4378
|
+
setRestartKey((k) => k + 1);
|
|
4379
|
+
softRestartCountRef.current = 0;
|
|
4380
|
+
if (reason.includes("hard restart") || reason.includes("native video error")) {
|
|
4381
|
+
if (onFatalError) {
|
|
4382
|
+
onFatalError();
|
|
4383
|
+
} else {
|
|
4384
|
+
throttledReloadDashboard();
|
|
4385
|
+
}
|
|
4386
|
+
}
|
|
4387
|
+
};
|
|
4388
|
+
const handleWaiting = () => {
|
|
4389
|
+
if (isNativeHlsRef.current) return;
|
|
4390
|
+
console.log("[HLS] Video waiting (buffer underrun)");
|
|
4391
|
+
if (waitingTimerRef.current) {
|
|
4392
|
+
clearTimeout(waitingTimerRef.current);
|
|
4393
|
+
}
|
|
4394
|
+
waitingTimerRef.current = setTimeout(() => {
|
|
4395
|
+
const video = videoRef.current;
|
|
4396
|
+
if (video && video.readyState < 3) {
|
|
4397
|
+
softRestart("waiting timeout");
|
|
4398
|
+
}
|
|
4399
|
+
}, 1e4);
|
|
4400
|
+
};
|
|
4401
|
+
const handleTimeUpdate = () => {
|
|
4402
|
+
const video = videoRef.current;
|
|
4403
|
+
if (!video) return;
|
|
4404
|
+
lastTimeUpdateRef.current = video.currentTime;
|
|
4405
|
+
if (waitingTimerRef.current) {
|
|
4406
|
+
clearTimeout(waitingTimerRef.current);
|
|
4407
|
+
waitingTimerRef.current = null;
|
|
4408
|
+
}
|
|
4409
|
+
};
|
|
4410
|
+
const handleNativeError = () => {
|
|
4411
|
+
console.error("[HLS] Native video error");
|
|
4412
|
+
hardRestart("native video error");
|
|
4413
|
+
};
|
|
4414
|
+
const startStallDetection = () => {
|
|
4415
|
+
if (isNativeHlsRef.current) return;
|
|
4416
|
+
stallCheckIntervalRef.current = setInterval(() => {
|
|
4417
|
+
const video = videoRef.current;
|
|
4418
|
+
if (!video || video.paused || video.ended) return;
|
|
4419
|
+
const currentTime = video.currentTime;
|
|
4420
|
+
const lastTime = lastTimeUpdateRef.current;
|
|
4421
|
+
if (Math.abs(currentTime - lastTime) < 0.1 && video.readyState >= 2) {
|
|
4422
|
+
console.warn("[HLS] Playback stall detected");
|
|
4423
|
+
if (!noProgressTimerRef.current) {
|
|
4424
|
+
noProgressTimerRef.current = setTimeout(() => {
|
|
4425
|
+
softRestart("playback stall");
|
|
4426
|
+
noProgressTimerRef.current = null;
|
|
4427
|
+
}, 8e3);
|
|
4428
|
+
}
|
|
4429
|
+
} else {
|
|
4430
|
+
if (noProgressTimerRef.current) {
|
|
4431
|
+
clearTimeout(noProgressTimerRef.current);
|
|
4432
|
+
noProgressTimerRef.current = null;
|
|
4433
|
+
}
|
|
4434
|
+
}
|
|
4435
|
+
}, 7e3);
|
|
4436
|
+
};
|
|
4437
|
+
React14.useEffect(() => {
|
|
4438
|
+
if (!src || !shouldPlay) {
|
|
4439
|
+
cleanup();
|
|
4440
|
+
return;
|
|
4441
|
+
}
|
|
4442
|
+
const video = videoRef.current;
|
|
4443
|
+
if (!video) return;
|
|
4444
|
+
isNativeHlsRef.current = video.canPlayType("application/vnd.apple.mpegurl") === "probably";
|
|
4445
|
+
if (Hls2__default.default.isSupported() && !isNativeHlsRef.current) {
|
|
4446
|
+
const hls = new Hls2__default.default(HLS_CONFIG);
|
|
4447
|
+
hlsRef.current = hls;
|
|
4448
|
+
hls.attachMedia(video);
|
|
4449
|
+
hls.loadSource(src);
|
|
4450
|
+
hls.on(Hls2__default.default.Events.ERROR, (_, data) => {
|
|
4451
|
+
if (!data.fatal) return;
|
|
4452
|
+
console.error("[HLS] Fatal error:", data.type, data.details);
|
|
4453
|
+
if (data.response?.code === 404) {
|
|
4454
|
+
hardRestart("404 hard restart");
|
|
4455
|
+
return;
|
|
4456
|
+
}
|
|
4457
|
+
switch (data.type) {
|
|
4458
|
+
case Hls2__default.default.ErrorTypes.NETWORK_ERROR:
|
|
4459
|
+
case Hls2__default.default.ErrorTypes.MEDIA_ERROR:
|
|
4460
|
+
softRestart(`${data.type}: ${data.details}`);
|
|
4461
|
+
break;
|
|
4462
|
+
default:
|
|
4463
|
+
hardRestart(`Fatal ${data.type}: ${data.details}`);
|
|
4464
|
+
break;
|
|
4465
|
+
}
|
|
4466
|
+
});
|
|
4467
|
+
hls.on(Hls2__default.default.Events.MANIFEST_PARSED, () => {
|
|
4468
|
+
video.play().catch((err) => {
|
|
4469
|
+
console.error("[HLS] Play failed:", err);
|
|
4470
|
+
});
|
|
4471
|
+
});
|
|
4472
|
+
video.addEventListener("waiting", handleWaiting);
|
|
4473
|
+
video.addEventListener("timeupdate", handleTimeUpdate);
|
|
4474
|
+
startStallDetection();
|
|
4475
|
+
} else if (isNativeHlsRef.current) {
|
|
4476
|
+
console.log("[HLS] Using native HLS");
|
|
4477
|
+
video.src = src;
|
|
4478
|
+
video.addEventListener("error", handleNativeError);
|
|
4479
|
+
video.play().catch((err) => {
|
|
4480
|
+
console.error("[HLS] Native play failed:", err);
|
|
4481
|
+
});
|
|
4482
|
+
} else {
|
|
4483
|
+
console.error("[HLS] HLS not supported");
|
|
4484
|
+
}
|
|
4485
|
+
return cleanup;
|
|
4486
|
+
}, [src, shouldPlay, restartKey, onFatalError]);
|
|
4487
|
+
return {
|
|
4488
|
+
restartKey,
|
|
4489
|
+
isNativeHls: isNativeHlsRef.current
|
|
4490
|
+
};
|
|
4491
|
+
}
|
|
4492
|
+
function useHlsStreamWithCropping(videoRef, canvasRef, options) {
|
|
4493
|
+
const { src, shouldPlay, cropping, canvasFps = 30, useRAF = true, onFatalError } = options;
|
|
4494
|
+
const animationFrameRef = React14.useRef(null);
|
|
4495
|
+
const intervalRef = React14.useRef(null);
|
|
4496
|
+
const isDrawingRef = React14.useRef(false);
|
|
4497
|
+
const hlsState = useHlsStream(videoRef, { src, shouldPlay, onFatalError });
|
|
4498
|
+
const calculateCropRect = React14.useCallback((video, cropping2) => {
|
|
4499
|
+
const videoWidth = video.videoWidth;
|
|
4500
|
+
const videoHeight = video.videoHeight;
|
|
4501
|
+
const sx = cropping2.x / 100 * videoWidth;
|
|
4502
|
+
const sy = cropping2.y / 100 * videoHeight;
|
|
4503
|
+
const sw = cropping2.width / 100 * videoWidth;
|
|
4504
|
+
const sh = cropping2.height / 100 * videoHeight;
|
|
4505
|
+
return { sx, sy, sw, sh };
|
|
4506
|
+
}, []);
|
|
4507
|
+
const drawFrame = React14.useCallback(() => {
|
|
4508
|
+
const video = videoRef.current;
|
|
4509
|
+
const canvas = canvasRef.current;
|
|
4510
|
+
if (!video || !canvas || !cropping) return;
|
|
4511
|
+
const ctx = canvas.getContext("2d");
|
|
4512
|
+
if (!ctx) return;
|
|
4513
|
+
if (video.readyState < 2) return;
|
|
4514
|
+
try {
|
|
4515
|
+
const videoWidth = video.videoWidth;
|
|
4516
|
+
const videoHeight = video.videoHeight;
|
|
4517
|
+
if (!videoWidth || !videoHeight) return;
|
|
4518
|
+
const { sx, sy, sw, sh } = calculateCropRect(video, cropping);
|
|
4519
|
+
const canvasContainer = canvas.parentElement;
|
|
4520
|
+
if (canvasContainer) {
|
|
4521
|
+
const containerWidth = canvasContainer.clientWidth;
|
|
4522
|
+
const containerHeight = canvasContainer.clientHeight;
|
|
4523
|
+
if (canvas.width !== containerWidth || canvas.height !== containerHeight) {
|
|
4524
|
+
canvas.width = containerWidth;
|
|
4525
|
+
canvas.height = containerHeight;
|
|
4526
|
+
}
|
|
4527
|
+
}
|
|
4528
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
4529
|
+
ctx.drawImage(
|
|
4530
|
+
video,
|
|
4531
|
+
sx,
|
|
4532
|
+
sy,
|
|
4533
|
+
sw,
|
|
4534
|
+
sh,
|
|
4535
|
+
// Source rectangle (cropped portion)
|
|
4536
|
+
0,
|
|
4537
|
+
0,
|
|
4538
|
+
canvas.width,
|
|
4539
|
+
canvas.height
|
|
4540
|
+
// Destination rectangle (full canvas)
|
|
4541
|
+
);
|
|
4542
|
+
} catch (err) {
|
|
4543
|
+
console.warn("Canvas drawing error:", err);
|
|
4544
|
+
}
|
|
4545
|
+
}, [videoRef, canvasRef, cropping, calculateCropRect]);
|
|
4546
|
+
const startCanvasRendering = React14.useCallback(() => {
|
|
4547
|
+
if (isDrawingRef.current) return;
|
|
4548
|
+
isDrawingRef.current = true;
|
|
4549
|
+
if (useRAF) {
|
|
4550
|
+
const animate = () => {
|
|
4551
|
+
drawFrame();
|
|
4552
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
4553
|
+
};
|
|
4554
|
+
animate();
|
|
4555
|
+
} else {
|
|
4556
|
+
const frameInterval = 1e3 / canvasFps;
|
|
4557
|
+
intervalRef.current = setInterval(drawFrame, frameInterval);
|
|
4558
|
+
}
|
|
4559
|
+
}, [drawFrame, canvasFps, useRAF]);
|
|
4560
|
+
const stopCanvasRendering = React14.useCallback(() => {
|
|
4561
|
+
isDrawingRef.current = false;
|
|
4562
|
+
if (animationFrameRef.current) {
|
|
4563
|
+
cancelAnimationFrame(animationFrameRef.current);
|
|
4564
|
+
animationFrameRef.current = null;
|
|
4565
|
+
}
|
|
4566
|
+
if (intervalRef.current) {
|
|
4567
|
+
clearInterval(intervalRef.current);
|
|
4568
|
+
intervalRef.current = null;
|
|
4569
|
+
}
|
|
4570
|
+
}, []);
|
|
4571
|
+
React14.useEffect(() => {
|
|
4572
|
+
const video = videoRef.current;
|
|
4573
|
+
if (!video || !cropping || !shouldPlay) {
|
|
4574
|
+
stopCanvasRendering();
|
|
4575
|
+
return;
|
|
4576
|
+
}
|
|
4577
|
+
const handlePlay = () => {
|
|
4578
|
+
if (cropping) {
|
|
4579
|
+
startCanvasRendering();
|
|
4580
|
+
}
|
|
4581
|
+
};
|
|
4582
|
+
const handlePause = () => {
|
|
4583
|
+
stopCanvasRendering();
|
|
4584
|
+
};
|
|
4585
|
+
const handleEnded = () => {
|
|
4586
|
+
stopCanvasRendering();
|
|
4587
|
+
};
|
|
4588
|
+
video.addEventListener("play", handlePlay);
|
|
4589
|
+
video.addEventListener("pause", handlePause);
|
|
4590
|
+
video.addEventListener("ended", handleEnded);
|
|
4591
|
+
if (!video.paused && video.readyState >= 2) {
|
|
4592
|
+
startCanvasRendering();
|
|
4593
|
+
}
|
|
4594
|
+
return () => {
|
|
4595
|
+
stopCanvasRendering();
|
|
4596
|
+
video.removeEventListener("play", handlePlay);
|
|
4597
|
+
video.removeEventListener("pause", handlePause);
|
|
4598
|
+
video.removeEventListener("ended", handleEnded);
|
|
4599
|
+
};
|
|
4600
|
+
}, [videoRef, cropping, shouldPlay, startCanvasRendering, stopCanvasRendering]);
|
|
4601
|
+
return {
|
|
4602
|
+
...hlsState,
|
|
4603
|
+
isCanvasRendering: isDrawingRef.current
|
|
4604
|
+
};
|
|
4605
|
+
}
|
|
4250
4606
|
function useThreads() {
|
|
4251
4607
|
const supabase = _getSupabaseInstance();
|
|
4252
4608
|
const fetcher = async (key) => {
|
|
@@ -4904,349 +5260,118 @@ function useNavigation(customNavigate) {
|
|
|
4904
5260
|
};
|
|
4905
5261
|
attemptNavigation();
|
|
4906
5262
|
},
|
|
4907
|
-
[router$1, customNavigate]
|
|
4908
|
-
);
|
|
4909
|
-
return {
|
|
4910
|
-
pathname,
|
|
4911
|
-
query,
|
|
4912
|
-
isReady,
|
|
4913
|
-
activeLineId,
|
|
4914
|
-
activeWorkspaceId,
|
|
4915
|
-
isActive,
|
|
4916
|
-
isInSection,
|
|
4917
|
-
isLineView,
|
|
4918
|
-
isWorkspaceView,
|
|
4919
|
-
goToDashboard,
|
|
4920
|
-
goToWorkspace,
|
|
4921
|
-
goToLine,
|
|
4922
|
-
goToTargets,
|
|
4923
|
-
goToShifts,
|
|
4924
|
-
goToLeaderboard,
|
|
4925
|
-
goToFactoryView,
|
|
4926
|
-
goToProfile,
|
|
4927
|
-
navigate
|
|
4928
|
-
};
|
|
4929
|
-
}
|
|
4930
|
-
function useWorkspaceNavigation() {
|
|
4931
|
-
const { defaultTimezone } = useDateTimeConfig();
|
|
4932
|
-
const getWorkspaceNavigationParams3 = React14.useCallback(
|
|
4933
|
-
(workspaceId, options) => {
|
|
4934
|
-
let dateToUse = options?.date;
|
|
4935
|
-
if (!dateToUse && options?.useCurrentDate) {
|
|
4936
|
-
dateToUse = getOperationalDate(defaultTimezone || "UTC");
|
|
4937
|
-
}
|
|
4938
|
-
return {
|
|
4939
|
-
workspaceId,
|
|
4940
|
-
date: dateToUse,
|
|
4941
|
-
shift: options?.shift,
|
|
4942
|
-
sourceType: options?.sourceType
|
|
4943
|
-
};
|
|
4944
|
-
},
|
|
4945
|
-
[defaultTimezone]
|
|
4946
|
-
);
|
|
4947
|
-
return {
|
|
4948
|
-
getWorkspaceNavigationParams: getWorkspaceNavigationParams3
|
|
4949
|
-
};
|
|
4950
|
-
}
|
|
4951
|
-
function useDateFormatter() {
|
|
4952
|
-
const { defaultTimezone, defaultLocale, dateFormatOptions, timeFormatOptions, dateTimeFormatOptions } = useDateTimeConfig();
|
|
4953
|
-
const formatDate = React14.useCallback(
|
|
4954
|
-
(date, formatString) => {
|
|
4955
|
-
const dateObj = typeof date === "string" ? dateFns.parseISO(date) : date;
|
|
4956
|
-
if (!dateFns.isValid(dateObj)) return "Invalid Date";
|
|
4957
|
-
const tz = defaultTimezone || "UTC";
|
|
4958
|
-
if (formatString) {
|
|
4959
|
-
return dateFnsTz.formatInTimeZone(dateObj, tz, formatString);
|
|
4960
|
-
}
|
|
4961
|
-
const effectiveOptions = dateFormatOptions || { year: "numeric", month: "short", day: "numeric" };
|
|
4962
|
-
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
4963
|
-
},
|
|
4964
|
-
[defaultTimezone, defaultLocale, dateFormatOptions]
|
|
4965
|
-
);
|
|
4966
|
-
const formatTime2 = React14.useCallback(
|
|
4967
|
-
(date, formatString) => {
|
|
4968
|
-
const dateObj = typeof date === "string" ? dateFns.parseISO(date) : date;
|
|
4969
|
-
if (!dateFns.isValid(dateObj)) return "Invalid Time";
|
|
4970
|
-
const tz = defaultTimezone || "UTC";
|
|
4971
|
-
if (formatString) {
|
|
4972
|
-
return dateFnsTz.formatInTimeZone(dateObj, tz, formatString);
|
|
4973
|
-
}
|
|
4974
|
-
const effectiveOptions = timeFormatOptions || { hour: "numeric", minute: "numeric" };
|
|
4975
|
-
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
4976
|
-
},
|
|
4977
|
-
[defaultTimezone, defaultLocale, timeFormatOptions]
|
|
4978
|
-
);
|
|
4979
|
-
const formatDateTime = React14.useCallback(
|
|
4980
|
-
(date, formatString) => {
|
|
4981
|
-
const dateObj = typeof date === "string" ? dateFns.parseISO(date) : date;
|
|
4982
|
-
if (!dateFns.isValid(dateObj)) return "Invalid Date/Time";
|
|
4983
|
-
const tz = defaultTimezone || "UTC";
|
|
4984
|
-
if (formatString) {
|
|
4985
|
-
return dateFnsTz.formatInTimeZone(dateObj, tz, formatString);
|
|
4986
|
-
}
|
|
4987
|
-
const effectiveOptions = dateTimeFormatOptions || { year: "numeric", month: "short", day: "numeric", hour: "numeric", minute: "numeric" };
|
|
4988
|
-
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
4989
|
-
},
|
|
4990
|
-
[defaultTimezone, defaultLocale, dateTimeFormatOptions]
|
|
4991
|
-
);
|
|
4992
|
-
const getNow = React14.useCallback(() => {
|
|
4993
|
-
return /* @__PURE__ */ new Date();
|
|
4994
|
-
}, []);
|
|
4995
|
-
return {
|
|
4996
|
-
formatDate,
|
|
4997
|
-
formatTime: formatTime2,
|
|
4998
|
-
formatDateTime,
|
|
4999
|
-
getNow,
|
|
5000
|
-
timezone: defaultTimezone || "UTC",
|
|
5001
|
-
locale: defaultLocale || "en-US"
|
|
5002
|
-
};
|
|
5003
|
-
}
|
|
5004
|
-
var useFormatNumber = () => {
|
|
5005
|
-
const { defaultLocale } = useDateTimeConfig();
|
|
5006
|
-
const formatNumber = React14.useCallback(
|
|
5007
|
-
(value, options) => {
|
|
5008
|
-
try {
|
|
5009
|
-
return new Intl.NumberFormat(defaultLocale || "en-US", options).format(value);
|
|
5010
|
-
} catch (error) {
|
|
5011
|
-
console.error("Error formatting number:", error);
|
|
5012
|
-
return String(value);
|
|
5013
|
-
}
|
|
5014
|
-
},
|
|
5015
|
-
[defaultLocale]
|
|
5016
|
-
);
|
|
5017
|
-
return { formatNumber };
|
|
5018
|
-
};
|
|
5019
|
-
|
|
5020
|
-
// src/lib/utils/dashboardReload.ts
|
|
5021
|
-
var createThrottledReload = (interval = 5e3) => {
|
|
5022
|
-
let last = 0;
|
|
5023
|
-
let queued = false;
|
|
5024
|
-
const doReload = () => {
|
|
5025
|
-
if (typeof window !== "undefined") {
|
|
5026
|
-
window.location.reload();
|
|
5027
|
-
}
|
|
5028
|
-
};
|
|
5029
|
-
return () => {
|
|
5030
|
-
const now2 = Date.now();
|
|
5031
|
-
if (now2 - last >= interval) {
|
|
5032
|
-
last = now2;
|
|
5033
|
-
doReload();
|
|
5034
|
-
} else if (!queued) {
|
|
5035
|
-
queued = true;
|
|
5036
|
-
setTimeout(() => {
|
|
5037
|
-
queued = false;
|
|
5038
|
-
last = Date.now();
|
|
5039
|
-
doReload();
|
|
5040
|
-
}, interval - (now2 - last));
|
|
5041
|
-
}
|
|
5042
|
-
};
|
|
5043
|
-
};
|
|
5044
|
-
var throttledReloadDashboard = createThrottledReload(5e3);
|
|
5045
|
-
|
|
5046
|
-
// src/lib/hooks/useHlsStream.ts
|
|
5047
|
-
var HLS_CONFIG = {
|
|
5048
|
-
maxBufferLength: 8,
|
|
5049
|
-
maxMaxBufferLength: 15,
|
|
5050
|
-
lowLatencyMode: false,
|
|
5051
|
-
enableWorker: true,
|
|
5052
|
-
// Retry + timeout tuned for quick recovery
|
|
5053
|
-
manifestLoadingMaxRetry: 4,
|
|
5054
|
-
levelLoadingMaxRetry: 3,
|
|
5055
|
-
fragLoadingMaxRetry: 4,
|
|
5056
|
-
manifestLoadingRetryDelay: 500,
|
|
5057
|
-
levelLoadingRetryDelay: 500,
|
|
5058
|
-
fragLoadingRetryDelay: 500,
|
|
5059
|
-
manifestLoadingTimeOut: 1e4,
|
|
5060
|
-
levelLoadingTimeOut: 8e3,
|
|
5061
|
-
fragLoadingTimeOut: 1e4,
|
|
5062
|
-
liveSyncDurationCount: 2
|
|
5063
|
-
// Follow live edge aggressively
|
|
5064
|
-
};
|
|
5065
|
-
function useHlsStream(videoRef, { src, shouldPlay, onFatalError }) {
|
|
5066
|
-
const [restartKey, setRestartKey] = React14.useState(0);
|
|
5067
|
-
const hlsRef = React14.useRef(null);
|
|
5068
|
-
const stallCheckIntervalRef = React14.useRef(null);
|
|
5069
|
-
const noProgressTimerRef = React14.useRef(null);
|
|
5070
|
-
const lastTimeUpdateRef = React14.useRef(0);
|
|
5071
|
-
const softRestartCountRef = React14.useRef(0);
|
|
5072
|
-
const isNativeHlsRef = React14.useRef(false);
|
|
5073
|
-
const waitingTimerRef = React14.useRef(null);
|
|
5074
|
-
const cleanup = () => {
|
|
5075
|
-
if (stallCheckIntervalRef.current) {
|
|
5076
|
-
clearInterval(stallCheckIntervalRef.current);
|
|
5077
|
-
stallCheckIntervalRef.current = null;
|
|
5078
|
-
}
|
|
5079
|
-
if (noProgressTimerRef.current) {
|
|
5080
|
-
clearTimeout(noProgressTimerRef.current);
|
|
5081
|
-
noProgressTimerRef.current = null;
|
|
5082
|
-
}
|
|
5083
|
-
if (waitingTimerRef.current) {
|
|
5084
|
-
clearTimeout(waitingTimerRef.current);
|
|
5085
|
-
waitingTimerRef.current = null;
|
|
5086
|
-
}
|
|
5087
|
-
if (hlsRef.current) {
|
|
5088
|
-
hlsRef.current.destroy();
|
|
5089
|
-
hlsRef.current = null;
|
|
5090
|
-
}
|
|
5091
|
-
const video = videoRef.current;
|
|
5092
|
-
if (video) {
|
|
5093
|
-
video.pause();
|
|
5094
|
-
video.removeAttribute("src");
|
|
5095
|
-
video.load();
|
|
5096
|
-
video.removeEventListener("waiting", handleWaiting);
|
|
5097
|
-
video.removeEventListener("timeupdate", handleTimeUpdate);
|
|
5098
|
-
video.removeEventListener("error", handleNativeError);
|
|
5099
|
-
}
|
|
5100
|
-
lastTimeUpdateRef.current = 0;
|
|
5101
|
-
softRestartCountRef.current = 0;
|
|
5102
|
-
};
|
|
5103
|
-
const seekToLiveEdge = () => {
|
|
5104
|
-
const hls = hlsRef.current;
|
|
5105
|
-
const video = videoRef.current;
|
|
5106
|
-
if (!hls || !video) return;
|
|
5107
|
-
if (hls.liveSyncPosition !== null && hls.liveSyncPosition !== void 0) {
|
|
5108
|
-
video.currentTime = hls.liveSyncPosition;
|
|
5109
|
-
} else if (hls.levels?.[hls.currentLevel]?.details) {
|
|
5110
|
-
const levelDetails = hls.levels[hls.currentLevel].details;
|
|
5111
|
-
if (levelDetails && levelDetails.edge !== void 0) {
|
|
5112
|
-
video.currentTime = Math.max(0, levelDetails.edge - 5);
|
|
5113
|
-
}
|
|
5114
|
-
}
|
|
5263
|
+
[router$1, customNavigate]
|
|
5264
|
+
);
|
|
5265
|
+
return {
|
|
5266
|
+
pathname,
|
|
5267
|
+
query,
|
|
5268
|
+
isReady,
|
|
5269
|
+
activeLineId,
|
|
5270
|
+
activeWorkspaceId,
|
|
5271
|
+
isActive,
|
|
5272
|
+
isInSection,
|
|
5273
|
+
isLineView,
|
|
5274
|
+
isWorkspaceView,
|
|
5275
|
+
goToDashboard,
|
|
5276
|
+
goToWorkspace,
|
|
5277
|
+
goToLine,
|
|
5278
|
+
goToTargets,
|
|
5279
|
+
goToShifts,
|
|
5280
|
+
goToLeaderboard,
|
|
5281
|
+
goToFactoryView,
|
|
5282
|
+
goToProfile,
|
|
5283
|
+
navigate
|
|
5115
5284
|
};
|
|
5116
|
-
|
|
5117
|
-
|
|
5118
|
-
|
|
5119
|
-
|
|
5120
|
-
|
|
5121
|
-
|
|
5122
|
-
|
|
5123
|
-
|
|
5124
|
-
softRestartCountRef.current++;
|
|
5125
|
-
if (softRestartCountRef.current >= 5) {
|
|
5126
|
-
hardRestart(`${reason} (escalated after ${softRestartCountRef.current} soft restarts)`);
|
|
5285
|
+
}
|
|
5286
|
+
function useWorkspaceNavigation() {
|
|
5287
|
+
const { defaultTimezone } = useDateTimeConfig();
|
|
5288
|
+
const getWorkspaceNavigationParams3 = React14.useCallback(
|
|
5289
|
+
(workspaceId, options) => {
|
|
5290
|
+
let dateToUse = options?.date;
|
|
5291
|
+
if (!dateToUse && options?.useCurrentDate) {
|
|
5292
|
+
dateToUse = getOperationalDate(defaultTimezone || "UTC");
|
|
5127
5293
|
}
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
|
|
5294
|
+
return {
|
|
5295
|
+
workspaceId,
|
|
5296
|
+
date: dateToUse,
|
|
5297
|
+
shift: options?.shift,
|
|
5298
|
+
sourceType: options?.sourceType
|
|
5299
|
+
};
|
|
5300
|
+
},
|
|
5301
|
+
[defaultTimezone]
|
|
5302
|
+
);
|
|
5303
|
+
return {
|
|
5304
|
+
getWorkspaceNavigationParams: getWorkspaceNavigationParams3
|
|
5132
5305
|
};
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
if (
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5306
|
+
}
|
|
5307
|
+
function useDateFormatter() {
|
|
5308
|
+
const { defaultTimezone, defaultLocale, dateFormatOptions, timeFormatOptions, dateTimeFormatOptions } = useDateTimeConfig();
|
|
5309
|
+
const formatDate = React14.useCallback(
|
|
5310
|
+
(date, formatString) => {
|
|
5311
|
+
const dateObj = typeof date === "string" ? dateFns.parseISO(date) : date;
|
|
5312
|
+
if (!dateFns.isValid(dateObj)) return "Invalid Date";
|
|
5313
|
+
const tz = defaultTimezone || "UTC";
|
|
5314
|
+
if (formatString) {
|
|
5315
|
+
return dateFnsTz.formatInTimeZone(dateObj, tz, formatString);
|
|
5143
5316
|
}
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
const
|
|
5154
|
-
if (
|
|
5155
|
-
|
|
5317
|
+
const effectiveOptions = dateFormatOptions || { year: "numeric", month: "short", day: "numeric" };
|
|
5318
|
+
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
5319
|
+
},
|
|
5320
|
+
[defaultTimezone, defaultLocale, dateFormatOptions]
|
|
5321
|
+
);
|
|
5322
|
+
const formatTime2 = React14.useCallback(
|
|
5323
|
+
(date, formatString) => {
|
|
5324
|
+
const dateObj = typeof date === "string" ? dateFns.parseISO(date) : date;
|
|
5325
|
+
if (!dateFns.isValid(dateObj)) return "Invalid Time";
|
|
5326
|
+
const tz = defaultTimezone || "UTC";
|
|
5327
|
+
if (formatString) {
|
|
5328
|
+
return dateFnsTz.formatInTimeZone(dateObj, tz, formatString);
|
|
5156
5329
|
}
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
console.error("[HLS] Native video error");
|
|
5170
|
-
hardRestart("native video error");
|
|
5171
|
-
};
|
|
5172
|
-
const startStallDetection = () => {
|
|
5173
|
-
if (isNativeHlsRef.current) return;
|
|
5174
|
-
stallCheckIntervalRef.current = setInterval(() => {
|
|
5175
|
-
const video = videoRef.current;
|
|
5176
|
-
if (!video || video.paused || video.ended) return;
|
|
5177
|
-
const currentTime = video.currentTime;
|
|
5178
|
-
const lastTime = lastTimeUpdateRef.current;
|
|
5179
|
-
if (Math.abs(currentTime - lastTime) < 0.1 && video.readyState >= 2) {
|
|
5180
|
-
console.warn("[HLS] Playback stall detected");
|
|
5181
|
-
if (!noProgressTimerRef.current) {
|
|
5182
|
-
noProgressTimerRef.current = setTimeout(() => {
|
|
5183
|
-
softRestart("playback stall");
|
|
5184
|
-
noProgressTimerRef.current = null;
|
|
5185
|
-
}, 8e3);
|
|
5186
|
-
}
|
|
5187
|
-
} else {
|
|
5188
|
-
if (noProgressTimerRef.current) {
|
|
5189
|
-
clearTimeout(noProgressTimerRef.current);
|
|
5190
|
-
noProgressTimerRef.current = null;
|
|
5191
|
-
}
|
|
5330
|
+
const effectiveOptions = timeFormatOptions || { hour: "numeric", minute: "numeric" };
|
|
5331
|
+
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
5332
|
+
},
|
|
5333
|
+
[defaultTimezone, defaultLocale, timeFormatOptions]
|
|
5334
|
+
);
|
|
5335
|
+
const formatDateTime = React14.useCallback(
|
|
5336
|
+
(date, formatString) => {
|
|
5337
|
+
const dateObj = typeof date === "string" ? dateFns.parseISO(date) : date;
|
|
5338
|
+
if (!dateFns.isValid(dateObj)) return "Invalid Date/Time";
|
|
5339
|
+
const tz = defaultTimezone || "UTC";
|
|
5340
|
+
if (formatString) {
|
|
5341
|
+
return dateFnsTz.formatInTimeZone(dateObj, tz, formatString);
|
|
5192
5342
|
}
|
|
5193
|
-
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5201
|
-
if (!video) return;
|
|
5202
|
-
isNativeHlsRef.current = video.canPlayType("application/vnd.apple.mpegurl") === "probably";
|
|
5203
|
-
if (Hls2__default.default.isSupported() && !isNativeHlsRef.current) {
|
|
5204
|
-
const hls = new Hls2__default.default(HLS_CONFIG);
|
|
5205
|
-
hlsRef.current = hls;
|
|
5206
|
-
hls.attachMedia(video);
|
|
5207
|
-
hls.loadSource(src);
|
|
5208
|
-
hls.on(Hls2__default.default.Events.ERROR, (_, data) => {
|
|
5209
|
-
if (!data.fatal) return;
|
|
5210
|
-
console.error("[HLS] Fatal error:", data.type, data.details);
|
|
5211
|
-
if (data.response?.code === 404) {
|
|
5212
|
-
hardRestart("404 hard restart");
|
|
5213
|
-
return;
|
|
5214
|
-
}
|
|
5215
|
-
switch (data.type) {
|
|
5216
|
-
case Hls2__default.default.ErrorTypes.NETWORK_ERROR:
|
|
5217
|
-
case Hls2__default.default.ErrorTypes.MEDIA_ERROR:
|
|
5218
|
-
softRestart(`${data.type}: ${data.details}`);
|
|
5219
|
-
break;
|
|
5220
|
-
default:
|
|
5221
|
-
hardRestart(`Fatal ${data.type}: ${data.details}`);
|
|
5222
|
-
break;
|
|
5223
|
-
}
|
|
5224
|
-
});
|
|
5225
|
-
hls.on(Hls2__default.default.Events.MANIFEST_PARSED, () => {
|
|
5226
|
-
video.play().catch((err) => {
|
|
5227
|
-
console.error("[HLS] Play failed:", err);
|
|
5228
|
-
});
|
|
5229
|
-
});
|
|
5230
|
-
video.addEventListener("waiting", handleWaiting);
|
|
5231
|
-
video.addEventListener("timeupdate", handleTimeUpdate);
|
|
5232
|
-
startStallDetection();
|
|
5233
|
-
} else if (isNativeHlsRef.current) {
|
|
5234
|
-
console.log("[HLS] Using native HLS");
|
|
5235
|
-
video.src = src;
|
|
5236
|
-
video.addEventListener("error", handleNativeError);
|
|
5237
|
-
video.play().catch((err) => {
|
|
5238
|
-
console.error("[HLS] Native play failed:", err);
|
|
5239
|
-
});
|
|
5240
|
-
} else {
|
|
5241
|
-
console.error("[HLS] HLS not supported");
|
|
5242
|
-
}
|
|
5243
|
-
return cleanup;
|
|
5244
|
-
}, [src, shouldPlay, restartKey, onFatalError]);
|
|
5343
|
+
const effectiveOptions = dateTimeFormatOptions || { year: "numeric", month: "short", day: "numeric", hour: "numeric", minute: "numeric" };
|
|
5344
|
+
return new Intl.DateTimeFormat(defaultLocale || "en-US", effectiveOptions).format(dateObj);
|
|
5345
|
+
},
|
|
5346
|
+
[defaultTimezone, defaultLocale, dateTimeFormatOptions]
|
|
5347
|
+
);
|
|
5348
|
+
const getNow = React14.useCallback(() => {
|
|
5349
|
+
return /* @__PURE__ */ new Date();
|
|
5350
|
+
}, []);
|
|
5245
5351
|
return {
|
|
5246
|
-
|
|
5247
|
-
|
|
5352
|
+
formatDate,
|
|
5353
|
+
formatTime: formatTime2,
|
|
5354
|
+
formatDateTime,
|
|
5355
|
+
getNow,
|
|
5356
|
+
timezone: defaultTimezone || "UTC",
|
|
5357
|
+
locale: defaultLocale || "en-US"
|
|
5248
5358
|
};
|
|
5249
5359
|
}
|
|
5360
|
+
var useFormatNumber = () => {
|
|
5361
|
+
const { defaultLocale } = useDateTimeConfig();
|
|
5362
|
+
const formatNumber = React14.useCallback(
|
|
5363
|
+
(value, options) => {
|
|
5364
|
+
try {
|
|
5365
|
+
return new Intl.NumberFormat(defaultLocale || "en-US", options).format(value);
|
|
5366
|
+
} catch (error) {
|
|
5367
|
+
console.error("Error formatting number:", error);
|
|
5368
|
+
return String(value);
|
|
5369
|
+
}
|
|
5370
|
+
},
|
|
5371
|
+
[defaultLocale]
|
|
5372
|
+
);
|
|
5373
|
+
return { formatNumber };
|
|
5374
|
+
};
|
|
5250
5375
|
|
|
5251
5376
|
// src/lib/utils/api.ts
|
|
5252
5377
|
var apiUtils = {
|
|
@@ -17188,15 +17313,15 @@ var HourlyOutputChart = ({
|
|
|
17188
17313
|
renderLegend()
|
|
17189
17314
|
] });
|
|
17190
17315
|
};
|
|
17191
|
-
|
|
17192
|
-
|
|
17193
|
-
|
|
17194
|
-
|
|
17195
|
-
|
|
17196
|
-
|
|
17197
|
-
|
|
17198
|
-
}
|
|
17199
|
-
|
|
17316
|
+
function getTrendArrowAndColor(trend) {
|
|
17317
|
+
if (trend > 0) {
|
|
17318
|
+
return { arrow: "\u2191", color: "text-green-400" };
|
|
17319
|
+
} else if (trend < 0) {
|
|
17320
|
+
return { arrow: "\u2193", color: "text-red-400" };
|
|
17321
|
+
} else {
|
|
17322
|
+
return { arrow: "\u2192", color: "text-gray-400" };
|
|
17323
|
+
}
|
|
17324
|
+
}
|
|
17200
17325
|
var VideoCard = React14__namespace.default.memo(({
|
|
17201
17326
|
workspace,
|
|
17202
17327
|
hlsUrl,
|
|
@@ -17204,14 +17329,29 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17204
17329
|
onClick,
|
|
17205
17330
|
onFatalError,
|
|
17206
17331
|
isVeryLowEfficiency = false,
|
|
17332
|
+
cropping,
|
|
17333
|
+
canvasFps = 30,
|
|
17334
|
+
useRAF = true,
|
|
17207
17335
|
className = ""
|
|
17208
17336
|
}) => {
|
|
17209
17337
|
const videoRef = React14.useRef(null);
|
|
17210
|
-
|
|
17211
|
-
|
|
17212
|
-
|
|
17213
|
-
|
|
17214
|
-
|
|
17338
|
+
const canvasRef = React14.useRef(null);
|
|
17339
|
+
if (cropping) {
|
|
17340
|
+
useHlsStreamWithCropping(videoRef, canvasRef, {
|
|
17341
|
+
src: hlsUrl,
|
|
17342
|
+
shouldPlay,
|
|
17343
|
+
cropping,
|
|
17344
|
+
canvasFps,
|
|
17345
|
+
useRAF,
|
|
17346
|
+
onFatalError: onFatalError ?? (() => throttledReloadDashboard())
|
|
17347
|
+
});
|
|
17348
|
+
} else {
|
|
17349
|
+
useHlsStream(videoRef, {
|
|
17350
|
+
src: hlsUrl,
|
|
17351
|
+
shouldPlay,
|
|
17352
|
+
onFatalError: onFatalError ?? (() => throttledReloadDashboard())
|
|
17353
|
+
});
|
|
17354
|
+
}
|
|
17215
17355
|
const displayName = getWorkspaceDisplayName(workspace.workspace_name);
|
|
17216
17356
|
workspace.workspace_uuid || workspace.workspace_name;
|
|
17217
17357
|
const getEfficiencyOverlayColor = (efficiency) => {
|
|
@@ -17266,17 +17406,26 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17266
17406
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Camera, { className: "w-6 h-6 text-gray-500" }),
|
|
17267
17407
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-gray-500 mt-1", children: "Loading..." })
|
|
17268
17408
|
] }) }),
|
|
17269
|
-
/* @__PURE__ */ jsxRuntime.
|
|
17270
|
-
|
|
17271
|
-
|
|
17272
|
-
|
|
17273
|
-
|
|
17274
|
-
|
|
17275
|
-
|
|
17276
|
-
|
|
17277
|
-
|
|
17278
|
-
|
|
17279
|
-
|
|
17409
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute inset-0 z-10", children: [
|
|
17410
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17411
|
+
"video",
|
|
17412
|
+
{
|
|
17413
|
+
ref: videoRef,
|
|
17414
|
+
className: `h-full w-full object-cover ${cropping ? "hidden" : ""}`,
|
|
17415
|
+
playsInline: true,
|
|
17416
|
+
muted: true,
|
|
17417
|
+
disablePictureInPicture: true,
|
|
17418
|
+
controlsList: "nodownload noplaybackrate"
|
|
17419
|
+
}
|
|
17420
|
+
),
|
|
17421
|
+
cropping && /* @__PURE__ */ jsxRuntime.jsx(
|
|
17422
|
+
"canvas",
|
|
17423
|
+
{
|
|
17424
|
+
ref: canvasRef,
|
|
17425
|
+
className: "h-full w-full object-cover"
|
|
17426
|
+
}
|
|
17427
|
+
)
|
|
17428
|
+
] }),
|
|
17280
17429
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: `absolute inset-0 z-20 pointer-events-none ${efficiencyOverlayClass}` }),
|
|
17281
17430
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "absolute top-2 right-2 z-30 bg-black/70 backdrop-blur-sm rounded px-2 py-0.5 text-white text-xs font-semibold border border-white/10", children: [
|
|
17282
17431
|
Math.round(workspace.efficiency),
|
|
@@ -17312,7 +17461,7 @@ var VideoCard = React14__namespace.default.memo(({
|
|
|
17312
17461
|
}
|
|
17313
17462
|
);
|
|
17314
17463
|
}, (prevProps, nextProps) => {
|
|
17315
|
-
return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay;
|
|
17464
|
+
return prevProps.workspace.workspace_uuid === nextProps.workspace.workspace_uuid && prevProps.workspace.workspace_name === nextProps.workspace.workspace_name && Math.abs(prevProps.workspace.efficiency - nextProps.workspace.efficiency) < 1 && prevProps.hlsUrl === nextProps.hlsUrl && prevProps.shouldPlay === nextProps.shouldPlay && prevProps.cropping?.x === nextProps.cropping?.x && prevProps.cropping?.y === nextProps.cropping?.y && prevProps.cropping?.width === nextProps.cropping?.width && prevProps.cropping?.height === nextProps.cropping?.height;
|
|
17316
17465
|
});
|
|
17317
17466
|
VideoCard.displayName = "VideoCard";
|
|
17318
17467
|
var DEFAULT_WORKSPACE_HLS_URLS = {
|
|
@@ -17340,6 +17489,8 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17340
17489
|
const observerRef = React14.useRef(null);
|
|
17341
17490
|
const [gridCols, setGridCols] = React14.useState(4);
|
|
17342
17491
|
const [visibleWorkspaces, setVisibleWorkspaces] = React14.useState(/* @__PURE__ */ new Set());
|
|
17492
|
+
const videoConfig = useVideoConfig();
|
|
17493
|
+
const { cropping, canvasConfig } = videoConfig;
|
|
17343
17494
|
const mergedVideoSources = {
|
|
17344
17495
|
defaultHlsUrl: videoSources.defaultHlsUrl || DEFAULT_HLS_URL,
|
|
17345
17496
|
workspaceHlsUrls: { ...DEFAULT_WORKSPACE_HLS_URLS, ...videoSources.workspaceHlsUrls }
|
|
@@ -17348,6 +17499,13 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17348
17499
|
const wsName = workspaceName.toUpperCase();
|
|
17349
17500
|
return mergedVideoSources.workspaceHlsUrls[wsName] || mergedVideoSources.defaultHlsUrl;
|
|
17350
17501
|
}, [mergedVideoSources]);
|
|
17502
|
+
const getWorkspaceCropping = React14.useCallback((workspaceName) => {
|
|
17503
|
+
if (!cropping) return void 0;
|
|
17504
|
+
if (cropping.workspaceOverrides?.[workspaceName]) {
|
|
17505
|
+
return cropping.workspaceOverrides[workspaceName];
|
|
17506
|
+
}
|
|
17507
|
+
return cropping.default;
|
|
17508
|
+
}, [cropping]);
|
|
17351
17509
|
const veryLowEfficiencyWorkspaces = React14.useMemo(() => {
|
|
17352
17510
|
return new Set(
|
|
17353
17511
|
workspaces.filter((w) => w.efficiency < 50 && w.efficiency >= 10).map((w) => w.workspace_name)
|
|
@@ -17486,6 +17644,7 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17486
17644
|
const workspaceId = workspace.workspace_uuid || workspace.workspace_name;
|
|
17487
17645
|
const isVisible = visibleWorkspaces.has(workspaceId);
|
|
17488
17646
|
const isVeryLowEfficiency = veryLowEfficiencyWorkspaces.has(workspace.workspace_name);
|
|
17647
|
+
const workspaceCropping = getWorkspaceCropping(workspace.workspace_name);
|
|
17489
17648
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17490
17649
|
"div",
|
|
17491
17650
|
{
|
|
@@ -17500,7 +17659,10 @@ var VideoGridView = React14__namespace.default.memo(({
|
|
|
17500
17659
|
shouldPlay: isVisible,
|
|
17501
17660
|
onClick: () => handleWorkspaceClick(workspace),
|
|
17502
17661
|
onFatalError: throttledReloadDashboard,
|
|
17503
|
-
isVeryLowEfficiency
|
|
17662
|
+
isVeryLowEfficiency,
|
|
17663
|
+
cropping: workspaceCropping,
|
|
17664
|
+
canvasFps: canvasConfig?.fps,
|
|
17665
|
+
useRAF: canvasConfig?.useRAF
|
|
17504
17666
|
}
|
|
17505
17667
|
)
|
|
17506
17668
|
},
|
|
@@ -22327,12 +22489,12 @@ var getEfficiencyColor = (efficiency) => {
|
|
|
22327
22489
|
return "bg-[#E34329]/90 hover:bg-[#E34329]/95";
|
|
22328
22490
|
}
|
|
22329
22491
|
};
|
|
22330
|
-
var
|
|
22492
|
+
var TREND_STYLES = {
|
|
22331
22493
|
0: { arrow: "\u2193", color: "text-red-500 font-bold text-shadow" },
|
|
22332
22494
|
1: { arrow: "=", color: "text-gray-500 font-bold text-shadow" },
|
|
22333
22495
|
2: { arrow: "\u2191", color: "text-green-500 font-bold text-shadow" }
|
|
22334
22496
|
};
|
|
22335
|
-
var getTrendArrowAndColor2 = (trend) =>
|
|
22497
|
+
var getTrendArrowAndColor2 = (trend) => TREND_STYLES[trend] || { arrow: "", color: "" };
|
|
22336
22498
|
var ARROW_POSITIONS = {
|
|
22337
22499
|
top: "-bottom-6",
|
|
22338
22500
|
"middle-top": "-bottom-6",
|
|
@@ -30803,6 +30965,7 @@ exports.DEFAULT_ENDPOINTS_CONFIG = DEFAULT_ENDPOINTS_CONFIG;
|
|
|
30803
30965
|
exports.DEFAULT_ENTITY_CONFIG = DEFAULT_ENTITY_CONFIG;
|
|
30804
30966
|
exports.DEFAULT_SHIFT_CONFIG = DEFAULT_SHIFT_CONFIG;
|
|
30805
30967
|
exports.DEFAULT_THEME_CONFIG = DEFAULT_THEME_CONFIG;
|
|
30968
|
+
exports.DEFAULT_VIDEO_CONFIG = DEFAULT_VIDEO_CONFIG;
|
|
30806
30969
|
exports.DEFAULT_WORKSPACE_CONFIG = DEFAULT_WORKSPACE_CONFIG;
|
|
30807
30970
|
exports.DEFAULT_WORKSPACE_POSITIONS = DEFAULT_WORKSPACE_POSITIONS;
|
|
30808
30971
|
exports.DashboardHeader = DashboardHeader;
|
|
@@ -30992,6 +31155,7 @@ exports.useFeatureFlags = useFeatureFlags;
|
|
|
30992
31155
|
exports.useFormatNumber = useFormatNumber;
|
|
30993
31156
|
exports.useHistoricWorkspaceMetrics = useHistoricWorkspaceMetrics;
|
|
30994
31157
|
exports.useHlsStream = useHlsStream;
|
|
31158
|
+
exports.useHlsStreamWithCropping = useHlsStreamWithCropping;
|
|
30995
31159
|
exports.useHookOverride = useHookOverride;
|
|
30996
31160
|
exports.useLeaderboardMetrics = useLeaderboardMetrics;
|
|
30997
31161
|
exports.useLineDetailedMetrics = useLineDetailedMetrics;
|
|
@@ -31013,6 +31177,7 @@ exports.useTargets = useTargets;
|
|
|
31013
31177
|
exports.useTheme = useTheme;
|
|
31014
31178
|
exports.useThemeConfig = useThemeConfig;
|
|
31015
31179
|
exports.useThreads = useThreads;
|
|
31180
|
+
exports.useVideoConfig = useVideoConfig;
|
|
31016
31181
|
exports.useWorkspaceConfig = useWorkspaceConfig;
|
|
31017
31182
|
exports.useWorkspaceDetailedMetrics = useWorkspaceDetailedMetrics;
|
|
31018
31183
|
exports.useWorkspaceDisplayName = useWorkspaceDisplayName;
|