analytica-frontend-lib 1.1.90 → 1.1.92

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