Add global search, in-app + push notifications, and fix card/beneficiary/scroll issues

- Global feature search for the user app, wired to the home search icon
- Notifications screen: swipe-to-delete, vanish animation, unread badge,
  and Notifee-backed foreground + background (scheduled) OS notifications
- Fix Add Beneficiary save (single source of truth via beneficiaries slice)
- Fix Cards tab scroll freeze and bottom blank space (use ScreenShell scroll)
- User-friendly toast copy across the app
- Android build tuning: parallel/caching/JVM G1 args, mobile-only ABIs

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Abin Toppo
2026-06-02 16:36:27 +05:30
co-authored by Claude Opus 4.8
parent d7907e1d64
commit 58af541536
48 changed files with 1773 additions and 157 deletions
+127 -6
View File
@@ -1,9 +1,130 @@
import { PermissionsAndroid, Platform } from 'react-native';
import notifee, {
AndroidImportance,
AuthorizationStatus,
TriggerType,
type TimestampTrigger,
} from '@notifee/react-native';
export const registerForPushNotifications = async () => {
if (Platform.OS === 'android' && Platform.Version >= 33) {
return PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS);
}
import type { NotificationCategory } from '../../types/app';
return 'granted';
const CHANNEL_ID = 'bankcbs-general';
export type DummyNotificationContent = {
category: NotificationCategory;
title: string;
body: string;
};
const DUMMY_POOL: DummyNotificationContent[] = [
{
category: 'transaction',
title: 'Money received',
body: '₹4,200 was credited to your Savings account from Rohan Mehta.',
},
{
category: 'transaction',
title: 'Payment successful',
body: 'Your payment of ₹1,150 for a mobile recharge went through.',
},
{
category: 'security',
title: 'New sign-in detected',
body: 'A new sign-in was detected on your account. Tap to review.',
},
{
category: 'offer',
title: 'Reward unlocked',
body: 'You just earned 250 reward points on your last card spend.',
},
{
category: 'reminder',
title: 'Bill reminder',
body: 'Your electricity bill of ₹2,340 is due in 3 days.',
},
];
const DEFAULT_CONTENT: DummyNotificationContent = DUMMY_POOL[0] ?? {
category: 'system',
title: 'New notification',
body: 'You have a new update.',
};
export const getDummyNotificationContent = (): DummyNotificationContent => {
const index = Math.floor(Math.random() * DUMMY_POOL.length);
return DUMMY_POOL[index] ?? DEFAULT_CONTENT;
};
let channelReady = false;
const ensureChannel = async () => {
if (!channelReady) {
await notifee.createChannel({
id: CHANNEL_ID,
name: 'General alerts',
importance: AndroidImportance.HIGH,
});
channelReady = true;
}
return CHANNEL_ID;
};
/** Request OS notification permission and make sure the Android channel exists. */
export const registerForPushNotifications = async () => {
const settings = await notifee.requestPermission();
await ensureChannel();
const granted =
settings.authorizationStatus === AuthorizationStatus.AUTHORIZED ||
settings.authorizationStatus === AuthorizationStatus.PROVISIONAL;
return granted ? 'granted' : 'denied';
};
/**
* Show a notification immediately. While the app is in the foreground this
* appears as a heads-up popup (HIGH importance channel); it also lands in the
* system tray.
*/
export const displayLocalNotification = async (content: DummyNotificationContent) => {
const channelId = await ensureChannel();
await notifee.displayNotification({
title: content.title,
body: content.body,
android: {
channelId,
smallIcon: 'ic_launcher',
importance: AndroidImportance.HIGH,
pressAction: { id: 'default' },
},
});
};
/**
* Schedule a notification to fire after `seconds`. This is how we demo a
* background notification: trigger it, then minimise the app and it arrives in
* the system tray even though the app is no longer in the foreground.
*/
export const scheduleLocalNotification = async (
content: DummyNotificationContent,
seconds = 5,
) => {
const channelId = await ensureChannel();
const trigger: TimestampTrigger = {
type: TriggerType.TIMESTAMP,
timestamp: Date.now() + seconds * 1000,
};
await notifee.createTriggerNotification(
{
title: content.title,
body: content.body,
android: {
channelId,
smallIcon: 'ic_launcher',
importance: AndroidImportance.HIGH,
pressAction: { id: 'default' },
},
},
trigger,
);
};