feat(notification): integrate expo-notifications for permission handling and deep linking
Some checks failed
Frontend CI / ota-android (push) Successful in 1m27s
Frontend CI / build-and-push-web (push) Has been cancelled
Frontend CI / build-android-apk (push) Has been cancelled

- Add expo-notifications dependency and configure with JPush plugin
- Request notification permission on app launch for iOS/Android
- Handle notification taps to navigate to chat or notifications screen
- Add UI to check and request system notification permission in settings
- Refactor background sync: WebSocket disconnects in background, JPush handles push
- Add checkNotificationPermission() and requestNotificationPermission() to jpushService
This commit is contained in:
lafay
2026-04-28 00:20:07 +08:00
parent 296e649fbb
commit b7ce9e3b9a
8 changed files with 188 additions and 137 deletions

View File

@@ -12,6 +12,7 @@ import {
ScrollView,
Alert,
TouchableOpacity,
Platform,
} from 'react-native';
import { SafeAreaView, useSafeAreaInsets } from 'react-native-safe-area-context';
import { MaterialCommunityIcons } from '@expo/vector-icons';
@@ -22,6 +23,7 @@ import {
setPushNotificationsPreference,
setSoundPreference,
setVibrationPreference,
jpushService,
} from '@/services/notification';
import { useResponsive, useResponsiveSpacing } from '../../hooks';
import { backgroundSyncManager, BackgroundSyncMode } from '@/services/background';
@@ -45,6 +47,7 @@ export const NotificationSettingsScreen: React.FC = () => {
const [pushEnabled, setPushEnabled] = useState(true);
const [soundEnabled, setSoundEnabled] = useState(true);
const [syncMode, setSyncMode] = useState<BackgroundSyncMode>(BackgroundSyncMode.BATTERY_SAVER);
const [systemPushEnabled, setSystemPushEnabled] = useState<boolean | null>(null);
const { isWideScreen, isMobile } = useResponsive();
const insets = useSafeAreaInsets();
@@ -60,6 +63,11 @@ export const NotificationSettingsScreen: React.FC = () => {
setPushEnabled(prefs.pushEnabled);
setSoundEnabled(prefs.soundEnabled);
setSyncMode(backgroundSyncManager.getMode());
if (Platform.OS !== 'web') {
const enabled = await jpushService.checkNotificationPermission();
setSystemPushEnabled(enabled);
}
} catch (error) {
console.error('加载通知设置失败:', error);
}
@@ -139,6 +147,21 @@ export const NotificationSettingsScreen: React.FC = () => {
},
];
const handleRequestSystemPermission = async () => {
if (Platform.OS === 'web') return;
const granted = await jpushService.requestNotificationPermission();
setSystemPushEnabled(granted);
if (!granted) {
Alert.alert(
'通知权限未开启',
'请在系统设置中手动开启通知权限,以便及时接收消息提醒。',
[
{ text: '知道了', style: 'cancel' },
]
);
}
};
const settings: NotificationSettingItem[] = [
{
key: 'push',
@@ -207,6 +230,23 @@ export const NotificationSettingsScreen: React.FC = () => {
))}
</View>
{/* 系统通知权限状态(仅移动端) */}
{Platform.OS !== 'web' && systemPushEnabled === false && (
<TouchableOpacity
style={[styles.tipContainer, { backgroundColor: colors.error.main + '14' }]}
onPress={handleRequestSystemPermission}
activeOpacity={0.7}
>
<MaterialCommunityIcons name="alert-circle-outline" size={16} color={colors.error.main} />
<View style={{ flex: 1 }}>
<Text variant="caption" color={colors.error.main} style={styles.tipText}>
</Text>
</View>
<MaterialCommunityIcons name="chevron-right" size={16} color={colors.error.main} />
</TouchableOpacity>
)}
{/* 提示信息 */}
<View style={styles.tipContainer}>
<MaterialCommunityIcons name="information-outline" size={16} color={colors.text.hint} />