analytica-frontend-lib 1.1.90 → 1.1.91

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.js CHANGED
@@ -8615,6 +8615,7 @@ var VideoPlayer = ({
8615
8615
  const [showControls, setShowControls] = (0, import_react27.useState)(true);
8616
8616
  const [hasCompleted, setHasCompleted] = (0, import_react27.useState)(false);
8617
8617
  const [showCaptions, setShowCaptions] = (0, import_react27.useState)(false);
8618
+ const [subtitlesValidation, setSubtitlesValidation] = (0, import_react27.useState)("idle");
8618
8619
  (0, import_react27.useEffect)(() => {
8619
8620
  setHasCompleted(false);
8620
8621
  }, [src]);
@@ -8900,11 +8901,12 @@ var VideoPlayer = ({
8900
8901
  setShowSpeedMenu(!showSpeedMenu);
8901
8902
  }, [showSpeedMenu]);
8902
8903
  const toggleCaptions = (0, import_react27.useCallback)(() => {
8903
- if (!trackRef.current?.track || !subtitles) return;
8904
+ if (!trackRef.current?.track || !subtitles || subtitlesValidation !== "valid")
8905
+ return;
8904
8906
  const newShowCaptions = !showCaptions;
8905
8907
  setShowCaptions(newShowCaptions);
8906
- trackRef.current.track.mode = newShowCaptions && subtitles ? "showing" : "hidden";
8907
- }, [showCaptions, subtitles]);
8908
+ trackRef.current.track.mode = newShowCaptions ? "showing" : "hidden";
8909
+ }, [showCaptions, subtitles, subtitlesValidation]);
8908
8910
  const checkVideoCompletion = (0, import_react27.useCallback)(
8909
8911
  (progressPercent) => {
8910
8912
  if (progressPercent >= 95 && !hasCompleted) {
@@ -8932,11 +8934,58 @@ var VideoPlayer = ({
8932
8934
  setDuration(videoRef.current.duration);
8933
8935
  }
8934
8936
  }, []);
8937
+ (0, import_react27.useEffect)(() => {
8938
+ const controller = new AbortController();
8939
+ const validateSubtitles = async () => {
8940
+ if (!subtitles) {
8941
+ setSubtitlesValidation("idle");
8942
+ return;
8943
+ }
8944
+ setSubtitlesValidation("validating");
8945
+ try {
8946
+ if (subtitles.startsWith("data:")) {
8947
+ setSubtitlesValidation("valid");
8948
+ return;
8949
+ }
8950
+ const response = await fetch(subtitles, {
8951
+ method: "HEAD",
8952
+ signal: controller.signal
8953
+ });
8954
+ if (response.ok) {
8955
+ const contentType = response.headers.get("content-type");
8956
+ const isValidType = !contentType || contentType.includes("text/vtt") || contentType.includes("text/plain") || contentType.includes("application/octet-stream");
8957
+ if (isValidType) {
8958
+ setSubtitlesValidation("valid");
8959
+ } else {
8960
+ setSubtitlesValidation("invalid");
8961
+ console.warn(
8962
+ `Subtitles URL has invalid content type: ${contentType}`
8963
+ );
8964
+ }
8965
+ } else {
8966
+ setSubtitlesValidation("invalid");
8967
+ console.warn(
8968
+ `Subtitles URL returned status: ${response.status} ${response.statusText}`
8969
+ );
8970
+ }
8971
+ } catch (error) {
8972
+ if (error instanceof Error && error.name === "AbortError") {
8973
+ return;
8974
+ }
8975
+ console.warn("Subtitles URL validation failed:", error);
8976
+ setSubtitlesValidation("invalid");
8977
+ }
8978
+ };
8979
+ validateSubtitles();
8980
+ return () => {
8981
+ controller.abort();
8982
+ };
8983
+ }, [subtitles]);
8935
8984
  (0, import_react27.useEffect)(() => {
8936
8985
  if (trackRef.current?.track) {
8937
- trackRef.current.track.mode = showCaptions && subtitles ? "showing" : "hidden";
8986
+ trackRef.current.track.mode = showCaptions && subtitles && subtitlesValidation === "valid" ? "showing" : "hidden";
8938
8987
  }
8939
- }, [subtitles, showCaptions]);
8988
+ }, [subtitles, showCaptions, subtitlesValidation]);
8940
8989
  (0, import_react27.useEffect)(() => {
8941
8990
  const handleVisibilityChange = () => {
8942
8991
  if (document.hidden && isPlaying && videoRef.current) {
@@ -8990,61 +9039,57 @@ var VideoPlayer = ({
8990
9039
  const getBottomControlsOpacity = (0, import_react27.useCallback)(() => {
8991
9040
  return showControls ? "opacity-100" : "opacity-0";
8992
9041
  }, [showControls]);
9042
+ const seekBackward = (0, import_react27.useCallback)(() => {
9043
+ if (videoRef.current) {
9044
+ videoRef.current.currentTime -= 10;
9045
+ }
9046
+ }, []);
9047
+ const seekForward = (0, import_react27.useCallback)(() => {
9048
+ if (videoRef.current) {
9049
+ videoRef.current.currentTime += 10;
9050
+ }
9051
+ }, []);
9052
+ const increaseVolume = (0, import_react27.useCallback)(() => {
9053
+ handleVolumeChange(Math.min(100, volume * 100 + 10));
9054
+ }, [handleVolumeChange, volume]);
9055
+ const decreaseVolume = (0, import_react27.useCallback)(() => {
9056
+ handleVolumeChange(Math.max(0, volume * 100 - 10));
9057
+ }, [handleVolumeChange, volume]);
8993
9058
  const handleVideoKeyDown = (0, import_react27.useCallback)(
8994
9059
  (e) => {
8995
- if (e.key) {
8996
- e.stopPropagation();
8997
- showControlsWithTimer();
8998
- }
8999
- switch (e.key) {
9000
- case " ":
9001
- case "Enter":
9002
- e.preventDefault();
9003
- togglePlayPause();
9004
- break;
9005
- case "ArrowLeft":
9006
- e.preventDefault();
9007
- if (videoRef.current) {
9008
- videoRef.current.currentTime -= 10;
9009
- }
9010
- break;
9011
- case "ArrowRight":
9012
- e.preventDefault();
9013
- if (videoRef.current) {
9014
- videoRef.current.currentTime += 10;
9015
- }
9016
- break;
9017
- case "ArrowUp":
9018
- e.preventDefault();
9019
- handleVolumeChange(Math.min(100, volume * 100 + 10));
9020
- break;
9021
- case "ArrowDown":
9022
- e.preventDefault();
9023
- handleVolumeChange(Math.max(0, volume * 100 - 10));
9024
- break;
9025
- case "m":
9026
- case "M":
9027
- e.preventDefault();
9028
- toggleMute();
9029
- break;
9030
- case "f":
9031
- case "F":
9032
- e.preventDefault();
9033
- toggleFullscreen();
9034
- break;
9035
- default:
9036
- break;
9060
+ if (!e.key) return;
9061
+ e.stopPropagation();
9062
+ showControlsWithTimer();
9063
+ const keyHandlers = {
9064
+ " ": togglePlayPause,
9065
+ Enter: togglePlayPause,
9066
+ ArrowLeft: seekBackward,
9067
+ ArrowRight: seekForward,
9068
+ ArrowUp: increaseVolume,
9069
+ ArrowDown: decreaseVolume,
9070
+ m: toggleMute,
9071
+ M: toggleMute,
9072
+ f: toggleFullscreen,
9073
+ F: toggleFullscreen
9074
+ };
9075
+ const handler = keyHandlers[e.key];
9076
+ if (handler) {
9077
+ e.preventDefault();
9078
+ handler();
9037
9079
  }
9038
9080
  },
9039
9081
  [
9040
9082
  showControlsWithTimer,
9041
9083
  togglePlayPause,
9042
- handleVolumeChange,
9043
- volume,
9084
+ seekBackward,
9085
+ seekForward,
9086
+ increaseVolume,
9087
+ decreaseVolume,
9044
9088
  toggleMute,
9045
9089
  toggleFullscreen
9046
9090
  ]
9047
9091
  );
9092
+ const groupedSubTitleValid = subtitles && subtitlesValidation === "valid";
9048
9093
  return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: cn("flex flex-col", className), children: [
9049
9094
  (title || subtitleText) && /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "bg-subject-1 px-8 py-4 flex items-end justify-between min-h-20", children: [
9050
9095
  /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex flex-col gap-1", children: [
@@ -9118,9 +9163,9 @@ var VideoPlayer = ({
9118
9163
  {
9119
9164
  ref: trackRef,
9120
9165
  kind: "captions",
9121
- src: subtitles || "data:text/vtt;charset=utf-8,WEBVTT",
9166
+ src: groupedSubTitleValid ? subtitles : "data:text/vtt;charset=utf-8,WEBVTT",
9122
9167
  srcLang: "pt-br",
9123
- label: subtitles ? "Legendas em Portugu\xEAs" : "Sem legendas dispon\xEDveis",
9168
+ label: groupedSubTitleValid ? "Legendas em Portugu\xEAs" : "Sem legendas dispon\xEDveis",
9124
9169
  default: false
9125
9170
  }
9126
9171
  )
@@ -9209,7 +9254,7 @@ var VideoPlayer = ({
9209
9254
  showSlider: !isUltraSmallMobile
9210
9255
  }
9211
9256
  ),
9212
- subtitles && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
9257
+ groupedSubTitleValid && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
9213
9258
  IconButton_default,
9214
9259
  {
9215
9260
  icon: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_phosphor_react19.ClosedCaptioning, { size: getIconSize2() }),