feat(message): add conversation notification mute feature
Add notification mute functionality for conversations with the following changes: - Add notification_muted field to ConversationResponse and related DTOs - Add notificationMutedMap to message store for tracking mute state - Add setConversationNotificationMuted API method - Integrate mute toggle in GroupInfoScreen and PrivateChatInfoScreen - Skip system notifications for muted conversations - Suppress vibration for muted conversations in WS handler - Clean up selected mentions when @mentions are removed from text Chore changes: - Update PostCard bookmark icon from 'bookmark' to 'star' - Refine card styles across AppsScreen, MaterialsScreen, and SubjectMaterialsScreen - Improve week selector scrolling to center selected week in ScheduleScreen
This commit is contained in:
@@ -310,6 +310,21 @@ class MessageManager {
|
||||
return useMessageStore.getState().setMutedStatus(groupId, isMuted);
|
||||
}
|
||||
|
||||
isNotificationMuted(conversationId: string): boolean {
|
||||
return useMessageStore.getState().isNotificationMuted(conversationId);
|
||||
}
|
||||
|
||||
setNotificationMuted(conversationId: string, notificationMuted: boolean): void {
|
||||
return useMessageStore.getState().setNotificationMuted(conversationId, notificationMuted);
|
||||
}
|
||||
|
||||
async toggleNotificationMuted(conversationId: string, notificationMuted: boolean): Promise<void> {
|
||||
const { messageService } = await import('@/services/message');
|
||||
await messageService.setConversationNotificationMuted(conversationId, notificationMuted);
|
||||
this.setNotificationMuted(conversationId, notificationMuted);
|
||||
this.updateConversation(conversationId, { notification_muted: notificationMuted });
|
||||
}
|
||||
|
||||
// ==================== 活动会话管理 ====================
|
||||
|
||||
setActiveConversation(conversationId: string | null): void {
|
||||
|
||||
@@ -317,7 +317,8 @@ export class WSMessageHandler implements IWSMessageHandler {
|
||||
!_isAck;
|
||||
|
||||
if (shouldIncrementUnread) {
|
||||
if (!suppressVibration) {
|
||||
const isNotificationMuted = store.isNotificationMuted(normalizedConversationId);
|
||||
if (!suppressVibration && !isNotificationMuted) {
|
||||
const vibrationType = message.type === 'group_message' ? 'group_message' : 'message';
|
||||
eventBus.emit({ type: 'VIBRATE', payload: { type: vibrationType } });
|
||||
}
|
||||
|
||||
@@ -55,6 +55,9 @@ export interface MessageState {
|
||||
|
||||
// 当前用户的禁言状态 - 按群组ID存储
|
||||
mutedStatusMap: Map<string, boolean>;
|
||||
|
||||
// 会话免打扰状态 - 按会话ID存储
|
||||
notificationMutedMap: Map<string, boolean>;
|
||||
}
|
||||
|
||||
// ==================== Actions 接口 ====================
|
||||
@@ -72,6 +75,7 @@ export interface MessageActions {
|
||||
getTypingUsers: (groupId: string) => string[];
|
||||
isMuted: (groupId: string) => boolean;
|
||||
getActiveConversation: () => string | null;
|
||||
isNotificationMuted: (conversationId: string) => boolean;
|
||||
|
||||
// 设置状态
|
||||
setConversations: (conversations: Map<string, ConversationResponse>) => void;
|
||||
@@ -88,6 +92,7 @@ export interface MessageActions {
|
||||
setLoadingMessages: (conversationId: string, loading: boolean) => void;
|
||||
setTypingUsers: (groupId: string, users: string[]) => void;
|
||||
setMutedStatus: (groupId: string, isMuted: boolean) => void;
|
||||
setNotificationMuted: (conversationId: string, notificationMuted: boolean) => void;
|
||||
setInitialized: (initialized: boolean) => void;
|
||||
|
||||
// 重置
|
||||
@@ -110,6 +115,7 @@ const initialState: MessageState = {
|
||||
isInitialized: false,
|
||||
typingUsersMap: new Map(),
|
||||
mutedStatusMap: new Map(),
|
||||
notificationMutedMap: new Map(),
|
||||
};
|
||||
|
||||
// ==================== 工具函数 ====================
|
||||
@@ -177,6 +183,7 @@ export const useMessageStore = create<MessageStore>((set, get) => ({
|
||||
isInitialized: state.isInitialized,
|
||||
typingUsersMap: state.typingUsersMap,
|
||||
mutedStatusMap: state.mutedStatusMap,
|
||||
notificationMutedMap: state.notificationMutedMap,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -227,11 +234,25 @@ export const useMessageStore = create<MessageStore>((set, get) => ({
|
||||
return get().currentConversationId;
|
||||
},
|
||||
|
||||
isNotificationMuted: (conversationId: string) => {
|
||||
return get().notificationMutedMap.get(conversationId) || false;
|
||||
},
|
||||
|
||||
// ==================== 设置状态 ====================
|
||||
|
||||
setConversations: (conversations: Map<string, ConversationResponse>) => {
|
||||
const conversationList = sortConversationList(conversations);
|
||||
set({ conversations, conversationList });
|
||||
const notificationMutedMap = new Map<string, boolean>();
|
||||
conversations.forEach((conv, id) => {
|
||||
if (conv.notification_muted) {
|
||||
notificationMutedMap.set(id, true);
|
||||
}
|
||||
});
|
||||
set(state => ({
|
||||
conversations,
|
||||
conversationList,
|
||||
notificationMutedMap: new Map([...state.notificationMutedMap, ...notificationMutedMap]),
|
||||
}));
|
||||
},
|
||||
|
||||
updateConversation: (conversation: ConversationResponse) => {
|
||||
@@ -240,7 +261,13 @@ export const useMessageStore = create<MessageStore>((set, get) => ({
|
||||
const newConversations = new Map(state.conversations);
|
||||
newConversations.set(id, { ...conversation, id });
|
||||
const conversationList = sortConversationList(newConversations);
|
||||
return { conversations: newConversations, conversationList };
|
||||
const newNotificationMutedMap = new Map(state.notificationMutedMap);
|
||||
if (conversation.notification_muted) {
|
||||
newNotificationMutedMap.set(id, true);
|
||||
} else {
|
||||
newNotificationMutedMap.delete(id);
|
||||
}
|
||||
return { conversations: newConversations, conversationList, notificationMutedMap: newNotificationMutedMap };
|
||||
});
|
||||
},
|
||||
|
||||
@@ -374,6 +401,14 @@ export const useMessageStore = create<MessageStore>((set, get) => ({
|
||||
});
|
||||
},
|
||||
|
||||
setNotificationMuted: (conversationId: string, notificationMuted: boolean) => {
|
||||
set(state => {
|
||||
const newNotificationMutedMap = new Map(state.notificationMutedMap);
|
||||
newNotificationMutedMap.set(conversationId, notificationMuted);
|
||||
return { notificationMutedMap: newNotificationMutedMap };
|
||||
});
|
||||
},
|
||||
|
||||
setInitialized: (initialized: boolean) => {
|
||||
set({ isInitialized: initialized });
|
||||
},
|
||||
@@ -388,6 +423,7 @@ export const useMessageStore = create<MessageStore>((set, get) => ({
|
||||
loadingMessagesSet: new Set(),
|
||||
typingUsersMap: new Map(),
|
||||
mutedStatusMap: new Map(),
|
||||
notificationMutedMap: new Map(),
|
||||
});
|
||||
AsyncStorage.removeItem(LAST_SYSTEM_MESSAGE_AT_KEY).catch(() => {});
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user