diff --git a/src/navigation/TabBar.js b/src/navigation/TabBar.js index 830d140..73aaab2 100644 --- a/src/navigation/TabBar.js +++ b/src/navigation/TabBar.js @@ -1,22 +1,37 @@ import * as Haptics from "expo-haptics"; -import React from "react"; +import React, { useMemo } from "react"; import { Text, TouchableOpacity, View } from "react-native"; +import { useGlobal } from "reactn"; import ItemContainer from "../components/ItemContainer/ItemContainer"; import useLayoutType from "../hooks/useLayoutType"; import { gutters, Palette, Style } from "../styles"; import { FONT_FAMILY } from "../styles/Fonts"; const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => { - const { isDesktop, windowWidth, mediumDesktopBreakpoint, isWeb } = - useLayoutType(); + const { windowWidth, isWeb } = useLayoutType(); + const [webLayoutMode] = useGlobal("webLayoutMode"); + + const containerWidth = useMemo(() => { + if (!isWeb) return "90%"; + + const containerFraction = webLayoutMode === "playbacks-wide" ? 0.9 : 0.6; + const containerMax = webLayoutMode === "playbacks-wide" ? 1440 : 800; + const computedContainerWidth = Math.min( + windowWidth * containerFraction, + containerMax + ); + const barWidth = Math.max(computedContainerWidth * 0.9, 360); + return barWidth; + }, [isWeb, webLayoutMode, windowWidth]); return ( { const { currentUID, currentUserData } = useUser() || {}; const [text, setText] = useState(""); @@ -177,98 +177,113 @@ const CommentsPanel = ({ - - Description - - - {descriptionText || "Description chanson..."} - - - - {`Commentaires${commentsCount ? ` (${commentsCount})` : ""}`} - - {Array.isArray(comments) && comments.length > 0 ? ( - comments.map((c, index) => ( - 0 && styles.commentRowSpacing]} - > - {c?.profilePicture ? ( - - ) : ( - - )} - - - - {c?.userId === currentUID ? "vous" : c?.userName || ""} - - - • {formatRelativeTime(c?.createdAt)} - - - {c?.text} - - - )) - ) : ( - - Aucun commentaire pour le moment - - )} - - - - [ - styles.sendButton, - (!canComment || !text.trim()) && styles.sendButtonDisabled, - pressed && canComment && styles.sendButtonPressed, - ]} + + - Description + + + {descriptionText || "Description chanson..."} + + + + {`Commentaires${commentsCount ? ` (${commentsCount})` : ""}`} + + {Array.isArray(comments) && comments.length > 0 ? ( + comments.map((c, index) => ( + 0 && styles.commentRowSpacing, + ]} + > + {c?.profilePicture ? ( + + ) : ( + + )} + + + + {c?.userId === currentUID ? "vous" : c?.userName || ""} + + + • {formatRelativeTime(c?.createdAt)} + + + {c?.text} + + + )) + ) : ( + + Aucun commentaire pour le moment + + )} + + + - + [ + styles.sendButton, + (!canComment || !text.trim()) && styles.sendButtonDisabled, + pressed && canComment && styles.sendButtonPressed, + ]} + > + + + ); }; const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { - const { width: viewportWidth } = useWindowDimensions(); - const [layoutWidth, setLayoutWidth] = useState(viewportWidth); + const { width: viewportWidth, height: viewportHeight } = + useWindowDimensions(); + const [layoutSize, setLayoutSize] = useState({ + width: viewportWidth, + height: viewportHeight, + }); const commentInputRef = useRef(null); const { currentUID, followUser, unfollowUser } = useUser() || {}; const videoUrl = item?.playbackUrl || null; @@ -439,12 +454,16 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { item?.description || item?.title || "Description chanson"; const handleLayout = useCallback((event) => { - const nextWidth = event?.nativeEvent?.layout?.width; - if (typeof nextWidth === "number" && nextWidth > 0) { - setLayoutWidth(nextWidth); - } + const { width = 0, height = 0 } = event?.nativeEvent?.layout || {}; + setLayoutSize((prev) => ({ + width: width > 0 ? width : prev.width, + height: height > 0 ? height : prev.height, + })); }, []); + const layoutWidth = layoutSize.width || viewportWidth; + const layoutHeight = layoutSize.height || viewportHeight; + const widePaddingThreshold = 900; const horizontalPadding = layoutWidth >= widePaddingThreshold ? 64 : 32; const innerWidth = Math.max(layoutWidth - horizontalPadding * 2, 0); @@ -454,20 +473,42 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { const minCommentsWidth = 260; const maxCommentsWidth = 420; - let sideBySide = innerWidth >= 620; + const baseInnerWidth = innerWidth > 0 ? innerWidth : viewportWidth; + let desiredHeight = Math.max(360, layoutHeight * 0.8); + let desiredWidth = desiredHeight * (9 / 16); + + if (desiredWidth > maxVideoWidth) { + desiredWidth = maxVideoWidth; + desiredHeight = desiredWidth * (16 / 9); + } + + if (desiredWidth < minVideoWidth) { + desiredWidth = minVideoWidth; + desiredHeight = desiredWidth * (16 / 9); + } + + let sideBySide = + innerWidth >= desiredWidth + minCommentsWidth + gapBetweenColumns; + let videoWidth = sideBySide - ? Math.min(maxVideoWidth, Math.max(innerWidth * 0.56, minVideoWidth)) - : Math.min(innerWidth, maxVideoWidth); + ? Math.min(maxVideoWidth, Math.max(desiredWidth, minVideoWidth)) + : Math.min(Math.max(baseInnerWidth * 0.88, minVideoWidth), maxVideoWidth); + let videoHeight = videoWidth * (16 / 9); + + if (videoHeight > desiredHeight) { + videoHeight = desiredHeight; + videoWidth = videoHeight * (9 / 16); + } + let commentsWidth = sideBySide ? innerWidth - videoWidth - gapBetweenColumns - : innerWidth; + : baseInnerWidth; if (sideBySide && commentsWidth > maxCommentsWidth) { - videoWidth = Math.min( - maxVideoWidth, - videoWidth + (commentsWidth - maxCommentsWidth) - ); + const excess = commentsWidth - maxCommentsWidth; commentsWidth = maxCommentsWidth; + videoWidth = Math.min(maxVideoWidth, videoWidth + excess); + videoHeight = videoWidth * (16 / 9); } if (sideBySide && commentsWidth < minCommentsWidth) { @@ -475,33 +516,28 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { if (videoWidth - deficit >= minVideoWidth) { videoWidth -= deficit; commentsWidth = minCommentsWidth; + videoHeight = videoWidth * (16 / 9); } else { sideBySide = false; - videoWidth = Math.min(innerWidth, maxVideoWidth); - commentsWidth = innerWidth; + videoWidth = Math.min(baseInnerWidth, maxVideoWidth); + commentsWidth = baseInnerWidth; + videoHeight = videoWidth * (16 / 9); } } - const baseInnerWidth = innerWidth > 0 ? innerWidth : viewportWidth; - const safeVideoWidth = Math.max( - minVideoWidth, - Math.min( - Number.isFinite(videoWidth) ? videoWidth : baseInnerWidth, - maxVideoWidth - ) - ); - const videoCardWidth = sideBySide - ? safeVideoWidth - : Math.min(Math.max(baseInnerWidth * 0.88, minVideoWidth), maxVideoWidth); + if (!sideBySide) { + videoHeight = Math.min(videoHeight, desiredHeight); + videoWidth = videoHeight * (9 / 16); + commentsWidth = videoWidth; + } + + const panelHeight = Math.min(videoHeight, desiredHeight); + + const containerHeight = viewportHeight; + const verticalPadding = Math.max((layoutHeight - panelHeight) / 2, 24); const safeCommentsWidth = sideBySide - ? Math.max( - minCommentsWidth, - Math.min( - Number.isFinite(commentsWidth) ? commentsWidth : baseInnerWidth, - maxCommentsWidth - ) - ) - : 0; + ? Math.max(minCommentsWidth, Math.min(commentsWidth, maxCommentsWidth)) + : undefined; return ( { styles.itemContainerBase, sideBySide ? styles.itemContainerRow : styles.itemContainerCompact, { - height: responsiveHeight(70), + height: "90%", paddingHorizontal: sideBySide ? horizontalPadding : 24, + paddingVertical: verticalPadding, }, ]} > @@ -519,11 +556,19 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => { style={[ styles.videoColumn, sideBySide - ? { width: safeVideoWidth, marginRight: gapBetweenColumns } + ? { width: videoWidth, marginRight: gapBetweenColumns } : { width: "100%" }, ]} > - + {!!videoUrl ? ( { style={[ styles.commentsColumn, sideBySide - ? { width: safeCommentsWidth } - : styles.commentsColumnCompact, + ? { width: safeCommentsWidth, height: panelHeight } + : [styles.commentsColumnCompact, { height: panelHeight }], ]} > { setCommentsCount((c) => Math.max(0, Number(c || 0) + 1)) } inputRef={commentInputRef} + panelHeight={panelHeight} /> @@ -726,12 +772,10 @@ const Playbacks = () => { }); useEffect(() => { - if (Platform.OS === "web") { - setGlobal({ webLayoutMode: "playbacks-wide" }); - return () => setGlobal({ webLayoutMode: "default" }); - } - return undefined; - }, []); + if (Platform.OS !== "web") return undefined; + setGlobal({ webLayoutMode: isFocused ? "playbacks-wide" : "default" }); + return () => setGlobal({ webLayoutMode: "default" }); + }, [isFocused]); const onSnap = useCallback( (index) => { @@ -790,11 +834,9 @@ export default Playbacks; const styles = StyleSheet.create({ screen: { flex: 1, - // backgroundColor: Palette.darkPurple, }, itemContainerBase: { width: "100%", - // backgroundColor: Palette.darkPurple, paddingVertical: 36, alignItems: "center", }, @@ -814,8 +856,8 @@ const styles = StyleSheet.create({ }, videoSurface: { alignSelf: "center", - width: "100%", - maxWidth: 620, + // width: 100, + // maxWidth: 400, aspectRatio: 9 / 16, borderRadius: 32, overflow: "hidden", @@ -915,8 +957,16 @@ const styles = StyleSheet.create({ backgroundColor: Palette.glass, minHeight: 0, }, + commentsInner: { + flex: 1, + justifyContent: "space-between", + }, + commentsScroll: { + flex: 1, + }, commentsContent: { paddingBottom: 24, + flexGrow: 1, }, sectionTitle: { fontSize: 18,