scroll
This commit is contained in:
@@ -11,6 +11,7 @@ import React, {
|
|||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import {
|
import {
|
||||||
|
FlatList,
|
||||||
Image,
|
Image,
|
||||||
Platform,
|
Platform,
|
||||||
Pressable,
|
Pressable,
|
||||||
@@ -22,7 +23,8 @@ import {
|
|||||||
View,
|
View,
|
||||||
useWindowDimensions,
|
useWindowDimensions,
|
||||||
} from "react-native";
|
} from "react-native";
|
||||||
import Carousel from "react-native-reanimated-carousel";
|
// Carousel removed; using FlatList for real scrollable content
|
||||||
|
|
||||||
import { setGlobal } from "reactn";
|
import { setGlobal } from "reactn";
|
||||||
import { icons, img } from "../../assets";
|
import { icons, img } from "../../assets";
|
||||||
import KaraokeLyrics from "../../components/KaraokeLyrics";
|
import KaraokeLyrics from "../../components/KaraokeLyrics";
|
||||||
@@ -42,6 +44,7 @@ import { Palette } from "../../styles";
|
|||||||
import { FONT_FAMILY } from "../../styles/Fonts";
|
import { FONT_FAMILY } from "../../styles/Fonts";
|
||||||
import { size } from "../../styles/Style";
|
import { size } from "../../styles/Style";
|
||||||
|
|
||||||
|
// === Helpers ===
|
||||||
const formatRelativeTime = (date) => {
|
const formatRelativeTime = (date) => {
|
||||||
try {
|
try {
|
||||||
const d = date instanceof Date ? date : date?.toDate?.() || null;
|
const d = date instanceof Date ? date : date?.toDate?.() || null;
|
||||||
@@ -60,6 +63,7 @@ const formatRelativeTime = (date) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// === Comments Panel ===
|
||||||
const CommentsPanel = ({
|
const CommentsPanel = ({
|
||||||
projectId,
|
projectId,
|
||||||
description,
|
description,
|
||||||
@@ -277,6 +281,7 @@ const CommentsPanel = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// === Playback Item (WEB-ONLY, side-by-side, sound on) ===
|
||||||
const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
||||||
const { width: viewportWidth, height: viewportHeight } =
|
const { width: viewportWidth, height: viewportHeight } =
|
||||||
useWindowDimensions();
|
useWindowDimensions();
|
||||||
@@ -287,6 +292,8 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
|||||||
const commentInputRef = useRef(null);
|
const commentInputRef = useRef(null);
|
||||||
const { currentUID, followUser, unfollowUser } = useUser() || {};
|
const { currentUID, followUser, unfollowUser } = useUser() || {};
|
||||||
const videoUrl = item?.playbackUrl || null;
|
const videoUrl = item?.playbackUrl || null;
|
||||||
|
|
||||||
|
// External audio source (if present)
|
||||||
const audioSource = useMemo(() => {
|
const audioSource = useMemo(() => {
|
||||||
const fromSong = item?.songUrl ? { uri: item.songUrl } : null;
|
const fromSong = item?.songUrl ? { uri: item.songUrl } : null;
|
||||||
return fromSong;
|
return fromSong;
|
||||||
@@ -368,53 +375,81 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
|||||||
setIsLiked(currentUID ? lb.includes(currentUID) : false);
|
setIsLiked(currentUID ? lb.includes(currentUID) : false);
|
||||||
}, [item?.likedBy, currentUID]);
|
}, [item?.likedBy, currentUID]);
|
||||||
|
|
||||||
|
// Players
|
||||||
const audioPlayer = useAudioPlayer(audioSource || undefined);
|
const audioPlayer = useAudioPlayer(audioSource || undefined);
|
||||||
const videoPlayer = useVideoPlayer(videoUrl || null, (p) => {
|
const videoPlayer = useVideoPlayer(videoUrl || null, (p) => {
|
||||||
p.loop = false;
|
p.loop = true;
|
||||||
p.muted = true;
|
p.muted = false; // 🔊 Sound must be on
|
||||||
p.timeUpdateEventInterval = 0.2;
|
p.timeUpdateEventInterval = 0.2;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Always attempt to start both audio & video together when active
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const toggle = async () => {
|
const startBoth = async () => {
|
||||||
try {
|
try {
|
||||||
if (isActive) {
|
if (!isActive) return;
|
||||||
|
// reset positions
|
||||||
try {
|
try {
|
||||||
if (audioPlayer && hasExternalAudio) await audioPlayer.seekTo?.(0);
|
if (audioPlayer && hasExternalAudio) await audioPlayer.seekTo?.(0);
|
||||||
} catch (_e) {}
|
} catch (_e) {}
|
||||||
try {
|
try {
|
||||||
if (videoPlayer) videoPlayer.currentTime = 0;
|
if (videoPlayer) videoPlayer.currentTime = 0;
|
||||||
} catch (_e) {}
|
} catch (_e) {}
|
||||||
|
// play both
|
||||||
try {
|
try {
|
||||||
if (videoPlayer) videoPlayer.play();
|
if (videoPlayer && !videoPlayer.playing) await videoPlayer.play();
|
||||||
} catch (_e) {}
|
} catch (_e) {}
|
||||||
try {
|
try {
|
||||||
if (audioPlayer && hasExternalAudio) audioPlayer.play?.();
|
if (hasExternalAudio && audioPlayer && !audioPlayer.playing)
|
||||||
|
await audioPlayer.play?.();
|
||||||
} catch (_e) {}
|
} catch (_e) {}
|
||||||
} else {
|
|
||||||
if (audioPlayer?.playing) await audioPlayer.pause?.();
|
|
||||||
if (videoPlayer?.playing) videoPlayer.pause();
|
|
||||||
}
|
|
||||||
} catch (_e) {}
|
} catch (_e) {}
|
||||||
};
|
};
|
||||||
toggle();
|
startBoth();
|
||||||
|
|
||||||
|
// If autoplay with sound is blocked, attach once-only global listeners
|
||||||
|
// to resume without any extra UI/button.
|
||||||
|
if (isActive) {
|
||||||
|
const resume = async () => {
|
||||||
|
try {
|
||||||
|
if (videoPlayer && !videoPlayer.playing) await videoPlayer.play();
|
||||||
|
if (hasExternalAudio && audioPlayer && !audioPlayer.playing)
|
||||||
|
await audioPlayer.play?.();
|
||||||
|
} catch (_e) {}
|
||||||
|
};
|
||||||
|
const events = [
|
||||||
|
"pointerdown",
|
||||||
|
"click",
|
||||||
|
"touchstart",
|
||||||
|
"keydown",
|
||||||
|
"wheel",
|
||||||
|
"scroll",
|
||||||
|
];
|
||||||
|
events.forEach((ev) =>
|
||||||
|
document.addEventListener(ev, resume, { once: true, passive: true })
|
||||||
|
);
|
||||||
|
return () => {
|
||||||
|
events.forEach((ev) => document.removeEventListener(ev, resume));
|
||||||
|
};
|
||||||
|
}
|
||||||
}, [isActive, audioPlayer, videoPlayer, hasExternalAudio]);
|
}, [isActive, audioPlayer, videoPlayer, hasExternalAudio]);
|
||||||
|
|
||||||
|
// Keep A/V roughly aligned
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isActive || !hasExternalAudio) return;
|
if (!isActive || !hasExternalAudio) return;
|
||||||
const t = setTimeout(() => {
|
const t = setInterval(() => {
|
||||||
try {
|
try {
|
||||||
const a = audioPlayer?.currentTime || 0;
|
const a = Number(audioPlayer?.currentTime || 0);
|
||||||
const v = videoPlayer?.currentTime || 0;
|
const v = Number(videoPlayer?.currentTime || 0);
|
||||||
if (Math.abs(a - v) > 0.2 && videoPlayer) {
|
if (Math.abs(a - v) > 0.2 && videoPlayer) {
|
||||||
videoPlayer.currentTime = Math.max(0, a);
|
videoPlayer.currentTime = Math.max(0, a);
|
||||||
}
|
}
|
||||||
} catch (_e) {}
|
} catch (_e) {}
|
||||||
}, 300);
|
}, 300);
|
||||||
return () => clearTimeout(t);
|
return () => clearInterval(t);
|
||||||
}, [isActive, hasExternalAudio, audioPlayer, videoPlayer]);
|
}, [isActive, hasExternalAudio, audioPlayer, videoPlayer]);
|
||||||
|
|
||||||
|
// Pause on unmount / when not active
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
try {
|
try {
|
||||||
@@ -427,7 +462,6 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
|||||||
const alignedWords = useMemo(() => {
|
const alignedWords = useMemo(() => {
|
||||||
const idx = Number(item?.songIndex) || 0;
|
const idx = Number(item?.songIndex) || 0;
|
||||||
const ts = item?.musicTimestamps?.[idx];
|
const ts = item?.musicTimestamps?.[idx];
|
||||||
|
|
||||||
const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : [];
|
const arr = Array.isArray(ts?.alignedWords) ? ts.alignedWords : [];
|
||||||
return arr.map((w) => ({
|
return arr.map((w) => ({
|
||||||
word: String(w?.word ?? ""),
|
word: String(w?.word ?? ""),
|
||||||
@@ -441,7 +475,8 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
|||||||
if (!isActive) return;
|
if (!isActive) return;
|
||||||
const id = setInterval(() => {
|
const id = setInterval(() => {
|
||||||
try {
|
try {
|
||||||
const t = hasExternalAudio
|
const useAudioTime = hasExternalAudio && !!audioPlayer?.playing;
|
||||||
|
const t = useAudioTime
|
||||||
? Number(audioPlayer?.currentTime || 0)
|
? Number(audioPlayer?.currentTime || 0)
|
||||||
: Number(videoPlayer?.currentTime || 0);
|
: Number(videoPlayer?.currentTime || 0);
|
||||||
setCurrentTimeS(t);
|
setCurrentTimeS(t);
|
||||||
@@ -453,6 +488,7 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
|||||||
const descriptionText =
|
const descriptionText =
|
||||||
item?.description || item?.title || "Description chanson";
|
item?.description || item?.title || "Description chanson";
|
||||||
|
|
||||||
|
// Layout: always side-by-side on web
|
||||||
const handleLayout = useCallback((event) => {
|
const handleLayout = useCallback((event) => {
|
||||||
const { width = 0, height = 0 } = event?.nativeEvent?.layout || {};
|
const { width = 0, height = 0 } = event?.nativeEvent?.layout || {};
|
||||||
setLayoutSize((prev) => ({
|
setLayoutSize((prev) => ({
|
||||||
@@ -464,111 +500,51 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
|||||||
const layoutWidth = layoutSize.width || viewportWidth;
|
const layoutWidth = layoutSize.width || viewportWidth;
|
||||||
const layoutHeight = layoutSize.height || viewportHeight;
|
const layoutHeight = layoutSize.height || viewportHeight;
|
||||||
|
|
||||||
const widePaddingThreshold = 900;
|
// Force side-by-side
|
||||||
const horizontalPadding = layoutWidth >= widePaddingThreshold ? 64 : 32;
|
const horizontalPadding = 64;
|
||||||
const innerWidth = Math.max(layoutWidth - horizontalPadding * 2, 0);
|
const innerWidth = Math.max(layoutWidth - horizontalPadding * 2, 0);
|
||||||
const gapBetweenColumns = 40;
|
const gapBetweenColumns = 40;
|
||||||
const minVideoWidth = 340;
|
const minVideoWidth = 420;
|
||||||
const maxVideoWidth = 620;
|
const maxVideoWidth = 720;
|
||||||
const minCommentsWidth = 260;
|
const minCommentsWidth = 300;
|
||||||
const maxCommentsWidth = 420;
|
const maxCommentsWidth = 420;
|
||||||
|
|
||||||
const baseInnerWidth = innerWidth > 0 ? innerWidth : viewportWidth;
|
let desiredHeight = Math.max(420, layoutHeight * 0.8);
|
||||||
let desiredHeight = Math.max(360, layoutHeight * 0.8);
|
let videoWidth = Math.min(
|
||||||
let desiredWidth = desiredHeight * (9 / 16);
|
maxVideoWidth,
|
||||||
|
Math.max(minVideoWidth, innerWidth * 0.58)
|
||||||
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(desiredWidth, minVideoWidth))
|
|
||||||
: Math.min(Math.max(baseInnerWidth * 0.88, minVideoWidth), maxVideoWidth);
|
|
||||||
let videoHeight = videoWidth * (16 / 9);
|
let videoHeight = videoWidth * (16 / 9);
|
||||||
|
|
||||||
if (videoHeight > desiredHeight) {
|
if (videoHeight > desiredHeight) {
|
||||||
videoHeight = desiredHeight;
|
videoHeight = desiredHeight;
|
||||||
videoWidth = videoHeight * (9 / 16);
|
videoWidth = videoHeight * (9 / 16);
|
||||||
}
|
}
|
||||||
|
let commentsWidth = Math.min(
|
||||||
let commentsWidth = sideBySide
|
maxCommentsWidth,
|
||||||
? innerWidth - videoWidth - gapBetweenColumns
|
Math.max(minCommentsWidth, innerWidth - videoWidth - gapBetweenColumns)
|
||||||
: baseInnerWidth;
|
);
|
||||||
|
|
||||||
if (sideBySide && commentsWidth > maxCommentsWidth) {
|
|
||||||
const excess = commentsWidth - maxCommentsWidth;
|
|
||||||
commentsWidth = maxCommentsWidth;
|
|
||||||
videoWidth = Math.min(maxVideoWidth, videoWidth + excess);
|
|
||||||
videoHeight = videoWidth * (16 / 9);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sideBySide && commentsWidth < minCommentsWidth) {
|
|
||||||
const deficit = minCommentsWidth - commentsWidth;
|
|
||||||
if (videoWidth - deficit >= minVideoWidth) {
|
|
||||||
videoWidth -= deficit;
|
|
||||||
commentsWidth = minCommentsWidth;
|
|
||||||
videoHeight = videoWidth * (16 / 9);
|
|
||||||
} else {
|
|
||||||
sideBySide = false;
|
|
||||||
videoWidth = Math.min(baseInnerWidth, maxVideoWidth);
|
|
||||||
commentsWidth = baseInnerWidth;
|
|
||||||
videoHeight = videoWidth * (16 / 9);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!sideBySide) {
|
|
||||||
videoHeight = Math.min(videoHeight, desiredHeight);
|
|
||||||
videoWidth = videoHeight * (9 / 16);
|
|
||||||
commentsWidth = videoWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
const panelHeight = Math.min(videoHeight, desiredHeight);
|
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(commentsWidth, maxCommentsWidth))
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
onLayout={handleLayout}
|
onLayout={handleLayout}
|
||||||
style={[
|
style={[
|
||||||
styles.itemContainerBase,
|
styles.itemContainerBase,
|
||||||
sideBySide ? styles.itemContainerRow : styles.itemContainerCompact,
|
styles.itemContainerRow,
|
||||||
{
|
{
|
||||||
height: "90%",
|
height: "90%",
|
||||||
paddingHorizontal: sideBySide ? horizontalPadding : 24,
|
paddingHorizontal: horizontalPadding,
|
||||||
paddingVertical: verticalPadding,
|
paddingVertical: Math.max((layoutHeight - panelHeight) / 2, 24),
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.videoColumn,
|
styles.videoColumn,
|
||||||
sideBySide
|
{ width: videoWidth, marginRight: gapBetweenColumns },
|
||||||
? { width: videoWidth, marginRight: gapBetweenColumns }
|
|
||||||
: { width: "100%" },
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<View
|
|
||||||
style={[
|
|
||||||
styles.videoSurface,
|
|
||||||
{
|
|
||||||
// width: videoWidth,
|
|
||||||
height: panelHeight,
|
|
||||||
},
|
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
|
<View style={[styles.videoSurface, { height: panelHeight }]}>
|
||||||
<View style={styles.videoContainer}>
|
<View style={styles.videoContainer}>
|
||||||
{!!videoUrl ? (
|
{!!videoUrl ? (
|
||||||
<VideoView
|
<VideoView
|
||||||
@@ -730,12 +706,12 @@ const PlaybackItem = ({ item, isActive, userCache, getUserByUid }) => {
|
|||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
||||||
|
{/* Comments always visible side-by-side */}
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.commentsColumn,
|
styles.commentsColumn,
|
||||||
sideBySide
|
{ width: commentsWidth, height: panelHeight },
|
||||||
? { width: safeCommentsWidth, height: panelHeight }
|
|
||||||
: [styles.commentsColumnCompact, { height: panelHeight }],
|
|
||||||
]}
|
]}
|
||||||
>
|
>
|
||||||
<CommentsPanel
|
<CommentsPanel
|
||||||
@@ -771,6 +747,7 @@ const Playbacks = () => {
|
|||||||
batchSize: 6,
|
batchSize: 6,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Web-only layout hint
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (Platform.OS !== "web") return undefined;
|
if (Platform.OS !== "web") return undefined;
|
||||||
setGlobal({ webLayoutMode: isFocused ? "playbacks-wide" : "default" });
|
setGlobal({ webLayoutMode: isFocused ? "playbacks-wide" : "default" });
|
||||||
@@ -804,26 +781,72 @@ const Playbacks = () => {
|
|||||||
}
|
}
|
||||||
}, [focusProjectId, playbacks, loadMore]);
|
}, [focusProjectId, playbacks, loadMore]);
|
||||||
|
|
||||||
|
// === FlatList (one real page per item) ===
|
||||||
|
const listRef = useRef(null);
|
||||||
|
|
||||||
|
// keep active index in sync with scroll
|
||||||
|
const onMomentumScrollEnd = useCallback(
|
||||||
|
(e) => {
|
||||||
|
try {
|
||||||
|
const y = e?.nativeEvent?.contentOffset?.y || 0;
|
||||||
|
const idx = Math.round(y / windowHeight);
|
||||||
|
if (!Number.isNaN(idx))
|
||||||
|
setActiveIndex(
|
||||||
|
Math.max(0, Math.min(idx, (playbacks?.length || 1) - 1))
|
||||||
|
);
|
||||||
|
if (idx >= (playbacks?.length || 0) - 6) loadMore?.();
|
||||||
|
} catch (_e) {}
|
||||||
|
},
|
||||||
|
[windowHeight, playbacks?.length, loadMore]
|
||||||
|
);
|
||||||
|
|
||||||
|
// programmatic jump to focus item
|
||||||
|
useEffect(() => {
|
||||||
|
if (!focusProjectId) return;
|
||||||
|
const idx = playbacks.findIndex((p) => p?.id === focusProjectId);
|
||||||
|
if (idx >= 0) {
|
||||||
|
setActiveIndex(idx);
|
||||||
|
setTimeout(() => {
|
||||||
|
try {
|
||||||
|
listRef.current?.scrollToIndex?.({ index: idx, animated: false });
|
||||||
|
} catch (_e) {}
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
}, [focusProjectId, playbacks]);
|
||||||
|
|
||||||
|
const getItemLayout = useCallback(
|
||||||
|
(_data, index) => ({
|
||||||
|
length: windowHeight,
|
||||||
|
offset: windowHeight * index,
|
||||||
|
index,
|
||||||
|
}),
|
||||||
|
[windowHeight]
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.screen}>
|
<View style={styles.screen}>
|
||||||
<Carousel
|
<FlatList
|
||||||
ref={carouselRef}
|
ref={listRef}
|
||||||
data={playbacks}
|
data={playbacks}
|
||||||
vertical
|
keyExtractor={(item, index) => String(item?.id || index)}
|
||||||
width={windowWidth}
|
|
||||||
height={windowHeight}
|
|
||||||
pagingEnabled
|
|
||||||
windowSize={5}
|
|
||||||
onSnapToItem={onSnap}
|
|
||||||
renderItem={({ item, index }) => (
|
renderItem={({ item, index }) => (
|
||||||
|
<View style={{ width: windowWidth, height: windowHeight }}>
|
||||||
<PlaybackItem
|
<PlaybackItem
|
||||||
key={item?.id || index}
|
|
||||||
item={item}
|
item={item}
|
||||||
userCache={userCache}
|
userCache={userCache}
|
||||||
getUserByUid={getUserByUid}
|
getUserByUid={getUserByUid}
|
||||||
isActive={isFocused && index === activeIndex}
|
isActive={isFocused && index === activeIndex}
|
||||||
/>
|
/>
|
||||||
|
</View>
|
||||||
)}
|
)}
|
||||||
|
pagingEnabled
|
||||||
|
showsVerticalScrollIndicator={false}
|
||||||
|
onMomentumScrollEnd={onMomentumScrollEnd}
|
||||||
|
getItemLayout={getItemLayout}
|
||||||
|
initialNumToRender={3}
|
||||||
|
windowSize={5}
|
||||||
|
removeClippedSubviews
|
||||||
|
scrollEventThrottle={32}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
@@ -831,9 +854,13 @@ const Playbacks = () => {
|
|||||||
|
|
||||||
export default Playbacks;
|
export default Playbacks;
|
||||||
|
|
||||||
|
// === Styles ===
|
||||||
const styles = StyleSheet.create({
|
const styles = StyleSheet.create({
|
||||||
screen: {
|
screen: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
// prevent page scroll bounce and ensure the wheel maps to paging
|
||||||
|
// (RN Web supports these CSS props on View)
|
||||||
|
overscrollBehavior: "none",
|
||||||
},
|
},
|
||||||
itemContainerBase: {
|
itemContainerBase: {
|
||||||
width: "100%",
|
width: "100%",
|
||||||
@@ -845,19 +872,12 @@ const styles = StyleSheet.create({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
itemContainerCompact: {
|
|
||||||
flexDirection: "column",
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "flex-start",
|
|
||||||
},
|
|
||||||
videoColumn: {
|
videoColumn: {
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
},
|
},
|
||||||
videoSurface: {
|
videoSurface: {
|
||||||
alignSelf: "center",
|
alignSelf: "center",
|
||||||
// width: 100,
|
|
||||||
// maxWidth: 400,
|
|
||||||
aspectRatio: 9 / 16,
|
aspectRatio: 9 / 16,
|
||||||
borderRadius: 32,
|
borderRadius: 32,
|
||||||
overflow: "hidden",
|
overflow: "hidden",
|
||||||
@@ -944,11 +964,6 @@ const styles = StyleSheet.create({
|
|||||||
commentsColumn: {
|
commentsColumn: {
|
||||||
alignSelf: "stretch",
|
alignSelf: "stretch",
|
||||||
},
|
},
|
||||||
commentsColumnCompact: {
|
|
||||||
width: "100%",
|
|
||||||
maxWidth: 640,
|
|
||||||
marginTop: 32,
|
|
||||||
},
|
|
||||||
commentsWrapper: {
|
commentsWrapper: {
|
||||||
flex: 1,
|
flex: 1,
|
||||||
borderRadius: 28,
|
borderRadius: 28,
|
||||||
|
|||||||
Reference in New Issue
Block a user