Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ function AppInner() {
// ─── Auto-schedule flight notifications on startup ─────────────────────────
useEffect(() => {
autoScheduleNotifications().then(count => {
if (count > 0) console.log(`Auto-scheduled ${count} notifications`);
if (count > 0 && __DEV__) console.log(`Auto-scheduled ${count} notifications`);
}).catch(() => {});
}, []);

Expand Down
9 changes: 5 additions & 4 deletions src/components/DrawerMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { version } from '../../package.json';
import React, { useEffect, useRef, useState, useMemo } from 'react';
import {
Animated, Modal, StyleSheet, Text, TouchableOpacity, View,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppTheme } from '../context/ThemeContext';
import { useAppTheme, type ThemeColors } from '../context/ThemeContext';

type DrawerItem = {
id: string;
Expand Down Expand Up @@ -89,7 +90,7 @@ export default function DrawerMenu({ visible, onClose, onSelect }: Props) {
activeOpacity={0.7}
>
<View style={styles.itemIcon}>
<MaterialIcons name={item.icon} size={22} color="#2563EB" />
<MaterialIcons name={item.icon} size={22} color={colors.primary} />
</View>
<View style={{ flex: 1 }}>
<Text style={styles.itemLabel}>{item.label}</Text>
Expand All @@ -103,14 +104,14 @@ export default function DrawerMenu({ visible, onClose, onSelect }: Props) {
{/* Divider */}
<View style={styles.divider} />

<Text style={styles.version}>AeroStaff Pro · v1.0</Text>
<Text style={styles.version}>AeroStaff Pro · v{version}</Text>
</Animated.View>
</View>
</Modal>
);
}

function makeStyles(c: any) {
function makeStyles(c: ThemeColors) {
return StyleSheet.create({
root: { flex: 1, flexDirection: 'row' },
overlay: { ...StyleSheet.absoluteFillObject, backgroundColor: 'rgba(15,23,42,0.5)' },
Expand Down
4 changes: 2 additions & 2 deletions src/components/ShiftTimeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
ActivityIndicator, Dimensions, LayoutAnimation, Platform, UIManager,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppTheme } from '../context/ThemeContext';
import { useAppTheme, type ThemeColors } from '../context/ThemeContext';
import { useAirport } from '../context/AirportContext';
import { getAirlineOps, getAirlineColor } from '../utils/airlineOps';
import { fetchAirportScheduleRaw } from '../utils/fr24api';
Expand Down Expand Up @@ -300,7 +300,7 @@ export default function ShiftTimeline({ visible, onClose, shiftStart, shiftEnd,
);
}

function makeStyles(c: any) {
function makeStyles(c: ThemeColors) {
return StyleSheet.create({
overlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'flex-end' },
sheet: {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useDynamicTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ async function resolveTheme(): Promise<Theme> {
globalCachedTheme = selected;
return selected;
} catch (err) {
console.warn('Errore caricamento tema dinamico:', err);
if (__DEV__) console.warn('Errore caricamento tema dinamico:', err);
return themes.default;
} finally {
pendingFetch = null;
Expand Down
19 changes: 9 additions & 10 deletions src/screens/CalendarScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import * as FileSystem from 'expo-file-system/legacy';
import { WebView } from 'react-native-webview';
import { MaterialIcons } from '@expo/vector-icons';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { useAppTheme } from '../context/ThemeContext';
import { useAppTheme, type ThemeColors } from '../context/ThemeContext';
import { useAirport } from '../context/AirportContext';
import { fetchAirportScheduleRaw } from '../utils/fr24api';
import {
Expand All @@ -23,7 +23,6 @@ import {
type ParsedSchedule, type ParsedEmployee, type ParsedShift,
} from '../utils/pdfShiftParser';

const PRIMARY = '#2563EB';
const STORAGE_KEY = '@shift_import_name';

type ShiftEvent = {
Expand Down Expand Up @@ -198,15 +197,15 @@ export default function CalendarScreen() {
localData[iso].push({ id: e.id, title: e.title, startDate: e.startDate, endDate: e.endDate });
// Lavoro has priority over Riposo for dot color
if (e.title.includes('Lavoro') || !dots[iso]) {
dots[iso] = e.title.includes('Riposo') ? '#10b981' : PRIMARY;
dots[iso] = e.title.includes('Riposo') ? '#10b981' : colors.primary;
}
}
});
setMarkedDates(dots);
setEventsData(localData);
setLoading(false);
fetchWeatherAndFlights(start, end, localData);
} catch (e) { console.error(e); setLoading(false); }
} catch (e) { if (__DEV__) console.error(e); setLoading(false); }
};

const fetchWeatherAndFlights = async (start: Date, end: Date, localData: Record<string, ShiftEvent[]>) => {
Expand All @@ -224,7 +223,7 @@ export default function CalendarScreen() {
dict[date] = { weatherText: m.text, weatherIcon: m.icon, flightCount: 0 };
});
}
} catch (e) { console.warn('[calWeather]', e); }
} catch (e) { if (__DEV__) console.warn('[calWeather]', e); }
try {
const { arrivals, departures } = await fetchAirportScheduleRaw(airportCode);
const allF = [...arrivals, ...departures];
Expand All @@ -240,7 +239,7 @@ export default function CalendarScreen() {
if (dict[iso]) dict[iso].flightCount = cnt; else dict[iso] = { weatherText: 'N/A', weatherIcon: '❓', flightCount: cnt };
}
});
} catch (e) { console.warn('[calFlights]', e); }
} catch (e) { if (__DEV__) console.warn('[calFlights]', e); }
setDailyStats(dict);
};

Expand Down Expand Up @@ -270,7 +269,7 @@ export default function CalendarScreen() {
setImportModalVisible(true);
setPdfHtml(getPdfExtractorHtml(base64));
} catch (e: any) {
console.error(`Import error at step=${step}:`, e);
if (__DEV__) console.error(`Import error at step=${step}:`, e);
Alert.alert('Errore', `Errore (${step}): ${e?.message || e}`);
}
};
Expand Down Expand Up @@ -311,7 +310,7 @@ export default function CalendarScreen() {

setImportStep('pickName');
} catch (e) {
console.error(e);
if (__DEV__) console.error(e);
Alert.alert('Errore', 'Errore nel parsing del PDF');
setImportModalVisible(false);
setImportStep('idle');
Expand Down Expand Up @@ -357,7 +356,7 @@ export default function CalendarScreen() {
Alert.alert('Importazione completata', `${saved} turni salvati nel calendario`);
}, 800);
} catch (e) {
console.error(e);
if (__DEV__) console.error(e);
Alert.alert('Errore', 'Errore durante il salvataggio');
setImportStep('idle');
}
Expand Down Expand Up @@ -730,7 +729,7 @@ export default function CalendarScreen() {
);
}

function makeStyles(c: any) {
function makeStyles(c: ThemeColors) {
return StyleSheet.create({
pageHeader: { backgroundColor: c.card, paddingHorizontal: 16, paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: c.border },
pageTitle: { fontSize: 22, fontWeight: 'bold', color: c.primaryDark },
Expand Down
14 changes: 7 additions & 7 deletions src/screens/FlightScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import * as Calendar from 'expo-calendar';
import * as Notifications from 'expo-notifications';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppTheme } from '../context/ThemeContext';
import { useAppTheme, type ThemeColors } from '../context/ThemeContext';
import { useAirport } from '../context/AirportContext';
import { getAirlineOps, getAirlineColor } from '../utils/airlineOps';
import { fetchAirportScheduleRaw } from '../utils/fr24api';
Expand All @@ -34,7 +34,7 @@ try { Notifications.setNotificationHandler({
shouldShowBanner: true,
shouldShowList: true,
}),
}); } catch (e) { console.warn('[notifHandler]', e); }
}); } catch (e) { if (__DEV__) console.warn('[notifHandler]', e); }


function LogoPill({ iataCode, airlineName, color }: { iataCode: string; airlineName: string; color: string }) {
Expand Down Expand Up @@ -396,7 +396,7 @@ export default function FlightScreen() {
await cancelPreviousNotifications();
setScheduledCount(0);
}
} catch (e) { console.error('[fetchAll]', e); } finally { setLoading(false); setRefreshing(false); }
} catch (e) { if (__DEV__) console.error('[fetchAll]', e); } finally { setLoading(false); setRefreshing(false); }
}, [airportCode, airportLoading]);

useEffect(() => {
Expand Down Expand Up @@ -461,7 +461,7 @@ export default function FlightScreen() {
const tab = activeTab;
await AsyncStorage.setItem(PINNED_FLIGHT_KEY, JSON.stringify({ ...item, _pinTab: tab, _pinnedAt: Date.now() }));
setPinnedFlightId(id);
try { await schedulePinnedNotifications(item, tab); } catch (e) { console.warn('[pinnedNotif]', e); }
try { await schedulePinnedNotifications(item, tab); } catch (e) { if (__DEV__) console.warn('[pinnedNotif]', e); }
// Send to watch
if (WearDataSender) {
const payload = JSON.stringify({
Expand All @@ -488,10 +488,10 @@ export default function FlightScreen() {
const unpinFlight = useCallback(async () => {
try {
await AsyncStorage.removeItem(PINNED_FLIGHT_KEY);
try { await cancelPinnedNotifications(); } catch (e) { console.warn('[cancelPinNotif]', e); }
try { await cancelPinnedNotifications(); } catch (e) { if (__DEV__) console.warn('[cancelPinNotif]', e); }
setPinnedFlightId(null);
if (WearDataSender) WearDataSender.clearPinnedFlight();
} catch (e) { console.error('[unpin]', e); }
} catch (e) { if (__DEV__) console.error('[unpin]', e); }
}, []);

const userShift = activeDay === 'today' ? shifts.today : shifts.tomorrow;
Expand Down Expand Up @@ -726,7 +726,7 @@ export default function FlightScreen() {
);
}

function makeStyles(c: any) {
function makeStyles(c: ThemeColors) {
return StyleSheet.create({
pageHeader: { backgroundColor: c.card, paddingHorizontal: 16, paddingVertical: 14, borderBottomWidth: 1, borderBottomColor: c.border, flexDirection: 'row', alignItems: 'center' },
notifBtn: { width: 42, height: 42, borderRadius: 21, backgroundColor: c.cardSecondary, justifyContent: 'center', alignItems: 'center' },
Expand Down
12 changes: 6 additions & 6 deletions src/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { WebView } from 'react-native-webview';
import * as ImagePicker from 'expo-image-picker';
import * as Calendar from 'expo-calendar';
import * as Location from 'expo-location';
import { useAppTheme } from '../context/ThemeContext';
import { useAppTheme, type ThemeColors } from '../context/ThemeContext';
import ShiftTimeline from '../components/ShiftTimeline';

import { getAirlineOps, getAirlineColor } from '../utils/airlineOps';
Expand Down Expand Up @@ -253,7 +253,7 @@ export default function HomeScreen() {
const events = await Calendar.getEventsAsync([cal.id], d, dEnd);
const shift = events.find(e => e.title.includes('Lavoro') || e.title.includes('Riposo'));
setShiftEvent(shift || null);
} catch (e) { console.error('[shift]', e); } finally { setLoadingShift(false); }
} catch (e) { if (__DEV__) console.error('[shift]', e); } finally { setLoadingShift(false); }
};

const fetchWeather = async () => {
Expand All @@ -267,7 +267,7 @@ export default function HomeScreen() {
const temp = Math.round(json.current?.temperature_2m ?? 0);
const w = weatherMap[code] || { text: 'Sereno', icon: '☀️' };
setWeather({ ...w, temp });
} catch (e) { console.warn('[weather]', e); }
} catch (e) { if (__DEV__) console.warn('[weather]', e); }
};

const pickImage = async () => {
Expand All @@ -291,15 +291,15 @@ export default function HomeScreen() {
true;
`);
}
} catch (e) { console.error('[imagePicker]', e); setProcessing(false); }
} catch (e) { if (__DEV__) console.error('[imagePicker]', e); setProcessing(false); }
};

const handleWebViewMessage = (event: any) => {
try {
const r = JSON.parse(event.nativeEvent.data);
if (r.success) setOcrText(r.text);
else Alert.alert('Errore riconoscimento testo', r.error || 'Prova con un\'immagine più nitida o meglio illuminata.');
} catch (e) { console.error('[ocrMessage]', e); } finally { setProcessing(false); }
} catch (e) { if (__DEV__) console.error('[ocrMessage]', e); } finally { setProcessing(false); }
};

const parseAndSave = async () => {
Expand Down Expand Up @@ -429,7 +429,7 @@ export default function HomeScreen() {
);
}

function makeStyles(c: any) {
function makeStyles(c: ThemeColors) {
return StyleSheet.create({
hiddenWV: { height: 1, width: 1, opacity: 0, position: 'absolute', top: -100 },
topRow: { flexDirection: 'row', gap: 12, padding: 16, paddingBottom: 8 },
Expand Down
8 changes: 4 additions & 4 deletions src/screens/ManualsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
LayoutAnimation, Platform, UIManager, TextInput, Modal, Alert, KeyboardAvoidingView,
} from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppTheme } from '../context/ThemeContext';
import { useAppTheme, type ThemeColors } from '../context/ThemeContext';

const STORAGE_KEY = 'manuals_data_v2';

Expand Down Expand Up @@ -416,7 +416,7 @@ function CommandsTab({ commands, colors }: { commands: DCSCommand[]; colors: any
}

// ─── Item component ───────────────────────────────────────────────────────────
function makeItemStyles(c: any) {
function makeItemStyles(c: ThemeColors) {
return StyleSheet.create({
wrapper: {
backgroundColor: c.card,
Expand Down Expand Up @@ -485,7 +485,7 @@ function ManualItemRow({
}

// ─── Section component ────────────────────────────────────────────────────────
function makeSectionStyles(c: any) {
function makeSectionStyles(c: ThemeColors) {
return StyleSheet.create({
wrapper: {
marginBottom: 12,
Expand Down Expand Up @@ -583,7 +583,7 @@ const modalStyles = StyleSheet.create({
});

// ─── Main Screen ──────────────────────────────────────────────────────────────
function makeStyles(c: any) {
function makeStyles(c: ThemeColors) {
return StyleSheet.create({
root: { flex: 1, backgroundColor: c.bg },
header: {
Expand Down
8 changes: 5 additions & 3 deletions src/screens/NotepadScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import {
} from 'react-native';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppTheme } from '../context/ThemeContext';
import { useAppTheme, type ThemeColors } from '../context/ThemeContext';

const STORAGE_KEY = 'aerostaff_notepad_v1';

function makeStyles(c: any) {
function makeStyles(c: ThemeColors) {
return StyleSheet.create({
root: { flex: 1, backgroundColor: c.bg },
toolbar: {
Expand All @@ -27,7 +27,9 @@ function makeStyles(c: any) {
backgroundColor: c.primary, borderRadius: 10,
paddingHorizontal: 14, paddingVertical: 8,
},
saveBtnDim: { backgroundColor: '#93C5FD' },
// Dims the entire save button (background + icon + label) when content is
// already saved — intentional: the full-button fade signals an inactive state.
saveBtnDim: { opacity: 0.55 },
saveTxt: { color: '#fff', fontWeight: '600', fontSize: 13 },
statusBar: {
flexDirection: 'row', alignItems: 'center', gap: 6,
Expand Down
14 changes: 7 additions & 7 deletions src/screens/PasswordScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as SecureStore from 'expo-secure-store';
import { MaterialIcons } from '@expo/vector-icons';
import { useAppTheme } from '../context/ThemeContext';
import { useAppTheme, type ThemeColors } from '../context/ThemeContext';

const PASSWORDS_KEY = 'aerostaff_passwords_v1';
const PIN_KEY = 'aerostaff_pin_v1';
Expand Down Expand Up @@ -167,7 +167,7 @@ export default function PasswordScreen() {
setPinEnabled(false);
await AsyncStorage.setItem(PIN_ENABLED_KEY, 'false');
await deleteSecurePin();
} catch (e) { console.error('[pin] disable error', e); }
} catch (e) { if (__DEV__) console.error('[pin] disable error', e); }
}},
]);
} else {
Expand All @@ -183,7 +183,7 @@ export default function PasswordScreen() {
setPinMode(null);
Alert.alert('PIN impostato', 'La schermata password è ora protetta.');
} catch (e) {
console.error('[pin] setup error', e);
if (__DEV__) console.error('[pin] setup error', e);
Alert.alert('Errore', 'Impossibile impostare il PIN. Riprova.');
}
}, []);
Expand All @@ -197,7 +197,7 @@ export default function PasswordScreen() {
Alert.alert('PIN errato', 'Riprova.');
}
} catch (e) {
console.error('[pin] unlock error', e);
if (__DEV__) console.error('[pin] unlock error', e);
Alert.alert('Errore', 'Impossibile verificare il PIN. Riprova.');
}
}, []);
Expand Down Expand Up @@ -349,7 +349,7 @@ export default function PasswordScreen() {
}

// ─── Styles ───────────────────────────────────────────────────────────────────
function makePinStyles(c: any) {
function makePinStyles(c: ThemeColors) {
return StyleSheet.create({
overlay: { flex: 1, backgroundColor: c.bg, justifyContent: 'center', alignItems: 'center' },
box: { alignItems: 'center', padding: 32, width: '100%', maxWidth: 320 },
Expand All @@ -364,7 +364,7 @@ function makePinStyles(c: any) {
});
}

function makeRowStyles(c: any) {
function makeRowStyles(c: ThemeColors) {
return StyleSheet.create({
card: { backgroundColor: c.card, borderRadius: 14, padding: 14, marginBottom: 10, flexDirection: 'row', alignItems: 'flex-start', borderWidth: 1, borderColor: c.border, shadowColor: '#000', shadowOpacity: c.isDark ? 0 : 0.05, shadowRadius: 6, elevation: c.isDark ? 0 : 2 },
cardLeft:{ flex: 1 },
Expand All @@ -380,7 +380,7 @@ function makeRowStyles(c: any) {
});
}

function makeStyles(c: any) {
function makeStyles(c: ThemeColors) {
return StyleSheet.create({
root: { flex: 1, backgroundColor: c.bg },
toolbar: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 16, paddingVertical: 12, backgroundColor: c.card, borderBottomWidth: 1, borderBottomColor: c.border },
Expand Down
Loading
Loading