SyntaxGameServer/RCCService2018/content/internal/Chat/Modules/LuaChat/Components/FriendSearchBox.lua

360 lines
11 KiB
Lua

local CoreGui = game:GetService("CoreGui")
local Modules = CoreGui.RobloxGui.Modules
local Common = Modules.Common
local LuaChat = Modules.LuaChat
local LuaApp = Modules.LuaApp
local Constants = require(LuaChat.Constants)
local Create = require(LuaChat.Create)
local Functional = require(Common.Functional)
local Signal = require(Common.Signal)
local ToastModel = require(LuaChat.Models.ToastModel)
local getInputEvent = require(LuaChat.Utils.getInputEvent)
local Components = LuaChat.Components
local ListSection = require(Components.ListSection)
local UserList = require(Components.UserList)
local UserThumbnailBar = require(Components.UserThumbnailBar)
local User = require(LuaApp.Models.User)
local ShowToast = require(LuaChat.Actions.ShowToast)
local FFlagLuaChatToSplitRbxConnections = settings():GetFFlag("LuaChatToSplitRbxConnections")
local FFlagTextBoxOverrideManualFocusRelease = settings():GetFFlag("TextBoxOverrideManualFocusRelease")
local FFlagLuaChatSortFriendsForConversation = settings():GetFFlag("LuaChatSortFriendsForConversation")
local CLEAR_TEXT_WIDTH = 44
local ICON_CELL_WIDTH = 60
local SEARCH_BOX_HEIGHT = 48
local FriendSearchBox = {}
FriendSearchBox.__index = FriendSearchBox
local PRESENCE_WEIGHTS = {
[User.PresenceType.IN_GAME] = 4,
[User.PresenceType.ONLINE] = 3,
[User.PresenceType.IN_STUDIO] = 2,
[User.PresenceType.OFFLINE] = 1,
}
local function friendSortPredicate(friend1, friend2)
local friend1Weight = PRESENCE_WEIGHTS[friend1.presence] or 0
local friend2Weight = PRESENCE_WEIGHTS[friend2.presence] or 0
if friend1Weight == friend2Weight then
return friend1.name:lower() < friend2.name:lower()
else
return friend1Weight > friend2Weight
end
end
function FriendSearchBox.new(appState, participants, maxParticipantCount, filter)
local self = {
appState = appState,
participants = participants,
users = appState.store:getState().Users,
maxParticipantCount = maxParticipantCount,
}
self.connections = {}
if FFlagLuaChatToSplitRbxConnections then
self.rbx_connections = {}
end
setmetatable(self, FriendSearchBox)
self.friendThumbnails = UserThumbnailBar.new(appState, maxParticipantCount, 1)
local removedConnection = self.friendThumbnails.removed:connect(function(id)
self:RemoveParticipant(id)
end)
table.insert(self.connections, removedConnection)
self.userList = UserList.new(appState, nil, filter)
local userSelectedConnection = self.userList.userSelected:connect(function(user)
local selected = Functional.Find(self.participants, user.id)
if selected then
self:RemoveParticipant(user.id)
else
self:AddParticipant(user.id)
end
self:ClearText()
end)
table.insert(self.connections, userSelectedConnection)
self.rbx = Create.new"Frame" {
Name = "FriendSearchBox",
BackgroundTransparency = 1,
BorderSizePixel = 0,
Size = UDim2.new(1, 0, 1, 0),
Create.new"UIListLayout" {
Name = "ListLayout",
SortOrder = "LayoutOrder",
},
self.friendThumbnails.rbx,
Create.new"Frame" {
Name = "Divider1",
BackgroundColor3 = Constants.Color.GRAY4,
BorderSizePixel = 0,
Size = UDim2.new(1, 0, 0, 1),
LayoutOrder = 2,
},
ListSection.new(appState, nil, 3).rbx,
Create.new"Frame" {
Name = "SearchContainer",
BackgroundTransparency = 0,
BackgroundColor3 = Constants.Color.WHITE,
BorderSizePixel = 0,
Size = UDim2.new(1, 0, 0, SEARCH_BOX_HEIGHT),
LayoutOrder = 4,
Create.new"ImageLabel" {
Name = "SearchIcon",
BackgroundTransparency = 1,
Size = UDim2.new(0, 24, 0, 24),
Position = UDim2.new(0, ICON_CELL_WIDTH/2, 0.5, 0),
AnchorPoint = Vector2.new(0.5, 0.5),
ImageColor3 = Constants.Color.GRAY3,
Image = "rbxasset://textures/ui/LuaChat/icons/ic-search.png",
},
Create.new"TextBox" {
Name = "Search",
BackgroundTransparency = 1,
Size = UDim2.new(1, -CLEAR_TEXT_WIDTH-ICON_CELL_WIDTH, 1, 0),
Position = UDim2.new(0, ICON_CELL_WIDTH, 0, 0),
TextSize = Constants.Font.FONT_SIZE_18,
TextColor3 = Constants.Color.GRAY1,
Font = Enum.Font.SourceSans,
Text = "",
PlaceholderText = appState.localization:Format("Feature.Friends.Label.SearchFriends"),
PlaceholderColor3 = Constants.Color.GRAY3,
TextXAlignment = Enum.TextXAlignment.Left,
OverlayNativeInput = true,
ClearTextOnFocus = false,
ClipsDescendants = true,
},
Create.new"ImageButton" {
Name = "Clear",
BackgroundTransparency = 1,
Size = UDim2.new(0, 16, 0, 16),
Position = UDim2.new(1, -(CLEAR_TEXT_WIDTH/2), 0.5, 0),
AnchorPoint = Vector2.new(0.5, 0.5),
AutoButtonColor = false,
Image = "rbxasset://textures/ui/LuaChat/icons/ic-clear-solid.png",
ImageTransparency = 1,
},
},
Create.new"Frame" {
Name = "Divider2",
BackgroundColor3 = Constants.Color.GRAY4,
BorderSizePixel = 0,
Size = UDim2.new(1, 0, 0, 1),
LayoutOrder = 5,
},
Create.new"ScrollingFrame" {
Name = "ScrollingFrame",
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
BorderSizePixel = 0,
ScrollBarThickness = 5,
BottomImage = "rbxasset://textures/ui/LuaChat/9-slice/scroll-bar.png",
MidImage = "rbxasset://textures/ui/LuaChat/9-slice/scroll-bar.png",
TopImage = "rbxasset://textures/ui/LuaChat/9-slice/scroll-bar.png",
LayoutOrder = 6,
self.userList.rbx,
},
}
self.searchContainer = self.rbx.SearchContainer
local clearButton = self.searchContainer.Clear
local search = self.searchContainer.Search
self.search = search
if FFlagTextBoxOverrideManualFocusRelease then
search.ManualFocusRelease = true
end
local clearButtonConnection = getInputEvent(clearButton):Connect(function()
self:ClearText()
end)
if FFlagLuaChatToSplitRbxConnections then
table.insert(self.rbx_connections, clearButtonConnection)
else
table.insert(self.connections, clearButtonConnection)
end
self:Resize()
local function updateClearButtonVisibility()
-- If we were to set the visible property of the clear button on the textbox focus lost event
-- it would disable the clear button, which in turn would stop the click event
-- from being able to notify the button
local visible = search:IsFocused() and (search.Text ~= "")
clearButton.ImageTransparency = visible and 0 or 1
end
self.searchChanged = Signal.new()
self.addParticipant = Signal.new()
self.removeParticipant = Signal.new()
local searchChangedConnection = search:GetPropertyChangedSignal("Text"):Connect(function()
updateClearButtonVisibility()
self.userList:ApplySearch(search.Text)
self:Resize()
self:ResizeCanvas()
end)
if FFlagLuaChatToSplitRbxConnections then
table.insert(self.rbx_connections, searchChangedConnection)
else
table.insert(self.connections, searchChangedConnection)
end
local focusedConnection = search.Focused:Connect(updateClearButtonVisibility)
if FFlagLuaChatToSplitRbxConnections then
table.insert(self.rbx_connections, focusedConnection)
else
table.insert(self.connections, focusedConnection)
end
local focusLostConnection = search.FocusLost:Connect(updateClearButtonVisibility)
if FFlagLuaChatToSplitRbxConnections then
table.insert(self.rbx_connections, focusLostConnection)
else
table.insert(self.connections, focusLostConnection)
end
self:UpdateFriends(appState.store:getState().Users, self.participants)
local userListAddConnection = self.userList.rbx.ChildAdded:Connect(function(child)
self:ResizeCanvas();
end)
if FFlagLuaChatToSplitRbxConnections then
table.insert(self.rbx_connections, userListAddConnection)
else
table.insert(self.connections, userListAddConnection)
end
local userListRemoveConnection = self.userList.rbx.ChildRemoved:Connect(function(child)
self:ResizeCanvas();
end)
if FFlagLuaChatToSplitRbxConnections then
table.insert(self.rbx_connections, userListRemoveConnection)
else
table.insert(self.connections, userListRemoveConnection)
end
local userListSizeConnection = self.userList.rbx:GetPropertyChangedSignal("AbsoluteSize"):Connect(function()
self:ResizeCanvas()
end)
if FFlagLuaChatToSplitRbxConnections then
table.insert(self.rbx_connections, userListSizeConnection)
else
table.insert(self.connections, userListSizeConnection)
end
return self
end
function FriendSearchBox:Resize()
local height = 0
for _, element in pairs(self.rbx:GetChildren()) do
if element:IsA("GuiObject") and element.Visible and element.Name ~= "ScrollingFrame" then
height = height + element.AbsoluteSize.Y
end
end
self.rbx.ScrollingFrame.Size = UDim2.new(1, 0, 1, -height)
end
function FriendSearchBox:ResizeCanvas()
local height = 0
for _, element in pairs(self.userList.rbx:GetChildren()) do
if element:IsA("GuiObject") and element.Visible then
height = height + element.AbsoluteSize.Y
end
end
self.rbx.ScrollingFrame.CanvasSize = UDim2.new(1, 0, 0, height)
end
function FriendSearchBox:AddParticipant(userId)
if #self.participants >= self.maxParticipantCount then
if self.tooManyFriendsToastModel == nil then
local messageKey = "Feature.Chat.Message.ToastText"
local messageArguments = {
friendNum = tostring(Constants.MAX_PARTICIPANT_COUNT),
}
local toastModel = ToastModel.new(Constants.ToastIDs.TOO_MANY_PEOPLE, messageKey, messageArguments)
self.tooManyFriendsToastModel = toastModel
end
self.appState.store:dispatch(ShowToast(self.tooManyFriendsToastModel))
else
self.addParticipant:fire(userId)
end
end
function FriendSearchBox:RemoveParticipant(userId)
self.removeParticipant:fire(userId)
end
function FriendSearchBox:UpdateFriends(users, selectedList)
local friends = {}
for _, user in pairs(users) do
table.insert(friends, user)
end
if FFlagLuaChatSortFriendsForConversation then
table.sort(friends, friendSortPredicate)
for _,friend in pairs (friends) do
if not PRESENCE_WEIGHTS[friend.presence] then
warn("Invalid presence value for "..friend.name)
end
end
end
self.userList:Update(friends, selectedList)
self:Resize()
end
function FriendSearchBox:ClearText()
self.searchContainer.Search.Text = ""
self:Resize()
end
function FriendSearchBox:Update(participants)
local state = self.appState.store:getState()
local users = state.Users
if participants ~= self.participants then
self.friendThumbnails:Update(participants)
end
if participants ~= self.participants or users ~= self.users then
self:UpdateFriends(users, participants)
end
self.participants = participants
self.users = users
self:Resize()
end
function FriendSearchBox:Destruct()
for _, connection in ipairs(self.connections) do
connection:disconnect()
end
self.connections = {}
if FFlagLuaChatToSplitRbxConnections then
for _, connection in ipairs(self.rbx_connections) do
connection:Disconnect()
end
self.rbx_connections = {}
end
self.userList:Destruct()
self.friendThumbnails:Destruct()
self.rbx.Parent = nil
self.rbx:Destroy()
end
return FriendSearchBox