@snapcall/stream-ui 1.28.1 → 1.29.1

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.
@@ -5,6 +5,7 @@ import {QueryClient as $3Sbms$QueryClient, QueryClientProvider as $3Sbms$QueryCl
5
5
  import $3Sbms$reacthottoast, {toast as $3Sbms$toast, Toaster as $3Sbms$Toaster1, ToastBar as $3Sbms$ToastBar} from "react-hot-toast";
6
6
  import $3Sbms$styledcomponents, {keyframes as $3Sbms$keyframes, ThemeProvider as $3Sbms$ThemeProvider, ThemeContext as $3Sbms$ThemeContext, css as $3Sbms$css, createGlobalStyle as $3Sbms$createGlobalStyle} from "styled-components";
7
7
  import {useState as $3Sbms$useState, useRef as $3Sbms$useRef, useCallback as $3Sbms$useCallback, useEffect as $3Sbms$useEffect, useContext as $3Sbms$useContext, useMemo as $3Sbms$useMemo, createContext as $3Sbms$createContext, useReducer as $3Sbms$useReducer, useLayoutEffect as $3Sbms$useLayoutEffect, cloneElement as $3Sbms$cloneElement, forwardRef as $3Sbms$forwardRef} from "react";
8
+ import $3Sbms$classnames from "classnames";
8
9
  import {TooltipProvider as $3Sbms$TooltipProvider, Toaster as $3Sbms$Toaster, Select as $3Sbms$Select, SelectTrigger as $3Sbms$SelectTrigger, SelectValue as $3Sbms$SelectValue, SelectContent as $3Sbms$SelectContent, SelectGroup as $3Sbms$SelectGroup, SelectItem as $3Sbms$SelectItem, useToast as $3Sbms$useToast, Dialog as $3Sbms$Dialog, DialogContent as $3Sbms$DialogContent, DialogHeader as $3Sbms$DialogHeader, DialogTitle as $3Sbms$DialogTitle, Tabs as $3Sbms$Tabs, TabsList as $3Sbms$TabsList, TabsTrigger as $3Sbms$TabsTrigger, TabsContent as $3Sbms$TabsContent, Input as $3Sbms$Input, Button as $3Sbms$Button, CreatableSelect as $3Sbms$CreatableSelect, Textarea as $3Sbms$Textarea, ToastAction as $3Sbms$ToastAction, Avatar as $3Sbms$Avatar, Tooltip as $3Sbms$Tooltip, TooltipContent as $3Sbms$TooltipContent, TooltipTrigger as $3Sbms$TooltipTrigger, AlertDialog as $3Sbms$AlertDialog, AlertDialogContent as $3Sbms$AlertDialogContent, AlertDialogFooter as $3Sbms$AlertDialogFooter, AlertDialogCancel as $3Sbms$AlertDialogCancel, AlertDialogAction as $3Sbms$AlertDialogAction, RawToast as $3Sbms$RawToast, ToastContent as $3Sbms$ToastContent, Sheet as $3Sbms$Sheet, DialogTrigger as $3Sbms$DialogTrigger, SheetTrigger as $3Sbms$SheetTrigger, SheetHeader as $3Sbms$SheetHeader, SheetClose as $3Sbms$SheetClose, SheetContent as $3Sbms$SheetContent, SheetTitle as $3Sbms$SheetTitle, DialogDescription as $3Sbms$DialogDescription, SheetDescription as $3Sbms$SheetDescription, DialogFooter as $3Sbms$DialogFooter, AlertDialogHeader as $3Sbms$AlertDialogHeader, AlertDialogTitle as $3Sbms$AlertDialogTitle, AlertDialogDescription as $3Sbms$AlertDialogDescription} from "@snapcall/design-system";
9
10
  import "inobounce";
10
11
  import {useTranslation as $3Sbms$useTranslation, initReactI18next as $3Sbms$initReactI18next, Trans as $3Sbms$Trans} from "react-i18next";
@@ -22,7 +23,6 @@ import {Buffer as $3Sbms$Buffer} from "buffer";
22
23
  import {Form as $3Sbms$Form, FormField as $3Sbms$FormField, FormItem as $3Sbms$FormItem, FormLabel as $3Sbms$FormLabel, FormControl as $3Sbms$FormControl, FormMessage as $3Sbms$FormMessage} from "@snapcall/design-system/form";
23
24
  import {useForm as $3Sbms$useForm} from "react-hook-form";
24
25
  import {createPortal as $3Sbms$createPortal} from "react-dom";
25
- import $3Sbms$classnames from "classnames";
26
26
  import {toCanvas as $3Sbms$toCanvas, toDataURL as $3Sbms$toDataURL} from "qrcode";
27
27
 
28
28
 
@@ -344,6 +344,7 @@ const $35b37252690084e8$export$1cbfb36c1655a9a = (root, element)=>{
344
344
 
345
345
 
346
346
 
347
+
347
348
  const $a3e657fb86ae23f3$export$604ba5624273df44 = ()=>{
348
349
  try {
349
350
  const storedTheme = localStorage.getItem('stream_ui_language');
@@ -503,19 +504,17 @@ const $67e45b2e30dcc030$var$audioContextConstructor = window.AudioContext || win
503
504
  const $67e45b2e30dcc030$var$AUDIO_MUTE_DETECTION_TIME = 2000;
504
505
  const $67e45b2e30dcc030$var$START_SPEAK_DETECTION_TIME = 50;
505
506
  const $67e45b2e30dcc030$var$STOP_SPEAK_DETECTION_TIME = 500;
507
+ const $67e45b2e30dcc030$var$AUDIO_DATA_RATE = 60;
506
508
  class $67e45b2e30dcc030$export$ea669869acd8f177 {
507
509
  constructor(stream, listener){
508
510
  this.speakStartEventTime = 0;
509
511
  this.speakStopEventTime = 0;
510
512
  this.isSpeaking = false;
511
- this.audioMedianInterval = -1;
512
- this.audioLevelInterval = -1;
513
- this.audioLevelAverageInterval = -1;
513
+ this.audioIntervals = {};
514
514
  this.audioLevelAverage = {
515
515
  count: 0,
516
516
  average: 0
517
517
  };
518
- this.audioLevels = [];
519
518
  this.id = stream.id;
520
519
  this.listener = listener;
521
520
  this.stream = stream;
@@ -532,15 +531,16 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
532
531
  this.analyser.minDecibels = -90;
533
532
  this.analyser.maxDecibels = -10;
534
533
  this.audioStreamSource.connect(this.analyser);
534
+ this.audioLevels = new Array(Math.round(1000 / $67e45b2e30dcc030$var$AUDIO_DATA_RATE)).fill(0);
535
535
  }
536
536
  /**
537
- * return the median of the audio levels (60 per second) for the
537
+ * return the average (mean) of the audio levels (AUDIO_DATA_RATE per second) for the
538
538
  * current second
539
- */ getAudioLevelMedian() {
539
+ */ getRecentAudioLevelAverage() {
540
540
  const { length: length } = this.audioLevels;
541
541
  const audioLevelsSum = this.audioLevels.reduce((sum, level)=>sum + level, 0);
542
- const audioLevelMedian = audioLevelsSum / length;
543
- return audioLevelMedian;
542
+ const audioLevelAverage = audioLevelsSum / length;
543
+ return audioLevelAverage;
544
544
  }
545
545
  getCurrentAudioLevel() {
546
546
  const { length: length } = this.audioLevels;
@@ -548,8 +548,8 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
548
548
  return 0;
549
549
  }
550
550
  audioMuteDetection() {
551
- const audioLevelMedian = this.getAudioLevelMedian();
552
- if (audioLevelMedian === 0 && this.audioLevels.length > 0) this.listener?.onMuteDetection?.(this.id);
551
+ const audioLevelAverage = this.getRecentAudioLevelAverage();
552
+ if (audioLevelAverage === 0 && this.audioLevels.length > 0) this.listener?.onMuteDetection?.(this.id);
553
553
  }
554
554
  detectSpeakingChange(audioLevel) {
555
555
  const threshold = 5;
@@ -588,24 +588,24 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
588
588
  }
589
589
  loopCalcul() {
590
590
  const audioLevel = this.getInstantAudioLevel();
591
- this.audioLevels = this.audioLevels.splice(-59);
592
- this.detectSpeakingChange(audioLevel);
591
+ this.audioLevels.shift();
593
592
  this.audioLevels.push(audioLevel);
593
+ this.detectSpeakingChange(audioLevel);
594
594
  this.listener?.onAudioLevel?.(audioLevel, this.id);
595
595
  }
596
596
  analyse() {
597
- this.audioLevelInterval = window.setInterval(()=>this.loopCalcul(), 1000 / 60);
598
- this.audioMedianInterval = window.setInterval(()=>this.audioMuteDetection(), $67e45b2e30dcc030$var$AUDIO_MUTE_DETECTION_TIME);
597
+ this.audioIntervals.level = setInterval(()=>this.loopCalcul(), 1000 / $67e45b2e30dcc030$var$AUDIO_DATA_RATE);
598
+ this.audioIntervals.muteDetection = setInterval(()=>this.audioMuteDetection(), $67e45b2e30dcc030$var$AUDIO_MUTE_DETECTION_TIME);
599
599
  }
600
600
  startAverageAnalysis() {
601
601
  this.audioLevelAverage = {
602
602
  count: 0,
603
603
  average: 0
604
604
  };
605
- clearInterval(this.audioLevelAverageInterval);
606
- this.audioLevelAverageInterval = window.setInterval(()=>{
605
+ clearInterval(this.audioIntervals.levelAverage);
606
+ this.audioIntervals.levelAverage = setInterval(()=>{
607
607
  const { count: count, average: average } = this.audioLevelAverage;
608
- const nextAverage = (average * count + this.getAudioLevelMedian()) / (count + 1);
608
+ const nextAverage = (average * count + this.getRecentAudioLevelAverage()) / (count + 1);
609
609
  this.audioLevelAverage = {
610
610
  count: count + 1,
611
611
  average: nextAverage
@@ -613,7 +613,8 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
613
613
  }, 1000);
614
614
  }
615
615
  stopAverageAnalysis() {
616
- clearInterval(this.audioLevelAverageInterval);
616
+ clearInterval(this.audioIntervals.levelAverage);
617
+ delete this.audioIntervals.levelAverage;
617
618
  return this.audioLevelAverage.average;
618
619
  }
619
620
  getFrequencyData() {
@@ -621,14 +622,18 @@ class $67e45b2e30dcc030$export$ea669869acd8f177 {
621
622
  this.analyser.getByteFrequencyData(FFTDataArray);
622
623
  return FFTDataArray;
623
624
  }
624
- clearListeners() {
625
- clearInterval(this.audioLevelInterval);
626
- clearInterval(this.audioMedianInterval);
627
- this.audioLevels = [];
625
+ clearIntervals() {
626
+ clearInterval(this.audioIntervals.level);
627
+ clearInterval(this.audioIntervals.levelAverage);
628
+ clearInterval(this.audioIntervals.muteDetection);
629
+ delete this.audioIntervals.level;
630
+ delete this.audioIntervals.levelAverage;
631
+ delete this.audioIntervals.muteDetection;
632
+ this.audioLevels.fill(0);
628
633
  }
629
634
  release() {
630
635
  this.listener = undefined;
631
- this.clearListeners();
636
+ this.clearIntervals();
632
637
  this.stream = undefined;
633
638
  try {
634
639
  this.audioStreamSource.disconnect(this.analyser);
@@ -982,8 +987,14 @@ class $ab40fd7a219a4259$export$2e2bcd8739ae039 {
982
987
  let needToAskVideo = Boolean(constraints.video && (!this.video.stream || !this.video.track || this.video.track.readyState === 'ended'));
983
988
  const audioDeviceId = $ab40fd7a219a4259$export$fceddabcb6d8e584(constraints.audio);
984
989
  const videoDeviceId = $ab40fd7a219a4259$export$fceddabcb6d8e584(constraints.video);
985
- if (audioDeviceId && audioDeviceId !== this.audio.track?.getSettings().deviceId) needToAskAudio = true;
986
- if (videoDeviceId && videoDeviceId !== this.video.track?.getSettings().deviceId) needToAskVideo = true;
990
+ const oldAudioDeviceId = this.audio.track?.getSettings().deviceId;
991
+ const oldVideoDeviceId = this.video.track?.getSettings().deviceId;
992
+ /*
993
+ If deviceId is 'default', we cant differentiate if it's the same device or not. https://issues.chromium.org/issues/40199570#comment23
994
+ A possible solution would be to compare the label of the track. There is no guarantee that it will be unique or match the deviceId.
995
+ ex track label: Default - Microphone (USB Audio Device) (046d:0992)
996
+ */ if (audioDeviceId && (audioDeviceId === 'default' || audioDeviceId !== oldAudioDeviceId)) needToAskAudio = true;
997
+ if (videoDeviceId && (videoDeviceId === 'default' || videoDeviceId !== oldVideoDeviceId)) needToAskVideo = true;
987
998
  if (typeof constraints.video === 'object' && constraints.video.facingMode && constraints.video.facingMode !== this.video.track?.getSettings().facingMode) needToAskVideo = true;
988
999
  return {
989
1000
  needToAskAudio: needToAskAudio,
@@ -1315,7 +1326,7 @@ const $120418cdeb6706cf$export$de363e709c412c8a = (fn, wait = 300)=>{
1315
1326
 
1316
1327
 
1317
1328
 
1318
- const $07e4bc01ab825269$export$6ad2c48011488f7 = async (apiUrl, { file: file, token: token })=>{
1329
+ const $07e4bc01ab825269$export$6ad2c48011488f7 = async (apiUrl, { file: file, token: token, type: type })=>{
1319
1330
  if (!file) throw new Error(`Missing file on "${file}"`);
1320
1331
  const upload = await fetch(`${apiUrl}/public/streams/${token}/events/upload`, {
1321
1332
  method: 'POST',
@@ -1324,7 +1335,8 @@ const $07e4bc01ab825269$export$6ad2c48011488f7 = async (apiUrl, { file: file, to
1324
1335
  },
1325
1336
  body: JSON.stringify({
1326
1337
  filename: file.name,
1327
- contentLength: file.size
1338
+ contentLength: file.size,
1339
+ type: type
1328
1340
  })
1329
1341
  });
1330
1342
  const { url: url, headers: headers, filename: filename } = await upload.json();
@@ -2072,6 +2084,7 @@ class $c31e3fb4360572af$export$2e2bcd8739ae039 extends $c31e3fb4360572af$var$Str
2072
2084
  await this.micProducer?.replaceTrack({
2073
2085
  track: track
2074
2086
  });
2087
+ if (this.micProducer?.paused) track.enabled = false;
2075
2088
  $c31e3fb4360572af$var$log.log('switchMicrophone', 'switched Microphone');
2076
2089
  const trackSettings = track.getSettings();
2077
2090
  const device = this.devicesList.find((it)=>it.deviceId === trackSettings.deviceId);
@@ -2621,6 +2634,7 @@ class $c31e3fb4360572af$export$2e2bcd8739ae039 extends $c31e3fb4360572af$var$Str
2621
2634
  audio: false,
2622
2635
  video: true
2623
2636
  });
2637
+ this.webcam.device = null;
2624
2638
  this.webcamProducer = null;
2625
2639
  this.webcamTrack = null;
2626
2640
  if (this.useVideoBackground) {
@@ -2755,9 +2769,10 @@ class $c31e3fb4360572af$export$2e2bcd8739ae039 extends $c31e3fb4360572af$var$Str
2755
2769
  base64Image: base64Image
2756
2770
  });
2757
2771
  }
2758
- async uploadAsset(file) {
2772
+ async uploadAsset(file, type) {
2759
2773
  return (0, $07e4bc01ab825269$export$6ad2c48011488f7)(this.config.apiUrl, {
2760
2774
  token: this.roomId,
2775
+ type: type,
2761
2776
  file: file
2762
2777
  });
2763
2778
  }
@@ -10937,14 +10952,6 @@ const $946223bbb2c552ef$export$5a5695b638d078e7 = ()=>{
10937
10952
 
10938
10953
 
10939
10954
 
10940
- const $20431dc869bb21e0$var$fileToDataUrl = (file)=>{
10941
- return new Promise((resolve, reject)=>{
10942
- const reader = new FileReader();
10943
- reader.addEventListener('load', ()=>resolve(reader.result));
10944
- reader.addEventListener('error', ()=>reject(reader.error));
10945
- reader.readAsDataURL(file);
10946
- });
10947
- };
10948
10955
  const $20431dc869bb21e0$var$generateVideoThumbnail = (file)=>{
10949
10956
  return new Promise((resolve)=>{
10950
10957
  const canvas = document.createElement('canvas');
@@ -10984,21 +10991,12 @@ const $20431dc869bb21e0$export$b3fd96a52c80b3af = ()=>{
10984
10991
  });
10985
10992
  openAssetsModal();
10986
10993
  try {
10987
- let url;
10988
10994
  let thumbnailUrl;
10989
- let filename;
10990
- if (type === 'image') {
10991
- const dataUrl = await $20431dc869bb21e0$var$fileToDataUrl(file);
10992
- const data = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).saveCapture(dataUrl);
10993
- url = data.url;
10994
- filename = data.filename;
10995
- } else {
10996
- const data = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).uploadAsset(file);
10997
- url = data.url;
10998
- filename = data.filename;
10999
- if (type === 'video') thumbnailUrl = await $20431dc869bb21e0$var$generateVideoThumbnail(file);
11000
- if (!url || !filename) throw new Error('upload failed');
11001
- }
10995
+ const data = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).uploadAsset(file, type);
10996
+ const url = data.url;
10997
+ const filename = data.filename;
10998
+ if (type === 'video') thumbnailUrl = await $20431dc869bb21e0$var$generateVideoThumbnail(file);
10999
+ if (!url || !filename) throw new Error('upload failed');
11002
11000
  addAsset({
11003
11001
  filename: filename,
11004
11002
  mode: mode,
@@ -12129,14 +12127,14 @@ const $64dee502cbd6331e$export$1ea93f9eface5983 = ({ duration: duration = 0, ave
12129
12127
  duotone: true
12130
12128
  })
12131
12129
  });
12132
- if (averageAudioLevel <= 5) return /*#__PURE__*/ (0, $3Sbms$jsx)($64dee502cbd6331e$var$Notification, {
12130
+ if (averageAudioLevel <= 1) return /*#__PURE__*/ (0, $3Sbms$jsx)($64dee502cbd6331e$var$Notification, {
12133
12131
  title: t('recorder.audioLevelNotification.spokenWordsWarning.title'),
12134
12132
  description: t('recorder.audioLevelNotification.spokenWordsWarning.description'),
12135
12133
  icon: /*#__PURE__*/ (0, $3Sbms$jsx)((0, $3Sbms$AlertTriangleIcon), {
12136
12134
  duotone: true
12137
12135
  })
12138
12136
  });
12139
- if (averageAudioLevel <= 25) return /*#__PURE__*/ (0, $3Sbms$jsx)($64dee502cbd6331e$var$Notification, {
12137
+ if (averageAudioLevel <= 3) return /*#__PURE__*/ (0, $3Sbms$jsx)($64dee502cbd6331e$var$Notification, {
12140
12138
  title: t('recorder.audioLevelNotification.spokenWordsQuestion.title'),
12141
12139
  description: t('recorder.audioLevelNotification.spokenWordsQuestion.description'),
12142
12140
  icon: /*#__PURE__*/ (0, $3Sbms$jsx)((0, $3Sbms$InfoCircleIcon), {
@@ -12277,7 +12275,7 @@ const $a5dd8f67439dd9eb$var$getStoredAssets = async ()=>{
12277
12275
  const storedAssets = JSON.parse(localStorage.getItem('snapcall_assets') || '[]');
12278
12276
  const assets = await Promise.all(storedAssets.map(async (storedAsset)=>{
12279
12277
  try {
12280
- let { url: url, thumbnailUrl: thumbnailUrl } = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).readAsset(storedAsset.filename);
12278
+ let { url: url, thumbnailUrl: thumbnailUrl, error: error } = await (0, $c9e496369b59be7a$export$2f377c2162fd02b2).readAsset(storedAsset.filename);
12281
12279
  if (url) {
12282
12280
  if (storedAsset.mode === 'photo') thumbnailUrl = url;
12283
12281
  return {
@@ -12285,7 +12283,7 @@ const $a5dd8f67439dd9eb$var$getStoredAssets = async ()=>{
12285
12283
  url: url,
12286
12284
  thumbnailUrl: thumbnailUrl
12287
12285
  };
12288
- }
12286
+ } else if (error) $a5dd8f67439dd9eb$export$df987b50509121ea(storedAsset.filename);
12289
12287
  } catch (error) {
12290
12288
  $a5dd8f67439dd9eb$export$df987b50509121ea(storedAsset.filename);
12291
12289
  }
@@ -12331,6 +12329,31 @@ const $a5dd8f67439dd9eb$export$931d641a2a152cf = ()=>{
12331
12329
 
12332
12330
 
12333
12331
 
12332
+
12333
+
12334
+ const $7c2ec1087f88cbe4$export$f2bc44ad94513462 = ()=>{
12335
+ const { clientInitResult: clientInitResult } = (0, $3Sbms$useContext)((0, $5f30d8bf4f04621e$export$2e2bcd8739ae039));
12336
+ const flowSource = clientInitResult.flow?.steps?.[0].config?.source;
12337
+ const onRecorderEnd = ()=>{
12338
+ if (flowSource === 'smooch') // @ts-ignore
12339
+ window.WebviewSdk?.close?.();
12340
+ else if (flowSource === 'whatsapp') window.location.href = 'https://wa.me';
12341
+ };
12342
+ (0, $3Sbms$useEffect)(()=>{
12343
+ if (flowSource === 'smooch') {
12344
+ const smoochScript = document.createElement('script');
12345
+ smoochScript.src = 'https://cdn.smooch.io/webview-sdk.min.js';
12346
+ if (!document.body.contains(smoochScript)) document.body.appendChild(smoochScript);
12347
+ }
12348
+ }, [
12349
+ flowSource
12350
+ ]);
12351
+ return {
12352
+ onRecorderEnd: onRecorderEnd
12353
+ };
12354
+ };
12355
+
12356
+
12334
12357
  const $3ecacdd28d707ec1$var$eventTypes = {
12335
12358
  screen: 'screenshare',
12336
12359
  photo: 'image',
@@ -12340,6 +12363,7 @@ const $3ecacdd28d707ec1$var$eventTypes = {
12340
12363
  const $3ecacdd28d707ec1$export$c01bb29adf88f117 = ({ state: state })=>{
12341
12364
  const { t: t } = (0, $3Sbms$useTranslation)();
12342
12365
  const { assets: assets, incomingAsset: incomingAsset } = (0, $75812785bb101fee$export$2174f25d572f9f31)();
12366
+ const flowSourceAction = (0, $7c2ec1087f88cbe4$export$f2bc44ad94513462)();
12343
12367
  const sendMutation = (0, $3Sbms$useMutation)({
12344
12368
  mutationFn: async ()=>{
12345
12369
  try {
@@ -12364,7 +12388,6 @@ const $3ecacdd28d707ec1$export$c01bb29adf88f117 = ({ state: state })=>{
12364
12388
  });
12365
12389
  throw new Error('some media not saved');
12366
12390
  }
12367
- (0, $c9e496369b59be7a$export$2f377c2162fd02b2).release();
12368
12391
  return results;
12369
12392
  } catch (error) {
12370
12393
  reportError({
@@ -12374,6 +12397,10 @@ const $3ecacdd28d707ec1$export$c01bb29adf88f117 = ({ state: state })=>{
12374
12397
  console.log(error);
12375
12398
  throw error;
12376
12399
  }
12400
+ },
12401
+ onSuccess: ()=>{
12402
+ (0, $c9e496369b59be7a$export$2f377c2162fd02b2).release();
12403
+ flowSourceAction.onRecorderEnd();
12377
12404
  }
12378
12405
  });
12379
12406
  const reportError = (0, $946223bbb2c552ef$export$5a5695b638d078e7)();
@@ -14600,7 +14627,7 @@ const $26ed036cbc17809a$var$StreamUI = ({ options: baseOptions })=>{
14600
14627
  /*#__PURE__*/ (0, $3Sbms$jsx)((0, $3Sbms$TooltipProvider), {
14601
14628
  children: /*#__PURE__*/ (0, $3Sbms$jsxs)((0, $4fb4815baa04b470$export$914ddf2021ea8ee6), {
14602
14629
  ref: streamUIContainerRef,
14603
- className: "dark-theme bg-white",
14630
+ className: (0, $3Sbms$classnames)('bg-white', streamState === 'greeting' ? 'light-theme' : 'dark-theme'),
14604
14631
  children: [
14605
14632
  /*#__PURE__*/ (0, $3Sbms$jsx)((0, $3a42b2ef7646d035$export$2e2bcd8739ae039), {}),
14606
14633
  /*#__PURE__*/ (0, $3Sbms$jsx)((0, $3Sbms$Toaster), {
package/dist/stream-ui.js CHANGED
@@ -5,6 +5,7 @@ var $jQDcL$tanstackreactquery = require("@tanstack/react-query");
5
5
  var $jQDcL$reacthottoast = require("react-hot-toast");
6
6
  var $jQDcL$styledcomponents = require("styled-components");
7
7
  var $jQDcL$react = require("react");
8
+ var $jQDcL$classnames = require("classnames");
8
9
  var $jQDcL$snapcalldesignsystem = require("@snapcall/design-system");
9
10
  require("inobounce");
10
11
  var $jQDcL$reacti18next = require("react-i18next");
@@ -22,7 +23,6 @@ var $jQDcL$buffer = require("buffer");
22
23
  var $jQDcL$snapcalldesignsystemform = require("@snapcall/design-system/form");
23
24
  var $jQDcL$reacthookform = require("react-hook-form");
24
25
  var $jQDcL$reactdom = require("react-dom");
25
- var $jQDcL$classnames = require("classnames");
26
26
  var $jQDcL$qrcode = require("qrcode");
27
27
 
28
28
 
@@ -350,6 +350,7 @@ const $57b7750d9786bf6f$export$1cbfb36c1655a9a = (root, element)=>{
350
350
 
351
351
 
352
352
 
353
+
353
354
  const $393bda1b33846dfc$export$604ba5624273df44 = ()=>{
354
355
  try {
355
356
  const storedTheme = localStorage.getItem('stream_ui_language');
@@ -509,19 +510,17 @@ const $6a90fae7e584afd4$var$audioContextConstructor = window.AudioContext || win
509
510
  const $6a90fae7e584afd4$var$AUDIO_MUTE_DETECTION_TIME = 2000;
510
511
  const $6a90fae7e584afd4$var$START_SPEAK_DETECTION_TIME = 50;
511
512
  const $6a90fae7e584afd4$var$STOP_SPEAK_DETECTION_TIME = 500;
513
+ const $6a90fae7e584afd4$var$AUDIO_DATA_RATE = 60;
512
514
  class $6a90fae7e584afd4$export$ea669869acd8f177 {
513
515
  constructor(stream, listener){
514
516
  this.speakStartEventTime = 0;
515
517
  this.speakStopEventTime = 0;
516
518
  this.isSpeaking = false;
517
- this.audioMedianInterval = -1;
518
- this.audioLevelInterval = -1;
519
- this.audioLevelAverageInterval = -1;
519
+ this.audioIntervals = {};
520
520
  this.audioLevelAverage = {
521
521
  count: 0,
522
522
  average: 0
523
523
  };
524
- this.audioLevels = [];
525
524
  this.id = stream.id;
526
525
  this.listener = listener;
527
526
  this.stream = stream;
@@ -538,15 +537,16 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
538
537
  this.analyser.minDecibels = -90;
539
538
  this.analyser.maxDecibels = -10;
540
539
  this.audioStreamSource.connect(this.analyser);
540
+ this.audioLevels = new Array(Math.round(1000 / $6a90fae7e584afd4$var$AUDIO_DATA_RATE)).fill(0);
541
541
  }
542
542
  /**
543
- * return the median of the audio levels (60 per second) for the
543
+ * return the average (mean) of the audio levels (AUDIO_DATA_RATE per second) for the
544
544
  * current second
545
- */ getAudioLevelMedian() {
545
+ */ getRecentAudioLevelAverage() {
546
546
  const { length: length } = this.audioLevels;
547
547
  const audioLevelsSum = this.audioLevels.reduce((sum, level)=>sum + level, 0);
548
- const audioLevelMedian = audioLevelsSum / length;
549
- return audioLevelMedian;
548
+ const audioLevelAverage = audioLevelsSum / length;
549
+ return audioLevelAverage;
550
550
  }
551
551
  getCurrentAudioLevel() {
552
552
  const { length: length } = this.audioLevels;
@@ -554,8 +554,8 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
554
554
  return 0;
555
555
  }
556
556
  audioMuteDetection() {
557
- const audioLevelMedian = this.getAudioLevelMedian();
558
- if (audioLevelMedian === 0 && this.audioLevels.length > 0) this.listener?.onMuteDetection?.(this.id);
557
+ const audioLevelAverage = this.getRecentAudioLevelAverage();
558
+ if (audioLevelAverage === 0 && this.audioLevels.length > 0) this.listener?.onMuteDetection?.(this.id);
559
559
  }
560
560
  detectSpeakingChange(audioLevel) {
561
561
  const threshold = 5;
@@ -594,24 +594,24 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
594
594
  }
595
595
  loopCalcul() {
596
596
  const audioLevel = this.getInstantAudioLevel();
597
- this.audioLevels = this.audioLevels.splice(-59);
598
- this.detectSpeakingChange(audioLevel);
597
+ this.audioLevels.shift();
599
598
  this.audioLevels.push(audioLevel);
599
+ this.detectSpeakingChange(audioLevel);
600
600
  this.listener?.onAudioLevel?.(audioLevel, this.id);
601
601
  }
602
602
  analyse() {
603
- this.audioLevelInterval = window.setInterval(()=>this.loopCalcul(), 1000 / 60);
604
- this.audioMedianInterval = window.setInterval(()=>this.audioMuteDetection(), $6a90fae7e584afd4$var$AUDIO_MUTE_DETECTION_TIME);
603
+ this.audioIntervals.level = setInterval(()=>this.loopCalcul(), 1000 / $6a90fae7e584afd4$var$AUDIO_DATA_RATE);
604
+ this.audioIntervals.muteDetection = setInterval(()=>this.audioMuteDetection(), $6a90fae7e584afd4$var$AUDIO_MUTE_DETECTION_TIME);
605
605
  }
606
606
  startAverageAnalysis() {
607
607
  this.audioLevelAverage = {
608
608
  count: 0,
609
609
  average: 0
610
610
  };
611
- clearInterval(this.audioLevelAverageInterval);
612
- this.audioLevelAverageInterval = window.setInterval(()=>{
611
+ clearInterval(this.audioIntervals.levelAverage);
612
+ this.audioIntervals.levelAverage = setInterval(()=>{
613
613
  const { count: count, average: average } = this.audioLevelAverage;
614
- const nextAverage = (average * count + this.getAudioLevelMedian()) / (count + 1);
614
+ const nextAverage = (average * count + this.getRecentAudioLevelAverage()) / (count + 1);
615
615
  this.audioLevelAverage = {
616
616
  count: count + 1,
617
617
  average: nextAverage
@@ -619,7 +619,8 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
619
619
  }, 1000);
620
620
  }
621
621
  stopAverageAnalysis() {
622
- clearInterval(this.audioLevelAverageInterval);
622
+ clearInterval(this.audioIntervals.levelAverage);
623
+ delete this.audioIntervals.levelAverage;
623
624
  return this.audioLevelAverage.average;
624
625
  }
625
626
  getFrequencyData() {
@@ -627,14 +628,18 @@ class $6a90fae7e584afd4$export$ea669869acd8f177 {
627
628
  this.analyser.getByteFrequencyData(FFTDataArray);
628
629
  return FFTDataArray;
629
630
  }
630
- clearListeners() {
631
- clearInterval(this.audioLevelInterval);
632
- clearInterval(this.audioMedianInterval);
633
- this.audioLevels = [];
631
+ clearIntervals() {
632
+ clearInterval(this.audioIntervals.level);
633
+ clearInterval(this.audioIntervals.levelAverage);
634
+ clearInterval(this.audioIntervals.muteDetection);
635
+ delete this.audioIntervals.level;
636
+ delete this.audioIntervals.levelAverage;
637
+ delete this.audioIntervals.muteDetection;
638
+ this.audioLevels.fill(0);
634
639
  }
635
640
  release() {
636
641
  this.listener = undefined;
637
- this.clearListeners();
642
+ this.clearIntervals();
638
643
  this.stream = undefined;
639
644
  try {
640
645
  this.audioStreamSource.disconnect(this.analyser);
@@ -988,8 +993,14 @@ class $d582bbc5717818b4$export$2e2bcd8739ae039 {
988
993
  let needToAskVideo = Boolean(constraints.video && (!this.video.stream || !this.video.track || this.video.track.readyState === 'ended'));
989
994
  const audioDeviceId = $d582bbc5717818b4$export$fceddabcb6d8e584(constraints.audio);
990
995
  const videoDeviceId = $d582bbc5717818b4$export$fceddabcb6d8e584(constraints.video);
991
- if (audioDeviceId && audioDeviceId !== this.audio.track?.getSettings().deviceId) needToAskAudio = true;
992
- if (videoDeviceId && videoDeviceId !== this.video.track?.getSettings().deviceId) needToAskVideo = true;
996
+ const oldAudioDeviceId = this.audio.track?.getSettings().deviceId;
997
+ const oldVideoDeviceId = this.video.track?.getSettings().deviceId;
998
+ /*
999
+ If deviceId is 'default', we cant differentiate if it's the same device or not. https://issues.chromium.org/issues/40199570#comment23
1000
+ A possible solution would be to compare the label of the track. There is no guarantee that it will be unique or match the deviceId.
1001
+ ex track label: Default - Microphone (USB Audio Device) (046d:0992)
1002
+ */ if (audioDeviceId && (audioDeviceId === 'default' || audioDeviceId !== oldAudioDeviceId)) needToAskAudio = true;
1003
+ if (videoDeviceId && (videoDeviceId === 'default' || videoDeviceId !== oldVideoDeviceId)) needToAskVideo = true;
993
1004
  if (typeof constraints.video === 'object' && constraints.video.facingMode && constraints.video.facingMode !== this.video.track?.getSettings().facingMode) needToAskVideo = true;
994
1005
  return {
995
1006
  needToAskAudio: needToAskAudio,
@@ -1321,7 +1332,7 @@ const $3898fb88b880f5ba$export$de363e709c412c8a = (fn, wait = 300)=>{
1321
1332
 
1322
1333
 
1323
1334
 
1324
- const $987c962fd22b0c93$export$6ad2c48011488f7 = async (apiUrl, { file: file, token: token })=>{
1335
+ const $987c962fd22b0c93$export$6ad2c48011488f7 = async (apiUrl, { file: file, token: token, type: type })=>{
1325
1336
  if (!file) throw new Error(`Missing file on "${file}"`);
1326
1337
  const upload = await fetch(`${apiUrl}/public/streams/${token}/events/upload`, {
1327
1338
  method: 'POST',
@@ -1330,7 +1341,8 @@ const $987c962fd22b0c93$export$6ad2c48011488f7 = async (apiUrl, { file: file, to
1330
1341
  },
1331
1342
  body: JSON.stringify({
1332
1343
  filename: file.name,
1333
- contentLength: file.size
1344
+ contentLength: file.size,
1345
+ type: type
1334
1346
  })
1335
1347
  });
1336
1348
  const { url: url, headers: headers, filename: filename } = await upload.json();
@@ -2078,6 +2090,7 @@ class $1dedebd5ff3002eb$export$2e2bcd8739ae039 extends $1dedebd5ff3002eb$var$Str
2078
2090
  await this.micProducer?.replaceTrack({
2079
2091
  track: track
2080
2092
  });
2093
+ if (this.micProducer?.paused) track.enabled = false;
2081
2094
  $1dedebd5ff3002eb$var$log.log('switchMicrophone', 'switched Microphone');
2082
2095
  const trackSettings = track.getSettings();
2083
2096
  const device = this.devicesList.find((it)=>it.deviceId === trackSettings.deviceId);
@@ -2627,6 +2640,7 @@ class $1dedebd5ff3002eb$export$2e2bcd8739ae039 extends $1dedebd5ff3002eb$var$Str
2627
2640
  audio: false,
2628
2641
  video: true
2629
2642
  });
2643
+ this.webcam.device = null;
2630
2644
  this.webcamProducer = null;
2631
2645
  this.webcamTrack = null;
2632
2646
  if (this.useVideoBackground) {
@@ -2761,9 +2775,10 @@ class $1dedebd5ff3002eb$export$2e2bcd8739ae039 extends $1dedebd5ff3002eb$var$Str
2761
2775
  base64Image: base64Image
2762
2776
  });
2763
2777
  }
2764
- async uploadAsset(file) {
2778
+ async uploadAsset(file, type) {
2765
2779
  return (0, $987c962fd22b0c93$export$6ad2c48011488f7)(this.config.apiUrl, {
2766
2780
  token: this.roomId,
2781
+ type: type,
2767
2782
  file: file
2768
2783
  });
2769
2784
  }
@@ -10943,14 +10958,6 @@ const $8dfcca373a03b9e8$export$5a5695b638d078e7 = ()=>{
10943
10958
 
10944
10959
 
10945
10960
 
10946
- const $ccbd73eb953b0bd0$var$fileToDataUrl = (file)=>{
10947
- return new Promise((resolve, reject)=>{
10948
- const reader = new FileReader();
10949
- reader.addEventListener('load', ()=>resolve(reader.result));
10950
- reader.addEventListener('error', ()=>reject(reader.error));
10951
- reader.readAsDataURL(file);
10952
- });
10953
- };
10954
10961
  const $ccbd73eb953b0bd0$var$generateVideoThumbnail = (file)=>{
10955
10962
  return new Promise((resolve)=>{
10956
10963
  const canvas = document.createElement('canvas');
@@ -10990,21 +10997,12 @@ const $ccbd73eb953b0bd0$export$b3fd96a52c80b3af = ()=>{
10990
10997
  });
10991
10998
  openAssetsModal();
10992
10999
  try {
10993
- let url;
10994
11000
  let thumbnailUrl;
10995
- let filename;
10996
- if (type === 'image') {
10997
- const dataUrl = await $ccbd73eb953b0bd0$var$fileToDataUrl(file);
10998
- const data = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).saveCapture(dataUrl);
10999
- url = data.url;
11000
- filename = data.filename;
11001
- } else {
11002
- const data = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).uploadAsset(file);
11003
- url = data.url;
11004
- filename = data.filename;
11005
- if (type === 'video') thumbnailUrl = await $ccbd73eb953b0bd0$var$generateVideoThumbnail(file);
11006
- if (!url || !filename) throw new Error('upload failed');
11007
- }
11001
+ const data = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).uploadAsset(file, type);
11002
+ const url = data.url;
11003
+ const filename = data.filename;
11004
+ if (type === 'video') thumbnailUrl = await $ccbd73eb953b0bd0$var$generateVideoThumbnail(file);
11005
+ if (!url || !filename) throw new Error('upload failed');
11008
11006
  addAsset({
11009
11007
  filename: filename,
11010
11008
  mode: mode,
@@ -12135,14 +12133,14 @@ const $c42fbc742adf8306$export$1ea93f9eface5983 = ({ duration: duration = 0, ave
12135
12133
  duotone: true
12136
12134
  })
12137
12135
  });
12138
- if (averageAudioLevel <= 5) return /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)($c42fbc742adf8306$var$Notification, {
12136
+ if (averageAudioLevel <= 1) return /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)($c42fbc742adf8306$var$Notification, {
12139
12137
  title: t('recorder.audioLevelNotification.spokenWordsWarning.title'),
12140
12138
  description: t('recorder.audioLevelNotification.spokenWordsWarning.description'),
12141
12139
  icon: /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)((0, $jQDcL$snapcalldesignsystemicons.AlertTriangleIcon), {
12142
12140
  duotone: true
12143
12141
  })
12144
12142
  });
12145
- if (averageAudioLevel <= 25) return /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)($c42fbc742adf8306$var$Notification, {
12143
+ if (averageAudioLevel <= 3) return /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)($c42fbc742adf8306$var$Notification, {
12146
12144
  title: t('recorder.audioLevelNotification.spokenWordsQuestion.title'),
12147
12145
  description: t('recorder.audioLevelNotification.spokenWordsQuestion.description'),
12148
12146
  icon: /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)((0, $jQDcL$snapcalldesignsystemicons.InfoCircleIcon), {
@@ -12283,7 +12281,7 @@ const $8a7a24ac08dbc187$var$getStoredAssets = async ()=>{
12283
12281
  const storedAssets = JSON.parse(localStorage.getItem('snapcall_assets') || '[]');
12284
12282
  const assets = await Promise.all(storedAssets.map(async (storedAsset)=>{
12285
12283
  try {
12286
- let { url: url, thumbnailUrl: thumbnailUrl } = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).readAsset(storedAsset.filename);
12284
+ let { url: url, thumbnailUrl: thumbnailUrl, error: error } = await (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).readAsset(storedAsset.filename);
12287
12285
  if (url) {
12288
12286
  if (storedAsset.mode === 'photo') thumbnailUrl = url;
12289
12287
  return {
@@ -12291,7 +12289,7 @@ const $8a7a24ac08dbc187$var$getStoredAssets = async ()=>{
12291
12289
  url: url,
12292
12290
  thumbnailUrl: thumbnailUrl
12293
12291
  };
12294
- }
12292
+ } else if (error) $8a7a24ac08dbc187$export$df987b50509121ea(storedAsset.filename);
12295
12293
  } catch (error) {
12296
12294
  $8a7a24ac08dbc187$export$df987b50509121ea(storedAsset.filename);
12297
12295
  }
@@ -12337,6 +12335,31 @@ const $8a7a24ac08dbc187$export$931d641a2a152cf = ()=>{
12337
12335
 
12338
12336
 
12339
12337
 
12338
+
12339
+
12340
+ const $663f53e6b55f0d5a$export$f2bc44ad94513462 = ()=>{
12341
+ const { clientInitResult: clientInitResult } = (0, $jQDcL$react.useContext)((0, $8b39f32976a7698a$export$2e2bcd8739ae039));
12342
+ const flowSource = clientInitResult.flow?.steps?.[0].config?.source;
12343
+ const onRecorderEnd = ()=>{
12344
+ if (flowSource === 'smooch') // @ts-ignore
12345
+ window.WebviewSdk?.close?.();
12346
+ else if (flowSource === 'whatsapp') window.location.href = 'https://wa.me';
12347
+ };
12348
+ (0, $jQDcL$react.useEffect)(()=>{
12349
+ if (flowSource === 'smooch') {
12350
+ const smoochScript = document.createElement('script');
12351
+ smoochScript.src = 'https://cdn.smooch.io/webview-sdk.min.js';
12352
+ if (!document.body.contains(smoochScript)) document.body.appendChild(smoochScript);
12353
+ }
12354
+ }, [
12355
+ flowSource
12356
+ ]);
12357
+ return {
12358
+ onRecorderEnd: onRecorderEnd
12359
+ };
12360
+ };
12361
+
12362
+
12340
12363
  const $e399416dd32d3252$var$eventTypes = {
12341
12364
  screen: 'screenshare',
12342
12365
  photo: 'image',
@@ -12346,6 +12369,7 @@ const $e399416dd32d3252$var$eventTypes = {
12346
12369
  const $e399416dd32d3252$export$c01bb29adf88f117 = ({ state: state })=>{
12347
12370
  const { t: t } = (0, $jQDcL$reacti18next.useTranslation)();
12348
12371
  const { assets: assets, incomingAsset: incomingAsset } = (0, $098350f721a0bb52$export$2174f25d572f9f31)();
12372
+ const flowSourceAction = (0, $663f53e6b55f0d5a$export$f2bc44ad94513462)();
12349
12373
  const sendMutation = (0, $jQDcL$tanstackreactquery.useMutation)({
12350
12374
  mutationFn: async ()=>{
12351
12375
  try {
@@ -12370,7 +12394,6 @@ const $e399416dd32d3252$export$c01bb29adf88f117 = ({ state: state })=>{
12370
12394
  });
12371
12395
  throw new Error('some media not saved');
12372
12396
  }
12373
- (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).release();
12374
12397
  return results;
12375
12398
  } catch (error) {
12376
12399
  reportError({
@@ -12380,6 +12403,10 @@ const $e399416dd32d3252$export$c01bb29adf88f117 = ({ state: state })=>{
12380
12403
  console.log(error);
12381
12404
  throw error;
12382
12405
  }
12406
+ },
12407
+ onSuccess: ()=>{
12408
+ (0, $c48c1ecc38fed4e9$export$2f377c2162fd02b2).release();
12409
+ flowSourceAction.onRecorderEnd();
12383
12410
  }
12384
12411
  });
12385
12412
  const reportError = (0, $8dfcca373a03b9e8$export$5a5695b638d078e7)();
@@ -14606,7 +14633,7 @@ const $ee8cb448c2c74888$var$StreamUI = ({ options: baseOptions })=>{
14606
14633
  /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)((0, $jQDcL$snapcalldesignsystem.TooltipProvider), {
14607
14634
  children: /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsxs)((0, $e3bb2c5d0e5b45b5$export$914ddf2021ea8ee6), {
14608
14635
  ref: streamUIContainerRef,
14609
- className: "dark-theme bg-white",
14636
+ className: (0, ($parcel$interopDefault($jQDcL$classnames)))('bg-white', streamState === 'greeting' ? 'light-theme' : 'dark-theme'),
14610
14637
  children: [
14611
14638
  /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)((0, $e66cc5db58913155$export$2e2bcd8739ae039), {}),
14612
14639
  /*#__PURE__*/ (0, $jQDcL$reactjsxruntime.jsx)((0, $jQDcL$snapcalldesignsystem.Toaster), {
package/dist/types.d.ts CHANGED
@@ -18,6 +18,7 @@ interface Step {
18
18
  config?: {
19
19
  description: string;
20
20
  image_url: string;
21
+ source?: string;
21
22
  };
22
23
  translation: {
23
24
  title?: string;
@@ -192,16 +193,16 @@ declare class AudioLevel {
192
193
  readonly id: string;
193
194
  constructor(stream: MediaStream, listener?: AudioLevelListener);
194
195
  /**
195
- * return the median of the audio levels (60 per second) for the
196
+ * return the average (mean) of the audio levels (AUDIO_DATA_RATE per second) for the
196
197
  * current second
197
198
  */
198
- getAudioLevelMedian(): number;
199
+ getRecentAudioLevelAverage(): number;
199
200
  getCurrentAudioLevel(): number;
200
201
  analyse(): void;
201
202
  startAverageAnalysis(): void;
202
203
  stopAverageAnalysis(): number;
203
204
  getFrequencyData(): Uint8Array;
204
- clearListeners(): void;
205
+ clearIntervals(): void;
205
206
  release(): void;
206
207
  static isAPIAvailable(): boolean;
207
208
  }
@@ -540,7 +541,7 @@ declare class StreamerClient extends StreamerEventTargetType implements AudioLev
540
541
  url: string;
541
542
  filename: string;
542
543
  }>;
543
- uploadAsset(file: any): Promise<{
544
+ uploadAsset(file: any, type: 'image' | 'video' | 'audio'): Promise<{
544
545
  url?: string;
545
546
  filename: string;
546
547
  }>;
@@ -599,6 +600,7 @@ declare class StreamerClient extends StreamerEventTargetType implements AudioLev
599
600
  readAsset(file: string): Promise<{
600
601
  url: string;
601
602
  thumbnailUrl?: string;
603
+ error?: string;
602
604
  }>;
603
605
  deleteAsset(file: string): Promise<{
604
606
  status: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snapcall/stream-ui",
3
- "version": "1.28.1",
3
+ "version": "1.29.1",
4
4
  "description": "",
5
5
  "source": "src/index.tsx",
6
6
  "main": "dist/stream-ui.js",