248 lines
9.5 KiB
Lua
248 lines
9.5 KiB
Lua
local CoreGui = game:GetService("CoreGui")
|
|
|
|
local Modules = CoreGui.RobloxGui.Modules
|
|
local Common = Modules.Common
|
|
local LuaChat = Modules.LuaChat
|
|
local Actions = LuaChat.Actions
|
|
|
|
local ChangedParticipants = require(Actions.ChangedParticipants)
|
|
local FetchedOldestMessage = require(Actions.FetchedOldestMessage)
|
|
local FetchingOlderMessages = require(Actions.FetchingOlderMessages)
|
|
local MessageFailedToSend = require(Actions.MessageFailedToSend)
|
|
local MessageModerated = require(Actions.MessageModerated)
|
|
local ReadConversation = require(Actions.ReadConversation)
|
|
local ReceivedConversation = require(Actions.ReceivedConversation)
|
|
local ReceivedMessages = require(Actions.ReceivedMessages)
|
|
local RemovedConversation = require(Actions.RemovedConversation)
|
|
local RenamedGroupConversation = require(Actions.RenamedGroupConversation)
|
|
local SendingMessage = require(Actions.SendingMessage)
|
|
local SentMessage = require(Actions.SentMessage)
|
|
local SetConversationLoadingStatus = require(Actions.SetConversationLoadingStatus)
|
|
local SetPinnedGameForConversation = require(Actions.SetPinnedGameForConversation)
|
|
local SetUserLeavingConversation = require(Actions.SetUserLeavingConversation)
|
|
local SetUserTyping = require(Actions.SetUserTyping)
|
|
|
|
local ConversationModel = require(LuaChat.Models.Conversation)
|
|
local Immutable = require(Common.Immutable)
|
|
local OrderedMap = require(LuaChat.OrderedMap)
|
|
|
|
return function(state, action)
|
|
state = state or {}
|
|
|
|
if action.type == ReceivedConversation.name then
|
|
local conversation = action.conversation
|
|
|
|
if conversation.conversationType == ConversationModel.Type.ONE_TO_ONE_CONVERSATION then
|
|
local idForFake = ConversationModel.IdForFakeOneOnOne(conversation.participants)
|
|
if state[idForFake] ~= nil then
|
|
state = Immutable.Set(state, idForFake, nil)
|
|
end
|
|
end
|
|
|
|
if not state[conversation.id] then
|
|
state = Immutable.Set(state, conversation.id, conversation)
|
|
end
|
|
elseif action.type == ReceivedMessages.name then
|
|
local conversationId = action.conversationId
|
|
local conversation = state[conversationId]
|
|
|
|
if conversation then
|
|
|
|
local lastMessage = nil
|
|
for i = 1, #action.messages do
|
|
local message = action.messages[i]
|
|
local existing = conversation.messages:Get(message.id)
|
|
if existing then
|
|
if lastMessage then
|
|
lastMessage.previousMessageId = existing.id
|
|
end
|
|
if message.previousMessageId == nil and existing.previousMessageId ~= nil then
|
|
message.previousMessageId = existing.previousMessageId
|
|
end
|
|
message.read = message.read or existing.read
|
|
end
|
|
lastMessage = message
|
|
end
|
|
|
|
local messages = OrderedMap.Insert(conversation.messages, unpack(action.messages))
|
|
|
|
if action.exclusiveStartMessageId and #action.messages > 0 then
|
|
if messages:Get(action.exclusiveStartMessageId) then
|
|
local prevMessage = action.messages[1]
|
|
local nextMessage = messages:Get(action.exclusiveStartMessageId)
|
|
nextMessage = Immutable.Set(nextMessage, "previousMessageId", prevMessage.id)
|
|
messages = messages:Insert(nextMessage)
|
|
end
|
|
end
|
|
|
|
local lastConversationKey = messages.keys[#messages.keys]
|
|
lastMessage = messages.values[lastConversationKey]
|
|
|
|
if lastMessage ~= nil then
|
|
local lastUpdatedConvo = conversation.lastUpdated and conversation.lastUpdated:GetUnixTimestamp() or 0
|
|
|
|
local lastUpdated = (lastMessage.sent:GetUnixTimestamp() > lastUpdatedConvo) and
|
|
lastMessage.sent or conversation.lastUpdated
|
|
|
|
local hasUnreadMessages = action.shouldMarkConversationUnread or conversation.hasUnreadMessages
|
|
|
|
local newConversation = Immutable.JoinDictionaries(conversation, {
|
|
messages = messages;
|
|
lastUpdated = lastUpdated;
|
|
hasUnreadMessages = hasUnreadMessages;
|
|
})
|
|
|
|
-- Mark all users as no longer typing
|
|
-- We should only do this if a specific user sent a message and it's
|
|
-- the last message in the list, but that check would be expensive
|
|
-- to make every time we request more messages.
|
|
-- Notably, this will fail for group conversations.
|
|
newConversation = Immutable.Set(newConversation, "usersTyping", {})
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
end
|
|
end
|
|
elseif action.type == SendingMessage.name then
|
|
local conversationId = action.conversationId
|
|
local conversation = state[conversationId]
|
|
|
|
if conversation then
|
|
local sendingMessages = OrderedMap.Insert(conversation.sendingMessages, action.message)
|
|
local newConversation = Immutable.Set(conversation, "sendingMessages", sendingMessages)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
end
|
|
elseif action.type == SentMessage.name then
|
|
local conversationId = action.conversationId
|
|
local conversation = state[conversationId]
|
|
|
|
if conversation then
|
|
local sendingMessages = OrderedMap.Delete(conversation.sendingMessages, action.messageId)
|
|
local newConversation = Immutable.Set(conversation, "sendingMessages", sendingMessages)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
end
|
|
elseif action.type == RenamedGroupConversation.name then
|
|
local conversationId = action.conversationId
|
|
|
|
local conversation = state[conversationId]
|
|
|
|
if conversation then
|
|
local newConversation = Immutable.JoinDictionaries(conversation, {
|
|
lastUpdated = action.lastUpdated,
|
|
title = action.title,
|
|
isDefaultTitle = action.isDefaultTitle,
|
|
})
|
|
state = Immutable.Set(state, conversationId, newConversation)
|
|
end
|
|
elseif action.type == ChangedParticipants.name then
|
|
local convoId = action.conversationId
|
|
local newParticipants = action.participants
|
|
|
|
local conversation = state[convoId]
|
|
|
|
if conversation then
|
|
local newConversation = Immutable.JoinDictionaries(conversation, {
|
|
participants = newParticipants,
|
|
lastUpdated = action.lastUpdated,
|
|
title = action.title,
|
|
})
|
|
state = Immutable.Set(state, convoId, newConversation)
|
|
end
|
|
elseif action.type == RemovedConversation.name then
|
|
local conversationId = action.conversationId
|
|
state = Immutable.Set(state, conversationId, nil)
|
|
|
|
elseif action.type == SetUserTyping.name then
|
|
local conversation = state[action.conversationId]
|
|
|
|
if conversation then
|
|
local usersTyping = conversation.usersTyping
|
|
local newUsersTyping = Immutable.Set(usersTyping, action.userId, action.value)
|
|
local newConversation = Immutable.Set(conversation, "usersTyping", newUsersTyping)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
end
|
|
elseif action.type == FetchingOlderMessages.name then
|
|
local conversation = state[action.conversationId]
|
|
if conversation then
|
|
local newConversation = Immutable.Set(conversation, "fetchingOlderMessages", action.fetchingOlderMessages)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
end
|
|
elseif action.type == FetchedOldestMessage.name then
|
|
local conversation = state[action.conversationId]
|
|
local newConversation = Immutable.Set(conversation, "fetchedOldestMessage", action.fetchedOldestMessage)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
|
|
elseif action.type == ReadConversation.name then
|
|
local conversation = state[action.conversationId]
|
|
|
|
if not conversation then
|
|
warn("Conversation " .. action.conversationId .. " not found in ReadConversation reducer")
|
|
return
|
|
end
|
|
|
|
local newMessages = conversation.messages:Map(function(message)
|
|
if message.read then
|
|
return message
|
|
else
|
|
return Immutable.Set(message, "read", true)
|
|
end
|
|
end)
|
|
|
|
local newConversation = Immutable.Set(conversation, "messages", newMessages)
|
|
newConversation = Immutable.Set(newConversation, "hasUnreadMessages", false)
|
|
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
|
|
elseif action.type == MessageModerated.name then
|
|
local conversation = state[action.conversationId]
|
|
local message = conversation.sendingMessages:Get(action.messageId)
|
|
|
|
if message then
|
|
local newMessage = Immutable.Set(message, "moderated", true)
|
|
local newSendingMessages = conversation.sendingMessages:Insert(newMessage)
|
|
local newConversation = Immutable.Set(conversation, "sendingMessages", newSendingMessages)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
end
|
|
|
|
elseif action.type == MessageFailedToSend.name then
|
|
local conversation = state[action.conversationId]
|
|
local message = conversation.sendingMessages:Get(action.messageId)
|
|
|
|
if message then
|
|
local newMessage = Immutable.Set(message, "failed", true)
|
|
local newSendingMessages = conversation.sendingMessages:Insert(newMessage)
|
|
local newConversation = Immutable.Set(conversation, "sendingMessages", newSendingMessages)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
end
|
|
|
|
elseif action.type == SetConversationLoadingStatus.name then
|
|
local conversation = state[action.conversationId]
|
|
local newConversation = Immutable.Set(conversation, "initialLoadingStatus", action.value)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
|
|
elseif action.type == SetUserLeavingConversation.name then
|
|
local conversation = state[action.id]
|
|
if conversation then
|
|
local newConversation = Immutable.Set(conversation, "isUserLeaving", action.isLeaving)
|
|
state = Immutable.Set(state, newConversation.id, newConversation)
|
|
end
|
|
|
|
elseif action.type == SetPinnedGameForConversation.name then
|
|
|
|
local conversationId = action.conversationId
|
|
local conversation = state[conversationId]
|
|
|
|
if conversation then
|
|
local newPinnedGame = {
|
|
rootPlaceId = action.rootPlaceId;
|
|
universeId = action.universeId;
|
|
}
|
|
|
|
local newConversation = Immutable.JoinDictionaries(conversation, {
|
|
pinnedGame = newPinnedGame;
|
|
})
|
|
|
|
state = Immutable.Set(state, conversationId, newConversation)
|
|
end
|
|
end
|
|
|
|
return state
|
|
end |