scroll indactor playbacks web
This commit is contained in:
@@ -1,6 +1,19 @@
|
||||
import { useIsFocused, useRoute } from "@react-navigation/native";
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { FlatList, StyleSheet, View, useWindowDimensions } from "react-native";
|
||||
import React, {
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import {
|
||||
FlatList,
|
||||
Image,
|
||||
StyleSheet,
|
||||
View,
|
||||
useWindowDimensions,
|
||||
} from "react-native";
|
||||
import { icons } from "../../assets";
|
||||
import { projectsRef } from "../../config/firebase";
|
||||
import useDataFromRef from "../../hooks/useDataFromRef";
|
||||
import { useUser } from "../../providers/UserDataProvider";
|
||||
@@ -17,7 +30,12 @@ const Playbacks = () => {
|
||||
const userCache = useRef(new Map());
|
||||
const { getUserByUid } = useUser() || {};
|
||||
const isFocused = useIsFocused();
|
||||
const { data: playbacks = [], loadMore } = useDataFromRef({
|
||||
const {
|
||||
data: playbacks = [],
|
||||
loadMore,
|
||||
hasMore,
|
||||
loading,
|
||||
} = useDataFromRef({
|
||||
ref: projectsRef.where("playbackUrl", "!=", null),
|
||||
simpleRef: false,
|
||||
listener: false,
|
||||
@@ -213,6 +231,47 @@ const Playbacks = () => {
|
||||
[windowHeight]
|
||||
);
|
||||
|
||||
const total = playbacks.length;
|
||||
const indicatorItems = useMemo(() => {
|
||||
if (total <= 0) return [];
|
||||
const maxVisible = 7;
|
||||
let start = 0;
|
||||
let end = total - 1;
|
||||
if (total > maxVisible) {
|
||||
const half = Math.floor(maxVisible / 2);
|
||||
start = activeIndex - half;
|
||||
end = start + maxVisible - 1;
|
||||
if (start < 0) {
|
||||
end += -start;
|
||||
start = 0;
|
||||
}
|
||||
if (end >= total) {
|
||||
const overshoot = end - (total - 1);
|
||||
start = Math.max(0, start - overshoot);
|
||||
end = total - 1;
|
||||
}
|
||||
}
|
||||
const items = [];
|
||||
for (let i = start; i <= end; i += 1) {
|
||||
items.push({
|
||||
key: `indicator-${i}`,
|
||||
isActive: i === activeIndex,
|
||||
isPast: i < activeIndex,
|
||||
});
|
||||
}
|
||||
return items;
|
||||
}, [total, activeIndex]);
|
||||
|
||||
const canScrollUp = total > 0 && activeIndex > 0;
|
||||
const atLastLoaded = total > 0 && activeIndex >= total - 1;
|
||||
const canScrollDown = total > 0 && (!atLastLoaded || hasMore);
|
||||
const showIndicators = total > 0;
|
||||
const indicatorLabel = useMemo(() => {
|
||||
if (total <= 0) return null;
|
||||
if (hasMore || loading) return `${activeIndex + 1}+`;
|
||||
return `${activeIndex + 1}/${total}`;
|
||||
}, [total, activeIndex, hasMore, loading]);
|
||||
|
||||
return (
|
||||
<View style={styles.screen}>
|
||||
{activeVideoUrl ? (
|
||||
@@ -264,6 +323,50 @@ const Playbacks = () => {
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={16}
|
||||
/>
|
||||
{showIndicators && (
|
||||
<View style={styles.indicatorContainer} pointerEvents="none">
|
||||
<Image
|
||||
source={icons.chevronDown}
|
||||
resizeMode="contain"
|
||||
style={[
|
||||
styles.indicatorArrow,
|
||||
styles.indicatorArrowUp,
|
||||
!canScrollUp && styles.indicatorArrowDisabled,
|
||||
]}
|
||||
/>
|
||||
<View style={styles.indicatorDotsWrapper}>
|
||||
{indicatorItems.map((item, index) => (
|
||||
<View
|
||||
key={item.key}
|
||||
style={[
|
||||
styles.indicatorDot,
|
||||
item.isActive && styles.indicatorDotActive,
|
||||
item.isPast && styles.indicatorDotPast,
|
||||
index < indicatorItems.length - 1
|
||||
? styles.indicatorDotSpacing
|
||||
: null,
|
||||
]}
|
||||
/>
|
||||
))}
|
||||
{canScrollDown && hasMore && (
|
||||
<View
|
||||
style={[styles.indicatorMoreDot, styles.indicatorDotSpacing]}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
{/* {indicatorLabel ? (
|
||||
<Text style={styles.indicatorLabel}>{indicatorLabel}</Text>
|
||||
) : null} */}
|
||||
<Image
|
||||
source={icons.chevronDown}
|
||||
resizeMode="contain"
|
||||
style={[
|
||||
styles.indicatorArrow,
|
||||
!canScrollDown && styles.indicatorArrowDisabled,
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
// </Page>
|
||||
);
|
||||
@@ -319,4 +422,57 @@ const styles = StyleSheet.create({
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
opacity: 0.9,
|
||||
},
|
||||
indicatorContainer: {
|
||||
position: "absolute",
|
||||
left: 20,
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
gap: 16,
|
||||
},
|
||||
indicatorArrow: {
|
||||
width: 20,
|
||||
height: 20,
|
||||
tintColor: Palette.white,
|
||||
opacity: 0.8,
|
||||
},
|
||||
indicatorArrowUp: {
|
||||
transform: [{ rotate: "180deg" }],
|
||||
},
|
||||
indicatorArrowDisabled: {
|
||||
opacity: 0.25,
|
||||
},
|
||||
indicatorDotsWrapper: {
|
||||
alignItems: "center",
|
||||
},
|
||||
indicatorDot: {
|
||||
width: 6,
|
||||
height: 12,
|
||||
borderRadius: 3,
|
||||
backgroundColor: "rgba(255,255,255,0.3)",
|
||||
},
|
||||
indicatorDotPast: {
|
||||
backgroundColor: "rgba(255,255,255,0.55)",
|
||||
},
|
||||
indicatorDotActive: {
|
||||
backgroundColor: Palette.white,
|
||||
height: 20,
|
||||
},
|
||||
indicatorDotSpacing: {
|
||||
marginVertical: 5,
|
||||
},
|
||||
indicatorMoreDot: {
|
||||
width: 4,
|
||||
height: 4,
|
||||
borderRadius: 2,
|
||||
backgroundColor: Palette.white,
|
||||
opacity: 0.7,
|
||||
},
|
||||
indicatorLabel: {
|
||||
color: Palette.white,
|
||||
fontSize: 12,
|
||||
fontFamily: FONT_FAMILY.InterMedium,
|
||||
textAlign: "center",
|
||||
},
|
||||
});
|
||||
|
||||
@@ -43,7 +43,7 @@ const uploadSourceRecording = async ({ uri, uid, projectId }) => {
|
||||
|
||||
const extension = guessExtension(uri);
|
||||
const sourcePath = `users/${uid}/projects/${projectId}/recordings/source-${Date.now()}.${extension}`;
|
||||
|
||||
console.log("source path : ", sourcePath);
|
||||
console.log("[DownloadSongs] uploadSourceRecording source path", {
|
||||
extension,
|
||||
sourcePath,
|
||||
|
||||
Reference in New Issue
Block a user