This commit is contained in:
lx
2026-07-06 14:01:11 -04:00
commit c4f97d729d
16468 changed files with 935321 additions and 0 deletions
@@ -0,0 +1,240 @@
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
@@ -0,0 +1,158 @@
local Modules = game:GetService("CoreGui").RobloxGui.Modules
local Roact = require(Modules.Common.Roact)
local memoize = require(Modules.Common.memoize)
local RoactRodux = require(Modules.Common.RoactRodux)
local CategoryMenuView = require(Modules.Shell.Components.Common.CategoryMenuView)
local SplitViewLR = require(Modules.Shell.Components.Common.SplitViewLR)
local Utility = require(Modules.Shell.Utility)
local SoundManager = require(Modules.Shell.SoundManager)
local Strings = require(Modules.Shell.LocalizedStrings)
local FriendsScrollingView = require(Modules.Shell.Components.Social.FriendsScrollingView)
local NoFriendsView = require(Modules.Shell.Components.Social.NoFriendsView)
local PageKeys = require(Modules.Shell.PageKeys)
local FriendsView = Roact.PureComponent:extend("FriendsView")
local MenuKey = PageKeys.FriendCategories.Key
local FriendCategoriesKeys = {
OnlineFriends = PageKeys.FriendCategories.OnlineFriends.Key,
AllFriends = PageKeys.FriendCategories.AllFriends.Key,
}
local FriendCategories = {}
FriendCategories[FriendCategoriesKeys.OnlineFriends] = { Order = 1, StringKey = "OnlineWord" }
FriendCategories[FriendCategoriesKeys.AllFriends] = { Order = 2, StringKey = "AllWord" }
local function onSelectSection(self, key)
if self.state.currentPage ~= key then
self:setState({
currentPage = key,
selectedPage = MenuKey,
})
end
end
function FriendsView:init()
self.selectedPage = MenuKey
self.onSelectionGained = function(key)
onSelectSection(self,key)
end
self.state = {
currentPage = FriendCategoriesKeys.OnlineFriends,
selectedPage = MenuKey,
}
self.enterSection = function()
SoundManager:Play("OverlayOpen")
Utility.SetSelectedCoreObject(nil)
self:setState({
selectedPage = self.state.currentPage,
})
end
self.exitSection = function()
SoundManager:Play("PopUp")
self:setState({
selectedPage = MenuKey,
})
end
end
function FriendsView:render()
local actionPriority = self.props.actionPriority or 0
local currentPage = self.state.currentPage
local friendsViewInFocus = self.props.inFocus
local friendsViewHide = self.props.hide
local friendCategoriesMenuInFocus = false
local friendPagesInFocus = false
if not friendsViewHide and friendsViewInFocus then
if self.state.selectedPage == MenuKey then
friendCategoriesMenuInFocus = true
end
if self.state.selectedPage ~= MenuKey then
friendPagesInFocus = true
end
end
local enterSection = self.enterSection
if currentPage == PageKeys.FriendCategories.OnlineFriends.Key and #self.props.onlineFriendsData == 0 then
enterSection = nil
elseif currentPage == PageKeys.FriendCategories.AllFriends.Key and #self.props.allFriendsData == 0 then
enterSection = nil
end
return Roact.createElement("Frame", {
Size = UDim2.new(1, -58, 1, 0),
Position = UDim2.new(0, 58, 0, 0),
BackgroundTransparency = 1,
},{
Mainview = Roact.createElement(SplitViewLR, {
Bias = 0.265,
LeftView = Roact.createElement(CategoryMenuView, {
Key = MenuKey,
Categories = FriendCategories,
InFocus = friendCategoriesMenuInFocus,
DefaultCategoryFocus = FriendCategoriesKeys.OnlineFriends,
OnSelectSection = self.onSelectionGained,
EnterSection = enterSection,
RedirectUp = self.props.redirectUp,
ActionPriority = actionPriority,
}),
RightView = Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
},{
OnlineFriendsView = Roact.createElement(FriendsScrollingView, {
friendsData = self.props.onlineFriendsData,
initialized = self.props.initialized,
hide = currentPage ~= PageKeys.FriendCategories.OnlineFriends.Key,
inFocus = friendPagesInFocus,
redirectLeft = self.exitSection,
redirectBack = self.exitSection,
redirectUp = self.props.redirectUp,
redirectRight = self.props.redirectRight,
size = UDim2.new(0, 440, 0, 770),
noFriendsView = Roact.createElement(NoFriendsView, {
text = Strings:LocalizedString("NoFriendsOnlinePhrase"),
}),
actionPriority = actionPriority + 1,
}),
AllFriendsView = Roact.createElement(FriendsScrollingView, {
friendsData = self.props.allFriendsData,
initialized = self.props.initialized,
hide = currentPage ~= PageKeys.FriendCategories.AllFriends.Key,
inFocus = friendPagesInFocus,
redirectLeft = self.exitSection,
redirectBack = self.exitSection,
redirectUp = self.props.redirectUp,
redirectRight = self.props.redirectRight,
size = UDim2.new(0, 440, 0, 770),
noFriendsView = Roact.createElement(NoFriendsView, {
text = Strings:LocalizedString("PlayAndMakeFriendsPhrase"),
}),
actionPriority = actionPriority + 1,
}),
}),
}),
})
end
local filterOnlineFriends = memoize(function(friendsData)
local onlineFriendsData = {}
for _, data in ipairs(friendsData) do
if data.robloxStatus ~= "Offline" or data.xboxStatus == "Online" then
table.insert(onlineFriendsData, data)
end
end
return onlineFriendsData
end)
local function mapStateToProps(state, props)
local friendsData = state.RenderedFriends.data
return {
allFriendsData = friendsData,
onlineFriendsData = filterOnlineFriends(friendsData),
initialized = state.RenderedFriends.initialized
}
end
return RoactRodux.UNSTABLE_connect2(mapStateToProps)(FriendsView)
@@ -0,0 +1,32 @@
--[[
Creates a component for no friends
]]
local Modules = game:GetService("CoreGui").RobloxGui.Modules
local Roact = require(Modules.Common.Roact)
local GlobalSettings = require(Modules.Shell.GlobalSettings)
return function(props)
return Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1
}, {
NoFriendsIcon = Roact.createElement("ImageLabel", {
Size = UDim2.new(0, 296, 0, 259),
Position = UDim2.new(0.5, -148, 0, 100),
BackgroundTransparency = 1,
Image = "rbxasset://textures/ui/Shell/Icons/FriendsIcon@1080.png",
}),
NoFriendsText = Roact.createElement("TextLabel", {
Size = UDim2.new(0, 440, 0, 72),
Position = UDim2.new(0.5, -220, 0, 392),
BackgroundTransparency = 1,
Font = GlobalSettings.RegularFont,
FontSize = GlobalSettings.ButtonSize,
TextColor3 = GlobalSettings.WhiteTextColor,
Text = props.text,
TextYAlignment = Enum.TextYAlignment.Top,
TextWrapped = true
}),
})
end
@@ -0,0 +1,223 @@
--[[
Creates a PresenceCard component
Props:
gamertag: string - Xbox Gamertag.
robloxName: string - Roblox name.
robloxuid: int - Roblox user id.
xuid: int - Xbox user id.
robloxStatus: string - User's roblox xboxStatus.
xboxStatus: string - User's xbox xboxStatus.
lastLocation: string - User's last location info.
layoutOrder: int - Controls the sorting priority of this button.
size: UDim2 - The size of the presence card.
onSelectionGained : function(guiObject : Ref<GuiObject>) -
Fires when the GuiObject is being focused on with the Gamepad selector.
onSelectionLost : function(guiObject : Ref<GuiObject>) -
Fires when the Gamepad selector stops focusing on the GuiObject.
onActivated : function(guiObject : Ref<GuiObject>) -
Fires when the button is activated.
]]
local Modules = game:GetService("CoreGui").RobloxGui.Modules
local Roact = require(Modules.Common.Roact)
local GlobalSettings = require(Modules.Shell.GlobalSettings)
local Components = Modules.Shell.Components
local UserThumbnailLoader = require(Components.Common.UserThumbnailLoader)
local Strings = require(Modules.Shell.LocalizedStrings)
local Utility = require(Modules.Shell.Utility)
local SoundComponent = require(Modules.Shell.Components.Common.SoundComponent)
local PresenceCard = Roact.PureComponent:extend("PresenceCard")
function PresenceCard:init()
self.selectionImageObject = Utility.Create "ImageLabel"({
Name = "SelectorImage",
Image = GlobalSettings.Images.ButtonSelector,
Position = UDim2.new(0, -7, 0, -7),
Size = UDim2.new(1, 14, 1, 14),
BackgroundTransparency = 1,
ScaleType = Enum.ScaleType.Slice,
SliceCenter = Rect.new(31, 31, 63, 63),
})
self.onCreate = function(rbx)
self.ref = rbx
end
self.defaultProps = {
buttonColor3 = GlobalSettings.Colors.WhiteButton,
buttonTransparency = 0.8,
textColor3 = GlobalSettings.Colors.WhiteText,
iconColor3 = GlobalSettings.Colors.WhiteText,
}
self.focusedProps = {
buttonColor3 = GlobalSettings.Colors.BlueButton,
buttonTransparency = 0,
textColor3 = GlobalSettings.Colors.BlackText,
iconColor3 = GlobalSettings.Colors.BlackText,
}
self.buttonImage = GlobalSettings.Images.ButtonDefault
end
function PresenceCard:render()
local props = self.props
local focused = self.props.focused
local currProps = focused and self.focusedProps or self.defaultProps
local gamertagText = props.gamertag or ""
local robloxNameText = props.robloxName or ""
local showGamertag = gamertagText ~= ""
local showRobloxName = robloxNameText ~= ""
local statusText = ""
local statusImageColor3 = GlobalSettings.Colors.GreySelectedButton
local function setPresence(statusStr, statusColor)
statusImageColor3 = statusColor
if statusStr and statusStr ~= "" then
statusText = statusStr
end
end
if props.robloxStatus == "InGame" then
setPresence(props.lastLocation, GlobalSettings.Colors.GreenText)
elseif props.robloxStatus == "InStudio" then
setPresence(props.lastLocation, GlobalSettings.Colors.OrangeText)
elseif props.robloxStatus == "Online" then
setPresence("Roblox", GlobalSettings.Colors.BlueText)
else
if props.xboxStatus and props.xboxStatus == "Online" then
setPresence(Strings:LocalizedString("OnlineWord"), GlobalSettings.Colors.BlueText)
else
setPresence(Strings:LocalizedString("OfflineWord"), GlobalSettings.Colors.GreyText)
end
end
return Roact.createElement("ImageButton", {
Image = self.buttonImage,
Position = UDim2.new(0.5, 0, 0.5, 0),
AnchorPoint = Vector2.new(0.5, 0.5),
LayoutOrder = props.layoutOrder,
Size = props.size or UDim2.new(0, 440, 0, 120),
ImageColor3 = currProps.buttonColor3,
ImageTransparency = currProps.buttonTransparency,
ScaleType = Enum.ScaleType.Slice,
SliceCenter = Rect.new(8, 8, 9, 9),
SelectionImageObject = self.selectionImageObject,
BackgroundTransparency = 1,
[Roact.Event.SelectionGained] = props.onSelectionGained,
[Roact.Event.SelectionLost] = props.onSelectionLost,
[Roact.Event.Activated] = props.onActivated,
[Roact.Ref] = self.onCreate,
},{
MoveSelection = Roact.createElement(SoundComponent, {
SoundName = "MoveSelection",
}),
AvatarImage = Roact.createElement(UserThumbnailLoader, {
rbxuid = props.robloxuid,
thumbnailType = Enum.ThumbnailType.HeadShot,
thumbnailSize = Enum.ThumbnailSize.Size100x100,
position = UDim2.new(0, 10, 0, 10),
size = UDim2.new(0, 100, 0, 100),
}),
ContentContainer = Roact.createElement("Frame",{
Size = UDim2.new(1, -140, 1, 0),
Position = UDim2.new(0, 126, 0, 0),
BackgroundTransparency = 1,
ClipsDescendants = true,
}, {
UIPadding = Roact.createElement("UIPadding", {
PaddingTop = UDim.new(0, 10),
PaddingBottom = UDim.new(0, 10)
}),
UIListLayout = Roact.createElement("UIListLayout", {
Padding = UDim.new(0, 7),
SortOrder = Enum.SortOrder.LayoutOrder,
HorizontalAlignment = Enum.HorizontalAlignment.Left,
VerticalAlignment = Enum.VerticalAlignment.Center,
}),
GamertagContainer = showGamertag and Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 0, 30),
LayoutOrder = 1,
BackgroundTransparency = 1
},{
GamertagLabel = Roact.createElement("TextLabel", {
Text = gamertagText,
Size = UDim2.new(1, 0, 1, 0),
Position = UDim2.new(0, 0, 0, 0),
TextXAlignment = Enum.TextXAlignment.Left,
TextColor3 = currProps.textColor3,
Font = GlobalSettings.Fonts.Regular,
TextSize = 30,
TextScaled = true,
BackgroundTransparency = 1,
}),
}),
RobloxNameContainer = showRobloxName and Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 0, 30),
LayoutOrder = 2,
BackgroundTransparency = 1
},{
RobloxIcon = Roact.createElement("ImageLabel", {
BackgroundTransparency = 1,
Image = GlobalSettings.Images.RobloxIcon,
ImageColor3 = currProps.iconColor3,
Position = UDim2.new(0, 0, 0, 1),
Size = UDim2.new(0, 28, 0, 28),
}),
RobloxNameLabel = Roact.createElement("TextLabel", {
Text = robloxNameText,
Size = UDim2.new(1, -38, 1, 0),
Position = UDim2.new(0, 38, 0, 0),
TextXAlignment = Enum.TextXAlignment.Left,
TextColor3 = currProps.textColor3,
Font = GlobalSettings.Fonts.Regular,
TextSize = 30,
TextScaled = true,
BackgroundTransparency = 1,
})
}),
StatusContainer = Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 0, 26),
LayoutOrder = 3,
BackgroundTransparency = 1
},{
PresenceStatusImage = Roact.createElement("ImageLabel", {
BackgroundTransparency = 1,
Image = GlobalSettings.Images.OnlineStatusIcon,
Size = UDim2.new(0, 18, 0, 18),
Position = UDim2.new(0, 5, 0, 4),
ImageColor3 = statusImageColor3,
}),
PresenceLabel = Roact.createElement("TextLabel", {
Text = statusText,
Size = UDim2.new(1, -38, 1, 0),
Position = UDim2.new(0, 33, 0, 0),
TextXAlignment = Enum.TextXAlignment.Left,
TextColor3 = currProps.textColor3,
Font = GlobalSettings.Fonts.Regular,
TextSize = 26,
BackgroundTransparency = 1,
})
}),
})
})
end
function PresenceCard:didMount()
delay(0, function()
if self.props.selected then
Utility.SetSelectedCoreObject(self.ref)
end
end)
end
function PresenceCard:didUpdate(previousProps, previousState)
if not previousProps.selected and self.props.selected then
Utility.SetSelectedCoreObject(self.ref)
end
end
return PresenceCard
@@ -0,0 +1,147 @@
local GuiService = game:GetService("GuiService")
local Modules = game:GetService("CoreGui").RobloxGui.Modules
local ShellModules = Modules:FindFirstChild("Shell")
local Roact = require(Modules.Common.Roact)
local RoactRodux = require(Modules.Common.RoactRodux)
local Strings = require(ShellModules:FindFirstChild("LocalizedStrings"))
local ScreenManager = require(ShellModules.ScreenManager)
local AppState = require(ShellModules.AppState)
local Analytics = require(ShellModules:FindFirstChild("Analytics"))
local Utility = require(ShellModules:FindFirstChild("Utility"))
local Components = ShellModules.Components
local FriendsView = require(Components.Social.FriendsView)
local FriendsData = require(ShellModules.FriendsData)
local function CreateSocialPane(parent)
local this = {}
local isPaneFocused = false
local HubContainer = parent.Parent
local UpSelector = HubContainer:FindFirstChild("TabContainer")
local noSelectionObject = Utility.Create"ImageLabel"({
BackgroundTransparency = 1,
})
local SocialPaneContainer = Utility.Create"Frame"({
Name = "SocialPane",
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = 1,
Visible = false,
SelectionImageObject = noSelectionObject,
Parent = parent,
})
local FriendsContainer = Utility.Create"Frame"({
Name = "FriendsContainer",
Size = UDim2.new(1, 0, 1, 0),
Position = UDim2.new(0, 0, 0, 23),
BackgroundTransparency = 1,
Parent = SocialPaneContainer,
})
local friendsScrollerInstance;
local function ReconcileFriendsScrollerInstance()
if not friendsScrollerInstance then
return
end
local friendsScroller = Roact.createElement(RoactRodux.StoreProvider, {
store = AppState.store,
}, {
FriendsView = Roact.createElement(FriendsView, {
inFocus = isPaneFocused,
hide = not SocialPaneContainer.Visible,
redirectUp = function()
Utility.SetSelectedCoreObject(UpSelector)
end,
})
})
friendsScrollerInstance = Roact.reconcile(friendsScrollerInstance, friendsScroller)
end
function this:GetName()
return Strings:LocalizedString("FriendsWord")
end
function this:IsFocused()
return isPaneFocused
end
--[[ Public API ]]--
function this:GetAnalyticsInfo()
return {[Analytics.WidgetNames("WidgetId")] = Analytics.WidgetNames("SocialPaneId")}
end
function this:Show(fromAppHub)
SocialPaneContainer.Visible = true
--Suspend Friends BG Update whenever we are on GamesPane
FriendsData:SuspendUpdate()
--We rebuild Friends Scroller only if we navigate from other tabs
if fromAppHub then
if friendsScrollerInstance then
Roact.unmount(friendsScrollerInstance)
end
local friendsScroller = Roact.createElement(RoactRodux.StoreProvider, {
store = AppState.store,
}, {
FriendsView = Roact.createElement(FriendsView, {
hide = not SocialPaneContainer.Visible,
inFocus = isPaneFocused,
redirectUp = function()
Utility.SetSelectedCoreObject(UpSelector)
end,
})
})
friendsScrollerInstance = Roact.mount(friendsScroller, FriendsContainer, "FriendsViewContainer")
else
ReconcileFriendsScrollerInstance()
end
ScreenManager:PlayDefaultOpenSound()
end
function this:Hide(fromAppHub)
SocialPaneContainer.Visible = false
--We destroy Friends Scroller if we navigate to other tabs
if fromAppHub then
if friendsScrollerInstance then
Roact.unmount(friendsScrollerInstance)
end
friendsScrollerInstance = nil
--We resume Friends Update only if we navigate to other tabs
FriendsData:ResumeUpdate()
else
ReconcileFriendsScrollerInstance()
end
end
function this:Focus()
isPaneFocused = true
ReconcileFriendsScrollerInstance()
end
function this:RemoveFocus()
isPaneFocused = false
ReconcileFriendsScrollerInstance()
local selectedObject = GuiService.SelectedCoreObject
if selectedObject and selectedObject:IsDescendantOf(SocialPaneContainer) then
Utility.SetSelectedCoreObject(nil)
end
end
function this:SetPosition(newPosition)
SocialPaneContainer.Position = newPosition
end
function this:SetParent(newParent)
SocialPaneContainer.Parent = newParent
end
function this:IsAncestorOf(object)
return SocialPaneContainer and SocialPaneContainer:IsAncestorOf(object)
end
return this
end
return CreateSocialPane