@@ -7,6 +7,52 @@ const resolveImageUrl = (url: string): string => {
77 return url . startsWith ( 'http' ) ? url : `${ getConfigValue ( 'APPFLOWY_BASE_URL' , '' ) } ${ url } ` ;
88} ;
99
10+ // Helper function to check image using Image() approach
11+ const checkImageWithImageElement = (
12+ imageUrl : string ,
13+ resolve : ( data : {
14+ ok : boolean ,
15+ status : number ,
16+ statusText : string ,
17+ error ?: string ,
18+ validatedUrl ?: string ,
19+ } ) => void
20+ ) => {
21+ const img = new Image ( ) ;
22+
23+ // Set a timeout to handle very slow loads
24+ const timeoutId = setTimeout ( ( ) => {
25+ resolve ( {
26+ ok : false ,
27+ status : 408 ,
28+ statusText : 'Request Timeout' ,
29+ error : 'Image loading timed out' ,
30+ } ) ;
31+ } , 10000 ) ; // 10 second timeout
32+
33+ img . onload = ( ) => {
34+ clearTimeout ( timeoutId ) ;
35+ resolve ( {
36+ ok : true ,
37+ status : 200 ,
38+ statusText : 'OK' ,
39+ validatedUrl : imageUrl ,
40+ } ) ;
41+ } ;
42+
43+ img . onerror = ( ) => {
44+ clearTimeout ( timeoutId ) ;
45+ resolve ( {
46+ ok : false ,
47+ status : 404 ,
48+ statusText : 'Image Not Found' ,
49+ error : 'Failed to load image' ,
50+ } ) ;
51+ } ;
52+
53+ img . src = imageUrl ;
54+ } ;
55+
1056export const checkImage = async ( url : string ) => {
1157 return new Promise ( ( resolve : ( data : {
1258 ok : boolean ,
@@ -15,17 +61,16 @@ export const checkImage = async (url: string) => {
1561 error ?: string ,
1662 validatedUrl ?: string ,
1763 } ) => void ) => {
18- // If it's an AppFlowy file storage URL, use authenticated fetch
64+ // If it's an AppFlowy file storage URL, try authenticated fetch first
1965 if ( isAppFlowyFileStorageUrl ( url ) ) {
2066 const token = getTokenParsed ( ) ;
2167
2268 if ( ! token ) {
23- resolve ( {
24- ok : false ,
25- status : 401 ,
26- statusText : 'Unauthorized' ,
27- error : 'No authentication token available' ,
28- } ) ;
69+ // Allow browser to load publicly-accessible URLs without authentication
70+ // Fall through to Image() approach with resolved URL
71+ const resolvedUrl = resolveImageUrl ( url ) ;
72+
73+ checkImageWithImageElement ( resolvedUrl , resolve ) ;
2974 return ;
3075 }
3176
@@ -37,6 +82,7 @@ export const checkImage = async (url: string) => {
3782 } ,
3883 } )
3984 . then ( ( response ) => {
85+ console . debug ( "fetchImageBlob response" , response ) ;
4086 if ( response . ok ) {
4187 // Convert to blob URL for use in img tag
4288 return response . blob ( ) . then ( ( blob ) => {
@@ -50,59 +96,22 @@ export const checkImage = async (url: string) => {
5096 } ) ;
5197 } ) ;
5298 } else {
53- resolve ( {
54- ok : false ,
55- status : response . status ,
56- statusText : response . statusText ,
57- error : `Failed to fetch image: ${ response . statusText } ` ,
58- } ) ;
99+ console . error ( 'Authenticated image fetch failed' , response . status , response . statusText ) ;
100+ // If authenticated fetch fails, fall back to Image() approach
101+ // This allows publicly-accessible URLs to still work
102+ checkImageWithImageElement ( fullUrl , resolve ) ;
59103 }
60104 } )
61105 . catch ( ( error ) => {
62- resolve ( {
63- ok : false ,
64- status : 500 ,
65- statusText : 'Internal Error' ,
66- error : error . message || 'Failed to fetch image' ,
67- } ) ;
106+ console . error ( 'Failed to fetch authenticated image' , error ) ;
107+ // If fetch throws an error (CORS, network, etc.), fall back to Image() approach
108+ checkImageWithImageElement ( fullUrl , resolve ) ;
68109 } ) ;
69110 return ;
70111 }
71112
72113 // For non-AppFlowy URLs, use the original Image() approach
73- const img = new Image ( ) ;
74-
75- // Set a timeout to handle very slow loads
76- const timeoutId = setTimeout ( ( ) => {
77- resolve ( {
78- ok : false ,
79- status : 408 ,
80- statusText : 'Request Timeout' ,
81- error : 'Image loading timed out' ,
82- } ) ;
83- } , 10000 ) ; // 10 second timeout
84-
85- img . onload = ( ) => {
86- clearTimeout ( timeoutId ) ;
87- resolve ( {
88- ok : true ,
89- status : 200 ,
90- statusText : 'OK' ,
91- validatedUrl : url ,
92- } ) ;
93- } ;
94-
95- img . onerror = ( ) => {
96- clearTimeout ( timeoutId ) ;
97- resolve ( {
98- ok : false ,
99- status : 404 ,
100- statusText : 'Image Not Found' ,
101- error : 'Failed to load image' ,
102- } ) ;
103- } ;
104-
105- img . src = url ;
114+ checkImageWithImageElement ( url , resolve ) ;
106115 } ) ;
107116} ;
108117
0 commit comments