build(config): update bundle identifier and add signing plugin
All checks were successful
Frontend CI / ota-ios (push) Successful in 1m33s
Frontend CI / ota-android (push) Successful in 1m40s
Frontend CI / build-and-push-web (push) Successful in 2m37s
Frontend CI / build-android-apk (push) Successful in 1h22m51s

feat(notification): improve JPush integration and message sync reliability

- Update iOS bundle identifier to `cn.qczlit.weiyou`
- Add `withSigning` Expo plugin
- Enhance `withJPush` plugin with improved Swift AppDelegate injection logic
- Update JPush default channel to `developer-default`
- Optimize `MessageSyncService` to prevent race conditions in unread count updates
- Implement promise deduplication for `fetchUnreadCount` to prevent redundant network requests
- Add `setConversationsWithUnread` to `useMessageStore` for atomic state updates of conversations and unread counts
This commit is contained in:
2026-05-12 01:28:46 +08:00
parent 1d9c312c6c
commit 7c7aaf9108
8 changed files with 243 additions and 32 deletions

View File

@@ -35,6 +35,8 @@ export class MessageSyncService implements IMessageSyncService {
private loadingMoreConversations = false;
/** 聊天页活跃期间延迟的会话列表刷新 */
private deferredConversationRefresh = false;
/** fetchUnreadCount 去重:复用 in-flight promise */
private fetchUnreadCountPromise: Promise<void> | null = null;
constructor(
getCurrentUserId: () => string | null,
@@ -108,15 +110,12 @@ export class MessageSyncService implements IMessageSyncService {
newConversations.set(normalizedConv.id, normalizedConv);
});
// 使用 store.setConversations 会自动排序并更新 conversationList
store.setConversations(newConversations);
// 计算并更新未读数
// 合并更新conversations + totalUnread 在同一次 set 中完成,消除中间状态窗口
const totalUnread = Array.from(newConversations.values()).reduce(
(sum, conv) => sum + (conv.unread_count || 0),
0
0,
);
store.setUnreadCount(totalUnread, store.getUnreadCount().system);
store.setConversationsWithUnread(newConversations, totalUnread, store.getUnreadCount().system);
this.persistConversationListCache();
} catch (error) {
@@ -360,11 +359,23 @@ export class MessageSyncService implements IMessageSyncService {
}
/**
* 获取未读数
* 获取未读数(去重:复用 in-flight promise
*/
async fetchUnreadCount(): Promise<void> {
if (this.fetchUnreadCountPromise) {
return this.fetchUnreadCountPromise;
}
this.fetchUnreadCountPromise = this.doFetchUnreadCount();
try {
await this.fetchUnreadCountPromise;
} finally {
this.fetchUnreadCountPromise = null;
}
}
private async doFetchUnreadCount(): Promise<void> {
const store = useMessageStore.getState();
try {
const [unreadData, systemUnreadData] = await Promise.all([
messageService.getUnreadCount(),
@@ -388,21 +399,28 @@ export class MessageSyncService implements IMessageSyncService {
}
}
// 服务端汇总未读为 0 时,清掉内存中残留的红点
// 服务端汇总未读为 0 时,仅在本地也一致时才清零(避免缓存竞态导致的抖动)
if (totalUnread === 0) {
const currentConversations = store.getState().conversations;
let anyCleared = false;
const newConversations = new Map(currentConversations);
for (const [cid, conv] of newConversations) {
if ((conv.unread_count || 0) > 0) {
newConversations.set(cid, { ...conv, unread_count: 0 });
anyCleared = true;
const localSum = Array.from(store.getState().conversations.values())
.reduce((sum, conv) => sum + (conv.unread_count || 0), 0);
if (localSum > 0) {
// 本地有未读但服务端返回 0 → 可能是后端缓存竞态,保留本地状态
// 下一次 fetchConversations 会提供权威的 per-conversation 数据
} else {
// 本地也无未读,确认清零
const currentConversations = store.getState().conversations;
let anyCleared = false;
const newConversations = new Map(currentConversations);
for (const [cid, conv] of newConversations) {
if ((conv.unread_count || 0) > 0) {
newConversations.set(cid, { ...conv, unread_count: 0 });
anyCleared = true;
}
}
if (anyCleared) {
store.setConversations(newConversations);
this.persistConversationListCache();
}
}
if (anyCleared) {
// 使用 zustand set 函数正确更新状态
store.setConversations(newConversations);
this.persistConversationListCache();
}
}
} catch (error) {
@@ -487,15 +505,12 @@ export class MessageSyncService implements IMessageSyncService {
newConversations.set(normalizedConv.id, normalizedConv);
});
// 使用 store.setConversations 会自动排序并更新 conversationList
store.setConversations(newConversations);
// 计算并更新未读数
// 合并更新conversations + totalUnread 在同一次 set 中完成
const totalUnread = Array.from(newConversations.values()).reduce(
(sum, conv) => sum + (conv.unread_count || 0),
0
0,
);
store.setUnreadCount(totalUnread, store.getUnreadCount().system);
store.setConversationsWithUnread(newConversations, totalUnread, store.getUnreadCount().system);
return true;
}