more menu
This commit is contained in:
@@ -12,6 +12,7 @@ import { Portal } from "@gorhom/portal";
|
||||
const MoreMenu = ({
|
||||
visible = false,
|
||||
top = 0,
|
||||
position = null,
|
||||
onClose = () => {},
|
||||
inPlaylist = false,
|
||||
playlistId = null,
|
||||
@@ -21,6 +22,17 @@ const MoreMenu = ({
|
||||
const { setTooltip } = useMinuit();
|
||||
if (!visible) return null;
|
||||
|
||||
const resolvedTop =
|
||||
typeof position?.top === "number"
|
||||
? position.top
|
||||
: typeof top === "number"
|
||||
? top
|
||||
: 0;
|
||||
const resolvedRight =
|
||||
typeof position?.right === "number" ? Math.max(position.right, 0) : null;
|
||||
const resolvedLeft =
|
||||
typeof position?.left === "number" ? Math.max(position.left, 0) : null;
|
||||
|
||||
const removeFromPlaylist = async () => {
|
||||
try {
|
||||
if (inPlaylist && playlistId && projectId) {
|
||||
@@ -49,6 +61,21 @@ const MoreMenu = ({
|
||||
onClose?.();
|
||||
};
|
||||
|
||||
const anchorStyle = {
|
||||
position: "absolute",
|
||||
top: resolvedTop,
|
||||
zIndex: 2,
|
||||
elevation: 2,
|
||||
};
|
||||
|
||||
if (resolvedRight != null) {
|
||||
anchorStyle.right = resolvedRight;
|
||||
} else if (resolvedLeft != null) {
|
||||
anchorStyle.left = resolvedLeft;
|
||||
} else {
|
||||
anchorStyle.right = 0;
|
||||
}
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<View
|
||||
@@ -77,13 +104,7 @@ const MoreMenu = ({
|
||||
<Animated.View
|
||||
entering={FadeIn.duration(300).easing(Easing.ease)}
|
||||
exiting={FadeOut.duration(300).easing(Easing.ease)}
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: 0,
|
||||
top,
|
||||
zIndex: 2,
|
||||
elevation: 2,
|
||||
}}
|
||||
style={anchorStyle}
|
||||
>
|
||||
<View style={{ gap: 2 }}>
|
||||
{inPlaylist && (
|
||||
|
||||
@@ -23,7 +23,7 @@ const HomeSave = () => {
|
||||
[userProjects],
|
||||
);
|
||||
const [, setTooltip] = useGlobal("_tooltip");
|
||||
const [menuTop, setMenuTop] = useState(0);
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [menuProjectId, setMenuProjectId] = useState(null);
|
||||
|
||||
@@ -83,15 +83,19 @@ const HomeSave = () => {
|
||||
}}
|
||||
onPressMore={(posTop) => {
|
||||
setMenuProjectId(item.id);
|
||||
setMenuTop(posTop);
|
||||
setShowMenu((prev) => !prev || posTop !== menuTop);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
<MoreMenu
|
||||
visible={showMenu}
|
||||
top={menuTop}
|
||||
top={menuPosition?.top ?? 0}
|
||||
position={menuPosition}
|
||||
onClose={() => setShowMenu(false)}
|
||||
inPlaylist={false}
|
||||
projectId={menuProjectId}
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function AllMyList() {
|
||||
: [];
|
||||
})();
|
||||
|
||||
const [top, setTop] = useState(0);
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
|
||||
@@ -70,14 +70,18 @@ export default function AllMyList() {
|
||||
onPress={() => onPressItem(item)}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(item.id);
|
||||
setTop(posTop);
|
||||
setShowMenu((prev) => !prev || posTop !== top);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<MoreMenu
|
||||
visible={showMenu}
|
||||
top={top}
|
||||
top={menuPosition?.top ?? 0}
|
||||
position={menuPosition}
|
||||
onClose={() => setShowMenu(false)}
|
||||
inPlaylist={false}
|
||||
projectId={selectedProjectId}
|
||||
|
||||
@@ -37,7 +37,7 @@ const AllMyPlaylist = ({ route }) => {
|
||||
condition: Array.isArray(playlist?.musics) && playlist.musics.length > 0,
|
||||
refreshArray: [selectedPlaylistId, playlist?.musics?.length || 0],
|
||||
});
|
||||
const [menuTop, setMenuTop] = useState(0);
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
console.log("musics are : ", musics);
|
||||
@@ -174,15 +174,19 @@ const AllMyPlaylist = ({ route }) => {
|
||||
}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(p.id);
|
||||
setMenuTop(posTop);
|
||||
setShowMenu((prev) => !prev || posTop !== menuTop);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
<MoreMenu
|
||||
visible={showMenu}
|
||||
top={menuTop}
|
||||
top={menuPosition?.top ?? 0}
|
||||
position={menuPosition}
|
||||
onClose={() => setShowMenu(false)}
|
||||
inPlaylist
|
||||
playlistId={selectedPlaylistId}
|
||||
|
||||
@@ -36,7 +36,7 @@ const PlaylistDetails = () => {
|
||||
refreshArray: [playlistId, playlist?.musics?.length || 0],
|
||||
});
|
||||
|
||||
const [menuTop, setMenuTop] = useState(0);
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
|
||||
@@ -90,15 +90,19 @@ const PlaylistDetails = () => {
|
||||
onPress={() => navigate(Routes.MusicDetails, { projectId: p.id })}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(p.id);
|
||||
setMenuTop(posTop);
|
||||
setShowMenu((prev) => !prev || posTop !== menuTop);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
<MoreMenu
|
||||
visible={showMenu}
|
||||
top={menuTop}
|
||||
top={menuPosition?.top ?? 0}
|
||||
position={menuPosition}
|
||||
onClose={() => setShowMenu(false)}
|
||||
inPlaylist
|
||||
playlistId={playlistId}
|
||||
|
||||
@@ -194,7 +194,7 @@ const Research = () => {
|
||||
}
|
||||
}
|
||||
}, [filteredUsers.length, usersLoading, usersQueryRef, autoLoads]);
|
||||
const [menuTop, setMenuTop] = useState(0);
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
|
||||
@@ -264,9 +264,11 @@ const Research = () => {
|
||||
}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(p.id);
|
||||
setMenuTop(posTop);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) => !prev || posTop !== menuTop,
|
||||
(prev) =>
|
||||
!prev ||
|
||||
posTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
@@ -391,7 +393,8 @@ const Research = () => {
|
||||
)}
|
||||
<MoreMenu
|
||||
visible={showMenu}
|
||||
top={menuTop}
|
||||
top={menuPosition?.top ?? 0}
|
||||
position={menuPosition}
|
||||
onClose={() => setShowMenu(false)}
|
||||
inPlaylist={false}
|
||||
projectId={selectedProjectId}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Text,
|
||||
View,
|
||||
Image as RNImage,
|
||||
Dimensions,
|
||||
} from "react-native";
|
||||
import { Image as ExpoImage } from "expo-image";
|
||||
import { useGlobal } from "reactn";
|
||||
@@ -28,13 +29,20 @@ const MusicCard = ({
|
||||
const [currentUID] = useGlobal("currentUID");
|
||||
const [selected, setSelected] = useState(false);
|
||||
const [layout, setLayout] = useState(null);
|
||||
const [menuPos, setMenuPos] = useState(0);
|
||||
const [menuPos, setMenuPos] = useState({
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
width: 0,
|
||||
height: 0,
|
||||
});
|
||||
const cardRef = useRef(null);
|
||||
const moreButtonRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (layout) {
|
||||
const top = layout?.y + 45;
|
||||
setMenuPos(top);
|
||||
const top = (layout?.y || 0) + 45;
|
||||
setMenuPos((prev) => ({ ...prev, top }));
|
||||
}
|
||||
}, [layout]);
|
||||
|
||||
@@ -59,13 +67,32 @@ const MusicCard = ({
|
||||
};
|
||||
|
||||
const onPressMenu = () => {
|
||||
const computeAnchor = (x = 0, y = 0, width = 0, height = 0) => {
|
||||
const windowWidth = Dimensions.get("window").width || 0;
|
||||
const top = (y || 0) + (height || 0) + 8;
|
||||
const right = Math.max(0, windowWidth - ((x || 0) + (width || 0)));
|
||||
const left = Math.max(0, x || 0);
|
||||
const anchor = { top, right, left, width, height };
|
||||
setMenuPos(anchor);
|
||||
onPressMore?.(anchor);
|
||||
};
|
||||
|
||||
if (moreButtonRef?.current?.measureInWindow) {
|
||||
try {
|
||||
moreButtonRef.current.measureInWindow((x, y, width, height) => {
|
||||
computeAnchor(x, y, width, height);
|
||||
});
|
||||
return;
|
||||
} catch (e) {
|
||||
// fallback to card measurement below
|
||||
}
|
||||
}
|
||||
|
||||
// Prefer absolute screen position when available (Portal rendering)
|
||||
if (cardRef?.current?.measureInWindow) {
|
||||
try {
|
||||
cardRef.current.measureInWindow((x, y, width, height) => {
|
||||
const top = (y || 0) + 45;
|
||||
setMenuPos(top);
|
||||
onPressMore?.(top);
|
||||
computeAnchor(x, y, width, height);
|
||||
});
|
||||
return;
|
||||
} catch (e) {
|
||||
@@ -132,7 +159,7 @@ const MusicCard = ({
|
||||
resizeMode="contain"
|
||||
/>
|
||||
</Pressable>
|
||||
<Pressable onPress={onPressMenu}>
|
||||
<Pressable ref={moreButtonRef} onPress={onPressMenu}>
|
||||
<RNImage source={icons.more} style={size({ size: 24 })} />
|
||||
</Pressable>
|
||||
</View>
|
||||
|
||||
@@ -9,7 +9,7 @@ import MoreMenu from "../../../components/MoreMenu";
|
||||
|
||||
const MyMusic = () => {
|
||||
const { userProjects = [] } = useUser();
|
||||
const [menuTop, setMenuTop] = useState(0);
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
const projects = Array.isArray(userProjects) ? userProjects.slice(0, 3) : [];
|
||||
@@ -37,14 +37,18 @@ const MyMusic = () => {
|
||||
onPress={() => navigate(Routes.MusicDetails, { projectId: p.id })}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(p.id);
|
||||
setMenuTop(posTop);
|
||||
setShowMenu((prev) => !prev || posTop !== menuTop);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
<MoreMenu
|
||||
visible={showMenu}
|
||||
top={menuTop}
|
||||
top={menuPosition?.top ?? 0}
|
||||
position={menuPosition}
|
||||
onClose={() => setShowMenu(false)}
|
||||
inPlaylist={false}
|
||||
projectId={selectedProjectId}
|
||||
|
||||
@@ -49,7 +49,7 @@ const Profile = () => {
|
||||
const [isFollowing, setIsFollowing] = useState(false);
|
||||
const [followers, setFollowers] = useState(0);
|
||||
const [following, setFollowing] = useState(0);
|
||||
const [menuTop, setMenuTop] = useState(0);
|
||||
const [menuPosition, setMenuPosition] = useState(null);
|
||||
const [showMenu, setShowMenu] = useState(false);
|
||||
const [selectedProjectId, setSelectedProjectId] = useState(null);
|
||||
const onPressMenu = (item) => {
|
||||
@@ -137,8 +137,11 @@ const Profile = () => {
|
||||
}
|
||||
onPressMore={(posTop) => {
|
||||
setSelectedProjectId(item.id);
|
||||
setMenuTop(posTop);
|
||||
setShowMenu((prev) => !prev || posTop !== menuTop);
|
||||
setMenuPosition(posTop);
|
||||
setShowMenu(
|
||||
(prev) =>
|
||||
!prev || posTop?.top !== (menuPosition?.top ?? null),
|
||||
);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@@ -148,7 +151,8 @@ const Profile = () => {
|
||||
)}
|
||||
<MoreMenu
|
||||
visible={showMenu}
|
||||
top={menuTop}
|
||||
top={menuPosition?.top ?? 0}
|
||||
position={menuPosition}
|
||||
onClose={() => setShowMenu(false)}
|
||||
inPlaylist={false}
|
||||
projectId={selectedProjectId}
|
||||
|
||||
Reference in New Issue
Block a user