@copilotz/chat-ui 0.1.10 → 0.1.11

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.cjs CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  chatUtils: () => chatUtils,
44
44
  cn: () => cn,
45
45
  configUtils: () => configUtils,
46
+ createObjectUrlFromDataUrl: () => createObjectUrlFromDataUrl,
46
47
  defaultChatConfig: () => defaultChatConfig,
47
48
  featureFlags: () => featureFlags,
48
49
  formatDate: () => formatDate,
@@ -333,6 +334,24 @@ var formatDate = (timestamp, labels) => {
333
334
  });
334
335
  }
335
336
  };
337
+ var createObjectUrlFromDataUrl = (dataUrl) => {
338
+ const match = dataUrl.match(/^data:(.+?);base64,(.+)$/s);
339
+ if (!match) {
340
+ return null;
341
+ }
342
+ try {
343
+ const [, mimeType, base64] = match;
344
+ const binary = atob(base64);
345
+ const bytes = new Uint8Array(binary.length);
346
+ for (let i = 0; i < binary.length; i += 1) {
347
+ bytes[i] = binary.charCodeAt(i);
348
+ }
349
+ const blob = new Blob([bytes], { type: mimeType || "application/octet-stream" });
350
+ return URL.createObjectURL(blob);
351
+ } catch {
352
+ return null;
353
+ }
354
+ };
336
355
 
337
356
  // src/components/ui/button.tsx
338
357
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -713,26 +732,22 @@ var StreamingText = (0, import_react.memo)(function StreamingText2({
713
732
  ] });
714
733
  });
715
734
  var MediaRenderer = (0, import_react.memo)(function MediaRenderer2({ attachment }) {
716
- const [isPlaying, setIsPlaying] = (0, import_react.useState)(false);
717
- const audioRef = (0, import_react.useRef)(null);
718
- const videoRef = (0, import_react.useRef)(null);
719
- const togglePlayback = () => {
720
- if (attachment.kind === "audio" && audioRef.current) {
721
- if (isPlaying) {
722
- audioRef.current.pause();
723
- } else {
724
- audioRef.current.play();
725
- }
726
- setIsPlaying(!isPlaying);
727
- } else if (attachment.kind === "video" && videoRef.current) {
728
- if (isPlaying) {
729
- videoRef.current.pause();
730
- } else {
731
- videoRef.current.play();
732
- }
733
- setIsPlaying(!isPlaying);
735
+ const [audioPlaybackSrc, setAudioPlaybackSrc] = (0, import_react.useState)(attachment.dataUrl);
736
+ (0, import_react.useEffect)(() => {
737
+ if (attachment.kind !== "audio" || !attachment.dataUrl.startsWith("data:")) {
738
+ setAudioPlaybackSrc(attachment.dataUrl);
739
+ return;
734
740
  }
735
- };
741
+ const objectUrl = createObjectUrlFromDataUrl(attachment.dataUrl);
742
+ if (!objectUrl) {
743
+ setAudioPlaybackSrc(attachment.dataUrl);
744
+ return;
745
+ }
746
+ setAudioPlaybackSrc(objectUrl);
747
+ return () => {
748
+ URL.revokeObjectURL(objectUrl);
749
+ };
750
+ }, [attachment.kind, attachment.dataUrl]);
736
751
  const formatDuration = (ms) => {
737
752
  if (!ms) return "";
738
753
  const seconds = Math.floor(ms / 1e3);
@@ -757,13 +772,10 @@ var MediaRenderer = (0, import_react.memo)(function MediaRenderer2({ attachment
757
772
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex w-full max-w-md py-0 min-w-64 items-center gap-3", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
758
773
  "audio",
759
774
  {
760
- ref: audioRef,
761
- src: attachment.dataUrl,
762
- onPlay: () => setIsPlaying(true),
763
- onPause: () => setIsPlaying(false),
764
- onEnded: () => setIsPlaying(false),
765
775
  className: "w-full mt-2",
766
- controls: true
776
+ preload: "metadata",
777
+ controls: true,
778
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("source", { src: audioPlaybackSrc, type: attachment.mimeType })
767
779
  }
768
780
  ) });
769
781
  case "video":
@@ -771,14 +783,10 @@ var MediaRenderer = (0, import_react.memo)(function MediaRenderer2({ attachment
771
783
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
772
784
  "video",
773
785
  {
774
- ref: videoRef,
775
786
  src: attachment.dataUrl,
776
787
  poster: attachment.poster,
777
788
  controls: true,
778
- className: "w-full h-auto",
779
- onPlay: () => setIsPlaying(true),
780
- onPause: () => setIsPlaying(false),
781
- onEnded: () => setIsPlaying(false)
789
+ className: "w-full h-auto"
782
790
  }
783
791
  ),
784
792
  attachment.fileName && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "absolute bottom-0 left-0 right-0 bg-black/50 text-white text-xs p-2", children: attachment.fileName })
@@ -2855,7 +2863,23 @@ var FileUploadItem = (0, import_react5.memo)(function FileUploadItem2({ file, pr
2855
2863
  });
2856
2864
  var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ attachment, onRemove }) {
2857
2865
  const [isPlaying, setIsPlaying] = (0, import_react5.useState)(false);
2866
+ const [audioPlaybackSrc, setAudioPlaybackSrc] = (0, import_react5.useState)(attachment.dataUrl);
2858
2867
  const audioRef = (0, import_react5.useRef)(null);
2868
+ (0, import_react5.useEffect)(() => {
2869
+ if (attachment.kind !== "audio" || !attachment.dataUrl.startsWith("data:")) {
2870
+ setAudioPlaybackSrc(attachment.dataUrl);
2871
+ return;
2872
+ }
2873
+ const objectUrl = createObjectUrlFromDataUrl(attachment.dataUrl);
2874
+ if (!objectUrl) {
2875
+ setAudioPlaybackSrc(attachment.dataUrl);
2876
+ return;
2877
+ }
2878
+ setAudioPlaybackSrc(objectUrl);
2879
+ return () => {
2880
+ URL.revokeObjectURL(objectUrl);
2881
+ };
2882
+ }, [attachment.kind, attachment.dataUrl]);
2859
2883
  const handlePlayPause = () => {
2860
2884
  if (audioRef.current) {
2861
2885
  if (isPlaying) {
@@ -2934,10 +2958,11 @@ var AttachmentPreview = (0, import_react5.memo)(function AttachmentPreview2({ at
2934
2958
  "audio",
2935
2959
  {
2936
2960
  ref: audioRef,
2937
- src: attachment.dataUrl,
2938
2961
  onPlay: () => setIsPlaying(true),
2939
2962
  onPause: () => setIsPlaying(false),
2940
- onEnded: () => setIsPlaying(false)
2963
+ onEnded: () => setIsPlaying(false),
2964
+ preload: "metadata",
2965
+ children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("source", { src: audioPlaybackSrc, type: attachment.mimeType })
2941
2966
  }
2942
2967
  ),
2943
2968
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
@@ -4649,6 +4674,7 @@ var chatUtils = {
4649
4674
  chatUtils,
4650
4675
  cn,
4651
4676
  configUtils,
4677
+ createObjectUrlFromDataUrl,
4652
4678
  defaultChatConfig,
4653
4679
  featureFlags,
4654
4680
  formatDate,