feat: fixes and formatter

This commit is contained in:
2026-01-12 16:01:32 +01:00
parent 85c6084351
commit 11e632acff
353 changed files with 23315 additions and 27361 deletions
+126 -141
View File
@@ -1,25 +1,25 @@
/* eslint-disable react/display-name */
import { Image, Pressable, Text, View, StyleSheet } from "react-native";
import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
import { SafeAreaView } from "react-native-safe-area-context";
import React from "reactn";
import { responsiveHeight } from "../actions/responsiveSizes.js";
import { subBadges } from "../assets";
import BaseHeader from "../components/BaseHeader";
import CreditAmount from "../components/CreditAmount";
import ConnectBtn from "../components/ConnectBtn.js";
import GradientButton from "../components/GradientButton";
import CoinPackModal from "../components/modal/CoinPackModal";
import NavigateHeader from "../components/NavigateHeader";
import ShareBtn from "../components/ShareBtn/ShareBtn";
import { isWeb } from "../hooks/useLayoutType.js";
import { useUserData } from "../providers/UserDataProvider";
import { Routes } from "../navigation";
import { navigate } from "../navigation/NavigationService";
import { gutters, Palette } from "../styles";
import { FONT_FAMILY } from "../styles/Fonts";
import { subscribeCoinPackModal } from "../utils/coinPackModal";
import { BlurView } from "expo-blur";
import { Image, Pressable, Text, View, StyleSheet } from 'react-native'
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'
import { SafeAreaView } from 'react-native-safe-area-context'
import React from 'reactn'
import { responsiveHeight } from '../actions/responsiveSizes.js'
import { subBadges } from '../assets'
import BaseHeader from '../components/BaseHeader'
import CreditAmount from '../components/CreditAmount'
import ConnectBtn from '../components/ConnectBtn.js'
import GradientButton from '../components/GradientButton'
import CoinPackModal from '../components/modal/CoinPackModal'
import NavigateHeader from '../components/NavigateHeader'
import ShareBtn from '../components/ShareBtn/ShareBtn'
import { isWeb } from '../hooks/useLayoutType.js'
import { useUserData } from '../providers/UserDataProvider'
import { Routes } from '../navigation'
import { navigate } from '../navigation/NavigationService'
import { gutters, Palette } from '../styles'
import { FONT_FAMILY } from '../styles/Fonts'
import { subscribeCoinPackModal } from '../utils/coinPackModal'
import { BlurView } from 'expo-blur'
export default ({
children,
@@ -27,11 +27,11 @@ export default ({
topStickyContent = null,
bottomStickyContent = null,
title = "",
title = '',
rightComponent = null,
containerType = "SAFE_AREA_VIEW",
headerType = "BASE",
containerType = 'SAFE_AREA_VIEW',
headerType = 'BASE',
containerStyle = {},
headerStyle = {},
@@ -48,159 +48,149 @@ export default ({
shareBtn = false,
connect = false,
blurIntensity = 0,
backgroundColor = "#000",
backgroundColor = '#000',
showCoin = true,
showReturnHome = false,
onReturnHome = null,
}) => {
const { currentUID = null, currentUserData = null } = useUserData?.() || {};
const { currentUID = null, currentUserData = null } = useUserData?.() || {}
const coinBalance = React.useMemo(() => {
const value = currentUserData?.coins;
if (typeof value === "number" && Number.isFinite(value)) {
return value;
const value = currentUserData?.coins
if (typeof value === 'number' && Number.isFinite(value)) {
return value
}
if (typeof value === "string") {
const parsed = Number(value);
if (typeof value === 'string') {
const parsed = Number(value)
if (Number.isFinite(parsed)) {
return parsed;
return parsed
}
}
return 0;
}, [currentUserData?.coins]);
return 0
}, [currentUserData?.coins])
const showCoinBadge = isWeb && !!currentUID && showCoin;
const showReturnHomeButton = isWeb && showReturnHome;
const coinBadgeContainerVisible = showCoinBadge || showReturnHomeButton;
const [isCoinModalVisible, setCoinModalVisible] = React.useState(false);
const showCoinBadge = isWeb && !!currentUID && showCoin
const showReturnHomeButton = isWeb && showReturnHome
const coinBadgeContainerVisible = showCoinBadge || showReturnHomeButton
const [isCoinModalVisible, setCoinModalVisible] = React.useState(false)
const subscriptionBadgeSource = React.useMemo(() => {
const allowedLevels = new Set(["starter", "pro", "premium"]);
const allowedLevels = new Set(['starter', 'pro', 'premium'])
const pickLevel = (value) => {
if (typeof value !== "string") {
return null;
if (typeof value !== 'string') {
return null
}
const normalized = value.trim().toLowerCase();
return normalized && allowedLevels.has(normalized) ? normalized : null;
};
const normalized = value.trim().toLowerCase()
return normalized && allowedLevels.has(normalized) ? normalized : null
}
const nestedSubscription =
currentUserData?.subscription &&
typeof currentUserData.subscription === "object"
currentUserData?.subscription && typeof currentUserData.subscription === 'object'
? currentUserData.subscription
: null;
: null
const stripeMetadata =
currentUserData?.stripeSubscription &&
typeof currentUserData.stripeSubscription === "object" &&
typeof currentUserData.stripeSubscription.metadata === "object"
typeof currentUserData.stripeSubscription === 'object' &&
typeof currentUserData.stripeSubscription.metadata === 'object'
? currentUserData.stripeSubscription.metadata
: null;
: null
const directCandidates = [
pickLevel(currentUserData?.premiumLevel),
pickLevel(currentUserData?.subscriptionLevel),
pickLevel(currentUserData?.subscriptionPlan),
pickLevel(currentUserData?.subscriptionPack),
];
]
const nestedCandidates = nestedSubscription
? ["level", "plan", "pack", "type"].map((key) =>
pickLevel(nestedSubscription?.[key])
)
: [];
? ['level', 'plan', 'pack', 'type'].map((key) => pickLevel(nestedSubscription?.[key]))
: []
const metadataCandidates = stripeMetadata
? [
"level",
"subscriptionLevel",
"subscription_level",
"pack",
"Pack",
].map((key) => pickLevel(stripeMetadata?.[key]))
: [];
? ['level', 'subscriptionLevel', 'subscription_level', 'pack', 'Pack'].map((key) =>
pickLevel(stripeMetadata?.[key])
)
: []
const resolvedLevel = [
...directCandidates,
...nestedCandidates,
...metadataCandidates,
].find(Boolean);
const resolvedLevel = [...directCandidates, ...nestedCandidates, ...metadataCandidates].find(
Boolean
)
return resolvedLevel ? subBadges[resolvedLevel] || null : null;
}, [currentUserData]);
return resolvedLevel ? subBadges[resolvedLevel] || null : null
}, [currentUserData])
const handleCoinPress = React.useCallback(() => {
if (!showCoinBadge) return;
setCoinModalVisible(true);
}, [showCoinBadge]);
if (!showCoinBadge) return
setCoinModalVisible(true)
}, [showCoinBadge])
const handleCloseCoinModal = React.useCallback(() => {
setCoinModalVisible(false);
}, []);
setCoinModalVisible(false)
}, [])
const handleReturnHomePress = React.useCallback(() => {
if (typeof onReturnHome === "function") {
onReturnHome();
return;
if (typeof onReturnHome === 'function') {
onReturnHome()
return
}
navigate(Routes.LandingPage);
}, [onReturnHome]);
navigate(Routes.LandingPage)
}, [onReturnHome])
React.useEffect(() => {
if (!showCoinBadge && isCoinModalVisible) {
setCoinModalVisible(false);
setCoinModalVisible(false)
}
}, [showCoinBadge, isCoinModalVisible]);
}, [showCoinBadge, isCoinModalVisible])
React.useEffect(() => {
const unsubscribe = subscribeCoinPackModal(() => {
if (!showCoinBadge) {
return;
return
}
setCoinModalVisible(true);
});
return unsubscribe;
}, [showCoinBadge]);
setCoinModalVisible(true)
})
return unsubscribe
}, [showCoinBadge])
const PageContainer =
containerType === "SAFE_AREA_VIEW" ? SafeAreaView : View;
const PageContainer = containerType === 'SAFE_AREA_VIEW' ? SafeAreaView : View
const ContentContainer = scrollEnabled ? KeyboardAwareScrollView : View;
const ContentContainer = scrollEnabled ? KeyboardAwareScrollView : View
const computedWidth = width ?? (isWeb ? "60%" : "100%");
const computedWidth = width ?? (isWeb ? '60%' : '100%')
const shareButtonElement = (() => {
if (!shareBtn) return null;
if (typeof React?.isValidElement === "function") {
if (!shareBtn) return null
if (typeof React?.isValidElement === 'function') {
if (React.isValidElement(shareBtn)) {
return shareBtn;
return shareBtn
}
}
if (typeof shareBtn === "object" && !Array.isArray(shareBtn)) {
return <ShareBtn {...shareBtn} />;
if (typeof shareBtn === 'object' && !Array.isArray(shareBtn)) {
return <ShareBtn {...shareBtn} />
}
return <ShareBtn />;
})();
return <ShareBtn />
})()
const resolvedContainerStyle = React.useMemo(
() => StyleSheet.flatten(containerStyle) || {},
[containerStyle]
);
)
const resolvedHeaderStyle = React.useMemo(
() => StyleSheet.flatten(headerStyle) || {},
[headerStyle]
);
)
const resolvedContentContainerStyle = React.useMemo(
() => StyleSheet.flatten(contentContainerStyle) || {},
[contentContainerStyle]
);
)
return (
<View
style={{
flex: 1,
minHeight: isWeb ? "100svh" : "100%",
position: "relative",
minHeight: isWeb ? '100svh' : '100%',
position: 'relative',
backgroundColor: backgroundColor,
}}
>
@@ -210,14 +200,12 @@ export default ({
resizeMode="cover"
blurIntensity={blurIntensity}
style={{
position: "absolute",
position: 'absolute',
top: 0,
left: 0,
width: "100%",
height: "100%",
...(isWeb && blurIntensity
? { filter: `blur(${blurIntensity}px)` }
: {}),
width: '100%',
height: '100%',
...(isWeb && blurIntensity ? { filter: `blur(${blurIntensity}px)` } : {}),
}}
/>
) : null}
@@ -234,7 +222,7 @@ export default ({
value={coinBalance}
iconSize={22}
textStyle={{
color: "#ffffff",
color: '#ffffff',
fontFamily: FONT_FAMILY.InterSemiBold,
fontSize: 14,
}}
@@ -248,7 +236,7 @@ export default ({
>
<Image
source={subscriptionBadgeSource}
style={{ height: 50, width: 50, resizeMode: "contain" }}
style={{ height: 50, width: 50, resizeMode: 'contain' }}
/>
</Pressable>
) : null}
@@ -268,10 +256,10 @@ export default ({
paddingHorizontal: 10,
paddingVertical: 8,
borderRadius: 12,
overflow: "hidden",
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
overflow: 'hidden',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text
@@ -290,21 +278,21 @@ export default ({
</View>
) : null}
<PageContainer
{...(containerType === "SAFE_AREA_VIEW" ? { edges: ["top"] } : {})}
{...(containerType === 'SAFE_AREA_VIEW' ? { edges: ['top'] } : {})}
style={{
height: "100%",
height: '100%',
paddingTop: isWeb ? gutters / 2 : 0,
padding: gutters,
paddingBottom: 0,
...(isWeb ? { maxHeight: "100svh" } : {}),
...(isWeb ? { maxHeight: '100svh' } : {}),
width: computedWidth,
maxWidth: maxWidth ? maxWidth : null,
alignSelf: isWeb ? "center" : "auto",
alignSelf: isWeb ? 'center' : 'auto',
...resolvedContainerStyle,
}}
>
{headerType !== "NONE" ? (
headerType === "BASE" ? (
{headerType !== 'NONE' ? (
headerType === 'BASE' ? (
<BaseHeader containerStyle={{ ...resolvedHeaderStyle }} />
) : (
<NavigateHeader
@@ -327,7 +315,7 @@ export default ({
scrollEventThrottle: 80,
showsVerticalScrollIndicator: false,
contentContainerStyle: { paddingBottom: responsiveHeight(55) },
keyboardDismissMode: "on-drag",
keyboardDismissMode: 'on-drag',
}
: {})}
>
@@ -339,11 +327,11 @@ export default ({
{(shareButtonElement || connect) && isWeb && (
<View
style={{
position: "absolute",
position: 'absolute',
top: 20,
right: 20,
flexDirection: "row",
alignItems: "center",
flexDirection: 'row',
alignItems: 'center',
gap: 12, // ou marginLeft sur chaque bouton si gap non supporté
}}
>
@@ -352,37 +340,34 @@ export default ({
</View>
)}
<CoinPackModal
visible={isCoinModalVisible}
onClose={handleCloseCoinModal}
/>
<CoinPackModal visible={isCoinModalVisible} onClose={handleCloseCoinModal} />
</View>
);
};
)
}
const styles = StyleSheet.create({
coinBadgeContainer: {
position: "absolute",
position: 'absolute',
top: gutters,
left: gutters,
alignItems: "flex-start",
alignItems: 'flex-start',
gap: 10,
zIndex: 20,
},
coinRow: {
flexDirection: "row",
alignItems: "center",
flexDirection: 'row',
alignItems: 'center',
gap: 6,
},
coinButton: {
paddingHorizontal: 14,
paddingVertical: 8,
borderRadius: 20,
backgroundColor: "rgba(12, 14, 18, 0.72)",
backgroundColor: 'rgba(12, 14, 18, 0.72)',
borderWidth: 1,
borderColor: "rgba(255, 255, 255, 0.1)",
flexDirection: "row",
alignItems: "center",
borderColor: 'rgba(255, 255, 255, 0.1)',
flexDirection: 'row',
alignItems: 'center',
gap: 8,
},
subscriptionBadge: {
@@ -390,6 +375,6 @@ const styles = StyleSheet.create({
},
returnHomeButton: {
width: 220,
alignSelf: "flex-start",
alignSelf: 'flex-start',
},
});
})