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.
@@ -582,6 +582,7 @@ var VideoPlayer = ({
582
582
  const [showControls, setShowControls] = (0, import_react4.useState)(true);
583
583
  const [hasCompleted, setHasCompleted] = (0, import_react4.useState)(false);
584
584
  const [showCaptions, setShowCaptions] = (0, import_react4.useState)(false);
585
+ const [subtitlesValidation, setSubtitlesValidation] = (0, import_react4.useState)("idle");
585
586
  (0, import_react4.useEffect)(() => {
586
587
  setHasCompleted(false);
587
588
  }, [src]);
@@ -867,11 +868,12 @@ var VideoPlayer = ({
867
868
  setShowSpeedMenu(!showSpeedMenu);
868
869
  }, [showSpeedMenu]);
869
870
  const toggleCaptions = (0, import_react4.useCallback)(() => {
870
- if (!trackRef.current?.track || !subtitles) return;
871
+ if (!trackRef.current?.track || !subtitles || subtitlesValidation !== "valid")
872
+ return;
871
873
  const newShowCaptions = !showCaptions;
872
874
  setShowCaptions(newShowCaptions);
873
- trackRef.current.track.mode = newShowCaptions && subtitles ? "showing" : "hidden";
874
- }, [showCaptions, subtitles]);
875
+ trackRef.current.track.mode = newShowCaptions ? "showing" : "hidden";
876
+ }, [showCaptions, subtitles, subtitlesValidation]);
875
877
  const checkVideoCompletion = (0, import_react4.useCallback)(
876
878
  (progressPercent) => {
877
879
  if (progressPercent >= 95 && !hasCompleted) {
@@ -899,11 +901,58 @@ var VideoPlayer = ({
899
901
  setDuration(videoRef.current.duration);
900
902
  }
901
903
  }, []);
904
+ (0, import_react4.useEffect)(() => {
905
+ const controller = new AbortController();
906
+ const validateSubtitles = async () => {
907
+ if (!subtitles) {
908
+ setSubtitlesValidation("idle");
909
+ return;
910
+ }
911
+ setSubtitlesValidation("validating");
912
+ try {
913
+ if (subtitles.startsWith("data:")) {
914
+ setSubtitlesValidation("valid");
915
+ return;
916
+ }
917
+ const response = await fetch(subtitles, {
918
+ method: "HEAD",
919
+ signal: controller.signal
920
+ });
921
+ if (response.ok) {
922
+ const contentType = response.headers.get("content-type");
923
+ const isValidType = !contentType || contentType.includes("text/vtt") || contentType.includes("text/plain") || contentType.includes("application/octet-stream");
924
+ if (isValidType) {
925
+ setSubtitlesValidation("valid");
926
+ } else {
927
+ setSubtitlesValidation("invalid");
928
+ console.warn(
929
+ `Subtitles URL has invalid content type: ${contentType}`
930
+ );
931
+ }
932
+ } else {
933
+ setSubtitlesValidation("invalid");
934
+ console.warn(
935
+ `Subtitles URL returned status: ${response.status} ${response.statusText}`
936
+ );
937
+ }
938
+ } catch (error) {
939
+ if (error instanceof Error && error.name === "AbortError") {
940
+ return;
941
+ }
942
+ console.warn("Subtitles URL validation failed:", error);
943
+ setSubtitlesValidation("invalid");
944
+ }
945
+ };
946
+ validateSubtitles();
947
+ return () => {
948
+ controller.abort();
949
+ };
950
+ }, [subtitles]);
902
951
  (0, import_react4.useEffect)(() => {
903
952
  if (trackRef.current?.track) {
904
- trackRef.current.track.mode = showCaptions && subtitles ? "showing" : "hidden";
953
+ trackRef.current.track.mode = showCaptions && subtitles && subtitlesValidation === "valid" ? "showing" : "hidden";
905
954
  }
906
- }, [subtitles, showCaptions]);
955
+ }, [subtitles, showCaptions, subtitlesValidation]);
907
956
  (0, import_react4.useEffect)(() => {
908
957
  const handleVisibilityChange = () => {
909
958
  if (document.hidden && isPlaying && videoRef.current) {
@@ -957,61 +1006,57 @@ var VideoPlayer = ({
957
1006
  const getBottomControlsOpacity = (0, import_react4.useCallback)(() => {
958
1007
  return showControls ? "opacity-100" : "opacity-0";
959
1008
  }, [showControls]);
1009
+ const seekBackward = (0, import_react4.useCallback)(() => {
1010
+ if (videoRef.current) {
1011
+ videoRef.current.currentTime -= 10;
1012
+ }
1013
+ }, []);
1014
+ const seekForward = (0, import_react4.useCallback)(() => {
1015
+ if (videoRef.current) {
1016
+ videoRef.current.currentTime += 10;
1017
+ }
1018
+ }, []);
1019
+ const increaseVolume = (0, import_react4.useCallback)(() => {
1020
+ handleVolumeChange(Math.min(100, volume * 100 + 10));
1021
+ }, [handleVolumeChange, volume]);
1022
+ const decreaseVolume = (0, import_react4.useCallback)(() => {
1023
+ handleVolumeChange(Math.max(0, volume * 100 - 10));
1024
+ }, [handleVolumeChange, volume]);
960
1025
  const handleVideoKeyDown = (0, import_react4.useCallback)(
961
1026
  (e) => {
962
- if (e.key) {
963
- e.stopPropagation();
964
- showControlsWithTimer();
965
- }
966
- switch (e.key) {
967
- case " ":
968
- case "Enter":
969
- e.preventDefault();
970
- togglePlayPause();
971
- break;
972
- case "ArrowLeft":
973
- e.preventDefault();
974
- if (videoRef.current) {
975
- videoRef.current.currentTime -= 10;
976
- }
977
- break;
978
- case "ArrowRight":
979
- e.preventDefault();
980
- if (videoRef.current) {
981
- videoRef.current.currentTime += 10;
982
- }
983
- break;
984
- case "ArrowUp":
985
- e.preventDefault();
986
- handleVolumeChange(Math.min(100, volume * 100 + 10));
987
- break;
988
- case "ArrowDown":
989
- e.preventDefault();
990
- handleVolumeChange(Math.max(0, volume * 100 - 10));
991
- break;
992
- case "m":
993
- case "M":
994
- e.preventDefault();
995
- toggleMute();
996
- break;
997
- case "f":
998
- case "F":
999
- e.preventDefault();
1000
- toggleFullscreen();
1001
- break;
1002
- default:
1003
- break;
1027
+ if (!e.key) return;
1028
+ e.stopPropagation();
1029
+ showControlsWithTimer();
1030
+ const keyHandlers = {
1031
+ " ": togglePlayPause,
1032
+ Enter: togglePlayPause,
1033
+ ArrowLeft: seekBackward,
1034
+ ArrowRight: seekForward,
1035
+ ArrowUp: increaseVolume,
1036
+ ArrowDown: decreaseVolume,
1037
+ m: toggleMute,
1038
+ M: toggleMute,
1039
+ f: toggleFullscreen,
1040
+ F: toggleFullscreen
1041
+ };
1042
+ const handler = keyHandlers[e.key];
1043
+ if (handler) {
1044
+ e.preventDefault();
1045
+ handler();
1004
1046
  }
1005
1047
  },
1006
1048
  [
1007
1049
  showControlsWithTimer,
1008
1050
  togglePlayPause,
1009
- handleVolumeChange,
1010
- volume,
1051
+ seekBackward,
1052
+ seekForward,
1053
+ increaseVolume,
1054
+ decreaseVolume,
1011
1055
  toggleMute,
1012
1056
  toggleFullscreen
1013
1057
  ]
1014
1058
  );
1059
+ const groupedSubTitleValid = subtitles && subtitlesValidation === "valid";
1015
1060
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: cn("flex flex-col", className), children: [
1016
1061
  (title || subtitleText) && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "bg-subject-1 px-8 py-4 flex items-end justify-between min-h-20", children: [
1017
1062
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-col gap-1", children: [
@@ -1085,9 +1130,9 @@ var VideoPlayer = ({
1085
1130
  {
1086
1131
  ref: trackRef,
1087
1132
  kind: "captions",
1088
- src: subtitles || "data:text/vtt;charset=utf-8,WEBVTT",
1133
+ src: groupedSubTitleValid ? subtitles : "data:text/vtt;charset=utf-8,WEBVTT",
1089
1134
  srcLang: "pt-br",
1090
- label: subtitles ? "Legendas em Portugu\xEAs" : "Sem legendas dispon\xEDveis",
1135
+ label: groupedSubTitleValid ? "Legendas em Portugu\xEAs" : "Sem legendas dispon\xEDveis",
1091
1136
  default: false
1092
1137
  }
1093
1138
  )
@@ -1176,7 +1221,7 @@ var VideoPlayer = ({
1176
1221
  showSlider: !isUltraSmallMobile
1177
1222
  }
1178
1223
  ),
1179
- subtitles && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1224
+ groupedSubTitleValid && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
1180
1225
  IconButton_default,
1181
1226
  {
1182
1227
  icon: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_phosphor_react2.ClosedCaptioning, { size: getIconSize() }),