SyntaxGameServer/RCCService2018/content/internal/AppShell/Modules/Shell/Components/Social/FriendsScrollingView.lua

240 lines
7.7 KiB
Lua

local Modules = game:GetService("CoreGui").RobloxGui.Modules
local HttpService = game:GetService("HttpService")
local PlatformService = nil
pcall(function() PlatformService = game:GetService("PlatformService") end)
local Roact = require(Modules.Common.Roact)
local Components = Modules.Shell.Components
local PresenceCard = require(Components.Social.PresenceCard)
local WindowedScrollingFrame = require(Components.Common.WindowedScrollingFrame)
local Immutable = require(Modules.Common.Immutable)
local Spinner = require(Components.Common.Spinner)
local SideBarComponent = require(Components.Common.SideBar)
local Utility = require(Modules.Shell.Utility)
local EventHub = require(Modules.Shell.EventHub)
local GameJoinModule = require(Modules.Shell.GameJoin)
local Strings = require(Modules.Shell.LocalizedStrings)
local SoundManager = require(Modules.Shell.SoundManager)
local RedirectComponent = require(Modules.Shell.Components.Common.RedirectComponent)
local UserThumbnailLoader = require(Components.Common.UserThumbnailLoader)
local SIDE_BAR_ITEMS = {
JoinGame = Strings:LocalizedString("JoinGameWord"),
ViewDetails = Strings:LocalizedString("ViewGameDetailsWord"),
ViewProfile = Strings:LocalizedString("ViewGamerCardWord"),
EmptyFriendSideBar = Strings:LocalizedString("EmptyFriendSideBarWord"),
}
local FriendsScrollingView = Roact.PureComponent:extend("FriendsScrollingView")
function FriendsScrollingView:init()
self.state = {
sideBarInFocus = false,
sideBarShow = false,
currentSelectedIndex = 1,
}
self.onSideBarClose = function()
self:setState({
sideBarInFocus = false,
sideBarShow = false,
})
end
self.onSideBarOpen = function(data)
Utility.SetSelectedCoreObject(nil)
self:setState({
sideBarInFocus = true,
sideBarShow = true,
})
end
self.groupKey = HttpService:GenerateGUID(false)
end
function FriendsScrollingView:render()
local props = self.props
local friendsData = props.friendsData
local initialized = props.initialized
local actionPriority = self.props.actionPriority or 0
local hide = props.hide
local inFocus = props.inFocus
local sideBarInFocus = false
local friendsScrollingFrameInFocus = false
local children = {}
if not hide and inFocus then
sideBarInFocus = self.state.sideBarShow and self.state.sideBarInFocus
if not sideBarInFocus and #friendsData > 0 then
friendsScrollingFrameInFocus = true
end
end
if initialized and friendsData then
if #friendsData > 0 then
local itemSize = Vector2.new(440, 120)
local itemsPaddingOffset = 20
local itemTotalSizeY = itemSize.Y + itemsPaddingOffset
local itemsCount = math.floor(self.props.size.Y.Offset / itemTotalSizeY)
assert(itemsCount ~= 0, "The scrolling window is too small to accommodate any presence card.")
--We should have at least two items to ensure we can always select the top second item
--while keep the top first item fully in view.
--If the window is too small, we will always select the top first item.
local itemOffsetStart = itemsCount > 2 and itemTotalSizeY or 0
--This make sure when we scroll down the top card won't be clipped
local itemOffsetEnd = self.props.size.Y.Offset - itemsCount * itemTotalSizeY + itemsPaddingOffset
children.FriendsScrollingFrame = Roact.createElement(WindowedScrollingFrame, {
items = friendsData,
itemSize = itemSize,
itemsPaddingOffset = itemsPaddingOffset,
itemOffsetStart = itemOffsetStart,
itemOffsetEnd = itemOffsetEnd,
scrollingDirection = Enum.ScrollingDirection.Y,
inFocus = friendsScrollingFrameInFocus,
renderItem = function(data, index)
local presenceCardProps = Immutable.JoinDictionaries(data, {
layoutOrder = index,
size = UDim2.new(0, itemSize.X, 0, itemSize.Y),
focused = inFocus and self.state.currentSelectedIndex == index,
selected = friendsScrollingFrameInFocus and self.state.currentSelectedIndex == index,
})
--Set up callbacks
presenceCardProps.onActivated = function(bt)
SoundManager:Play("SideMenuSlideIn")
self.onSideBarOpen()
end
presenceCardProps.onSelectionGained = function()
if self.state.currentSelectedIndex ~= index then
self:setState({
currentSelectedIndex = index,
})
end
end
return Roact.createElement(PresenceCard, presenceCardProps)
end
})
local data = friendsData[self.state.currentSelectedIndex]
if inFocus and data and data.robloxuid then
children.ProfileImage = Roact.createElement(UserThumbnailLoader, {
rbxuid = data.robloxuid,
thumbnailType = Enum.ThumbnailType.AvatarThumbnail,
thumbnailSize = Enum.ThumbnailSize.Size352x352,
position = UDim2.new(1, 101, 0, 0),
size = UDim2.new(0, 680, 0, 680),
backgroundTransparency = 1,
showSpinner = true
})
end
if self.state.sideBarShow and data then
local sideBarButtons = {}
if data.robloxuid and data.robloxuid > 0 and data.robloxStatus == "InGame" then
local placeId = data.placeId
local lastLocation = data.lastLocation
local robloxuid = data.robloxuid
table.insert(sideBarButtons, {
text = SIDE_BAR_ITEMS.JoinGame,
callback = function()
GameJoinModule:StartGame(GameJoinModule.JoinType.Follow, robloxuid)
end
})
table.insert(sideBarButtons, {
text = SIDE_BAR_ITEMS.ViewDetails,
callback = function()
EventHub:dispatchEvent(EventHub.Notifications["OpenGameDetail"], placeId, lastLocation, nil)
end
})
end
if data.xuid and #data.xuid > 0 and PlatformService then
local xuid = data.xuid
table.insert(sideBarButtons, {
text = SIDE_BAR_ITEMS.ViewProfile,
callback = function()
-- NOTE: This will try to pop up the xbox system gamer card, failure will be handled by the xbox.
pcall(function()
PlatformService:PopupProfileUI(Enum.UserInputType.Gamepad1, xuid)
end)
end
})
end
local sideBarText = nil
if #sideBarButtons == 0 then
sideBarText = SIDE_BAR_ITEMS.EmptyFriendSideBar
sideBarButtons = nil
end
children.SideBar = Roact.createElement(SideBarComponent, {
actionPriority = actionPriority + 1,
text = sideBarText,
buttons = sideBarButtons,
inFocus = sideBarInFocus,
onClose = self.onSideBarClose,
onRemoveFocus = function()
self:setState({
sideBarInFocus = false
})
end,
})
end
else
children.NoFriendsView = props.noFriendsView
end
else
children.Spinner = Roact.createElement(Spinner)
end
children.NavObj = Roact.createElement(RedirectComponent, {
ActionPriority = actionPriority,
Key = self.groupKey,
InFocus = inFocus,
RedirectBack = props.redirectBack,
RedirectLeft = props.redirectLeft,
RedirectRight = props.redirectRight,
RedirectUp = props.redirectUp,
RedirectDown = props.redirectDown,
})
return Roact.createElement("Frame", {
BackgroundTransparency = 1,
Size = self.props.size,
Position = self.props.position,
[Roact.Ref] = function(rbx)
self.ref = rbx
end,
Visible = not hide,
}, children)
end
function FriendsScrollingView:didMount()
delay(0, function()
if self.props.hide == false and self.props.inFocus then
if self.ref ~= nil then
Utility.RemoveSelectionGroup(self.groupKey)
Utility.AddSelectionParent(self.groupKey, self.ref)
end
end
end)
end
function FriendsScrollingView:didUpdate(previousProps, previousState)
if self.props.hide or self.props.inFocus == previousProps.inFocus then
return
end
if self.props.inFocus then
if self.ref then
Utility.RemoveSelectionGroup(self.groupKey)
Utility.AddSelectionParent(self.groupKey, self.ref)
end
else
Utility.RemoveSelectionGroup(self.groupKey)
end
end
function FriendsScrollingView:willUnmount()
Utility.RemoveSelectionGroup(self.groupKey)
end
return FriendsScrollingView