Conversation
Refactor build configuration and fix jsEngine issues
UI improvements for all screens
Add background running applications and improve crash safety
Fixed back button exitting from app issue
Chat feature
eas build workflow change
transfer project to organization
- Set handling Contactus form data Co-authored-by: Lal Pushpakumaran <161225569+LPK98@users.noreply.github.com>
Implement dashboard announcements, safety indicators, and new pages
There was a problem hiding this comment.
Pull request overview
This PR expands the app’s dashboard and supporting screens with new UI patterns (themed cards, back navigation behavior), adds safety indicators (crime color mapping + Safety Zone map styling), and introduces new feature areas like announcements, chat with media/voice, and background duty location tracking.
Changes:
- Added announcements fetching/service + dashboard carousel UI.
- Implemented chat messaging with Firebase (subscribe/send) plus image/audio upload and new chat UI components.
- Improved duty background location tracking (task definition, permission error codes, bootstrap on app start) and updated multiple screens’ layouts/navigation and theming.
Reviewed changes
Copilot reviewed 45 out of 46 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| src/utils/utils.ts | Adds a helper to map crime type → color. |
| src/types/weaponTypes.ts | Extends weapon type with imageUrl. |
| src/types/crime.ts | Adds a new crime-type constant/type definition. |
| src/types/chat.ts | Introduces chat/message payload types for text/image/audio. |
| src/types/announcement.ts | Adds Announcement / tag typing. |
| src/types/AuthContextDefinition.ts | Extends AuthUser with badgeNo. |
| src/theme/theme.ts | Adds black color token; adjusts dark background. |
| src/services/weapon/weaponService.ts | Normalizes weapon responses; maps imageUrl; returns typed list. |
| src/services/location/locationTracker.ts | Adds permission error codes; android foreground service config; safer task definition. |
| src/services/location/locationBootstrap.ts | Bootstraps location DB + resumes/stops tracking on startup based on duty toggle. |
| src/services/chat/mediaUpload.ts | Uploads chat media to Firebase Storage and returns download URLs. |
| src/services/chat/chatService.ts | Adds Firestore subscribe/send wrappers for chat messages. |
| src/services/authService.ts | Maps backend badgeNo into AuthUser. |
| src/services/announcementService.ts | Fetches announcements with flexible response-shape extraction. |
| src/constants/crimeTypeColors.ts | Defines crime-type → hex color mapping. |
| src/components/chat/VoiceMessage.tsx | Voice message playback UI using expo-av. |
| src/components/chat/MessageBubble.tsx | Renders message bubble variations (text/image/audio). |
| src/components/chat/ImageMessage.tsx | Renders image messages with fullscreen modal. |
| src/components/chat/ChatInput.tsx | Adds chat input with image picker + voice recording + upload flow. |
| src/components/WeaponListItem.tsx | Displays weapon images via weapon.imageUrl and passes to route params. |
| src/components/UI/Searchbar.tsx | Converts Searchbar into a controlled component with theme support + ref prop. |
| src/components/TopSectionTemplate.tsx | Updates back navigation behavior to use canGoBack() fallback. |
| src/components/TopBar.tsx | New styled top bar with avatar initial + welcome text. |
| src/components/SideBar.tsx | Activates routes for Contact/Translate/FAQ and adjusts navigation behavior. |
| package.json | Adds expo-av dependency. |
| package-lock.json | Locks expo-av dependency. |
| firebase.js | Adds Firebase Storage initialization/export. |
| app/login.tsx | Refactors login screen styling to be theme-aware and more structured. |
| app/_layout.tsx | Bootstraps location tracking after auth load; custom Android hardware back handler. |
| app/Translate.tsx | Adds Translate screen UI and sidebar integration. |
| app/Settings.tsx | Refactors Settings UI into themed cards and improved layout. |
| app/FAQPage.tsx | Adds FAQ screen UI with accessible expand/collapse. |
| app/DutyToggleScreen.tsx | Adds permission-specific error handling and settings deep link prompts. |
| app/Dashboard.tsx | Adds announcements carousel + refreshed menu layout/icons. |
| app/ContactUs.tsx | Adds Contact Us screen with Google Form submission + call/email shortcuts. |
| app/Chat.tsx | Replaces prior chat implementation with new service + media-capable UI. |
| app/(screens)/[serialNo].tsx | Updates weapon request UI; supports banner image URL + improved layout. |
| app/(screens)/WeaponRequest.tsx | Improves weapon selection UI; uses typed weapon list and loading state. |
| app/(screens)/Weapon.tsx | Refactors weapon management UI and navigation; adds themed background. |
| app/(screens)/SafetyZone.tsx | Overhauls Safety Zone UI; uses crime color circles and themed layout. |
| app/(screens)/Plate.tsx | Refactors plate registry screen to themed UI with filters and responsive layout. |
| app/(screens)/Duty.tsx | Updates duty calendar screen UI/logic (per PR file list). |
| app/(screens)/BulletRequest.tsx | Refactors ammo request UI with progress + slider and themed layout. |
| app.config.js | Updates Expo config: slug/owner/projectId + maps keys + location permissions/plugins. |
| .github/workflows/eas-build.yml | Updates Expo token secret used in EAS builds. |
| .github/workflows/codeql.yml | Expands CodeQL scanning to the dev branch. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const handleMenuPress = (item: SideBarItem) => { | ||
| if (item.status === "placeholder") { | ||
| Alert.alert( | ||
| "Coming soon", | ||
| item.helperText ?? "This feature is not ready yet.", | ||
| ); | ||
| return; | ||
| } | ||
| // if (item.status === "placeholder") { | ||
| // Alert.alert( | ||
| // "Coming soon", | ||
| // item.helperText ?? "This feature is not ready yet.", |
There was a problem hiding this comment.
There is a block of commented-out placeholder alert logic in handleMenuPress marked //REMOVE. Please delete this commented code (or restore the placeholder behavior) to keep the handler readable and avoid shipping dead code.
| TaskManager.defineTask(TASK_NAME, async ({ data, error }) => { | ||
| console.log("[LOCATION] Background task triggered"); //REMOVE: for testing | ||
| if (error) { | ||
| console.error("[LOCATION] Task error", error); //REMOVE: for testing | ||
| return; |
There was a problem hiding this comment.
Background location tasks still have console logs marked //REMOVE: for testing. These can be noisy (and sometimes expensive) in production builds, especially when running frequently in the background. Please remove them or guard them behind a dev-only flag.
| <View style={styles.mapUnavailable}> | ||
| <Text | ||
| style={[styles.mapUnavailableText, { color: colors.text }]} | ||
| > | ||
| Map is loading. Please wait... |
There was a problem hiding this comment.
The fallback UI here is also shown when the Google Maps API key is missing (!hasGoogleMapsApiKey). In that case, the message "Map is loading" is misleading and will never resolve. Split the condition so missing-key shows a distinct configuration message (and/or disables map actions).
| type SearchbarProps = { | ||
| onChange: (text: string) => void; | ||
| value: string; | ||
| searchInputRef: React.RefObject<HTMLInputElement | null>; |
There was a problem hiding this comment.
searchInputRef is typed as React.RefObject<HTMLInputElement | null>, but this is a React Native TextInput (not a DOM input). This will either fail type-checking (depending on TS libs) or encourage incorrect usage. Type the ref as React.RefObject<TextInput | null> (or React.Ref<TextInput>) and import the TextInput type from react-native.
| searchInputRef: React.RefObject<HTMLInputElement | null>; | |
| searchInputRef: React.RefObject<TextInput | null>; |
| const hasGoogleMapsApiKey = Boolean(appConfig.googleMapsApiKey?.trim()); | ||
| const searchInputRef = React.useRef<HTMLInputElement | null>(null); | ||
|
|
There was a problem hiding this comment.
searchInputRef is declared as React.useRef<HTMLInputElement | null>, but the ref is passed to a React Native TextInput. Use React.useRef<TextInput | null>(null) (from react-native) to match the actual component type.
| "axios": "^1.13.2", | ||
| "dotenv": "^17.3.1", | ||
| "expo": "~54.0.31", | ||
| "expo-av": "^16.0.8", |
There was a problem hiding this comment.
Expo modules are typically pinned with ~ (or an exact version) to match the Expo SDK. Using a caret (^16.0.8) for expo-av can accidentally pull an incompatible minor version. Prefer the Expo-recommended version range (e.g., ~16.0.x) via npx expo install expo-av.
| "expo-av": "^16.0.8", | |
| "expo-av": "~16.0.8", |
| const count = countPendingLocations(); //REMOVE:for testing | ||
| console.log("[LOCATION] Pending rows in SQLite:", count); |
There was a problem hiding this comment.
Calling countPendingLocations() on every background task run adds an extra SQLite query purely for logging (also marked //REMOVE). Consider removing this debug-only count/log to reduce background work.
| weaponType: raw?.weaponType ?? raw?.weapon_type, | ||
| status: raw?.status, | ||
| updatedDate: raw?.updatedDate ?? raw?.updated_date, | ||
| registerDate: raw?.registerDate ?? raw?.register_date, | ||
| imageUrl: typeof imageUrl === "string" ? imageUrl : undefined, |
There was a problem hiding this comment.
weaponType.updatedDate / registerDate are typed as Date, but this normalization assigns raw API values directly (often strings). This breaks the contract of weaponType. Either parse these into Dates here, or widen the type in weaponTypes.ts to accept string | Date and normalize consistently.
| width: 20, | ||
| height: 20, | ||
| borderRadius: 10, |
There was a problem hiding this comment.
checkboxInner is 20x20, but the outer checkbox container is 14x14. This will overflow/clamp and can cause layout issues. Make the inner element fit within the outer (or simplify to a single styled checkbox container).
| width: 20, | |
| height: 20, | |
| borderRadius: 10, | |
| width: 10, | |
| height: 10, | |
| borderRadius: 5, |
| ]).start(); | ||
| }, [isSidebarOpen, overlayOpacity, slideX]); | ||
|
|
||
| const diadNumber = (number: string) => { |
There was a problem hiding this comment.
Function name diadNumber looks like a typo (likely meant dialNumber). Renaming it will make the intent clearer and improve searchability.
| const diadNumber = (number: string) => { | |
| const dialNumber = (number: string) => { |
No description provided.