memoize images

This commit is contained in:
2025-10-03 15:24:42 +02:00
parent ce9571ec7f
commit 2b6bf7e433
@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef, useState } from "react"; import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { import {
FlatList, FlatList,
Image, Image,
@@ -66,30 +66,36 @@ const ProjectDropDown = ({
}) })
: normalizedProjects; : normalizedProjects;
const toggleDropdown = () => { const toggleDropdown = useCallback(() => {
if (isDisabled) { if (isDisabled) {
return; return;
} }
setIsOpen((prev) => !prev); setIsOpen((prev) => !prev);
}; }, [isDisabled]);
const closeDropdown = () => setIsOpen(false); const closeDropdown = useCallback(() => setIsOpen(false), []);
const handleSelect = (project) => { const handleSelect = useCallback(
if (!project?.id) return; (project) => {
onSelectProject?.(project); if (!project?.id) return;
closeDropdown(); onSelectProject?.(project);
}; closeDropdown();
},
[closeDropdown, onSelectProject],
);
const handleModify = (project, topPosition) => { const handleModify = useCallback(
if (!project?.id) return; (project, topPosition) => {
onModifyProject?.(project, topPosition); if (!project?.id) return;
}; onModifyProject?.(project, topPosition);
},
[onModifyProject],
);
const handleCreate = () => { const handleCreate = useCallback(() => {
onCreateProject?.(); onCreateProject?.();
closeDropdown(); closeDropdown();
}; }, [closeDropdown, onCreateProject]);
const dropdownWidth = useMemo( const dropdownWidth = useMemo(
() => triggerLayout?.width || 0, () => triggerLayout?.width || 0,
@@ -124,35 +130,26 @@ const ProjectDropDown = ({
/> />
</BlurView> </BlurView>
{isOpen && ( <BlurView
<BlurView intensity={BUTTON_BLUR_INTENSITY}
intensity={BUTTON_BLUR_INTENSITY} tint="dark"
tint="dark" pointerEvents={isOpen ? "auto" : "none"}
style={{ style={[
position: "absolute", styles.dropdownOverlay,
top: 0, { width: dropdownWidth || "100%" },
left: 0, !isOpen && styles.dropdownOverlayHidden,
borderRadius: 16, ]}
paddingHorizontal: 8, >
paddingVertical: 8, <ProjectRow
gap: 9, isTitle={true}
maxHeight: 400, isOpen={isOpen}
zIndex: 4, project={currentProject}
elevation: 4, formatDate={formatDate}
width: dropdownWidth || "100%", onSelect={toggleDropdown}
overflow: "hidden", />
}}
>
<ProjectRow
isTitle={true}
isOpen={isOpen}
project={currentProject}
formatDate={formatDate}
onSelect={toggleDropdown}
/>
<View style={styles.dropdownOverlayContent}> <View style={styles.dropdownOverlayContent}>
<FlatList <FlatList
data={dropdownProjects} data={dropdownProjects}
keyExtractor={(project, index) => keyExtractor={(project, index) =>
project?.id || project?.title || `project-${index}` project?.id || project?.title || `project-${index}`
@@ -171,14 +168,13 @@ const ProjectDropDown = ({
contentContainerStyle={styles.dropdownListContent} contentContainerStyle={styles.dropdownListContent}
style={styles.dropdownList} style={styles.dropdownList}
/> />
<GradientButton <GradientButton
containerStyle={styles.createButtonContainer} containerStyle={styles.createButtonContainer}
title="Commencer à créer" title="Commencer à créer"
onPress={handleCreate} onPress={handleCreate}
/> />
</View> </View>
</BlurView> </BlurView>
)}
</View> </View>
</View> </View>
); );
@@ -227,6 +223,10 @@ const ProjectRow = ({
project?.coverUrl || project?.coverUrl ||
project?.coverUri || project?.coverUri ||
(typeof project?.cover === "string" ? project.cover : project?.cover?.uri); (typeof project?.cover === "string" ? project.cover : project?.cover?.uri);
const imageSource = useMemo(
() => (coverUri ? { uri: coverUri } : img.placeholder),
[coverUri],
);
const title = const title =
project?.title || (isEmptyProject ? "Nouvelle musique" : "Sans titre"); project?.title || (isEmptyProject ? "Nouvelle musique" : "Sans titre");
const formattedDate = !isEmptyProject const formattedDate = !isEmptyProject
@@ -245,10 +245,7 @@ const ProjectRow = ({
onLayout={(event) => setLayout(event.nativeEvent.layout)} onLayout={(event) => setLayout(event.nativeEvent.layout)}
style={styles.projectRowPressable} style={styles.projectRowPressable}
> >
<Image <Image source={imageSource} style={styles.projectImage} />
source={coverUri ? { uri: coverUri } : img.placeholder}
style={styles.projectImage}
/>
<BlurView tint="dark" style={styles.projectInfo}> <BlurView tint="dark" style={styles.projectInfo}>
<View style={styles.projectTexts}> <View style={styles.projectTexts}>
<Text style={styles.projectTitle} numberOfLines={1}> <Text style={styles.projectTitle} numberOfLines={1}>
@@ -306,6 +303,22 @@ const styles = StyleSheet.create({
position: "relative", position: "relative",
zIndex: 3, zIndex: 3,
}, },
dropdownOverlay: {
position: "absolute",
top: 0,
left: 0,
borderRadius: 16,
paddingHorizontal: 8,
paddingVertical: 8,
gap: 9,
maxHeight: 400,
zIndex: 4,
elevation: 4,
overflow: "hidden",
},
dropdownOverlayHidden: {
opacity: 0,
},
dropdownOverlayContent: { dropdownOverlayContent: {
maxHeight: 260, maxHeight: 260,
width: "100%", width: "100%",