Skip to content

Commit 3427d53

Browse files
committed
improve
1 parent 79b9801 commit 3427d53

File tree

1 file changed

+38
-23
lines changed

1 file changed

+38
-23
lines changed

src/dashboard/Data/Browser/DataBrowser.react.js

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -812,8 +812,17 @@ export default class DataBrowser extends React.Component {
812812
}
813813
}
814814

815+
isSafeHttpUrl(url) {
816+
try {
817+
const parsed = new URL(url);
818+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
819+
} catch {
820+
return false;
821+
}
822+
}
823+
815824
extractMediaUrls(data) {
816-
const urls = { images: [], videos: [], audios: [] };
825+
const urls = { images: new Set(), videos: new Set(), audios: new Set() };
817826

818827
if (!data?.panel?.segments) {
819828
return urls;
@@ -822,12 +831,12 @@ export default class DataBrowser extends React.Component {
822831
data.panel.segments.forEach(segment => {
823832
if (segment.items) {
824833
segment.items.forEach(item => {
825-
if (item.type === 'image' && item.url) {
826-
urls.images.push(item.url);
827-
} else if (item.type === 'video' && item.url) {
828-
urls.videos.push(item.url);
829-
} else if (item.type === 'audio' && item.url) {
830-
urls.audios.push(item.url);
834+
if (item.type === 'image' && item.url && this.isSafeHttpUrl(item.url)) {
835+
urls.images.add(item.url);
836+
} else if (item.type === 'video' && item.url && this.isSafeHttpUrl(item.url)) {
837+
urls.videos.add(item.url);
838+
} else if (item.type === 'audio' && item.url && this.isSafeHttpUrl(item.url)) {
839+
urls.audios.add(item.url);
831840
}
832841
});
833842
}
@@ -837,23 +846,29 @@ export default class DataBrowser extends React.Component {
837846
}
838847

839848
prefetchMedia(urls, mediaType) {
840-
if (!urls || urls.length === 0) {
849+
if (!urls || urls.size === 0) {
841850
return;
842851
}
843852

844853
urls.forEach(url => {
845-
if (mediaType === 'image') {
846-
const img = new Image();
847-
img.onerror = () => {
848-
console.error(`Failed to prefetch image: ${url}`);
849-
};
850-
img.src = url;
851-
} else if (mediaType === 'video' || mediaType === 'audio') {
852-
// For video and audio, we can use fetch to cache the content
853-
fetch(url, { mode: 'no-cors' }).catch(error => {
854-
console.error(`Failed to prefetch ${mediaType}: ${url}`, error);
855-
});
856-
}
854+
// Use link-based prefetching for better browser optimization and caching
855+
const link = document.createElement('link');
856+
link.rel = mediaType === 'image' ? 'preload' : 'prefetch';
857+
link.as = mediaType;
858+
link.href = url;
859+
860+
link.onerror = () => {
861+
console.error(`Failed to prefetch ${mediaType}: ${url}`);
862+
};
863+
864+
document.head.appendChild(link);
865+
866+
// Clean up the link element after a delay to prevent memory leaks
867+
setTimeout(() => {
868+
if (link.parentNode) {
869+
link.parentNode.removeChild(link);
870+
}
871+
}, 30000); // Remove after 30 seconds
857872
});
858873
}
859874

@@ -884,13 +899,13 @@ export default class DataBrowser extends React.Component {
884899
const { prefetchImage, prefetchVideo, prefetchAudio } = this.getPrefetchSettings();
885900
const mediaUrls = this.extractMediaUrls(result);
886901

887-
if (prefetchImage && mediaUrls.images.length > 0) {
902+
if (prefetchImage && mediaUrls.images.size > 0) {
888903
this.prefetchMedia(mediaUrls.images, 'image');
889904
}
890-
if (prefetchVideo && mediaUrls.videos.length > 0) {
905+
if (prefetchVideo && mediaUrls.videos.size > 0) {
891906
this.prefetchMedia(mediaUrls.videos, 'video');
892907
}
893-
if (prefetchAudio && mediaUrls.audios.length > 0) {
908+
if (prefetchAudio && mediaUrls.audios.size > 0) {
894909
this.prefetchMedia(mediaUrls.audios, 'audio');
895910
}
896911
}).catch(error => {

0 commit comments

Comments
 (0)