diff --git a/src/assets/images/friendlist/icons/icon_new_message.png b/src/assets/images/friendlist/icons/icon_new_message.png new file mode 100644 index 00000000..f7a31fa0 Binary files /dev/null and b/src/assets/images/friendlist/icons/icon_new_message.png differ diff --git a/src/assets/images/friendlist/icons/icon_warning.png b/src/assets/images/friendlist/icons/icon_warning.png new file mode 100644 index 00000000..3a3ffcf9 Binary files /dev/null and b/src/assets/images/friendlist/icons/icon_warning.png differ diff --git a/src/assets/styles/icons.scss b/src/assets/styles/icons.scss index a5108a7c..3d8f14ab 100644 --- a/src/assets/styles/icons.scss +++ b/src/assets/styles/icons.scss @@ -693,6 +693,18 @@ height: 16px; } + &.icon-friendlist-warning { + background: url('../images/friendlist/icons/icon_warning.png'); + width: 23px; + height: 21px; + } + + &.icon-friendlist-new-message { + background: url('../images/friendlist/icons/icon_new_message.png'); + width: 14px; + height: 16px; + } + &.spin { animation: rotating 1s linear infinite; } diff --git a/src/views/friends/FriendsMessageHandler.tsx b/src/views/friends/FriendsMessageHandler.tsx index e1e055f2..479fc961 100644 --- a/src/views/friends/FriendsMessageHandler.tsx +++ b/src/views/friends/FriendsMessageHandler.tsx @@ -77,7 +77,8 @@ export const FriendsMessageHandler: FC<{}> = props => dispatchFriendsState({ type: FriendsActions.ADD_CHAT_MESSAGE, payload: { - chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, userId, parser.messageText, parser.secondsSinceSent, parser.extraData) + chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, userId, parser.messageText, parser.secondsSinceSent, parser.extraData), + boolValue: true } }); }, [ dispatchFriendsState ]); diff --git a/src/views/friends/common/MessengerChat.ts b/src/views/friends/common/MessengerChat.ts index 2369a7c9..4b49d0ae 100644 --- a/src/views/friends/common/MessengerChat.ts +++ b/src/views/friends/common/MessengerChat.ts @@ -6,19 +6,25 @@ export class MessengerChat private _isRead: boolean; private _messageGroups: MessengerChatMessageGroup[]; - constructor(friendId: number, isRead: boolean = true) + constructor(friendId: number) { this._friendId = friendId; - this._isRead = isRead; + this._isRead = true; this._messageGroups = []; } - public addMessage(message: MessengerChatMessage): void + public addMessage(message: MessengerChatMessage, setAsNotRead: boolean = true, isSystem: boolean = false): void { - if(!this.lastMessageGroup || this.lastMessageGroup.userId !== message.senderId) this._messageGroups.push(new MessengerChatMessageGroup(message.senderId)); + if(!this.lastMessageGroup || this.lastMessageGroup.userId !== message.senderId || isSystem || this.lastMessageGroup.isSystem) this._messageGroups.push(new MessengerChatMessageGroup(message.senderId, isSystem)); this.lastMessageGroup.addMessage(message); - this._isRead = false; + + if(setAsNotRead) this._isRead = false; + } + + public read(): void + { + this._isRead = true; } public get friendId(): number diff --git a/src/views/friends/common/MessengerChatMessage.ts b/src/views/friends/common/MessengerChatMessage.ts index 5ded0a7d..6a0aced7 100644 --- a/src/views/friends/common/MessengerChatMessage.ts +++ b/src/views/friends/common/MessengerChatMessage.ts @@ -2,7 +2,8 @@ export class MessengerChatMessage { public static MESSAGE: number = 0; public static ROOM_INVITE: number = 1; - public static SYSTEM_NOTIFICATION: number = 2; + public static SECURITY_ALERT: number = 2; + public static STATUS_ALERT: number = 3; private _type: number; private _senderId: number; diff --git a/src/views/friends/common/MessengerChatMessageGroup.ts b/src/views/friends/common/MessengerChatMessageGroup.ts index 0bb27fe3..0fad7be8 100644 --- a/src/views/friends/common/MessengerChatMessageGroup.ts +++ b/src/views/friends/common/MessengerChatMessageGroup.ts @@ -4,11 +4,13 @@ export class MessengerChatMessageGroup { private _userId: number; private _messages: MessengerChatMessage[]; + private _isSystem: boolean; - constructor(userId: number) + constructor(userId: number, isSystem: boolean) { this._userId = userId; this._messages = []; + this._isSystem = isSystem; } public addMessage(message: MessengerChatMessage): void @@ -25,4 +27,9 @@ export class MessengerChatMessageGroup { return this._messages; } + + public get isSystem(): boolean + { + return this._isSystem; + } } diff --git a/src/views/friends/reducers/FriendsReducer.tsx b/src/views/friends/reducers/FriendsReducer.tsx index f66ce6fd..82f2e734 100644 --- a/src/views/friends/reducers/FriendsReducer.tsx +++ b/src/views/friends/reducers/FriendsReducer.tsx @@ -19,6 +19,7 @@ export interface IFriendsState friends: MessengerFriend[]; requests: MessengerRequest[]; activeChats: MessengerChat[]; + firstChatEverOpen: boolean; } export interface IFriendsAction @@ -32,6 +33,7 @@ export interface IFriendsAction chats?: MessengerChat[]; chatMessage?: MessengerChatMessage; numberValue?: number; + boolValue?: boolean; } } @@ -43,6 +45,7 @@ export class FriendsActions public static PROCESS_UPDATE: string = 'FA_PROCESS_UPDATE'; public static PROCESS_REQUESTS: string = 'FA_PROCESS_REQUESTS'; public static SET_ACTIVE_CHATS: string = 'FA_SET_ACTIVE_CHATS'; + public static SET_CHAT_READ: string = 'FA_SET_CHAT_READ'; public static ADD_CHAT_MESSAGE: string = 'FA_ADD_CHAT_MESSAGE'; } @@ -50,7 +53,8 @@ export const initialFriends: IFriendsState = { settings: null, friends: [], requests: [], - activeChats: [] + activeChats: [], + firstChatEverOpen: false } export const FriendsReducer: Reducer = (state, action) => @@ -145,11 +149,25 @@ export const FriendsReducer: Reducer = (state, ac case FriendsActions.SET_ACTIVE_CHATS: { const activeChats = (action.payload.chats || []); + if(!state.firstChatEverOpen && activeChats.length > 0) activeChats[0].addMessage(new MessengerChatMessage(MessengerChatMessage.SECURITY_ALERT, 0, null, 0), false, true); + + return { ...state, activeChats, firstChatEverOpen: true }; + } + case FriendsActions.SET_CHAT_READ: { + const friendId = action.payload.numberValue; + + const activeChats = Array.from(state.activeChats); + + let activeChatIndex = activeChats.findIndex(c => c.friendId === friendId); + + if(activeChatIndex > -1) activeChats[activeChatIndex].read(); + return { ...state, activeChats }; } case FriendsActions.ADD_CHAT_MESSAGE: { const message = action.payload.chatMessage; const toFriendId = action.payload.numberValue; + const setAsNotRead = action.payload.boolValue; const activeChats = Array.from(state.activeChats); @@ -157,11 +175,11 @@ export const FriendsReducer: Reducer = (state, ac if(activeChatIndex === -1) { - activeChats.push(new MessengerChat(message.senderId, false)); + activeChats.push(new MessengerChat(message.senderId)); activeChatIndex = activeChats.length - 1; } - activeChats[activeChatIndex].addMessage(message); + activeChats[activeChatIndex].addMessage(message, setAsNotRead); return { ...state, activeChats }; } diff --git a/src/views/friends/views/messenger/FriendsMessengerView.scss b/src/views/friends/views/messenger/FriendsMessengerView.scss index 429f64cf..bbfdb0aa 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.scss +++ b/src/views/friends/views/messenger/FriendsMessengerView.scss @@ -1,5 +1,5 @@ .nitro-friends-messenger { - width: 300px; + width: 280px; .friend-head { position: relative; @@ -7,6 +7,13 @@ height: 40px; overflow: hidden; + .icon { + position: absolute; + top: 1px; + right: 1px; + z-index: 10; + } + .avatar-image { position: absolute; margin-left: -27px; diff --git a/src/views/friends/views/messenger/FriendsMessengerView.tsx b/src/views/friends/views/messenger/FriendsMessengerView.tsx index c3679025..882b435f 100644 --- a/src/views/friends/views/messenger/FriendsMessengerView.tsx +++ b/src/views/friends/views/messenger/FriendsMessengerView.tsx @@ -50,7 +50,7 @@ export const FriendsMessengerView: FC<{}> = props => if(existingChatIndex === -1) { const clonedActiveChats = Array.from(activeChats); - clonedActiveChats.push(new MessengerChat(friendId, true)); + clonedActiveChats.push(new MessengerChat(friendId)); dispatchFriendsState({ type: FriendsActions.SET_ACTIVE_CHATS, @@ -75,8 +75,24 @@ export const FriendsMessengerView: FC<{}> = props => return friend.figure; }, [ friends ]); - const selectedChat = useMemo(() => + const selectChat = useCallback((index: number) => { + const chat = activeChats[index]; + + if(!chat) return; + + dispatchFriendsState({ + type: FriendsActions.SET_CHAT_READ, + payload: { + numberValue: chat.friendId + } + }); + + setSelectedChatIndex(index); + }, [ activeChats, dispatchFriendsState ]); + + const selectedChat = useMemo(() => + { return activeChats[selectedChatIndex]; }, [ activeChats, selectedChatIndex ]); @@ -131,7 +147,8 @@ export const FriendsMessengerView: FC<{}> = props => type: FriendsActions.ADD_CHAT_MESSAGE, payload: { chatMessage: new MessengerChatMessage(MessengerChatMessage.MESSAGE, 0, message, (new Date().getMilliseconds())), - numberValue: selectedChat.friendId + numberValue: selectedChat.friendId, + boolValue: false } }); setMessage(''); @@ -152,7 +169,8 @@ export const FriendsMessengerView: FC<{}> = props =>
{ activeChats && activeChats.map((chat, index) => { - return
setSelectedChatIndex(index) }> + return
selectChat(index) }> + { !chat.isRead && }
; }) } @@ -176,18 +194,31 @@ export const FriendsMessengerView: FC<{}> = props => { selectedChat.messageGroups.map((group, groupIndex) => { return
- { group.userId !== 0 &&
- -
} -
+ { group.isSystem && <> { group.messages.map((message, messageIndex) => - { - return
{ message.message }
- }) } -
- { group.userId === 0 &&
- -
} + { + return
+ { message.type === MessengerChatMessage.SECURITY_ALERT &&
+ +
{ LocalizeText('messenger.moderationinfo') }
+
} +
+ }) } + } + { !group.isSystem && <> + { group.userId !== 0 &&
+ +
} +
+ { group.messages.map((message, messageIndex) => + { + return
{ message.message }
+ }) } +
+ { group.userId === 0 &&
+ +
} + }
; }) }