@umituz/react-native-settings 4.23.80 → 4.23.82
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -7
- package/src/domains/about/presentation/screens/AboutScreen.tsx +49 -3
- package/src/domains/about/presentation/screens/AboutScreenContent.tsx +2 -4
- package/src/domains/localization/index.ts +2 -2
- package/src/domains/localization/presentation/providers/{LocalizationProvider.tsx → LocalizationManager.tsx} +1 -1
- package/src/domains/localization/presentation/screens/LanguageSelectionScreen.tsx +1 -1
- package/src/presentation/screens/SettingsScreen.tsx +38 -57
- package/src/presentation/screens/components/SettingsHeader.tsx +28 -39
- package/src/presentation/screens/hooks/useSettingsScreen.ts +64 -0
- package/src/utils/appUtils.ts +36 -0
- package/src/utils/index.ts +1 -0
- package/src/domains/about/presentation/screens/AboutScreenContainer.tsx +0 -109
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-settings",
|
|
3
|
-
"version": "4.23.
|
|
3
|
+
"version": "4.23.82",
|
|
4
4
|
"description": "Complete settings hub for React Native apps - consolidated package with settings, localization, about, legal, appearance, feedback, FAQs, rating, and gamification",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -41,14 +41,12 @@
|
|
|
41
41
|
"firebase": "^12.7.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
|
-
"expo": ">=54.0.0",
|
|
45
44
|
"@expo/vector-icons": ">=14.0.0",
|
|
46
|
-
"@react-native-async-storage/async-storage": ">=2.0.0",
|
|
47
|
-
"@react-native-community/datetimepicker": ">=8.0.0",
|
|
48
45
|
"@react-navigation/native": ">=6.0.0",
|
|
49
46
|
"@react-navigation/stack": ">=6.0.0",
|
|
50
47
|
"@tanstack/react-query": ">=5.0.0",
|
|
51
48
|
"@umituz/react-native-design-system": "*",
|
|
49
|
+
"expo": ">=54.0.0",
|
|
52
50
|
"expo-device": ">=6.0.0",
|
|
53
51
|
"expo-haptics": ">=15.0.0",
|
|
54
52
|
"expo-localization": ">=16.0.0",
|
|
@@ -65,7 +63,7 @@
|
|
|
65
63
|
"@expo/vector-icons": "^15.0.0",
|
|
66
64
|
"@gorhom/bottom-sheet": "^5.2.8",
|
|
67
65
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
68
|
-
"@react-native-community/datetimepicker": "^8.
|
|
66
|
+
"@react-native-community/datetimepicker": "^8.6.0",
|
|
69
67
|
"@react-native-community/slider": "^5.1.1",
|
|
70
68
|
"@react-navigation/bottom-tabs": "^7.9.0",
|
|
71
69
|
"@react-navigation/native": "^7.1.26",
|
|
@@ -77,7 +75,7 @@
|
|
|
77
75
|
"@typescript-eslint/eslint-plugin": "^7.18.0",
|
|
78
76
|
"@typescript-eslint/parser": "^7.18.0",
|
|
79
77
|
"@umituz/react-native-auth": "^3.6.49",
|
|
80
|
-
"@umituz/react-native-design-system": "
|
|
78
|
+
"@umituz/react-native-design-system": "*",
|
|
81
79
|
"@umituz/react-native-firebase": "^1.13.102",
|
|
82
80
|
"@umituz/react-native-sentry": "*",
|
|
83
81
|
"eslint": "^8.57.0",
|
|
@@ -115,7 +113,6 @@
|
|
|
115
113
|
"react-native-reanimated": "^4.2.1",
|
|
116
114
|
"react-native-safe-area-context": "^5.6.2",
|
|
117
115
|
"react-native-svg": "^15.15.1",
|
|
118
|
-
"rn-emoji-keyboard": "^1.7.0",
|
|
119
116
|
"typescript": "^5.3.0",
|
|
120
117
|
"zustand": "^5.0.9"
|
|
121
118
|
},
|
|
@@ -4,8 +4,10 @@
|
|
|
4
4
|
* Fully configurable and generic
|
|
5
5
|
* Optimized for performance and memory safety
|
|
6
6
|
*/
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
7
|
+
import { ScreenLayout, NavigationHeader, useAppDesignTokens, useAppNavigation, AtomicText, AtomicSpinner } from '@umituz/react-native-design-system';
|
|
8
|
+
import { useLocalization } from '../../../localization';
|
|
9
|
+
import { useAboutInfo } from '../hooks/useAboutInfo';
|
|
10
|
+
import { AboutScreenContent } from './AboutScreenContent';
|
|
9
11
|
|
|
10
12
|
export interface AboutScreenProps {
|
|
11
13
|
/** Configuration for the about screen */
|
|
@@ -29,5 +31,49 @@ export interface AboutScreenProps {
|
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export const AboutScreen: React.FC<AboutScreenProps> = (props) => {
|
|
32
|
-
|
|
34
|
+
const { config, testID = 'about-screen' } = props;
|
|
35
|
+
const tokens = useAppDesignTokens();
|
|
36
|
+
const navigation = useAppNavigation();
|
|
37
|
+
const { t } = useLocalization();
|
|
38
|
+
|
|
39
|
+
const { appInfo, loading, error } = useAboutInfo({
|
|
40
|
+
autoInit: true,
|
|
41
|
+
initialConfig: config,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const header = (
|
|
45
|
+
<NavigationHeader
|
|
46
|
+
title={t("settings.about.title")}
|
|
47
|
+
onBackPress={() => navigation.goBack()}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
if (loading) {
|
|
52
|
+
return (
|
|
53
|
+
<ScreenLayout header={header} testID={testID}>
|
|
54
|
+
<AtomicSpinner fullContainer size="lg" />
|
|
55
|
+
</ScreenLayout>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (error || !appInfo) {
|
|
60
|
+
const errorText = error ? `${config.texts?.errorPrefix || 'Error:'} ${error}` : (config.texts?.noInfo || 'No info available');
|
|
61
|
+
return (
|
|
62
|
+
<ScreenLayout header={header} testID={testID}>
|
|
63
|
+
<AtomicText type="bodyMedium" color="error" style={{ textAlign: 'center', marginTop: 20 }}>
|
|
64
|
+
{errorText}
|
|
65
|
+
</AtomicText>
|
|
66
|
+
</ScreenLayout>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<ScreenLayout header={header} testID={testID}>
|
|
72
|
+
<AboutScreenContent
|
|
73
|
+
{...props}
|
|
74
|
+
appInfo={appInfo}
|
|
75
|
+
_tokens={tokens}
|
|
76
|
+
/>
|
|
77
|
+
</ScreenLayout>
|
|
78
|
+
);
|
|
33
79
|
};
|
|
@@ -7,7 +7,6 @@ import React, { useMemo, useCallback } from 'react';
|
|
|
7
7
|
import {
|
|
8
8
|
View,
|
|
9
9
|
StyleSheet,
|
|
10
|
-
ScrollView,
|
|
11
10
|
} from 'react-native';
|
|
12
11
|
import { AboutHeader } from '../components/AboutHeader';
|
|
13
12
|
import { AboutContent } from '../components/AboutContent';
|
|
@@ -98,15 +97,14 @@ export const AboutScreenContent: React.FC<AboutScreenContentProps> = ({
|
|
|
98
97
|
}, [containerStyle, colors.backgroundPrimary, styles]);
|
|
99
98
|
|
|
100
99
|
return (
|
|
101
|
-
<
|
|
100
|
+
<View
|
|
102
101
|
style={containerStyles}
|
|
103
102
|
testID={testID}
|
|
104
|
-
contentContainerStyle={{ paddingBottom: 32 }}
|
|
105
103
|
>
|
|
106
104
|
{renderHeader()}
|
|
107
105
|
{renderContent()}
|
|
108
106
|
{renderFooter()}
|
|
109
|
-
</
|
|
107
|
+
</View>
|
|
110
108
|
);
|
|
111
109
|
};
|
|
112
110
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
//
|
|
2
|
-
export {
|
|
1
|
+
// Managers
|
|
2
|
+
export { LocalizationManager } from './presentation/providers/LocalizationManager';
|
|
3
3
|
|
|
4
4
|
// Hooks
|
|
5
5
|
export { useLocalization } from './infrastructure/hooks/useLocalization';
|
|
@@ -13,7 +13,7 @@ interface LocalizationProviderProps {
|
|
|
13
13
|
defaultLanguage?: string;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export const
|
|
16
|
+
export const LocalizationManager: React.FC<LocalizationProviderProps> = ({
|
|
17
17
|
children,
|
|
18
18
|
translations,
|
|
19
19
|
defaultLanguage = "en-US",
|
|
@@ -43,7 +43,7 @@ export const LanguageSelectionScreen: React.FC<LanguageSelectionScreenProps> = (
|
|
|
43
43
|
}
|
|
44
44
|
await handleLanguageSelect(code, () => {
|
|
45
45
|
if (__DEV__) {
|
|
46
|
-
console.log('[LanguageSelectionScreen] Navigating back using
|
|
46
|
+
console.log('[LanguageSelectionScreen] Navigating back using standard navigation');
|
|
47
47
|
}
|
|
48
48
|
navigation.goBack();
|
|
49
49
|
});
|
|
@@ -8,10 +8,9 @@ import {
|
|
|
8
8
|
ScreenLayout,
|
|
9
9
|
useAppNavigation,
|
|
10
10
|
} from "@umituz/react-native-design-system";
|
|
11
|
+
import { useSettingsScreen } from "./hooks/useSettingsScreen";
|
|
11
12
|
import { SettingsHeader } from "./components/SettingsHeader";
|
|
12
13
|
import { SettingsContent } from "./components/SettingsContent";
|
|
13
|
-
import { normalizeSettingsConfig } from "./utils/normalizeConfig";
|
|
14
|
-
import { useFeatureDetection } from "./hooks/useFeatureDetection";
|
|
15
14
|
import type { SettingsConfig, CustomSettingsSection } from "./types";
|
|
16
15
|
import type { DevSettingsProps } from "../../domains/dev";
|
|
17
16
|
|
|
@@ -55,63 +54,44 @@ export interface SettingsScreenProps {
|
|
|
55
54
|
showHeader?: boolean;
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
57
|
+
export const SettingsScreen: React.FC<SettingsScreenProps> = (props) => {
|
|
58
|
+
const {
|
|
59
|
+
children,
|
|
60
|
+
config = {},
|
|
61
|
+
showUserProfile,
|
|
62
|
+
userProfile,
|
|
63
|
+
showFooter = true,
|
|
64
|
+
footerText,
|
|
65
|
+
appVersion: providedVersion,
|
|
66
|
+
customSections = [],
|
|
67
|
+
showCloseButton = false,
|
|
68
|
+
showHeader = true,
|
|
69
|
+
onClose,
|
|
70
|
+
featureOptions,
|
|
71
|
+
devSettings,
|
|
72
|
+
gamificationConfig,
|
|
73
|
+
} = props;
|
|
75
74
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
// Determine if user profile should be shown (explicit prop takes priority, then config)
|
|
92
|
-
const shouldShowUserProfile = showUserProfile ?? features.userProfile;
|
|
75
|
+
const {
|
|
76
|
+
normalizedConfig,
|
|
77
|
+
features,
|
|
78
|
+
shouldShowUserProfile,
|
|
79
|
+
appVersion,
|
|
80
|
+
handleClose,
|
|
81
|
+
} = useSettingsScreen({
|
|
82
|
+
config,
|
|
83
|
+
showUserProfile,
|
|
84
|
+
featureOptions,
|
|
85
|
+
appVersion: providedVersion,
|
|
86
|
+
onClose,
|
|
87
|
+
});
|
|
93
88
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
{children ?? (
|
|
98
|
-
<SettingsContent
|
|
99
|
-
normalizedConfig={normalizedConfig}
|
|
100
|
-
features={features}
|
|
101
|
-
showUserProfile={shouldShowUserProfile}
|
|
102
|
-
userProfile={userProfile}
|
|
103
|
-
showFooter={showFooter}
|
|
104
|
-
footerText={footerText}
|
|
105
|
-
appVersion={appVersion}
|
|
106
|
-
customSections={customSections}
|
|
107
|
-
devSettings={devSettings}
|
|
108
|
-
gamificationConfig={gamificationConfig}
|
|
109
|
-
/>
|
|
110
|
-
)}
|
|
111
|
-
</ScreenLayout>;
|
|
112
|
-
}
|
|
89
|
+
const header = showHeader ? (
|
|
90
|
+
<SettingsHeader showCloseButton={showCloseButton} onClose={handleClose} />
|
|
91
|
+
) : undefined;
|
|
113
92
|
|
|
114
|
-
return
|
|
93
|
+
return (
|
|
94
|
+
<ScreenLayout header={header}>
|
|
115
95
|
{children ?? (
|
|
116
96
|
<SettingsContent
|
|
117
97
|
normalizedConfig={normalizedConfig}
|
|
@@ -126,5 +106,6 @@ export const SettingsScreen: React.FC<SettingsScreenProps> = ({
|
|
|
126
106
|
gamificationConfig={gamificationConfig}
|
|
127
107
|
/>
|
|
128
108
|
)}
|
|
129
|
-
|
|
109
|
+
</ScreenLayout>
|
|
110
|
+
);
|
|
130
111
|
};
|
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
* Handles close button functionality
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import
|
|
7
|
-
import { View, Pressable, StyleSheet } from "react-native";
|
|
8
|
-
import { useAppDesignTokens, AtomicIcon, AtomicText, useAppNavigation } from "@umituz/react-native-design-system";
|
|
6
|
+
import { useAppDesignTokens, AtomicIcon, useAppNavigation, NavigationHeader } from "@umituz/react-native-design-system";
|
|
9
7
|
import { useLocalization } from "../../../domains/localization";
|
|
10
8
|
|
|
11
9
|
interface SettingsHeaderProps {
|
|
@@ -29,41 +27,32 @@ export const SettingsHeader: React.FC<SettingsHeaderProps> = ({
|
|
|
29
27
|
}
|
|
30
28
|
};
|
|
31
29
|
|
|
30
|
+
const rightElement = showCloseButton ? (
|
|
31
|
+
<Pressable
|
|
32
|
+
onPress={handleClose}
|
|
33
|
+
style={({ pressed }) => [
|
|
34
|
+
{
|
|
35
|
+
width: 44,
|
|
36
|
+
height: 44,
|
|
37
|
+
justifyContent: "center",
|
|
38
|
+
alignItems: "center",
|
|
39
|
+
backgroundColor: pressed ? tokens.colors.surfaceVariant : tokens.colors.surface,
|
|
40
|
+
borderRadius: tokens.borders.radius.full,
|
|
41
|
+
},
|
|
42
|
+
]}
|
|
43
|
+
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
44
|
+
>
|
|
45
|
+
<AtomicIcon name="close-outline" size="lg" color="textPrimary" />
|
|
46
|
+
</Pressable>
|
|
47
|
+
) : undefined;
|
|
48
|
+
|
|
32
49
|
return (
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
{showCloseButton
|
|
39
|
-
|
|
40
|
-
onPress={handleClose}
|
|
41
|
-
style={({ pressed }) => [
|
|
42
|
-
styles.closeButton,
|
|
43
|
-
{
|
|
44
|
-
backgroundColor: pressed ? tokens.colors.surfaceVariant : tokens.colors.surface,
|
|
45
|
-
borderRadius: tokens.borders.radius.full,
|
|
46
|
-
},
|
|
47
|
-
]}
|
|
48
|
-
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
49
|
-
>
|
|
50
|
-
<AtomicIcon name="close-outline" size="lg" color="textPrimary" />
|
|
51
|
-
</Pressable>
|
|
52
|
-
)}
|
|
53
|
-
</View>
|
|
50
|
+
<NavigationHeader
|
|
51
|
+
title={t('settings.title')}
|
|
52
|
+
rightElement={rightElement}
|
|
53
|
+
// If NOT showing close button, we might want a back button?
|
|
54
|
+
// But usually Settings is a root screen in a modal or stack.
|
|
55
|
+
onBackPress={!showCloseButton ? handleClose : undefined}
|
|
56
|
+
/>
|
|
54
57
|
);
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
const styles = StyleSheet.create({
|
|
58
|
-
container: {
|
|
59
|
-
flexDirection: 'row',
|
|
60
|
-
justifyContent: 'space-between',
|
|
61
|
-
alignItems: 'center',
|
|
62
|
-
},
|
|
63
|
-
closeButton: {
|
|
64
|
-
width: 44,
|
|
65
|
-
height: 44,
|
|
66
|
-
justifyContent: "center",
|
|
67
|
-
alignItems: "center",
|
|
68
|
-
},
|
|
69
|
-
});
|
|
58
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useSettingsScreen Hook
|
|
3
|
+
* Refactored: Extracted business logic from SettingsScreen component
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { useMemo, useCallback } from "react";
|
|
7
|
+
import { useAppNavigation } from "@umituz/react-native-design-system";
|
|
8
|
+
import { normalizeSettingsConfig } from "../utils/normalizeConfig";
|
|
9
|
+
import { useFeatureDetection } from "./useFeatureDetection";
|
|
10
|
+
import { getAppVersion } from "../../../utils/appUtils";
|
|
11
|
+
import type { SettingsConfig } from "../types";
|
|
12
|
+
|
|
13
|
+
export interface UseSettingsScreenParams {
|
|
14
|
+
config?: SettingsConfig;
|
|
15
|
+
showUserProfile?: boolean;
|
|
16
|
+
featureOptions?: {
|
|
17
|
+
notificationServiceAvailable?: boolean;
|
|
18
|
+
};
|
|
19
|
+
appVersion?: string;
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function useSettingsScreen({
|
|
24
|
+
config = {},
|
|
25
|
+
showUserProfile,
|
|
26
|
+
featureOptions,
|
|
27
|
+
appVersion: providedVersion,
|
|
28
|
+
onClose,
|
|
29
|
+
}: UseSettingsScreenParams) {
|
|
30
|
+
const navigation = useAppNavigation();
|
|
31
|
+
|
|
32
|
+
// Normalize config
|
|
33
|
+
const normalizedConfig = useMemo(
|
|
34
|
+
() => normalizeSettingsConfig(config),
|
|
35
|
+
[config]
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
// Feature detection
|
|
39
|
+
const features = useFeatureDetection(
|
|
40
|
+
normalizedConfig,
|
|
41
|
+
navigation,
|
|
42
|
+
featureOptions
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const shouldShowUserProfile = showUserProfile ?? features.userProfile;
|
|
46
|
+
|
|
47
|
+
const appVersion = providedVersion || getAppVersion();
|
|
48
|
+
|
|
49
|
+
const handleClose = useCallback(() => {
|
|
50
|
+
if (onClose) {
|
|
51
|
+
onClose();
|
|
52
|
+
} else {
|
|
53
|
+
navigation.goBack();
|
|
54
|
+
}
|
|
55
|
+
}, [onClose, navigation]);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
normalizedConfig,
|
|
59
|
+
features,
|
|
60
|
+
shouldShowUserProfile,
|
|
61
|
+
appVersion,
|
|
62
|
+
handleClose,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* App and Platform Utilities
|
|
3
|
+
*/
|
|
4
|
+
import { Platform } from "react-native";
|
|
5
|
+
import Constants from "expo-constants";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Gets the current app version from Expo constants
|
|
9
|
+
*/
|
|
10
|
+
export function getAppVersion(): string {
|
|
11
|
+
const version = Constants.expoConfig?.version ?? Constants.manifest2?.extra?.expoClient?.version;
|
|
12
|
+
if (!version) {
|
|
13
|
+
// Return a default if not found
|
|
14
|
+
return "1.0.0";
|
|
15
|
+
}
|
|
16
|
+
return version;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Validates if the current platform is supported
|
|
21
|
+
*/
|
|
22
|
+
export function validatePlatform(): "ios" | "android" {
|
|
23
|
+
const platform = Platform.OS;
|
|
24
|
+
if (platform !== "ios" && platform !== "android") {
|
|
25
|
+
// Default to android for consistency if something goes wrong in detection
|
|
26
|
+
return "android";
|
|
27
|
+
}
|
|
28
|
+
return platform;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Checks if the app is currently in development mode
|
|
33
|
+
*/
|
|
34
|
+
export function isDev(): boolean {
|
|
35
|
+
return __DEV__;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./appUtils";
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* AboutScreen Container Component
|
|
3
|
-
* Handles business logic and state management for About screen
|
|
4
|
-
*/
|
|
5
|
-
import React from 'react';
|
|
6
|
-
import { View, StyleSheet } from 'react-native';
|
|
7
|
-
import { AboutScreenContent } from './AboutScreenContent';
|
|
8
|
-
import { useAboutInfo } from '../hooks/useAboutInfo';
|
|
9
|
-
import { useAppDesignTokens, AtomicText, type DesignTokens } from '@umituz/react-native-design-system';
|
|
10
|
-
import type { AboutScreenProps } from './AboutScreen';
|
|
11
|
-
|
|
12
|
-
export const AboutScreenContainer: React.FC<AboutScreenProps> = ({
|
|
13
|
-
config,
|
|
14
|
-
containerStyle,
|
|
15
|
-
headerStyle,
|
|
16
|
-
titleStyle,
|
|
17
|
-
versionStyle,
|
|
18
|
-
showHeader = true,
|
|
19
|
-
headerComponent,
|
|
20
|
-
footerComponent,
|
|
21
|
-
testID,
|
|
22
|
-
}) => {
|
|
23
|
-
const tokens = useAppDesignTokens();
|
|
24
|
-
const styles = getStyles(tokens);
|
|
25
|
-
|
|
26
|
-
const { appInfo, loading, error } = useAboutInfo({
|
|
27
|
-
autoInit: true,
|
|
28
|
-
initialConfig: config,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
const containerStyles = React.useMemo(() => {
|
|
32
|
-
return [
|
|
33
|
-
styles.container,
|
|
34
|
-
{ backgroundColor: tokens.colors.backgroundPrimary },
|
|
35
|
-
containerStyle
|
|
36
|
-
];
|
|
37
|
-
}, [containerStyle, tokens.colors.backgroundPrimary, styles]);
|
|
38
|
-
|
|
39
|
-
const texts = config.texts || {};
|
|
40
|
-
|
|
41
|
-
if (loading) {
|
|
42
|
-
return (
|
|
43
|
-
<View style={containerStyles} testID={testID}>
|
|
44
|
-
<AtomicText
|
|
45
|
-
type="bodyMedium"
|
|
46
|
-
color="textSecondary"
|
|
47
|
-
style={styles.statusText}
|
|
48
|
-
>
|
|
49
|
-
{texts.loading}
|
|
50
|
-
</AtomicText>
|
|
51
|
-
</View>
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (error) {
|
|
56
|
-
return (
|
|
57
|
-
<View style={containerStyles} testID={testID}>
|
|
58
|
-
<AtomicText
|
|
59
|
-
type="bodyMedium"
|
|
60
|
-
color="error"
|
|
61
|
-
style={styles.statusText}
|
|
62
|
-
>
|
|
63
|
-
{texts.errorPrefix} {error}
|
|
64
|
-
</AtomicText>
|
|
65
|
-
</View>
|
|
66
|
-
);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (!appInfo) {
|
|
70
|
-
return (
|
|
71
|
-
<View style={containerStyles} testID={testID}>
|
|
72
|
-
<AtomicText
|
|
73
|
-
type="bodyMedium"
|
|
74
|
-
color="textSecondary"
|
|
75
|
-
style={styles.statusText}
|
|
76
|
-
>
|
|
77
|
-
{texts.noInfo}
|
|
78
|
-
</AtomicText>
|
|
79
|
-
</View>
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return (
|
|
84
|
-
<AboutScreenContent
|
|
85
|
-
appInfo={appInfo}
|
|
86
|
-
config={config}
|
|
87
|
-
containerStyle={containerStyle}
|
|
88
|
-
headerStyle={headerStyle}
|
|
89
|
-
titleStyle={titleStyle}
|
|
90
|
-
versionStyle={versionStyle}
|
|
91
|
-
showHeader={showHeader}
|
|
92
|
-
headerComponent={headerComponent}
|
|
93
|
-
footerComponent={footerComponent}
|
|
94
|
-
testID={testID}
|
|
95
|
-
_tokens={tokens}
|
|
96
|
-
/>
|
|
97
|
-
);
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const getStyles = (tokens: DesignTokens) => StyleSheet.create({
|
|
101
|
-
container: {
|
|
102
|
-
flex: 1,
|
|
103
|
-
},
|
|
104
|
-
statusText: {
|
|
105
|
-
textAlign: 'center',
|
|
106
|
-
fontSize: tokens.typography.bodyMedium.responsiveFontSize,
|
|
107
|
-
marginTop: 20,
|
|
108
|
-
},
|
|
109
|
-
});
|