@umituz/react-native-notifications 1.3.21 → 1.5.0
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
CHANGED
|
@@ -1,24 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* NotificationsSection Component
|
|
3
|
-
* Settings section for notifications
|
|
3
|
+
* Settings section for notifications - navigates to full screen
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React, {
|
|
6
|
+
import React, { useCallback, useMemo } from 'react';
|
|
7
7
|
import type { StyleProp, ViewStyle } from 'react-native';
|
|
8
|
-
import { View, TouchableOpacity, StyleSheet
|
|
8
|
+
import { View, TouchableOpacity, StyleSheet } from 'react-native';
|
|
9
9
|
import { AtomicText, AtomicIcon } from '@umituz/react-native-design-system';
|
|
10
10
|
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
11
11
|
// @ts-ignore - Optional peer dependency
|
|
12
12
|
import { useNavigation } from '@react-navigation/native';
|
|
13
|
-
import { notificationService } from '../../infrastructure/services/NotificationService';
|
|
14
13
|
|
|
15
14
|
export interface NotificationsSectionConfig {
|
|
16
|
-
initialValue?: boolean;
|
|
17
|
-
onToggleChange?: (value: boolean) => void;
|
|
18
15
|
route?: string;
|
|
19
16
|
title?: string;
|
|
20
17
|
description?: string;
|
|
21
|
-
showToggle?: boolean;
|
|
22
18
|
}
|
|
23
19
|
|
|
24
20
|
export interface NotificationsSectionProps {
|
|
@@ -34,70 +30,32 @@ export const NotificationsSection: React.FC<NotificationsSectionProps> = ({
|
|
|
34
30
|
const tokens = useAppDesignTokens();
|
|
35
31
|
const styles = useMemo(() => createStyles(tokens), [tokens]);
|
|
36
32
|
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
useEffect(() => {
|
|
40
|
-
if (config?.initialValue !== undefined) {
|
|
41
|
-
setEnabled(config.initialValue);
|
|
42
|
-
}
|
|
43
|
-
}, [config?.initialValue]);
|
|
44
|
-
|
|
45
|
-
const handleToggle = useCallback(async (value: boolean) => {
|
|
46
|
-
if (value) {
|
|
47
|
-
const hasPermissions = await notificationService.hasPermissions();
|
|
48
|
-
if (!hasPermissions) {
|
|
49
|
-
const granted = await notificationService.requestPermissions();
|
|
50
|
-
if (!granted) return;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
setEnabled(value);
|
|
54
|
-
config?.onToggleChange?.(value);
|
|
55
|
-
}, [config]);
|
|
56
|
-
|
|
57
|
-
const handlePress = useCallback(async () => {
|
|
33
|
+
const handlePress = useCallback(() => {
|
|
58
34
|
const route = config?.route || 'Notifications';
|
|
59
35
|
navigation.navigate(route as never);
|
|
60
36
|
}, [config?.route, navigation]);
|
|
61
37
|
|
|
62
38
|
const title = config?.title || 'Notifications';
|
|
63
39
|
const description = config?.description || 'Manage notification preferences';
|
|
64
|
-
const showToggle = config?.showToggle ?? false;
|
|
65
40
|
|
|
66
41
|
return (
|
|
67
42
|
<View style={[styles.container, containerStyle]}>
|
|
68
43
|
<AtomicText type="bodyLarge" style={styles.sectionTitle}>General</AtomicText>
|
|
69
44
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
trackColor={{ false: tokens.colors.surfaceSecondary, true: tokens.colors.primary }}
|
|
82
|
-
thumbColor={tokens.colors.surface}
|
|
83
|
-
/>
|
|
45
|
+
<TouchableOpacity
|
|
46
|
+
style={styles.itemContainer}
|
|
47
|
+
onPress={handlePress}
|
|
48
|
+
activeOpacity={0.7}
|
|
49
|
+
>
|
|
50
|
+
<View style={styles.iconContainer}>
|
|
51
|
+
<AtomicIcon name="notifications" size="md" color="primary" />
|
|
52
|
+
</View>
|
|
53
|
+
<View style={styles.textContainer}>
|
|
54
|
+
<AtomicText type="bodyLarge">{title}</AtomicText>
|
|
55
|
+
<AtomicText type="bodySmall" style={styles.description}>{description}</AtomicText>
|
|
84
56
|
</View>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
style={styles.itemContainer}
|
|
88
|
-
onPress={handlePress}
|
|
89
|
-
activeOpacity={0.7}
|
|
90
|
-
>
|
|
91
|
-
<View style={styles.iconContainer}>
|
|
92
|
-
<AtomicIcon name="notifications" size="md" color="primary" />
|
|
93
|
-
</View>
|
|
94
|
-
<View style={styles.textContainer}>
|
|
95
|
-
<AtomicText type="bodyLarge">{title}</AtomicText>
|
|
96
|
-
<AtomicText type="bodySmall" style={styles.description}>{description}</AtomicText>
|
|
97
|
-
</View>
|
|
98
|
-
<AtomicIcon name="chevron-forward" size="md" color="secondary" />
|
|
99
|
-
</TouchableOpacity>
|
|
100
|
-
)}
|
|
57
|
+
<AtomicIcon name="chevron-forward" size="md" color="secondary" />
|
|
58
|
+
</TouchableOpacity>
|
|
101
59
|
</View>
|
|
102
60
|
);
|
|
103
61
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Clean presentation-only screen for notification settings
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import React, { useMemo } from 'react';
|
|
6
|
+
import React, { useMemo, useState } from 'react';
|
|
7
7
|
import { View, StyleSheet, ActivityIndicator, TouchableOpacity } from 'react-native';
|
|
8
8
|
import { AtomicText, AtomicIcon, AtomicCard, ScreenLayout } from '@umituz/react-native-design-system';
|
|
9
9
|
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
@@ -11,28 +11,29 @@ import { QuietHoursCard } from '../../domains/quietHours/presentation/components
|
|
|
11
11
|
import { SettingRow } from '../components/SettingRow';
|
|
12
12
|
import { useNotificationSettingsUI } from '../hooks/useNotificationSettingsUI';
|
|
13
13
|
import { useReminders } from '../../domains/reminders/infrastructure/storage/RemindersStore';
|
|
14
|
+
import { useQuietHoursActions } from '../../domains/quietHours/infrastructure/hooks/useQuietHoursActions';
|
|
14
15
|
import type { NotificationSettingsTranslations, QuietHoursTranslations } from '../../infrastructure/services/types';
|
|
16
|
+
// @ts-ignore - Optional peer dependency
|
|
17
|
+
import DateTimePicker from '@react-native-community/datetimepicker';
|
|
18
|
+
|
|
19
|
+
type PickerMode = 'start' | 'end' | null;
|
|
15
20
|
|
|
16
21
|
export interface NotificationSettingsScreenProps {
|
|
17
22
|
translations: NotificationSettingsTranslations;
|
|
18
23
|
quietHoursTranslations: QuietHoursTranslations;
|
|
19
|
-
onRemindersPress: () => void;
|
|
20
|
-
onStartTimePress: () => void;
|
|
21
|
-
onEndTimePress: () => void;
|
|
22
24
|
onHapticFeedback?: () => void;
|
|
23
25
|
}
|
|
24
26
|
|
|
25
27
|
export const NotificationSettingsScreen: React.FC<NotificationSettingsScreenProps> = ({
|
|
26
28
|
translations,
|
|
27
29
|
quietHoursTranslations,
|
|
28
|
-
onRemindersPress,
|
|
29
|
-
onStartTimePress,
|
|
30
|
-
onEndTimePress,
|
|
31
30
|
onHapticFeedback,
|
|
32
31
|
}) => {
|
|
33
32
|
const tokens = useAppDesignTokens();
|
|
34
33
|
const styles = useMemo(() => createStyles(tokens), [tokens]);
|
|
35
34
|
const reminders = useReminders();
|
|
35
|
+
const { setStartTime, setEndTime } = useQuietHoursActions();
|
|
36
|
+
const [pickerMode, setPickerMode] = useState<PickerMode>(null);
|
|
36
37
|
|
|
37
38
|
const {
|
|
38
39
|
preferences,
|
|
@@ -44,6 +45,42 @@ export const NotificationSettingsScreen: React.FC<NotificationSettingsScreenProp
|
|
|
44
45
|
handleQuietHoursToggle,
|
|
45
46
|
} = useNotificationSettingsUI();
|
|
46
47
|
|
|
48
|
+
const handleRemindersPress = () => {
|
|
49
|
+
// Navigate to reminders screen when implemented
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const handleStartTimePress = () => {
|
|
53
|
+
setPickerMode('start');
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const handleEndTimePress = () => {
|
|
57
|
+
setPickerMode('end');
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
const handleTimeChange = (event: any, selectedDate?: Date) => {
|
|
61
|
+
if (event.type === 'set' && selectedDate) {
|
|
62
|
+
const hours = selectedDate.getHours();
|
|
63
|
+
const minutes = selectedDate.getMinutes();
|
|
64
|
+
|
|
65
|
+
if (pickerMode === 'start') {
|
|
66
|
+
setStartTime(hours, minutes);
|
|
67
|
+
} else if (pickerMode === 'end') {
|
|
68
|
+
setEndTime(hours, minutes);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
setPickerMode(null);
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const getPickerDate = () => {
|
|
75
|
+
const date = new Date();
|
|
76
|
+
if (pickerMode === 'start') {
|
|
77
|
+
date.setHours(quietHours.startHour, quietHours.startMinute);
|
|
78
|
+
} else if (pickerMode === 'end') {
|
|
79
|
+
date.setHours(quietHours.endHour, quietHours.endMinute);
|
|
80
|
+
}
|
|
81
|
+
return date;
|
|
82
|
+
};
|
|
83
|
+
|
|
47
84
|
if (isLoading) {
|
|
48
85
|
return (
|
|
49
86
|
<ScreenLayout>
|
|
@@ -118,12 +155,20 @@ export const NotificationSettingsScreen: React.FC<NotificationSettingsScreenProp
|
|
|
118
155
|
config={quietHours}
|
|
119
156
|
translations={quietHoursTranslations}
|
|
120
157
|
onToggle={handleQuietHoursToggle}
|
|
121
|
-
onStartTimePress={
|
|
122
|
-
onEndTimePress={
|
|
158
|
+
onStartTimePress={handleStartTimePress}
|
|
159
|
+
onEndTimePress={handleEndTimePress}
|
|
123
160
|
/>
|
|
124
161
|
</>
|
|
125
162
|
)}
|
|
126
163
|
</View>
|
|
164
|
+
{pickerMode && (
|
|
165
|
+
<DateTimePicker
|
|
166
|
+
value={getPickerDate()}
|
|
167
|
+
mode="time"
|
|
168
|
+
is24Hour={true}
|
|
169
|
+
onChange={handleTimeChange}
|
|
170
|
+
/>
|
|
171
|
+
)}
|
|
127
172
|
</ScreenLayout>
|
|
128
173
|
);
|
|
129
174
|
};
|