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

248 lines
7.4 KiB
Lua

--
-- FriendCarousel
--
-- This is a scrollable list of friend icons.
--
local CoreGui = game:GetService("CoreGui")
local Modules = CoreGui.RobloxGui.Modules
local Common = Modules.Common
local LuaApp = Modules.LuaApp
local ApiFetchUsersThumbnail = require(LuaApp.Thunks.ApiFetchUsersThumbnail)
local ChatConstants = require(Modules.LuaChat.Constants)
local Constants = require(LuaApp.Constants)
local FriendIcon = require(Modules.LuaApp.Components.FriendIcon)
local Roact = require(Common.Roact)
local RoactRodux = require(Common.RoactRodux)
local UserModel = require(LuaApp.Models.User)
local FFlagLuaChatReplacePresenceIndicatorImages = settings():GetFFlag("LuaChatReplacePresenceIndicatorImages")
local FFlagLuaChatFriendIconRefactor = settings():GetFFlag("LuaChatFriendIconRefactor")
local FriendCarousel = Roact.Component:extend("FriendCarousel")
local IMAGE_DOT_INGAME = "rbxasset://textures/ui/LuaApp/icons/ic-green-dot.png"
local IMAGE_DOT_ONLINE = "rbxasset://textures/ui/LuaApp/icons/ic-blue-dot.png"
local IMAGE_DOT_STUDIO = "rbxasset://textures/ui/LuaApp/icons/ic-orange-dot.png"
local DEFAULT_DOT_SIZE = 8
local IMAGE_MASK = "rbxasset://textures/ui/LuaChat/graphic/friendmask.png"
local MASK_WIDTH = 10
-- Frame around the profile image:
local IMAGE_PROFILE_BORDER = "rbxasset://textures/ui/LuaChat/graphic/gr-profile-border-36x36.png"
local IMAGE_PROFILE_DEFAULT = "rbxasset://textures/ui/LuaChat/icons/ic-profile.png"
function FriendCarousel:init()
self.state = {
fadeScrollLeft = false,
fadeScrollRight = false,
}
end
function FriendCarousel:onPositionChanged(rbx)
-- Programatically show / hide the fade bars at either side of the carousel.
-- This hides items that are partly visible, but completely reveals the
-- first / last items when they're present.
-- Early return if we're not set up yet:
if (rbx.CanvasSize.X.Offset == 0) or (rbx.CanvasSize.Y.Offset == 0) or
(rbx.AbsoluteWindowSize.X == 0) or (rbx.AbsoluteWindowSize.Y == 0) then
return
end
local fadeLeft = (0 < rbx.CanvasPosition.X)
local fadeRight = (rbx.CanvasSize.X.Offset - rbx.CanvasPosition.X) > rbx.AbsoluteWindowSize.X
if (fadeLeft ~= self.state.fadeScrollLeft) or
(fadeRight ~= self.state.fadeScrollRight) then
spawn(function()
self:setState({
fadeScrollLeft = fadeLeft,
fadeScrollRight = fadeRight,
})
end)
end
end
function FriendCarousel:didMount()
if self.rbxScroller then
self:onPositionChanged(self.rbxScroller)
end
end
function FriendCarousel:render()
-- Visual properties of this game card:
local dotSize = self.props.dotSize or DEFAULT_DOT_SIZE
local friends = self.props.friends or {}
local getUserThumbnail = self.props.getUserThumbnail
local horizontalAlignment = self.props.HorizontalAlignment or Enum.HorizontalAlignment.Left
local itemGap = self.props.itemGap
local itemSize = self.props.itemSize
local layoutOrder = self.props.LayoutOrder
local size = self.props.Size or UDim2.new(1, 0, 0, itemSize)
local users = self.props.users
local presenceIndicatorSizeKey = ChatConstants:GetPresenceIndicatorSizeKey(dotSize)
-- Build up a horizontal list of items for our card:
local friendItems = {}
friendItems["Layout"] = Roact.createElement("UIListLayout", {
FillDirection = Enum.FillDirection.Horizontal,
HorizontalAlignment = horizontalAlignment,
Padding = UDim.new(0, itemGap),
SortOrder = Enum.SortOrder.LayoutOrder,
VerticalAlignment = Enum.VerticalAlignment.Center,
})
local countFriends = #friends
if countFriends > 0 then
for index, friend in ipairs(friends) do
if FFlagLuaChatFriendIconRefactor then
local userFriend = users[friend.uid]
friendItems[index] = Roact.createElement(FriendIcon, {
user = userFriend,
dotSize = dotSize,
itemSize = itemSize,
layoutOrder = index,
})
else
-- Look up the presence information:
local imageFriend = nil
local iconDot = not FFlagLuaChatReplacePresenceIndicatorImages and IMAGE_DOT_ONLINE or nil
local userFriend = users[friend.uid]
if userFriend then
if FFlagLuaChatReplacePresenceIndicatorImages then
iconDot = ChatConstants.PresenceIndicatorImagesBySize[presenceIndicatorSizeKey][userFriend.presence]
else
if userFriend.presence == UserModel.PresenceType.IN_GAME then
iconDot = IMAGE_DOT_INGAME
elseif userFriend.presence == UserModel.PresenceType.IN_STUDIO then
iconDot = IMAGE_DOT_STUDIO
end
end
-- Find images for the friend portraits:
if userFriend.thumbnails and userFriend.thumbnails.HeadShot
and userFriend.thumbnails.HeadShot.Size48x48 then
imageFriend = userFriend.thumbnails.HeadShot.Size48x48
end
if imageFriend == nil then
imageFriend = IMAGE_PROFILE_DEFAULT
getUserThumbnail(friend.uid)
end
end
friendItems[index] = Roact.createElement("Frame", {
BackgroundTransparency = 1,
BorderSizePixel = 0,
LayoutOrder = index,
Size = UDim2.new(0, itemSize, 0, itemSize),
}, {
Profile = Roact.createElement("ImageButton", {
BackgroundTransparency = 1,
BorderSizePixel = 0,
Image = imageFriend,
Size = UDim2.new(0, itemSize, 0, itemSize),
ZIndex = 1,
}),
Border = Roact.createElement("ImageLabel", {
BackgroundTransparency = 1,
BorderSizePixel = 0,
Image = IMAGE_PROFILE_BORDER,
Size = UDim2.new(0, itemSize, 0, itemSize),
ZIndex = 2,
}),
Dot = Roact.createElement("ImageLabel", {
BackgroundTransparency = 1,
BorderSizePixel = 0,
Image = iconDot,
Position = UDim2.new(1, -dotSize, 1, -dotSize),
Size = UDim2.new(0, dotSize, 0, dotSize),
ZIndex = 3,
}),
})
end
end
end
local maskLeft = nil
if self.state.fadeScrollLeft then
maskLeft = Roact.createElement("ImageLabel", {
BackgroundTransparency = 1,
BorderSizePixel = 0,
Image = IMAGE_MASK,
Position = UDim2.new(0, 0, 0, 0),
Rotation = 180,
Size = UDim2.new(0, MASK_WIDTH, 1, 0),
ZIndex = 2,
})
end
local maskRight = nil
if self.state.fadeScrollRight then
maskRight = Roact.createElement("ImageLabel", {
BackgroundTransparency = 1,
BorderSizePixel = 0,
Image = IMAGE_MASK,
Position = UDim2.new(1, -MASK_WIDTH, 0, 0),
Size = UDim2.new(0, MASK_WIDTH, 1, 0),
ZIndex = 2,
})
end
-- This frame arrangement adds a semi-transparent overlay to
-- fade out items at the edge of the frame:
return Roact.createElement("Frame", {
BackgroundTransparency = 1,
BorderSizePixel = 0,
LayoutOrder = layoutOrder,
Position = UDim2.new(0, 0, 0, 0),
Size = size,
},{
MaskLeft = maskLeft,
MaskRight = maskRight,
ScrollyFrame = Roact.createElement("ScrollingFrame", {
BackgroundTransparency = 1,
BorderSizePixel = 0,
CanvasSize = UDim2.new(0, (itemSize + itemGap) * countFriends, 0, itemSize),
ClipsDescendants = true,
ScrollBarThickness = 0,
Size = UDim2.new(1, 0, 1, 0),
[Roact.Change.AbsolutePosition] = function(rbx, changed)
self:onPositionChanged(rbx)
end,
[Roact.Ref] = function(rbx)
self.rbxScroller = rbx
end,
}, friendItems)
})
end
FriendCarousel = RoactRodux.UNSTABLE_connect2(
function(state, props)
return {
users = state.Users,
}
end,
function(dispatch)
return {
getUserThumbnail = function(friendId)
spawn(function()
dispatch(ApiFetchUsersThumbnail(nil, { friendId },
Constants.AvatarThumbnailRequests.FRIEND_CAROUSEL
))
end)
end,
}
end
)(FriendCarousel)
return FriendCarousel