From 47bca948aa832cc2c1ebba95f6dcdb3079112991 Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Fri, 1 May 2026 00:19:44 +0000
Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Enhance=20flight?=
=?UTF-8?q?=20card=20haptics=20and=20accessibility?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add haptic feedback to flight card swipe gestures using expo-haptics.
- Implement comprehensive accessibility labels for flight cards.
- Add accessibility actions (pin/unpin) for screen reader users.
- Add necessary translations for new accessibility strings.
Co-authored-by: TargetMisser <52361977+TargetMisser@users.noreply.github.com>
---
src/i18n/translations.ts | 8 +++++++
src/screens/FlightScreen.tsx | 42 ++++++++++++++++++++++++++++++++----
2 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts
index 26c05cb..e389828 100644
--- a/src/i18n/translations.ts
+++ b/src/i18n/translations.ts
@@ -121,6 +121,8 @@ const it = {
flightCheckin: 'Check-in', flightGate: 'Gate', flightStand: 'Stand', flightBelt: 'Nastro', flightDeparted: 'Partito',
flightLanded: 'Atterrato', flightEstimated: 'Stimato', flightOnTime: 'In orario',
flightPinned: 'PINNATO', flightPinnedLabel: 'Pinnato',
+ flightAccessibilityPin: 'Pinna volo', flightAccessibilityUnpin: 'Rimuovi pin',
+ flightFrom: 'da', flightTo: 'per',
flightNotifEnabled: 'Notifiche attivate',
flightNotifPermDenied: 'Permesso negato',
flightNotifPermMsg: 'Abilita le notifiche nelle impostazioni del telefono per usare questa funzione.',
@@ -129,6 +131,8 @@ const it = {
flightNotifMsg1: 'Programmate {count} notifiche per il turno di oggi.',
flightNotifMsg0: 'Nessuna notifica futura trovata con i filtri attivi.',
flightNotifAccessEnable: 'Attiva notifiche voli', flightNotifAccessDisable: 'Disattiva notifiche voli',
+ flightAccessibilityPin: 'Pinna volo', flightAccessibilityUnpin: 'Rimuovi pin',
+ flightFrom: 'da', flightTo: 'per',
flightNotifSettingsTitle: 'Impostazioni notifiche',
flightNotifSettingsSub: 'Decidi cosa ricevere, sticky e minutaggi.',
flightNotifOnlyTracked: 'Solo compagnie monitorate',
@@ -320,6 +324,8 @@ const en: typeof it = {
flightCheckin: 'Check-in', flightGate: 'Gate', flightStand: 'Stand', flightBelt: 'Belt', flightDeparted: 'Departed',
flightLanded: 'Landed', flightEstimated: 'Estimated', flightOnTime: 'On time',
flightPinned: 'PINNED', flightPinnedLabel: 'Pinned',
+ flightAccessibilityPin: 'Pin flight', flightAccessibilityUnpin: 'Unpin flight',
+ flightFrom: 'from', flightTo: 'to',
flightNotifEnabled: 'Notifications enabled',
flightNotifPermDenied: 'Permission denied',
flightNotifPermMsg: 'Enable notifications in phone settings to use this feature.',
@@ -328,6 +334,8 @@ const en: typeof it = {
flightNotifMsg1: '{count} notifications scheduled for today’s shift.',
flightNotifMsg0: 'No upcoming notifications found with current filters.',
flightNotifAccessEnable: 'Enable flight notifications', flightNotifAccessDisable: 'Disable flight notifications',
+ flightAccessibilityPin: 'Pin flight', flightAccessibilityUnpin: 'Unpin flight',
+ flightFrom: 'from', flightTo: 'to',
flightNotifSettingsTitle: 'Notification settings',
flightNotifSettingsSub: 'Choose what to receive, sticky behavior and timing.',
flightNotifOnlyTracked: 'Only tracked airlines',
diff --git a/src/screens/FlightScreen.tsx b/src/screens/FlightScreen.tsx
index 09dbe5d..bc103ea 100644
--- a/src/screens/FlightScreen.tsx
+++ b/src/screens/FlightScreen.tsx
@@ -3,8 +3,10 @@ import {
View, Text, StyleSheet, ActivityIndicator, Modal, ScrollView,
FlatList, TouchableOpacity, RefreshControl, Image,
Animated, PanResponder, NativeModules, Platform, Switch,
+ type ViewProps, type AccessibilityActionEvent,
} from 'react-native';
import { Easing } from 'react-native';
+import * as Haptics from 'expo-haptics';
import * as Calendar from 'expo-calendar';
import * as Notifications from 'expo-notifications';
import AsyncStorage from '@react-native-async-storage/async-storage';
@@ -302,15 +304,17 @@ const SWIPE_MAX_TRANSLATE = 96;
const SWIPE_DRAG_RESISTANCE = 0.82;
function SwipeableFlightCardComponent({
- children, isPinned, onToggle,
+ children, isPinned, onToggle, ...rest
}: {
children: React.ReactNode;
isPinned: boolean;
onToggle: () => void;
-}) {
+} & ViewProps) {
const translateX = useRef(new Animated.Value(0)).current;
const onToggleRef = useRef(onToggle);
onToggleRef.current = onToggle;
+
+ const hasTriggeredHaptic = useRef(false);
const dragScale = useMemo(() => translateX.interpolate({
inputRange: [-SWIPE_MAX_TRANSLATE, 0],
outputRange: [0.985, 1],
@@ -336,9 +340,17 @@ function SwipeableFlightCardComponent({
? Math.max(g.dx * SWIPE_DRAG_RESISTANCE, -SWIPE_MAX_TRANSLATE)
: g.dx * 0.08;
translateX.setValue(nextTranslate);
+
+ if (nextTranslate <= -SWIPE_THRESHOLD && !hasTriggeredHaptic.current) {
+ Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium);
+ hasTriggeredHaptic.current = true;
+ } else if (nextTranslate > -SWIPE_THRESHOLD && hasTriggeredHaptic.current) {
+ hasTriggeredHaptic.current = false;
+ }
},
onPanResponderRelease: (_, g) => {
if (g.dx < -SWIPE_THRESHOLD || g.vx < -SWIPE_TRIGGER_VELOCITY) {
+ Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success);
Animated.timing(translateX, {
toValue: -SWIPE_MAX_TRANSLATE,
duration: 170,
@@ -351,6 +363,7 @@ function SwipeableFlightCardComponent({
} else {
animateBack(g.vx);
}
+ hasTriggeredHaptic.current = false;
},
onPanResponderTerminate: () => {
animateBack();
@@ -359,7 +372,11 @@ function SwipeableFlightCardComponent({
return (
-
+
{children}
@@ -515,12 +532,29 @@ function FlightRowComponent({ item, activeTab, userShift, pinnedFlightId, onPin,
return () => clearInterval(interval);
}, []);
+ const aLabel = useMemo(() => {
+ const direction = activeTab === 'arrivals' ? t('flightFrom') : t('flightTo');
+ const pinnedState = isPinned ? `${t('flightPinnedLabel')}. ` : '';
+ return `${pinnedState}${flightNumber}, ${airline}, ${direction} ${originDest}, ${time}, ${statusText}`;
+ }, [activeTab, airline, flightNumber, isPinned, originDest, statusText, t, time]);
+
+ const handleAccessibilityAction = useCallback((event: AccessibilityActionEvent) => {
+ if (event.nativeEvent.actionName === 'togglePin') {
+ if (isPinned) onUnpin();
+ else onPin(item);
+ }
+ }, [isPinned, onPin, onUnpin, item]);
+
return (
isPinned ? onUnpin() : onPin(item)}
+ accessible
+ accessibilityLabel={aLabel}
+ accessibilityActions={[{ name: 'togglePin', label: isPinned ? t('flightAccessibilityUnpin') : t('flightAccessibilityPin') }]}
+ onAccessibilityAction={handleAccessibilityAction}
>
-
+
{isPinned && {t('flightPinned')}}
{/* Header */}
From d4a3794a579fd916a761c6cddf0da81140221742 Mon Sep 17 00:00:00 2001
From: "google-labs-jules[bot]"
<161369871+google-labs-jules[bot]@users.noreply.github.com>
Date: Fri, 1 May 2026 00:36:35 +0000
Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8E=A8=20Palette:=20Enhance=20flight?=
=?UTF-8?q?=20card=20haptics=20and=20accessibility?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Add haptic feedback to flight card swipe gestures using expo-haptics.
- Implement comprehensive accessibility labels for flight cards.
- Add accessibility actions (pin/unpin) for screen reader users.
- Add necessary translations for new accessibility strings.
Co-authored-by: TargetMisser <52361977+TargetMisser@users.noreply.github.com>
---
src/i18n/translations.ts | 4 ----
1 file changed, 4 deletions(-)
diff --git a/src/i18n/translations.ts b/src/i18n/translations.ts
index e389828..f3982df 100644
--- a/src/i18n/translations.ts
+++ b/src/i18n/translations.ts
@@ -121,8 +121,6 @@ const it = {
flightCheckin: 'Check-in', flightGate: 'Gate', flightStand: 'Stand', flightBelt: 'Nastro', flightDeparted: 'Partito',
flightLanded: 'Atterrato', flightEstimated: 'Stimato', flightOnTime: 'In orario',
flightPinned: 'PINNATO', flightPinnedLabel: 'Pinnato',
- flightAccessibilityPin: 'Pinna volo', flightAccessibilityUnpin: 'Rimuovi pin',
- flightFrom: 'da', flightTo: 'per',
flightNotifEnabled: 'Notifiche attivate',
flightNotifPermDenied: 'Permesso negato',
flightNotifPermMsg: 'Abilita le notifiche nelle impostazioni del telefono per usare questa funzione.',
@@ -324,8 +322,6 @@ const en: typeof it = {
flightCheckin: 'Check-in', flightGate: 'Gate', flightStand: 'Stand', flightBelt: 'Belt', flightDeparted: 'Departed',
flightLanded: 'Landed', flightEstimated: 'Estimated', flightOnTime: 'On time',
flightPinned: 'PINNED', flightPinnedLabel: 'Pinned',
- flightAccessibilityPin: 'Pin flight', flightAccessibilityUnpin: 'Unpin flight',
- flightFrom: 'from', flightTo: 'to',
flightNotifEnabled: 'Notifications enabled',
flightNotifPermDenied: 'Permission denied',
flightNotifPermMsg: 'Enable notifications in phone settings to use this feature.',