@umituz/react-native-settings 5.4.10 → 5.4.11
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/core/index.ts +1 -1
- package/src/core/patterns/Screen/useScreenData.ts +0 -1
- package/src/core/utils/logger.ts +5 -5
- package/src/domains/disclaimer/index.ts +0 -3
- package/src/domains/disclaimer/presentation/components/DisclaimerSetting.tsx +18 -43
- package/src/domains/disclaimer/presentation/screens/DisclaimerScreen.tsx +42 -92
- package/src/domains/feedback/index.ts +2 -2
- package/src/domains/feedback/presentation/components/SupportSection.tsx +16 -43
- package/src/domains/feedback/presentation/screens/FeatureRequestScreen.tsx +4 -4
- package/src/domains/feedback/presentation/screens/FeedbackScreen.tsx +75 -0
- package/src/domains/notifications/infrastructure/services/NotificationService.ts +2 -4
- package/src/domains/rating/application/services/RatingService.ts +31 -0
- package/src/domains/rating/index.ts +3 -3
- package/src/domains/rating/presentation/hooks/useAppRating.tsx +42 -65
- package/src/domains/rating/presentation/screens/RatingPromptScreen.tsx +162 -0
- package/src/infrastructure/services/SettingsService.ts +3 -9
- package/src/presentation/components/GenericModal.tsx +3 -7
- package/src/presentation/components/GenericScreen.tsx +1 -6
- package/src/presentation/navigation/hooks/useSettingsScreens.ts +26 -1
- package/src/presentation/navigation/types.ts +6 -0
- package/src/domains/disclaimer/presentation/hooks/useDisclaimerModal.ts +0 -72
- package/src/domains/feedback/presentation/hooks/useFeedbackModal.ts +0 -182
- package/src/domains/rating/presentation/hooks/useRatingPromptModal.ts +0 -122
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useFeedbackModal Hook
|
|
3
|
-
*
|
|
4
|
-
* Refactored to use GenericModal and ModalConfig.
|
|
5
|
-
* Replaces old FeedbackModal component.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* const { FeedbackModal, showFeedbackModal } = useFeedbackModal();
|
|
10
|
-
*
|
|
11
|
-
* return (
|
|
12
|
-
* <>
|
|
13
|
-
* <Button onPress={() => showFeedbackModal({ onSubmit: ... })} />
|
|
14
|
-
* <FeedbackModal />
|
|
15
|
-
* </>
|
|
16
|
-
* );
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { useCallback, useState } from 'react';
|
|
21
|
-
import { View, TouchableOpacity, StyleSheet } from 'react-native';
|
|
22
|
-
import { BaseModal } from '@umituz/react-native-design-system/molecules';
|
|
23
|
-
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system/atoms';
|
|
24
|
-
import { ScreenLayout } from '@umituz/react-native-design-system/layouts';
|
|
25
|
-
import { useAppDesignTokens } from '@umituz/react-native-design-system/theme';
|
|
26
|
-
import { FeedbackForm } from '../components/FeedbackForm';
|
|
27
|
-
import type { FeedbackType, FeedbackRating } from '../../domain/entities/FeedbackEntity';
|
|
28
|
-
import type { FeedbackFormProps } from '../components/FeedbackFormProps';
|
|
29
|
-
|
|
30
|
-
export interface FeedbackModalOptions {
|
|
31
|
-
/**
|
|
32
|
-
* Submit callback
|
|
33
|
-
*/
|
|
34
|
-
onSubmit: (data: {
|
|
35
|
-
type: FeedbackType;
|
|
36
|
-
rating: FeedbackRating;
|
|
37
|
-
description: string;
|
|
38
|
-
title: string;
|
|
39
|
-
}) => Promise<void>;
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Initial feedback type
|
|
43
|
-
*/
|
|
44
|
-
initialType?: FeedbackType;
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Modal title
|
|
48
|
-
*/
|
|
49
|
-
title?: string;
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Modal subtitle
|
|
53
|
-
*/
|
|
54
|
-
subtitle?: string;
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Form texts
|
|
58
|
-
*/
|
|
59
|
-
texts: FeedbackFormProps['texts'];
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
* Custom configuration
|
|
63
|
-
*/
|
|
64
|
-
config?: {
|
|
65
|
-
showHeader?: boolean;
|
|
66
|
-
showCloseButton?: boolean;
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Feedback modal hook
|
|
72
|
-
*/
|
|
73
|
-
export function useFeedbackModal() {
|
|
74
|
-
const [visible, setVisible] = useState(false);
|
|
75
|
-
const [options, setOptions] = useState<FeedbackModalOptions | null>(null);
|
|
76
|
-
const [isSubmitting, setIsSubmitting] = useState(false);
|
|
77
|
-
|
|
78
|
-
const tokens = useAppDesignTokens();
|
|
79
|
-
const styles = getStyles(tokens);
|
|
80
|
-
|
|
81
|
-
const showFeedbackModal = useCallback((newOptions: FeedbackModalOptions) => {
|
|
82
|
-
setOptions(newOptions);
|
|
83
|
-
setVisible(true);
|
|
84
|
-
}, []);
|
|
85
|
-
|
|
86
|
-
const hideFeedbackModal = useCallback(() => {
|
|
87
|
-
setVisible(false);
|
|
88
|
-
setIsSubmitting(false);
|
|
89
|
-
}, []);
|
|
90
|
-
|
|
91
|
-
const handleSubmit = useCallback(async (data: any) => {
|
|
92
|
-
if (!options) return;
|
|
93
|
-
|
|
94
|
-
setIsSubmitting(true);
|
|
95
|
-
try {
|
|
96
|
-
await options.onSubmit(data);
|
|
97
|
-
hideFeedbackModal();
|
|
98
|
-
} catch (error) {
|
|
99
|
-
setIsSubmitting(false);
|
|
100
|
-
}
|
|
101
|
-
}, [options, hideFeedbackModal]);
|
|
102
|
-
|
|
103
|
-
const header = options?.config?.showHeader !== false ? (
|
|
104
|
-
<View style={styles.header}>
|
|
105
|
-
<View style={styles.headerText}>
|
|
106
|
-
{options?.title && (
|
|
107
|
-
<AtomicText style={{ fontSize: 20, fontWeight: '600' }}>
|
|
108
|
-
{options.title}
|
|
109
|
-
</AtomicText>
|
|
110
|
-
)}
|
|
111
|
-
{options?.subtitle && (
|
|
112
|
-
<AtomicText style={{ fontSize: 14, marginTop: 4 }}>
|
|
113
|
-
{options.subtitle}
|
|
114
|
-
</AtomicText>
|
|
115
|
-
)}
|
|
116
|
-
</View>
|
|
117
|
-
{options?.config?.showCloseButton !== false && (
|
|
118
|
-
<TouchableOpacity
|
|
119
|
-
onPress={hideFeedbackModal}
|
|
120
|
-
style={[styles.closeButton, { backgroundColor: tokens.colors.surfaceVariant }]}
|
|
121
|
-
>
|
|
122
|
-
<AtomicIcon name="close" size="sm" color="onSurface" />
|
|
123
|
-
</TouchableOpacity>
|
|
124
|
-
)}
|
|
125
|
-
</View>
|
|
126
|
-
) : undefined;
|
|
127
|
-
|
|
128
|
-
const FeedbackModal = useCallback(() => {
|
|
129
|
-
if (!options) return null;
|
|
130
|
-
|
|
131
|
-
return (
|
|
132
|
-
<BaseModal visible={visible} onClose={hideFeedbackModal}>
|
|
133
|
-
<ScreenLayout
|
|
134
|
-
header={header}
|
|
135
|
-
scrollable={true}
|
|
136
|
-
edges={[]}
|
|
137
|
-
keyboardAvoiding={true}
|
|
138
|
-
contentContainerStyle={styles.content}
|
|
139
|
-
hideScrollIndicator={false}
|
|
140
|
-
>
|
|
141
|
-
<FeedbackForm
|
|
142
|
-
onSubmit={handleSubmit}
|
|
143
|
-
initialType={options.initialType}
|
|
144
|
-
isSubmitting={isSubmitting}
|
|
145
|
-
texts={options.texts}
|
|
146
|
-
/>
|
|
147
|
-
</ScreenLayout>
|
|
148
|
-
</BaseModal>
|
|
149
|
-
);
|
|
150
|
-
}, [visible, options, header, styles, handleSubmit, isSubmitting, hideFeedbackModal]);
|
|
151
|
-
|
|
152
|
-
return {
|
|
153
|
-
FeedbackModal,
|
|
154
|
-
showFeedbackModal,
|
|
155
|
-
hideFeedbackModal,
|
|
156
|
-
isVisible: visible,
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const getStyles = (_tokens: ReturnType<typeof useAppDesignTokens>) =>
|
|
161
|
-
StyleSheet.create({
|
|
162
|
-
header: {
|
|
163
|
-
flexDirection: 'row',
|
|
164
|
-
justifyContent: 'space-between',
|
|
165
|
-
alignItems: 'center',
|
|
166
|
-
padding: 16,
|
|
167
|
-
borderBottomWidth: 1,
|
|
168
|
-
},
|
|
169
|
-
headerText: {
|
|
170
|
-
flex: 1,
|
|
171
|
-
},
|
|
172
|
-
closeButton: {
|
|
173
|
-
width: 36,
|
|
174
|
-
height: 36,
|
|
175
|
-
borderRadius: 18,
|
|
176
|
-
justifyContent: 'center',
|
|
177
|
-
alignItems: 'center',
|
|
178
|
-
},
|
|
179
|
-
content: {
|
|
180
|
-
padding: 20,
|
|
181
|
-
},
|
|
182
|
-
});
|
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useRatingPromptModal Hook
|
|
3
|
-
*
|
|
4
|
-
* Refactored to use GenericModal and ModalConfig.
|
|
5
|
-
* Replaces old RatingPromptModal component.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```ts
|
|
9
|
-
* const { RatingPrompt, showRatingPrompt } = useRatingPromptModal();
|
|
10
|
-
*
|
|
11
|
-
* return (
|
|
12
|
-
* <>
|
|
13
|
-
* <Button onPress={() => showRatingPrompt({ onPositive: ... })} />
|
|
14
|
-
* <RatingPrompt />
|
|
15
|
-
* </>
|
|
16
|
-
* );
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { useCallback } from 'react';
|
|
21
|
-
import { GenericModal } from '../../../../presentation/components/GenericModal';
|
|
22
|
-
import { useModalState } from '../../../../core/patterns/Modal/useModalState';
|
|
23
|
-
import type { ModalConfig } from '../../../../core/patterns/Modal/ModalConfig';
|
|
24
|
-
import type { RatingTranslations } from '../../domain/entities/RatingConfig';
|
|
25
|
-
|
|
26
|
-
export interface RatingPromptOptions {
|
|
27
|
-
/**
|
|
28
|
-
* Callback when user clicks positive (loves the app)
|
|
29
|
-
*/
|
|
30
|
-
onPositive: () => void | Promise<void>;
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Callback when user clicks negative (doesn't love the app)
|
|
34
|
-
*/
|
|
35
|
-
onNegative: () => void | Promise<void>;
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Callback when user clicks later
|
|
39
|
-
*/
|
|
40
|
-
onLater: () => void | Promise<void>;
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* App name for message
|
|
44
|
-
*/
|
|
45
|
-
appName?: string;
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Custom translations
|
|
49
|
-
*/
|
|
50
|
-
translations?: RatingTranslations;
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Custom modal configuration
|
|
54
|
-
*/
|
|
55
|
-
config?: Partial<ModalConfig>;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Rating prompt modal hook
|
|
60
|
-
*/
|
|
61
|
-
export function useRatingPromptModal() {
|
|
62
|
-
const modal = useModalState();
|
|
63
|
-
|
|
64
|
-
const showRatingPrompt = useCallback((options: RatingPromptOptions) => {
|
|
65
|
-
const {
|
|
66
|
-
onPositive,
|
|
67
|
-
onNegative,
|
|
68
|
-
onLater,
|
|
69
|
-
appName = 'this app',
|
|
70
|
-
translations,
|
|
71
|
-
config: customConfig,
|
|
72
|
-
} = options;
|
|
73
|
-
|
|
74
|
-
const defaultTranslations: RatingTranslations = {
|
|
75
|
-
title: translations?.title ?? 'Enjoying the app?',
|
|
76
|
-
message:
|
|
77
|
-
translations?.message ??
|
|
78
|
-
`If you love using ${appName}, would you mind taking a moment to rate it?`,
|
|
79
|
-
positiveButton: translations?.positiveButton ?? 'Yes, I love it!',
|
|
80
|
-
negativeButton: translations?.negativeButton ?? 'Not really',
|
|
81
|
-
laterButton: translations?.laterButton ?? 'Maybe later',
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
const modalConfig: ModalConfig = {
|
|
85
|
-
title: defaultTranslations.title,
|
|
86
|
-
message: defaultTranslations.message,
|
|
87
|
-
icon: 'star',
|
|
88
|
-
iconColor: 'primary',
|
|
89
|
-
actions: [
|
|
90
|
-
{
|
|
91
|
-
label: defaultTranslations.positiveButton,
|
|
92
|
-
onPress: onPositive,
|
|
93
|
-
variant: 'primary',
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
label: defaultTranslations.negativeButton,
|
|
97
|
-
onPress: onNegative,
|
|
98
|
-
variant: 'outline',
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
label: defaultTranslations.laterButton,
|
|
102
|
-
onPress: onLater,
|
|
103
|
-
variant: 'text',
|
|
104
|
-
},
|
|
105
|
-
],
|
|
106
|
-
dismissible: true,
|
|
107
|
-
...customConfig,
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
modal.show(modalConfig);
|
|
111
|
-
}, [modal]);
|
|
112
|
-
|
|
113
|
-
const RatingPrompt = useCallback(() => {
|
|
114
|
-
return <GenericModal state={modal} testID="rating-prompt-modal" />;
|
|
115
|
-
}, [modal]);
|
|
116
|
-
|
|
117
|
-
return {
|
|
118
|
-
RatingPrompt,
|
|
119
|
-
showRatingPrompt,
|
|
120
|
-
modal,
|
|
121
|
-
};
|
|
122
|
-
}
|