feat(Notification): implement notification preferences management and enhance notification handling
All checks were successful
Frontend CI / build-and-push-web (push) Successful in 8m28s
Frontend CI / ota-android (push) Successful in 11m6s
Frontend CI / build-android-apk (push) Successful in 1h3m35s

- Introduced a new service for managing notification preferences, including push notifications, sound, and vibration settings.
- Updated the notification handling logic to respect user preferences, ensuring notifications are displayed according to user settings.
- Refactored the App and various screens to integrate the new notification preferences, improving user experience and consistency.
- Enhanced the HomeScreen and NotificationSettingsScreen to load and update notification settings seamlessly.
- Implemented a mechanism to hide the bottom tab bar based on scroll events, improving navigation usability.
This commit is contained in:
lafay
2026-03-25 01:30:00 +08:00
parent cedb8284ba
commit 583ac64dfd
19 changed files with 666 additions and 396 deletions

View File

@@ -1,11 +1,12 @@
import { useMemo } from 'react';
import { Platform, useWindowDimensions } from 'react-native';
import { Tabs } from 'expo-router';
import { Tabs, usePathname } from 'expo-router';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { colors, shadows } from '../../../src/theme';
import { BREAKPOINTS } from '../../../src/hooks/useResponsive';
import { useTotalUnreadCount } from '../../../src/stores';
import { useHomeTabBarVisibilityStore, useTotalUnreadCount } from '../../../src/stores';
const TAB_BAR_HEIGHT = 56;
const TAB_BAR_FLOATING_MARGIN = 12;
@@ -14,31 +15,50 @@ const TAB_BAR_MARGIN = 20;
export default function TabsLayout() {
const { width } = useWindowDimensions();
const insets = useSafeAreaInsets();
const pathname = usePathname();
const unreadCount = useTotalUnreadCount();
const scrollHideTabBar = useHomeTabBarVisibilityStore((s) => s.bottomTabBarHiddenByScroll);
const hideTabBar = Platform.OS === 'web' && width >= BREAKPOINTS.desktop;
const isHomeStackRoute = pathname === '/home' || pathname.startsWith('/home/');
const tabBarStyle = useMemo(() => {
if (hideTabBar) {
return { display: 'none' as const, height: 0, overflow: 'hidden' as const };
}
const visibleStyle = {
position: 'absolute' as const,
left: 0,
right: 0,
marginHorizontal: TAB_BAR_MARGIN,
bottom: TAB_BAR_FLOATING_MARGIN + insets.bottom,
height: TAB_BAR_HEIGHT,
borderRadius: 22,
backgroundColor: colors.background.paper,
...shadows.lg,
borderTopWidth: 0,
elevation: 100,
zIndex: 100,
};
if (isHomeStackRoute && scrollHideTabBar) {
return {
...visibleStyle,
display: 'none' as const,
height: 0,
opacity: 0,
overflow: 'hidden' as const,
};
}
return visibleStyle;
}, [hideTabBar, insets.bottom, isHomeStackRoute, scrollHideTabBar]);
return (
<Tabs
screenOptions={{
headerShown: false,
tabBarActiveTintColor: colors.primary.main,
tabBarInactiveTintColor: colors.text.secondary,
tabBarStyle: hideTabBar
? { display: 'none', height: 0, overflow: 'hidden' }
: {
position: 'absolute',
left: 0,
right: 0,
marginHorizontal: TAB_BAR_MARGIN,
bottom: TAB_BAR_FLOATING_MARGIN + insets.bottom,
height: TAB_BAR_HEIGHT,
borderRadius: 22,
backgroundColor: colors.background.paper,
...shadows.lg,
borderTopWidth: 0,
elevation: 100,
zIndex: 100,
},
tabBarStyle,
tabBarItemStyle: {
borderRadius: 16,
marginHorizontal: 2,
@@ -62,13 +82,12 @@ export default function TabsLayout() {
}}
/>
<Tabs.Screen
name="messages"
name="apps"
options={{
title: '消息',
tabBarBadge: unreadCount > 0 ? (unreadCount > 99 ? 99 : unreadCount) : undefined,
title: '应用',
tabBarIcon: ({ color, focused }) => (
<MaterialCommunityIcons
name={focused ? 'message-text' : 'message-text-outline'}
name={focused ? 'view-grid' : 'view-grid-outline'}
size={focused ? 24 : 22}
color={color}
/>
@@ -76,12 +95,13 @@ export default function TabsLayout() {
}}
/>
<Tabs.Screen
name="apps"
name="messages"
options={{
title: '应用',
title: '消息',
tabBarBadge: unreadCount > 0 ? (unreadCount > 99 ? 99 : unreadCount) : undefined,
tabBarIcon: ({ color, focused }) => (
<MaterialCommunityIcons
name={focused ? 'view-grid' : 'view-grid-outline'}
name={focused ? 'message-text' : 'message-text-outline'}
size={focused ? 24 : 22}
color={color}
/>