feat(notification): migrate from expo-notifications to JPush push service
Some checks failed
Frontend CI / build-and-push-web (push) Has started running
Frontend CI / ota-android (push) Has been cancelled
Frontend CI / build-android-apk (push) Has been cancelled

Replace expo-notifications with JPush for push notifications across the app.
This includes adding JPush native module dependencies, configuring the JPush
plugin in app.json, implementing jpushService wrapper, and updating notification
services to use JPush APIs. Also adds device registration on token refresh for
both mobile and web platforms.

BREAKING CHANGE: expo-notifications removed in favor of JPush for push notifications
This commit is contained in:
lafay
2026-04-27 23:21:08 +08:00
parent 0e4306c3ac
commit ba89b3dc94
13 changed files with 690 additions and 163 deletions

View File

@@ -356,10 +356,10 @@ class ApiClient {
const data = await response.json();
if (data.code === 0 && data.data?.token) {
await this.setToken(data.data.token);
// 后端返回refresh_token (snake_case),兼容两种命名
if (data.data.refresh_token || data.data.refreshToken) {
await this.setRefreshToken(data.data.refresh_token || data.data.refreshToken);
}
this.registerDeviceOnRefresh();
return true;
}
@@ -370,6 +370,52 @@ class ApiClient {
}
}
// 冷启动/刷新token后自动注册设备方便存量设备接入
private registerDeviceOnRefresh(): void {
(async () => {
try {
const { pushService } = await import('../notification/pushService');
const { jpushService } = await import('../notification/jpushService');
const AsyncStorage = (await import('@react-native-async-storage/async-storage')).default;
const DEVICE_ID_KEY = 'withyou_device_id';
let deviceId = await AsyncStorage.getItem(DEVICE_ID_KEY);
if (Platform.OS === 'web') {
if (!deviceId) {
const timestamp = Date.now().toString(36);
const random = Math.random().toString(36).substring(2, 8);
deviceId = `web_${timestamp}_${random}`;
await AsyncStorage.setItem(DEVICE_ID_KEY, deviceId);
}
await pushService.registerDevice({
device_id: deviceId,
device_type: 'web',
device_name: 'Web Browser',
});
} else {
// Mobile: use JPush registration ID if available
const regID = jpushService.getRegistrationIDValue();
if (!deviceId) {
const timestamp = Date.now().toString(36);
const random = Math.random().toString(36).substring(2, 8);
deviceId = `${Platform.OS}_${timestamp}_${random}`;
await AsyncStorage.setItem(DEVICE_ID_KEY, deviceId);
}
await pushService.registerDevice({
device_id: deviceId,
device_type: Platform.OS === 'ios' ? 'ios' : 'android',
...(regID ? { push_token: regID } : {}),
device_name: `${Platform.OS === 'ios' ? 'iOS' : 'Android'} Device`,
});
}
console.log('[API] device registered on token refresh');
} catch (error) {
console.warn('[API] device register on refresh failed:', error);
}
})();
}
// GET 请求
async get<T>(path: string, params?: Record<string, any>): Promise<ApiResponse<T>> {
return this.request<T>('GET', path, params);