template_0205
This commit is contained in:
217
RN_TEMPLATE/app/screens/AboutScreen.tsx
Normal file
217
RN_TEMPLATE/app/screens/AboutScreen.tsx
Normal file
@@ -0,0 +1,217 @@
|
||||
import { FC, useCallback, useState } from "react"
|
||||
import { Image, ImageStyle, TextStyle, View, ViewStyle } from "react-native"
|
||||
import * as Application from "expo-application"
|
||||
import * as WebBrowser from "expo-web-browser"
|
||||
|
||||
import { Icon } from "@/components/Icon"
|
||||
import { ListItem } from "@/components/ListItem"
|
||||
import { Modal } from "@/components/Modal"
|
||||
import { Screen } from "@/components/Screen"
|
||||
import { Text } from "@/components/Text"
|
||||
import { translate } from "@/i18n/translate"
|
||||
import { AppStackScreenProps } from "@/navigators/navigationTypes"
|
||||
import { useAppTheme } from "@/theme/context"
|
||||
import { $styles } from "@/theme/styles"
|
||||
import type { ThemedStyle } from "@/theme/types"
|
||||
import { s } from "@/utils/responsive"
|
||||
import { useHeader } from "@/utils/useHeader"
|
||||
|
||||
const appLogo = require("@assets/images/logo.png")
|
||||
|
||||
const usingHermes = typeof HermesInternal === "object" && HermesInternal !== null
|
||||
|
||||
export const AboutScreen: FC<AppStackScreenProps<"About">> = function AboutScreen({ navigation }) {
|
||||
const { themed, theme } = useAppTheme()
|
||||
const [showVersionDetails, setShowVersionDetails] = useState(false)
|
||||
|
||||
// @ts-expect-error
|
||||
const usingFabric = global.nativeFabricUIManager != null
|
||||
|
||||
const appVersion = Application.nativeApplicationVersion || "1.0.0"
|
||||
|
||||
const openPrivacyPolicy = useCallback(async () => {
|
||||
// TODO: Replace with actual privacy policy URL
|
||||
await WebBrowser.openBrowserAsync("https://example.com/privacy")
|
||||
}, [])
|
||||
|
||||
const openTermsOfService = useCallback(async () => {
|
||||
// TODO: Replace with actual terms of service URL
|
||||
await WebBrowser.openBrowserAsync("https://example.com/terms")
|
||||
}, [])
|
||||
|
||||
useHeader(
|
||||
{
|
||||
titleTx: "aboutScreen:title",
|
||||
leftIcon: "back",
|
||||
onLeftPress: () => navigation.goBack(),
|
||||
},
|
||||
[],
|
||||
)
|
||||
|
||||
return (
|
||||
<Screen preset="fixed" contentContainerStyle={$styles.flex1}>
|
||||
{/* Logo Section */}
|
||||
<View style={themed($logoSection)}>
|
||||
<Image style={themed($logo)} source={appLogo} resizeMode="contain" />
|
||||
<Text size="lg" weight="medium" style={themed($appName)}>
|
||||
{Application.applicationName}
|
||||
</Text>
|
||||
<Text size="sm" style={themed($versionText)}>
|
||||
v{appVersion}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{/* List Items Section */}
|
||||
<View style={themed($listContainer)}>
|
||||
<ListItem
|
||||
tx="aboutScreen:privacyPolicy"
|
||||
leftIcon="shield"
|
||||
leftIconColor={theme.colors.tint}
|
||||
rightIcon="caretRight"
|
||||
onPress={openPrivacyPolicy}
|
||||
/>
|
||||
|
||||
<ListItem
|
||||
tx="aboutScreen:termsOfService"
|
||||
leftIcon="fileText"
|
||||
leftIconColor={theme.colors.tint}
|
||||
rightIcon="caretRight"
|
||||
onPress={openTermsOfService}
|
||||
/>
|
||||
|
||||
<ListItem
|
||||
tx="aboutScreen:version"
|
||||
leftIcon="info"
|
||||
leftIconColor={theme.colors.tint}
|
||||
RightComponent={
|
||||
<View style={$rightContainer}>
|
||||
<Text size="xs" style={themed($versionBadge)}>
|
||||
v{appVersion}
|
||||
</Text>
|
||||
<Icon icon="caretRight" size={24} color={theme.colors.textDim} />
|
||||
</View>
|
||||
}
|
||||
onPress={() => setShowVersionDetails(true)}
|
||||
/>
|
||||
</View>
|
||||
|
||||
{/* Version Details Modal */}
|
||||
<Modal
|
||||
visible={showVersionDetails}
|
||||
onClose={() => setShowVersionDetails(false)}
|
||||
titleTx="aboutScreen:appInfo"
|
||||
confirmButtonProps={{
|
||||
tx: "common:ok",
|
||||
onPress: () => setShowVersionDetails(false),
|
||||
}}
|
||||
>
|
||||
<View style={themed($infoRow)}>
|
||||
<Text size="sm" style={themed($infoLabel)}>
|
||||
{translate("aboutScreen:appName")}
|
||||
</Text>
|
||||
<Text size="sm">{Application.applicationName}</Text>
|
||||
</View>
|
||||
|
||||
<View style={themed($infoRow)}>
|
||||
<Text size="sm" style={themed($infoLabel)}>
|
||||
{translate("aboutScreen:version")}
|
||||
</Text>
|
||||
<Text size="sm">{Application.nativeApplicationVersion}</Text>
|
||||
</View>
|
||||
|
||||
<View style={themed($infoRow)}>
|
||||
<Text size="sm" style={themed($infoLabel)}>
|
||||
{translate("aboutScreen:buildVersion")}
|
||||
</Text>
|
||||
<Text size="sm">{Application.nativeBuildVersion}</Text>
|
||||
</View>
|
||||
|
||||
<View style={themed($infoRow)}>
|
||||
<Text size="sm" style={themed($infoLabel)}>
|
||||
{translate("aboutScreen:appId")}
|
||||
</Text>
|
||||
<Text size="sm" style={themed($infoValue)}>
|
||||
{Application.applicationId}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={themed($infoRow)}>
|
||||
<Text size="sm" style={themed($infoLabel)}>
|
||||
Hermes
|
||||
</Text>
|
||||
<Text size="sm">{usingHermes ? "Enabled" : "Disabled"}</Text>
|
||||
</View>
|
||||
|
||||
<View style={themed($infoRowLast)}>
|
||||
<Text size="sm" style={themed($infoLabel)}>
|
||||
Fabric
|
||||
</Text>
|
||||
<Text size="sm">{usingFabric ? "Enabled" : "Disabled"}</Text>
|
||||
</View>
|
||||
</Modal>
|
||||
</Screen>
|
||||
)
|
||||
}
|
||||
|
||||
const $logoSection: ThemedStyle<ViewStyle> = ({ spacing }) => ({
|
||||
alignItems: "center",
|
||||
paddingHorizontal: spacing.lg,
|
||||
paddingTop: spacing.xxxl,
|
||||
paddingBottom: spacing.xl,
|
||||
})
|
||||
|
||||
const $listContainer: ThemedStyle<ViewStyle> = ({ spacing }) => ({
|
||||
flex: 1,
|
||||
paddingHorizontal: spacing.lg,
|
||||
})
|
||||
|
||||
const $logo: ThemedStyle<ImageStyle> = ({ spacing }) => ({
|
||||
height: s(100),
|
||||
width: s(100),
|
||||
marginBottom: spacing.md,
|
||||
})
|
||||
|
||||
const $appName: ThemedStyle<TextStyle> = ({ spacing }) => ({
|
||||
marginBottom: spacing.xs,
|
||||
})
|
||||
|
||||
const $versionText: ThemedStyle<TextStyle> = ({ colors }) => ({
|
||||
color: colors.textDim,
|
||||
})
|
||||
|
||||
const $rightContainer: ViewStyle = {
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
}
|
||||
|
||||
const $versionBadge: ThemedStyle<TextStyle> = ({ colors, spacing }) => ({
|
||||
color: colors.textDim,
|
||||
marginRight: spacing.xs,
|
||||
})
|
||||
|
||||
const $infoRow: ThemedStyle<ViewStyle> = ({ spacing }) => ({
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
paddingVertical: spacing.sm,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: "rgba(0,0,0,0.05)",
|
||||
})
|
||||
|
||||
const $infoRowLast: ThemedStyle<ViewStyle> = ({ spacing }) => ({
|
||||
flexDirection: "row",
|
||||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
paddingVertical: spacing.sm,
|
||||
})
|
||||
|
||||
const $infoLabel: ThemedStyle<TextStyle> = ({ colors }) => ({
|
||||
color: colors.textDim,
|
||||
flexShrink: 0,
|
||||
marginRight: s(16),
|
||||
})
|
||||
|
||||
const $infoValue: ThemedStyle<TextStyle> = () => ({
|
||||
flex: 1,
|
||||
textAlign: "right",
|
||||
})
|
||||
Reference in New Issue
Block a user