1- import React , { useEffect , useState } from 'react' ;
1+ import React , { useEffect , useRef , useState } from 'react' ;
22import { View } from 'react-native' ;
33
44import { Icon , Image , createStyleSheet , useUIKitTheme } from '@sendbird/uikit-react-native-foundation' ;
@@ -7,35 +7,49 @@ import { getAvailableUriFromFileMessage } from '@sendbird/uikit-utils';
77import { usePlatformService } from '../../../hooks/useContext' ;
88import type { FileMessageProps } from './index' ;
99
10- const VideoFileMessage = ( { message } : FileMessageProps ) => {
11- const { colors } = useUIKitTheme ( ) ;
10+ const useRetry = ( videoFileUrl : string , retryCount = 5 ) => {
11+ const [ state , setState ] = useState ( { thumbnail : null as null | string , loading : true } ) ;
12+ const retryCountRef = useRef ( 0 ) ;
13+ const retryTimeoutRef = useRef < NodeJS . Timeout > ( ) ;
1214
1315 const { mediaService } = usePlatformService ( ) ;
14- const fileUrl = getAvailableUriFromFileMessage ( message ) ;
15- const style = [ styles . image , { backgroundColor : colors . onBackground04 } ] ;
1616
17- const [ state , setState ] = useState ( {
18- thumbnail : null as null | string ,
19- loading : true ,
20- imageNotFound : false ,
21- } ) ;
17+ const fetchThumbnail = ( ) => {
18+ return mediaService ?. getVideoThumbnail ( { url : videoFileUrl , timeMills : 1000 } ) . then ( ( result ) => {
19+ setState ( { loading : false , thumbnail : result ?. path ?? null } ) ;
20+ } ) ;
21+ } ;
2222
2323 useEffect ( ( ) => {
24- mediaService
25- ?. getVideoThumbnail ( { url : fileUrl , timeMills : 1000 } )
26- . then ( ( result ) => {
27- if ( result ?. path ) {
28- setState ( ( prev ) => ( { ...prev , loading : false , thumbnail : result . path } ) ) ;
29- } else {
30- throw new Error ( 'Cannot generate thumbnail' ) ;
24+ if ( ! state . thumbnail ) {
25+ const reloadReservation = ( ) => {
26+ if ( retryCountRef . current < retryCount ) {
27+ retryTimeoutRef . current = setTimeout ( ( ) => {
28+ retryCountRef . current ++ ;
29+ reloadReservation ( ) ;
30+ fetchThumbnail ( ) ;
31+ } , retryCountRef . current * 5000 ) ;
3132 }
32- } )
33- . catch ( ( ) => {
34- setState ( ( prev ) => ( { ...prev , loading : false , imageNotFound : true } ) ) ;
35- } ) ;
36- } , [ ] ) ;
33+ } ;
34+
35+ return reloadReservation ( ) ;
36+ } else {
37+ return clearTimeout ( retryTimeoutRef . current ) ;
38+ }
39+ } , [ state . thumbnail ] ) ;
40+
41+ return state ;
42+ } ;
43+
44+ const VideoFileMessage = ( { message } : FileMessageProps ) => {
45+ const { colors } = useUIKitTheme ( ) ;
46+
47+ const fileUrl = getAvailableUriFromFileMessage ( message ) ;
48+ const style = [ styles . image , { backgroundColor : colors . onBackground04 } ] ;
49+
50+ const { loading, thumbnail } = useRetry ( fileUrl ) ;
3751
38- if ( state . loading || state . imageNotFound ) {
52+ if ( loading ) {
3953 return (
4054 < View style = { [ style , styles . container ] } >
4155 < PlayIcon />
@@ -45,13 +59,7 @@ const VideoFileMessage = ({ message }: FileMessageProps) => {
4559
4660 return (
4761 < View style = { styles . container } >
48- < Image
49- source = { { uri : state . thumbnail || fileUrl } }
50- style = { style }
51- resizeMode = { 'cover' }
52- resizeMethod = { 'resize' }
53- onError = { ( ) => setState ( ( prev ) => ( { ...prev , imageNotFound : true } ) ) }
54- />
62+ < Image source = { { uri : thumbnail || fileUrl } } style = { style } resizeMode = { 'cover' } resizeMethod = { 'resize' } />
5563 < PlayIcon />
5664 </ View >
5765 ) ;
0 commit comments