Skip to content

Commit 537ff11

Browse files
Gabry848claude
andcommitted
fix(home): rimuovi icona calendario inutilizzata dall'entry testuale
- Rimossa icona calendar-outline dalla barra di input della Home (il bottone non aveva azione, solo TODO) - Refactoring prompt notifiche: sostituito Alert nativo con PermissionModal custom - Aggiunto prompt ottimizzazione batteria per Android tramite PermissionModal - Aggiunte traduzioni per batteryPrompt in en.json e it.json - Rimossa emoji dal titolo enablePrompt nelle traduzioni Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 8482de0 commit 537ff11

7 files changed

Lines changed: 271 additions & 54 deletions

File tree

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@
5858
"Bash(xargs:*)",
5959
"WebFetch(domain:www.npmjs.com)",
6060
"WebFetch(domain:docs.expo.dev)",
61-
"WebFetch(domain:github.com)"
61+
"WebFetch(domain:github.com)",
62+
"Bash(git push:*)"
6263
],
6364
"deny": [],
6465
"defaultMode": "acceptEdits"
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import React from "react";
2+
import {
3+
Modal,
4+
View,
5+
Text,
6+
TouchableOpacity,
7+
StyleSheet,
8+
Dimensions,
9+
} from "react-native";
10+
import { Ionicons } from "@expo/vector-icons";
11+
12+
const { width } = Dimensions.get("window");
13+
14+
interface PermissionModalProps {
15+
visible: boolean;
16+
icon: keyof typeof Ionicons.glyphMap;
17+
title: string;
18+
message: string;
19+
primaryLabel: string;
20+
secondaryLabel?: string;
21+
badge?: string;
22+
onPrimary: () => void;
23+
onSecondary?: () => void;
24+
}
25+
26+
const PermissionModal: React.FC<PermissionModalProps> = ({
27+
visible,
28+
icon,
29+
title,
30+
message,
31+
primaryLabel,
32+
secondaryLabel,
33+
badge,
34+
onPrimary,
35+
onSecondary,
36+
}) => {
37+
return (
38+
<Modal
39+
transparent
40+
visible={visible}
41+
animationType="fade"
42+
statusBarTranslucent
43+
>
44+
<View style={styles.overlay}>
45+
<View style={styles.card}>
46+
{badge ? (
47+
<View style={styles.badge}>
48+
<Text style={styles.badgeText}>{badge}</Text>
49+
</View>
50+
) : null}
51+
52+
<View style={styles.iconWrap}>
53+
<Ionicons name={icon} size={36} color="#000000" />
54+
</View>
55+
56+
<Text style={styles.title}>{title}</Text>
57+
<Text style={styles.message}>{message}</Text>
58+
59+
<TouchableOpacity
60+
style={styles.primaryButton}
61+
onPress={onPrimary}
62+
activeOpacity={0.85}
63+
>
64+
<Text style={styles.primaryButtonText}>{primaryLabel}</Text>
65+
</TouchableOpacity>
66+
67+
{secondaryLabel && onSecondary ? (
68+
<TouchableOpacity
69+
style={styles.secondaryButton}
70+
onPress={onSecondary}
71+
activeOpacity={0.7}
72+
>
73+
<Text style={styles.secondaryButtonText}>{secondaryLabel}</Text>
74+
</TouchableOpacity>
75+
) : null}
76+
</View>
77+
</View>
78+
</Modal>
79+
);
80+
};
81+
82+
const styles = StyleSheet.create({
83+
overlay: {
84+
flex: 1,
85+
backgroundColor: "rgba(0, 0, 0, 0.45)",
86+
justifyContent: "center",
87+
alignItems: "center",
88+
paddingHorizontal: 24,
89+
},
90+
card: {
91+
width: Math.min(width - 48, 360),
92+
backgroundColor: "#ffffff",
93+
borderRadius: 20,
94+
padding: 28,
95+
alignItems: "center",
96+
shadowColor: "#000",
97+
shadowOffset: { width: 0, height: 8 },
98+
shadowOpacity: 0.12,
99+
shadowRadius: 24,
100+
elevation: 12,
101+
},
102+
badge: {
103+
alignSelf: "flex-end",
104+
backgroundColor: "#f0f0f0",
105+
borderRadius: 8,
106+
paddingHorizontal: 10,
107+
paddingVertical: 3,
108+
marginBottom: 12,
109+
},
110+
badgeText: {
111+
fontSize: 11,
112+
fontWeight: "500",
113+
color: "#666666",
114+
letterSpacing: 0.2,
115+
},
116+
iconWrap: {
117+
width: 72,
118+
height: 72,
119+
borderRadius: 36,
120+
backgroundColor: "#f5f5f5",
121+
justifyContent: "center",
122+
alignItems: "center",
123+
marginBottom: 20,
124+
},
125+
title: {
126+
fontSize: 20,
127+
fontWeight: "600",
128+
color: "#000000",
129+
letterSpacing: -0.5,
130+
textAlign: "center",
131+
marginBottom: 12,
132+
},
133+
message: {
134+
fontSize: 14,
135+
fontWeight: "400",
136+
color: "#555555",
137+
lineHeight: 21,
138+
textAlign: "center",
139+
marginBottom: 28,
140+
},
141+
primaryButton: {
142+
width: "100%",
143+
backgroundColor: "#000000",
144+
borderRadius: 12,
145+
paddingVertical: 14,
146+
alignItems: "center",
147+
marginBottom: 10,
148+
},
149+
primaryButtonText: {
150+
fontSize: 15,
151+
fontWeight: "600",
152+
color: "#ffffff",
153+
letterSpacing: -0.2,
154+
},
155+
secondaryButton: {
156+
width: "100%",
157+
paddingVertical: 12,
158+
alignItems: "center",
159+
},
160+
secondaryButtonText: {
161+
fontSize: 14,
162+
fontWeight: "400",
163+
color: "#888888",
164+
letterSpacing: -0.1,
165+
},
166+
});
167+
168+
export default PermissionModal;

src/locales/en.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -680,10 +680,17 @@
680680
},
681681
"notifications": {
682682
"enablePrompt": {
683-
"title": "🔔 Enable notifications",
683+
"title": "Enable notifications",
684684
"message": "Would you like to receive notifications for your task reminders? We'll notify you when a task is due, so you never miss an important deadline.",
685685
"enable": "Enable",
686686
"later": "Later"
687+
},
688+
"batteryPrompt": {
689+
"title": "Battery optimization",
690+
"badge": "Optional",
691+
"message": "To receive notifications even when your phone is in stand-by, we recommend disabling battery optimization for MyTaskly.\n\nWithout this setting, some notifications may not arrive while your device is in power-saving mode.\n\nYou can do this anytime from Settings → Apps → MyTaskly → Battery.",
692+
"openSettings": "Open Settings",
693+
"skip": "Skip for now"
687694
}
688695
},
689696
"profile": {

src/locales/it.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -679,10 +679,17 @@
679679
},
680680
"notifications": {
681681
"enablePrompt": {
682-
"title": "🔔 Abilita le notifiche",
682+
"title": "Abilita le notifiche",
683683
"message": "Vuoi ricevere notifiche per i promemoria dei tuoi task? Ti avviseremo quando un task è in scadenza, così non perderai mai una scadenza importante.",
684684
"enable": "Abilita",
685685
"later": "Più tardi"
686+
},
687+
"batteryPrompt": {
688+
"title": "Ottimizzazione batteria",
689+
"badge": "Facoltativo",
690+
"message": "Per ricevere notifiche anche quando il telefono è in stand-by, ti consigliamo di disabilitare l'ottimizzazione della batteria per MyTaskly.\n\nSenza questa impostazione, alcune notifiche potrebbero non arrivare mentre il dispositivo è in risparmio energetico.\n\nPuoi farlo in qualsiasi momento da Impostazioni → App → MyTaskly → Batteria.",
691+
"openSettings": "Apri Impostazioni",
692+
"skip": "Salta per ora"
686693
}
687694
},
688695
"profile": {

src/navigation/index.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ import { TutorialOnboarding } from "../components/Tutorial/exports";
5353
import { LanguageProvider } from "../contexts/LanguageContext";
5454
import "../services/i18n"; // Initialize i18n
5555
import { useTranslation } from 'react-i18next';
56+
import PermissionModal from "../components/UI/PermissionModal";
5657

5758
// Definizione del tipo per le route dello Stack principale
5859
export type RootStackParamList = {
@@ -244,7 +245,15 @@ function AppStack() {
244245
const { triggerPostLoginTutorial } = useTutorialContext();
245246

246247
// 🔔 Inizializza il sistema di notifiche quando l'utente è autenticato
247-
const { notification } = useNotifications();
248+
const {
249+
notification,
250+
showNotificationPrompt,
251+
showBatteryPrompt,
252+
handleNotificationAccept,
253+
handleNotificationDismiss,
254+
handleBatteryAccept,
255+
handleBatteryDismiss,
256+
} = useNotifications();
248257

249258
useEffect(() => {
250259
const checkAuthStatus = async () => {
@@ -375,6 +384,27 @@ function AppStack() {
375384
return (
376385
<>
377386
<NavigationHandler />
387+
<PermissionModal
388+
visible={showNotificationPrompt}
389+
icon="notifications-outline"
390+
title={t('notifications.enablePrompt.title')}
391+
message={t('notifications.enablePrompt.message')}
392+
primaryLabel={t('notifications.enablePrompt.enable')}
393+
secondaryLabel={t('notifications.enablePrompt.later')}
394+
onPrimary={handleNotificationAccept}
395+
onSecondary={handleNotificationDismiss}
396+
/>
397+
<PermissionModal
398+
visible={showBatteryPrompt}
399+
icon="battery-half-outline"
400+
title={t('notifications.batteryPrompt.title')}
401+
message={t('notifications.batteryPrompt.message')}
402+
primaryLabel={t('notifications.batteryPrompt.openSettings')}
403+
secondaryLabel={t('notifications.batteryPrompt.skip')}
404+
badge={t('notifications.batteryPrompt.badge')}
405+
onPrimary={handleBatteryAccept}
406+
onSecondary={handleBatteryDismiss}
407+
/>
378408
<Stack.Navigator id={undefined} initialRouteName={initialRoute}>
379409
<Stack.Screen
380410
name="WelcomeCarousel"

src/navigation/screens/Home.tsx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -881,14 +881,6 @@ const HomeScreen = () => {
881881
]}
882882
>
883883
<View style={styles.inputContainer}>
884-
<TouchableOpacity
885-
style={styles.calendarToggleButton}
886-
onPress={() => {/* TODO: Open calendar */}}
887-
activeOpacity={0.7}
888-
disabled={isLoading}
889-
>
890-
<Ionicons name="calendar-outline" size={24} color={isLoading ? "#ccc" : "#000"} />
891-
</TouchableOpacity>
892884
<Animated.View
893885
style={{
894886
opacity: micButtonAnim,
@@ -1125,10 +1117,6 @@ const styles = StyleSheet.create({
11251117
shadowRadius: 12,
11261118
elevation: 3,
11271119
},
1128-
calendarToggleButton: {
1129-
marginRight: 8,
1130-
padding: 4,
1131-
},
11321120
attachButton: {
11331121
marginRight: 8,
11341122
padding: 4,

0 commit comments

Comments
 (0)