@umituz/react-native-settings 4.20.53 → 4.20.55
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 +1 -1
- package/src/domains/about/presentation/components/AboutSettingItem.tsx +39 -86
- package/src/domains/about/presentation/hooks/useAboutInfo.ts +80 -200
- package/src/domains/about/presentation/hooks/useAboutInfo.types.ts +32 -0
- package/src/domains/about/presentation/hooks/useAboutInfo.utils.ts +167 -0
- package/src/domains/about/utils/AppInfoFactory.ts +19 -0
- package/src/domains/about/utils/index.ts +2 -0
- package/src/domains/legal/index.ts +1 -0
- package/src/domains/legal/presentation/screens/LegalContentScreen.tsx +140 -0
- package/src/domains/legal/presentation/screens/PrivacyPolicyScreen.tsx +17 -155
- package/src/domains/legal/presentation/screens/TermsOfServiceScreen.tsx +17 -155
- package/src/presentation/components/SettingsItemCard.tsx +2 -2
- package/src/presentation/navigation/SettingsStackNavigator.tsx +50 -129
- package/src/presentation/navigation/components/wrappers/AboutScreenWrapper.tsx +13 -0
- package/src/presentation/navigation/components/wrappers/LegalScreenWrapper.tsx +50 -0
- package/src/presentation/navigation/components/wrappers/SettingsScreenWrapper.tsx +32 -0
- package/src/presentation/navigation/components/wrappers/index.ts +9 -0
- package/src/presentation/navigation/utils/index.ts +5 -0
- package/src/presentation/navigation/utils/navigationScreenOptions.ts +56 -0
- package/src/presentation/navigation/utils/navigationTranslations.ts +46 -0
- package/src/presentation/screens/components/SettingsHeader.tsx +1 -1
- package/src/presentation/screens/types/BaseTypes.ts +12 -0
- package/src/presentation/screens/types/ContentConfig.ts +82 -0
- package/src/presentation/screens/types/SettingsConfig.ts +6 -4
- package/src/presentation/screens/types/UserFeatureConfig.ts +137 -0
- package/src/presentation/screens/types/index.ts +10 -8
- package/src/presentation/screens/types/FeatureConfig.ts +0 -263
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useAboutInfo Hook Utilities
|
|
3
|
+
* Shared utility functions for about info hook
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { MutableRefObject } from 'react';
|
|
7
|
+
import type { AppInfo, AboutConfig } from '../../domain/entities/AppInfo';
|
|
8
|
+
import type { AboutRepository } from '../../infrastructure/repositories/AboutRepository';
|
|
9
|
+
import { createDefaultAppInfo } from '../../utils/AppInfoFactory';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Safely set error if component is mounted
|
|
13
|
+
*/
|
|
14
|
+
export const setErrorIfMounted = (
|
|
15
|
+
isMountedRef: MutableRefObject<boolean>,
|
|
16
|
+
setError: (error: string | null) => void,
|
|
17
|
+
err: string | null
|
|
18
|
+
) => {
|
|
19
|
+
if (isMountedRef.current) {
|
|
20
|
+
setError(err);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Safely set loading state if component is mounted
|
|
26
|
+
*/
|
|
27
|
+
export const setLoadingIfMounted = (
|
|
28
|
+
isMountedRef: MutableRefObject<boolean>,
|
|
29
|
+
setLoading: (loading: boolean) => void,
|
|
30
|
+
value: boolean
|
|
31
|
+
) => {
|
|
32
|
+
if (isMountedRef.current) {
|
|
33
|
+
setLoading(value);
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Initialize app info with config
|
|
39
|
+
*/
|
|
40
|
+
export const initializeAppInfo = async (
|
|
41
|
+
config: AboutConfig,
|
|
42
|
+
repository: AboutRepository,
|
|
43
|
+
isMountedRef: MutableRefObject<boolean>,
|
|
44
|
+
isInitializedRef: MutableRefObject<boolean>,
|
|
45
|
+
setAppInfo: (info: AppInfo | null) => void,
|
|
46
|
+
setError: (error: string | null) => void,
|
|
47
|
+
setLoading: (loading: boolean) => void,
|
|
48
|
+
force = false
|
|
49
|
+
): Promise<void> => {
|
|
50
|
+
if (isInitializedRef.current && !force) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (!isMountedRef.current) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
setLoading(true);
|
|
59
|
+
setError(null);
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
const defaultAppInfo = createDefaultAppInfo(config);
|
|
63
|
+
await repository.saveAppInfo(defaultAppInfo);
|
|
64
|
+
|
|
65
|
+
if (isMountedRef.current) {
|
|
66
|
+
setAppInfo(defaultAppInfo);
|
|
67
|
+
isInitializedRef.current = true;
|
|
68
|
+
}
|
|
69
|
+
} catch (err) {
|
|
70
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
71
|
+
} finally {
|
|
72
|
+
setLoading(false);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Update app info with new config
|
|
78
|
+
*/
|
|
79
|
+
export const updateAppInfoConfig = async (
|
|
80
|
+
config: AboutConfig,
|
|
81
|
+
repository: AboutRepository,
|
|
82
|
+
isMountedRef: MutableRefObject<boolean>,
|
|
83
|
+
setAppInfo: (info: AppInfo | null) => void,
|
|
84
|
+
setError: (error: string | null) => void,
|
|
85
|
+
setLoading: (loading: boolean) => void
|
|
86
|
+
): Promise<void> => {
|
|
87
|
+
if (!isMountedRef.current) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
setLoading(true);
|
|
92
|
+
setError(null);
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const updatedAppInfo = createDefaultAppInfo(config);
|
|
96
|
+
await repository.saveAppInfo(updatedAppInfo);
|
|
97
|
+
|
|
98
|
+
if (isMountedRef.current) {
|
|
99
|
+
setAppInfo(updatedAppInfo);
|
|
100
|
+
}
|
|
101
|
+
} catch (err) {
|
|
102
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
103
|
+
} finally {
|
|
104
|
+
setLoading(false);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Update app info with partial updates
|
|
110
|
+
*/
|
|
111
|
+
export const updateAppInfoPartial = async (
|
|
112
|
+
updates: Partial<AppInfo>,
|
|
113
|
+
repository: AboutRepository,
|
|
114
|
+
isMountedRef: MutableRefObject<boolean>,
|
|
115
|
+
setAppInfo: (info: AppInfo | null) => void,
|
|
116
|
+
setError: (error: string | null) => void,
|
|
117
|
+
setLoading: (loading: boolean) => void
|
|
118
|
+
): Promise<void> => {
|
|
119
|
+
if (!isMountedRef.current) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
setLoading(true);
|
|
124
|
+
setError(null);
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const updatedInfo = await repository.updateAppInfo(updates);
|
|
128
|
+
|
|
129
|
+
if (isMountedRef.current) {
|
|
130
|
+
setAppInfo(updatedInfo);
|
|
131
|
+
}
|
|
132
|
+
} catch (err) {
|
|
133
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
134
|
+
} finally {
|
|
135
|
+
setLoading(false);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Refresh app info from repository
|
|
141
|
+
*/
|
|
142
|
+
export const refreshAppInfo = async (
|
|
143
|
+
repository: AboutRepository,
|
|
144
|
+
isMountedRef: MutableRefObject<boolean>,
|
|
145
|
+
setAppInfo: (info: AppInfo | null) => void,
|
|
146
|
+
setError: (error: string | null) => void,
|
|
147
|
+
setLoading: (loading: boolean) => void
|
|
148
|
+
): Promise<void> => {
|
|
149
|
+
if (!isMountedRef.current) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
setLoading(true);
|
|
154
|
+
setError(null);
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const refreshedInfo = await repository.getAppInfo();
|
|
158
|
+
|
|
159
|
+
if (isMountedRef.current) {
|
|
160
|
+
setAppInfo(refreshedInfo);
|
|
161
|
+
}
|
|
162
|
+
} catch (err) {
|
|
163
|
+
setError(err instanceof Error ? err.message : 'Unknown error');
|
|
164
|
+
} finally {
|
|
165
|
+
setLoading(false);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AppInfo Factory Utility
|
|
3
|
+
* Creates AppInfo objects from AboutConfig
|
|
4
|
+
*/
|
|
5
|
+
import { AppInfo, AboutConfig } from '../domain/entities/AppInfo';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Creates a default AppInfo object from AboutConfig
|
|
9
|
+
*/
|
|
10
|
+
export const createDefaultAppInfo = (config: AboutConfig): AppInfo => ({
|
|
11
|
+
name: config.appInfo?.name || '',
|
|
12
|
+
version: config.appInfo?.version || '1.0.0',
|
|
13
|
+
description: config.appInfo?.description,
|
|
14
|
+
developer: config.appInfo?.developer,
|
|
15
|
+
contactEmail: config.appInfo?.contactEmail,
|
|
16
|
+
websiteUrl: config.appInfo?.websiteUrl,
|
|
17
|
+
websiteDisplay: config.appInfo?.websiteDisplay,
|
|
18
|
+
moreAppsUrl: config.appInfo?.moreAppsUrl,
|
|
19
|
+
});
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Legal Content Screen Component
|
|
3
|
+
* Shared logic for legal document screens
|
|
4
|
+
*/
|
|
5
|
+
import React from "react";
|
|
6
|
+
import { View, ScrollView, StyleSheet } from "react-native";
|
|
7
|
+
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
8
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
9
|
+
import { AtomicText, AtomicButton } from "@umituz/react-native-design-system";
|
|
10
|
+
import { UrlHandlerService } from "../../domain/services/UrlHandlerService";
|
|
11
|
+
import { ContentValidationService } from "../../domain/services/ContentValidationService";
|
|
12
|
+
import { StyleCacheService } from "../../domain/services/StyleCacheService";
|
|
13
|
+
|
|
14
|
+
export interface LegalContentScreenProps {
|
|
15
|
+
content?: string;
|
|
16
|
+
url?: string;
|
|
17
|
+
title: string;
|
|
18
|
+
viewOnlineText?: string;
|
|
19
|
+
openText?: string;
|
|
20
|
+
onUrlPress?: () => void;
|
|
21
|
+
testID?: string;
|
|
22
|
+
styleCacheKey: string;
|
|
23
|
+
createStyles: (tokens: any) => ReturnType<typeof StyleSheet.create>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const LegalContentScreen: React.FC<LegalContentScreenProps> = React.memo(({
|
|
27
|
+
content,
|
|
28
|
+
url,
|
|
29
|
+
title,
|
|
30
|
+
viewOnlineText,
|
|
31
|
+
openText,
|
|
32
|
+
onUrlPress,
|
|
33
|
+
testID,
|
|
34
|
+
styleCacheKey,
|
|
35
|
+
createStyles,
|
|
36
|
+
}) => {
|
|
37
|
+
const tokens = useAppDesignTokens();
|
|
38
|
+
const insets = useSafeAreaInsets();
|
|
39
|
+
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
ContentValidationService.validateScreenContent(
|
|
42
|
+
content,
|
|
43
|
+
url,
|
|
44
|
+
title,
|
|
45
|
+
viewOnlineText,
|
|
46
|
+
openText,
|
|
47
|
+
styleCacheKey
|
|
48
|
+
);
|
|
49
|
+
}, [content, url, title, viewOnlineText, openText, styleCacheKey]);
|
|
50
|
+
|
|
51
|
+
const styles = React.useMemo(() => {
|
|
52
|
+
const cacheKey = StyleCacheService.createTokenCacheKey(tokens);
|
|
53
|
+
return StyleCacheService.getCachedStyles(
|
|
54
|
+
styleCacheKey,
|
|
55
|
+
cacheKey,
|
|
56
|
+
() => createStyles(tokens)
|
|
57
|
+
);
|
|
58
|
+
}, [tokens, styleCacheKey, createStyles]);
|
|
59
|
+
|
|
60
|
+
const handleUrlPress = React.useCallback(async () => {
|
|
61
|
+
if (onUrlPress) {
|
|
62
|
+
onUrlPress();
|
|
63
|
+
} else if (url) {
|
|
64
|
+
try {
|
|
65
|
+
await UrlHandlerService.openUrl(url);
|
|
66
|
+
} catch {
|
|
67
|
+
// Silent error handling
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}, [onUrlPress, url]);
|
|
71
|
+
|
|
72
|
+
const containerStyle = React.useMemo(() => [
|
|
73
|
+
styles.container,
|
|
74
|
+
{
|
|
75
|
+
backgroundColor: tokens.colors.backgroundPrimary,
|
|
76
|
+
paddingTop: insets.top,
|
|
77
|
+
},
|
|
78
|
+
], [styles.container, tokens.colors.backgroundPrimary, insets.top]);
|
|
79
|
+
|
|
80
|
+
const showContent = React.useMemo(() => !!(content), [content]);
|
|
81
|
+
const showUrlSection = React.useMemo(() =>
|
|
82
|
+
ContentValidationService.shouldShowUrlSection(url, onUrlPress),
|
|
83
|
+
[url, onUrlPress]
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const contentSection = React.useMemo(() => {
|
|
87
|
+
if (showContent) {
|
|
88
|
+
return (
|
|
89
|
+
<AtomicText type="bodyMedium" color="onSurface" style={styles.text}>
|
|
90
|
+
{content}
|
|
91
|
+
</AtomicText>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (showUrlSection) {
|
|
96
|
+
return (
|
|
97
|
+
<View style={styles.urlContainer}>
|
|
98
|
+
<AtomicText
|
|
99
|
+
type="bodyMedium"
|
|
100
|
+
color="secondary"
|
|
101
|
+
style={styles.urlText}
|
|
102
|
+
>
|
|
103
|
+
{viewOnlineText}
|
|
104
|
+
</AtomicText>
|
|
105
|
+
<AtomicButton
|
|
106
|
+
variant="primary"
|
|
107
|
+
onPress={handleUrlPress}
|
|
108
|
+
fullWidth
|
|
109
|
+
style={styles.urlButton}
|
|
110
|
+
>
|
|
111
|
+
{openText}
|
|
112
|
+
</AtomicButton>
|
|
113
|
+
</View>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return null;
|
|
118
|
+
}, [showContent, showUrlSection, styles, content, viewOnlineText, openText, handleUrlPress]);
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<View style={containerStyle} testID={testID}>
|
|
122
|
+
<ScrollView
|
|
123
|
+
contentContainerStyle={styles.scrollContent}
|
|
124
|
+
showsVerticalScrollIndicator={false}
|
|
125
|
+
>
|
|
126
|
+
<View style={styles.content}>
|
|
127
|
+
<AtomicText
|
|
128
|
+
type="headlineLarge"
|
|
129
|
+
color="primary"
|
|
130
|
+
style={styles.title}
|
|
131
|
+
>
|
|
132
|
+
{title}
|
|
133
|
+
</AtomicText>
|
|
134
|
+
|
|
135
|
+
{contentSection}
|
|
136
|
+
</View>
|
|
137
|
+
</ScrollView>
|
|
138
|
+
</View>
|
|
139
|
+
);
|
|
140
|
+
});
|
|
@@ -2,46 +2,17 @@
|
|
|
2
2
|
* Privacy Policy Screen Component
|
|
3
3
|
* Display Privacy Policy content
|
|
4
4
|
*/
|
|
5
|
-
|
|
6
5
|
import React from "react";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
10
|
-
import { AtomicText, AtomicButton } from "@umituz/react-native-design-system";
|
|
11
|
-
import { UrlHandlerService } from "../../domain/services/UrlHandlerService";
|
|
12
|
-
import { ContentValidationService } from "../../domain/services/ContentValidationService";
|
|
13
|
-
import { StyleCacheService } from "../../domain/services/StyleCacheService";
|
|
6
|
+
import { StyleSheet } from "react-native";
|
|
7
|
+
import { LegalContentScreen } from "./LegalContentScreen";
|
|
14
8
|
|
|
15
9
|
export interface PrivacyPolicyScreenProps {
|
|
16
|
-
/**
|
|
17
|
-
* Privacy Policy content (HTML or plain text)
|
|
18
|
-
* Either content or url must be provided
|
|
19
|
-
*/
|
|
20
10
|
content?: string;
|
|
21
|
-
/**
|
|
22
|
-
* Privacy Policy URL (if content is not provided, will open URL)
|
|
23
|
-
* Either content or url must be provided
|
|
24
|
-
*/
|
|
25
11
|
url?: string;
|
|
26
|
-
/**
|
|
27
|
-
* Custom title
|
|
28
|
-
*/
|
|
29
12
|
title: string;
|
|
30
|
-
/**
|
|
31
|
-
* Text for viewing online button (required when url is provided)
|
|
32
|
-
*/
|
|
33
13
|
viewOnlineText?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Text for open button (required when url is provided)
|
|
36
|
-
*/
|
|
37
14
|
openText?: string;
|
|
38
|
-
/**
|
|
39
|
-
* Callback when URL is pressed (if content is not provided)
|
|
40
|
-
*/
|
|
41
15
|
onUrlPress?: () => void;
|
|
42
|
-
/**
|
|
43
|
-
* Test ID for E2E testing
|
|
44
|
-
*/
|
|
45
16
|
testID?: string;
|
|
46
17
|
}
|
|
47
18
|
|
|
@@ -54,119 +25,7 @@ export const PrivacyPolicyScreen: React.FC<PrivacyPolicyScreenProps> = React.mem
|
|
|
54
25
|
onUrlPress,
|
|
55
26
|
testID = "privacy-policy-screen",
|
|
56
27
|
}) => {
|
|
57
|
-
const
|
|
58
|
-
const insets = useSafeAreaInsets();
|
|
59
|
-
|
|
60
|
-
// Validate required props
|
|
61
|
-
React.useEffect(() => {
|
|
62
|
-
ContentValidationService.validateScreenContent(
|
|
63
|
-
content,
|
|
64
|
-
url,
|
|
65
|
-
title,
|
|
66
|
-
viewOnlineText,
|
|
67
|
-
openText,
|
|
68
|
-
'PrivacyPolicyScreen'
|
|
69
|
-
);
|
|
70
|
-
}, [content, url, title, viewOnlineText, openText]);
|
|
71
|
-
|
|
72
|
-
// Use cached styles
|
|
73
|
-
const styles = React.useMemo(() => {
|
|
74
|
-
const cacheKey = StyleCacheService.createTokenCacheKey(tokens);
|
|
75
|
-
return StyleCacheService.getCachedStyles(
|
|
76
|
-
'PrivacyPolicyScreen',
|
|
77
|
-
cacheKey,
|
|
78
|
-
() => createPrivacyPolicyStyles(tokens)
|
|
79
|
-
);
|
|
80
|
-
}, [tokens]);
|
|
81
|
-
|
|
82
|
-
// Memoize URL press handler to prevent child re-renders
|
|
83
|
-
const handleUrlPress = React.useCallback(async () => {
|
|
84
|
-
if (onUrlPress) {
|
|
85
|
-
onUrlPress();
|
|
86
|
-
} else if (url) {
|
|
87
|
-
try {
|
|
88
|
-
await UrlHandlerService.openUrl(url);
|
|
89
|
-
} catch {
|
|
90
|
-
// Silent error handling
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}, [onUrlPress, url]);
|
|
94
|
-
|
|
95
|
-
// Memoize container style to prevent object creation
|
|
96
|
-
const containerStyle = React.useMemo(() => [
|
|
97
|
-
styles.container,
|
|
98
|
-
{
|
|
99
|
-
backgroundColor: tokens.colors.backgroundPrimary,
|
|
100
|
-
paddingTop: insets.top,
|
|
101
|
-
},
|
|
102
|
-
], [styles.container, tokens.colors.backgroundPrimary, insets.top]);
|
|
103
|
-
|
|
104
|
-
// Memoize conditional rendering
|
|
105
|
-
const showContent = React.useMemo(() => !!(content), [content]);
|
|
106
|
-
const showUrlSection = React.useMemo(() =>
|
|
107
|
-
ContentValidationService.shouldShowUrlSection(url, onUrlPress),
|
|
108
|
-
[url, onUrlPress]
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
// Memoize content section
|
|
112
|
-
const contentSection = React.useMemo(() => {
|
|
113
|
-
if (showContent) {
|
|
114
|
-
return (
|
|
115
|
-
<AtomicText type="bodyMedium" color="onSurface" style={styles.text}>
|
|
116
|
-
{content}
|
|
117
|
-
</AtomicText>
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
if (showUrlSection) {
|
|
122
|
-
return (
|
|
123
|
-
<View style={styles.urlContainer}>
|
|
124
|
-
<AtomicText
|
|
125
|
-
type="bodyMedium"
|
|
126
|
-
color="secondary"
|
|
127
|
-
style={styles.urlText}
|
|
128
|
-
>
|
|
129
|
-
{viewOnlineText}
|
|
130
|
-
</AtomicText>
|
|
131
|
-
<AtomicButton
|
|
132
|
-
variant="primary"
|
|
133
|
-
onPress={handleUrlPress}
|
|
134
|
-
fullWidth
|
|
135
|
-
style={styles.urlButton}
|
|
136
|
-
>
|
|
137
|
-
{openText}
|
|
138
|
-
</AtomicButton>
|
|
139
|
-
</View>
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
return null;
|
|
144
|
-
}, [showContent, showUrlSection, styles.text, styles.urlContainer, styles.urlText, styles.urlButton, content, viewOnlineText, openText, handleUrlPress]);
|
|
145
|
-
|
|
146
|
-
return (
|
|
147
|
-
<View style={containerStyle} testID={testID}>
|
|
148
|
-
<ScrollView
|
|
149
|
-
contentContainerStyle={styles.scrollContent}
|
|
150
|
-
showsVerticalScrollIndicator={false}
|
|
151
|
-
>
|
|
152
|
-
<View style={styles.content}>
|
|
153
|
-
<AtomicText
|
|
154
|
-
type="headlineLarge"
|
|
155
|
-
color="primary"
|
|
156
|
-
style={styles.title}
|
|
157
|
-
>
|
|
158
|
-
{title}
|
|
159
|
-
</AtomicText>
|
|
160
|
-
|
|
161
|
-
{contentSection}
|
|
162
|
-
</View>
|
|
163
|
-
</ScrollView>
|
|
164
|
-
</View>
|
|
165
|
-
);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
const createPrivacyPolicyStyles = (tokens: any) => {
|
|
169
|
-
return StyleSheet.create({
|
|
28
|
+
const createStyles = (tokens: any) => StyleSheet.create({
|
|
170
29
|
container: {
|
|
171
30
|
flex: 1,
|
|
172
31
|
},
|
|
@@ -197,15 +56,18 @@ const createPrivacyPolicyStyles = (tokens: any) => {
|
|
|
197
56
|
marginTop: 8,
|
|
198
57
|
},
|
|
199
58
|
});
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
59
|
|
|
60
|
+
return (
|
|
61
|
+
<LegalContentScreen
|
|
62
|
+
content={content}
|
|
63
|
+
url={url}
|
|
64
|
+
title={title}
|
|
65
|
+
viewOnlineText={viewOnlineText}
|
|
66
|
+
openText={openText}
|
|
67
|
+
onUrlPress={onUrlPress}
|
|
68
|
+
testID={testID}
|
|
69
|
+
styleCacheKey="PrivacyPolicyScreen"
|
|
70
|
+
createStyles={createStyles}
|
|
71
|
+
/>
|
|
72
|
+
);
|
|
73
|
+
});
|