Skip to content

Commit 7f85d6f

Browse files
authored
Merge pull request #59 from fleetbase/patch/fix-android-notifications
v2.0.3 ~ fix android push notifications + add POD viewing + Order UI update
2 parents a8d75f4 + 4316cd3 commit 7f85d6f

19 files changed

+1252
-968
lines changed
Binary file not shown.

android/app/build.gradle

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ dependencies {
133133
implementation project(':react-native-notifications')
134134
implementation project(':react-native-i18n')
135135
implementation project(':react-native-config')
136+
137+
// Firebase setup
138+
implementation platform('com.google.firebase:firebase-bom:32.7.3')
139+
implementation 'com.google.firebase:firebase-messaging'
140+
141+
// Splash screen
136142
implementation 'androidx.core:core-splashscreen:1.0.0-alpha02'
137143

138144
if (hermesEnabled.toBoolean()) {

android/app/src/main/AndroidManifest.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
1313
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" />
1414
<uses-permission android:name="android.permission.INTERNET"/>
15+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
1516
<application
1617
android:name=".MainApplication"
1718
android:label="@string/app_name"
@@ -41,6 +42,8 @@
4142
<data android:scheme="${appLinkScheme}" />
4243
</intent-filter>
4344
</activity>
45+
<meta-data android:name="com.google.firebase.messaging.default_notification_icon" android:resource="@drawable/ic_notification" />
46+
<meta-data android:name="com.google.firebase.messaging.default_notification_color" android:resource="@color/colorAccent" />
4447
<meta-data android:name="com.transistorsoft.locationmanager.license" android:value="@string/TRANSISTORSOFT_LICENSE_KEY" />
4548
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/FACEBOOK_APP_ID"/>
4649
<meta-data android:name="com.facebook.sdk.ClientToken" android:value="@string/FACEBOOK_CLIENT_TOKEN"/>

android/app/src/main/assets/index.android.bundle

Lines changed: 936 additions & 936 deletions
Large diffs are not rendered by default.
69.6 KB
Loading
33.5 KB
Loading
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
<resources>
22
<color name="bootsplash_background">#111827</color>
3+
<color name="colorAccent">#111827</color>
34
</resources>

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@fleetbase/navigator-app",
3-
"version": "2.0.2",
3+
"version": "2.0.3",
44
"license": "AGPL-3.0-or-later",
55
"author": "Fleetbase Pte Ltd <hello@fleetbase.io>",
66
"description": "Order management, geolocation tracking and navigation for Fleetbase drivers.",
@@ -136,7 +136,7 @@
136136
},
137137
"resolutions": {
138138
"react-native-i18n@^2.0.15": "patch:react-native-i18n@npm%3A2.0.15#./.yarn/patches/react-native-i18n-npm-2.0.15-7f3cf7cee6.patch",
139-
"react-native-notifications@^5.1.0": "patch:react-native-notifications@npm%3A5.1.0#./.yarn/patches/react-native-notifications-npm-5.1.0-3e3b2ea3f8.patch",
140-
"react-native-launch-navigator@^1.0.9": "patch:react-native-launch-navigator@npm%3A1.0.9#./.yarn/patches/react-native-launch-navigator-npm-1.0.9-f069a6b5fd.patch"
139+
"react-native-launch-navigator@^1.0.9": "patch:react-native-launch-navigator@npm%3A1.0.9#./.yarn/patches/react-native-launch-navigator-npm-1.0.9-f069a6b5fd.patch",
140+
"react-native-notifications@^5.1.0": "patch:react-native-notifications@npm%3A5.1.0#./.yarn/patches/react-native-notifications-npm-5.1.0-3e3b2ea3f8.patch"
141141
}
142142
}

src/components/OrderActivitySelect.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import PlaceMapView from './PlaceMapView';
1515
import Spacer from './Spacer';
1616
import Badge from './Badge';
1717

18-
const OrderActivitySelect = forwardRef(({ onChange, waypoint, activities = [], snapTo = '100%', isLoading = false, activityLoading, ...props }, ref) => {
18+
const OrderActivitySelect = forwardRef(({ onChange, waypoint, activities = [], snapTo = '100%', isLoading = false, activityLoading, portalHost = 'MainPortal', ...props }, ref) => {
1919
const theme = useTheme();
2020
const navigation = useNavigation();
2121
const { isDarkMode } = useAppTheme();
@@ -97,7 +97,7 @@ const OrderActivitySelect = forwardRef(({ onChange, waypoint, activities = [], s
9797

9898
return (
9999
<YStack>
100-
<Portal hostName='MainPortal'>
100+
<Portal hostName={portalHost}>
101101
<BottomSheet
102102
ref={bottomSheetRef}
103103
index={-1}
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import React, { useRef, useState, useEffect, useCallback } from 'react';
2+
import { useNavigation, useFocusEffect } from '@react-navigation/native';
3+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
4+
import { FlatList, Pressable, Modal } from 'react-native';
5+
import { SimpleGrid } from 'react-native-super-grid';
6+
import { FontAwesomeIcon } from '@fortawesome/react-native-fontawesome';
7+
import { faTimes, faQrcode } from '@fortawesome/free-solid-svg-icons';
8+
import { Text, YStack, XStack, useTheme, Button } from 'tamagui';
9+
import { format } from 'date-fns';
10+
import FastImage from 'react-native-fast-image';
11+
import useStorage from '../hooks/use-storage';
12+
import useFleetbase from '../hooks/use-fleetbase';
13+
14+
const PROOF_COLUMN_WIDTH = 160;
15+
16+
const OrderProofOfDelivery = ({ order, subject }) => {
17+
const { adapter } = useFleetbase();
18+
const theme = useTheme();
19+
const insets = useSafeAreaInsets();
20+
const id = order.id ?? null;
21+
const [proofs, setProofs] = useStorage(`${id}_proofs`, []);
22+
const [isLoading, setIsLoading] = useState(false);
23+
const [fullscreenImage, setFullscreenImage] = useState(null);
24+
25+
const loadOrderProof = useCallback(async () => {
26+
if (!adapter) return;
27+
setIsLoading(true);
28+
29+
const subjectSuffix = subject ? `/${subject.id}` : '';
30+
31+
try {
32+
const proofs = await adapter.get(`orders/${order.id}/proofs${subjectSuffix}`);
33+
setProofs(proofs);
34+
return proofs;
35+
} catch (err) {
36+
console.warn('Error loading order proofs:', err);
37+
} finally {
38+
setIsLoading(false);
39+
}
40+
}, [adapter]);
41+
42+
const openImage = (proof) => {
43+
let url = proof.url;
44+
if (proof.remarks.endsWith('Signature')) {
45+
url = proof.raw;
46+
}
47+
setFullscreenImage(url);
48+
};
49+
50+
const closeImage = () => {
51+
setFullscreenImage(null);
52+
};
53+
54+
const renderProof = ({ item: proof }) => {
55+
return (
56+
<YStack px='$3' py='$2' width={PROOF_COLUMN_WIDTH}>
57+
<YStack mb='$2'>
58+
<Pressable onPress={() => openImage(proof)}>
59+
{proof.remarks.endsWith('Photo') && (
60+
<FastImage
61+
source={{ uri: proof.url }}
62+
style={{
63+
width: PROOF_COLUMN_WIDTH - 25,
64+
height: PROOF_COLUMN_WIDTH - 25,
65+
borderRadius: 8,
66+
}}
67+
/>
68+
)}
69+
{proof.remarks.endsWith('Signature') && (
70+
<FastImage
71+
source={{ uri: proof.raw }}
72+
style={{
73+
width: PROOF_COLUMN_WIDTH - 25,
74+
height: PROOF_COLUMN_WIDTH - 25,
75+
borderRadius: 8,
76+
}}
77+
/>
78+
)}
79+
{proof.remarks.endsWith('Scan') && (
80+
<YStack alignItems='center' justifyContent='center'>
81+
<FontAwesomeIcon icon={faQrcode} color={theme['$blue-400'].val} size={40} />
82+
</YStack>
83+
)}
84+
</Pressable>
85+
</YStack>
86+
<YStack textAlign='center' alignItems='center' justifyContent='center' width='100%' flex={1}>
87+
<Text color='$textPrimary' fontSize='$2' textAlign='center' fontWeight='bold' mb='$1'>
88+
{proof.remarks}
89+
</Text>
90+
<Text color='$textSecondary' fontSize='$2' textAlign='center'>
91+
{proof.id}
92+
</Text>
93+
<Text color='$textSecondary' fontSize='$2' textAlign='center'>
94+
{format(proof.created_at, 'MMM d, Y HH:mm')}
95+
</Text>
96+
</YStack>
97+
</YStack>
98+
);
99+
};
100+
101+
useFocusEffect(
102+
useCallback(() => {
103+
loadOrderProof();
104+
}, [id])
105+
);
106+
107+
if (proofs.length === 0) {
108+
return (
109+
<YStack py='$5' alignItems='center' justifyContent='center'>
110+
<Text color='$textSecondary'>No Proof of Delivery Captured.</Text>
111+
</YStack>
112+
);
113+
}
114+
115+
return (
116+
<YStack>
117+
<SimpleGrid
118+
data={proofs}
119+
maxItemsPerRow={2}
120+
itemDimension={PROOF_COLUMN_WIDTH}
121+
scrollEnabled={false}
122+
showsVerticalScrollIndicator={false}
123+
showsHorizontalScrollIndicator={false}
124+
keyExtractor={(item, index) => item.id || index}
125+
renderItem={renderProof}
126+
/>
127+
128+
{fullscreenImage && (
129+
<Modal visible={true} animationType='fade' transparent={true}>
130+
<YStack position='absolute' fullscreen bg='rgba(0,0,0,0.9)' justifyContent='center' alignItems='center' zIndex={9999}>
131+
<Button position='absolute' top={20} right={20} size='$3' circular bg='$colorTransparent' onPress={closeImage} zIndex={10000} mt={insets.top}>
132+
<FontAwesomeIcon icon={faTimes} color={theme['$textPrimary'].val} />
133+
</Button>
134+
135+
<FastImage
136+
source={{ uri: fullscreenImage }}
137+
style={{
138+
width: '100%',
139+
height: '100%',
140+
resizeMode: 'contain',
141+
}}
142+
/>
143+
</YStack>
144+
</Modal>
145+
)}
146+
</YStack>
147+
);
148+
};
149+
150+
export default OrderProofOfDelivery;

0 commit comments

Comments
 (0)