Clients/Client2018/content/internal/AppShell/Modules/Shell/HomePane.lua

486 lines
17 KiB
Lua

-- Written by Kip Turner, Copyright Roblox 2015
local CoreGui = game:GetService("CoreGui")
local GuiService = game:GetService('GuiService')
local RunService = game:GetService("RunService")
local GuiRoot = CoreGui:FindFirstChild("RobloxGui")
local Modules = GuiRoot:FindFirstChild("Modules")
local ShellModules = Modules:FindFirstChild("Shell")
local Utility = require(ShellModules:FindFirstChild('Utility'))
local GlobalSettings = require(ShellModules:FindFirstChild('GlobalSettings'))
local EventHub = require(ShellModules:FindFirstChild('EventHub'))
local FriendsData = require(ShellModules:FindFirstChild('FriendsData'))
local FriendsView = require(ShellModules:FindFirstChild('FriendsView'))
local ScrollingGridModule = require(ShellModules:FindFirstChild('ScrollingGrid'))
local GameSort = require(ShellModules:FindFirstChild('GameSort'))
local ScreenManager = require(ShellModules:FindFirstChild('ScreenManager'))
local SoundManager = require(ShellModules:FindFirstChild('SoundManager'))
local AssetManager = require(ShellModules:FindFirstChild('AssetManager'))
local LoadingWidget = require(ShellModules:FindFirstChild('LoadingWidget'))
local Strings = require(ShellModules:FindFirstChild('LocalizedStrings'))
local ThumbnailLoader = require(ShellModules:FindFirstChild('ThumbnailLoader'))
local SortsData = require(ShellModules:FindFirstChild('SortsData'))
local Analytics = require(ShellModules:FindFirstChild('Analytics'))
local XboxAppState = require(ShellModules:FindFirstChild('AppState'))
local XboxRecommendedPeople = settings():GetFFlag("XboxRecommendedPeople2")
local MOCKUP_SIZE = Vector2.new(1920, 1080)
local PROFILE_SIZE = Vector2.new(450, 343)
local PROFILE_NAME_SIZE = Vector2.new(450, 38)
local PROFILE_BUTTON_SIZE = Vector2.new(450, 300)
local PROFILE_IMAGE_SIZE = Vector2.new(450, 300)
local SORTS_SIZE = Vector2.new(1234, 608)
local function CreateHomePane(parent)
local this = {}
local inFocus = false
local sortsObjects = {}
local HomePaneContainer = Utility.Create'Frame'
{
Name = 'HomePane';
Size = UDim2.new(1, 0, 1, 0);
BackgroundTransparency = 1;
Parent = parent;
}
local ProfileContainer = Utility.Create'Frame'
{
Name = 'ProfileContainer';
Position = UDim2.new(0,0,0,0);
BackgroundTransparency = 1;
Parent = HomePaneContainer;
}
local NameLabel = Utility.Create'TextLabel'
{
Name = 'NameLabel';
Text = '';
TextXAlignment = 'Left';
TextYAlignment = 'Top';
-- TextScaled = true;
TextColor3 = GlobalSettings.WhiteTextColor;
Font = GlobalSettings.RegularFont;
FontSize = GlobalSettings.SubHeaderSize;
BackgroundTransparency = 1;
Parent = ProfileContainer;
};
local ProfileButton = Utility.Create'ImageButton'
{
Name = 'ProfileButton';
AutoButtonColor = false;
BackgroundTransparency = 1;
Parent = ProfileContainer;
SoundManager:CreateSound('MoveSelection');
}
local ProfileImage = Utility.Create'ImageLabel'
{
Name = 'ProfileImage';
Position = UDim2.new(0,0,0,0);
BackgroundTransparency = 1;
BorderSizePixel = 0;
ZIndex = 3;
Parent = ProfileButton;
};
Utility.Create'Frame'
{
Name = 'ProfileImageBackground';
Size = UDim2.new(1,0,1,0);
BorderSizePixel = 0;
BackgroundTransparency = 0;
BackgroundColor3 = GlobalSettings.CharacterBackgroundColor;
ZIndex = 2;
Parent = ProfileImage;
AssetManager.CreateShadow(1);
}
local AvatarBrushBackground = Utility.Create'Frame'
{
Name = 'AvatarBrushImage';
BorderSizePixel = 0;
BackgroundColor3 = GlobalSettings.AvatarBoxBackgroundColor;
BackgroundTransparency = GlobalSettings.AvatarBoxBackgroundDeselectedTransparency;
ZIndex = 2;
-- Parent = ProfileButton;
}
local AvatarBrushImage = Utility.Create'ImageLabel'
{
Name = 'AvatarBrushImage';
BorderSizePixel = 0;
BackgroundTransparency = 1;
ZIndex = 2;
Parent = AvatarBrushBackground;
Image = "rbxasset://textures/ui/Shell/Icons/CustomizeIcon@1080.png";
Size = UDim2.new(0,47,0,48);
};
local AvatarTextLabel = Utility.Create'TextLabel'
{
Name = 'AvatarTextLabel';
Text = Strings:LocalizedString('EditAvatarPhrase');
TextColor3 = GlobalSettings.WhiteTextColor;
Font = GlobalSettings.RegularFont;
FontSize = GlobalSettings.ButtonSize;
BackgroundTransparency = 1;
ZIndex = 2;
Parent = AvatarBrushBackground;
};
ProfileButton.MouseButton1Click:connect(function()
SoundManager:Play('ButtonPress')
EventHub:dispatchEvent(EventHub.Notifications["NavigateToEquippedAvatar"])
-- EventHub:dispatchEvent(EventHub.Notifications["OpenProfileDetail"], "AppHub");
end)
local function OnProfileButtonSelectionChanged()
local selectedObject = GuiService.SelectedCoreObject
local newBackgroundTransparency = selectedObject == ProfileButton and
GlobalSettings.AvatarBoxBackgroundSelectedTransparency or
GlobalSettings.AvatarBoxBackgroundDeselectedTransparency
local newTextTransparency = selectedObject == ProfileButton and
GlobalSettings.AvatarBoxTextSelectedTransparency or
GlobalSettings.AvatarBoxTextDeselectedTransparency
Utility.PropertyTweener(AvatarBrushBackground, 'BackgroundTransparency', newBackgroundTransparency, newBackgroundTransparency, 0, nil, true)
Utility.PropertyTweener(AvatarTextLabel, 'TextTransparency', newTextTransparency, newTextTransparency, 0, nil, true)
Utility.PropertyTweener(AvatarBrushImage, 'ImageTransparency', newTextTransparency, newTextTransparency, 0, nil, true)
end
local existingThumbnailLoader = nil
local function UpdateProfileInfo()
local playerName = XboxAppState.store:getState().XboxUser.gamertag
NameLabel.Text = playerName and playerName or ''
local rbxuid = XboxAppState.store:getState().RobloxUser.rbxuid
if rbxuid then
if existingThumbnailLoader then
existingThumbnailLoader:Cancel()
end
local thumbnailSize = ThumbnailLoader.AvatarSizes.Size352x352
local thumbLoader = ThumbnailLoader:LoadAvatarThumbnailAsync(ProfileImage, rbxuid,
Enum.ThumbnailType.AvatarThumbnail, Enum.ThumbnailSize.Size352x352, true)
existingThumbnailLoader = thumbLoader
spawn(function()
thumbLoader:LoadAsync()
ProfileImage.ImageRectSize = Vector2.new(thumbnailSize.X, (PROFILE_IMAGE_SIZE.Y/PROFILE_IMAGE_SIZE.X) * thumbnailSize.X)
end)
end
end
UpdateProfileInfo()
local FriendActivityContainer = Utility.Create'Frame'
{
Name = 'FriendActivityContainer';
BackgroundTransparency = 1;
Parent = HomePaneContainer;
}
local FriendActivityTitle = Utility.Create'TextLabel'
{
Name = 'FriendActivityTitle';
Text = Strings:LocalizedString('FriendActivityWord');
Size = UDim2.new(1,0,0,50);
Position = UDim2.new(0,0,0,10);
TextXAlignment = 'Left';
TextColor3 = GlobalSettings.WhiteTextColor;
Font = GlobalSettings.RegularFont;
FontSize = GlobalSettings.SubHeaderSize;
BackgroundTransparency = 1;
Parent = FriendActivityContainer;
};
local NoFriendsOnlineMessage = Utility.Create'TextLabel'
{
Name = 'NoFriendsOnlineMessage';
Text = Strings:LocalizedString('NoFriendsOnlinePhrase');
Size = UDim2.new(0.9,0,1,-125);
Position = UDim2.new(0.05, 0, 0, 125);
TextYAlignment = 'Top';
TextColor3 = GlobalSettings.GreyTextColor;
TextWrapped = true;
TextTransparency = GlobalSettings.FriendStatusTextTransparency;
Font = GlobalSettings.BoldFont;
FontSize = GlobalSettings.DescriptionSize;
BackgroundTransparency = 1;
Visible = false;
Parent = FriendActivityContainer;
};
local friendsScroller = ScrollingGridModule({SelectionMode = "Middle"; Dynamic = true})
friendsScroller:SetSize(UDim2.new(1,0,1,-60))
friendsScroller:SetRowColumnConstraint(1)
friendsScroller:SetScrollDirection(friendsScroller.Enum.ScrollDirection.Vertical)
friendsScroller:SetCellSize(Vector2.new(446,114))
friendsScroller:SetSpacing(Vector2.new(0, 26))
friendsScroller:SetPosition(UDim2.new(0,0,0,FriendActivityTitle.Position.Y.Offset + FriendActivityTitle.Size.Y.Offset))
local friendScrollerContainer = friendsScroller:GetGuiObject()
friendScrollerContainer.Visible = false
friendsScroller:SetParent(FriendActivityContainer)
local function onFriendsUpdated(friendCount)
NoFriendsOnlineMessage.Visible = friendCount == 0
friendScrollerContainer.Visible = friendCount > 0
end
local function setFriendItems()
local friendsData = FriendsData.GetOnlineFriendsAsync()
FriendsView(friendsScroller, friendsData, nil, onFriendsUpdated)
onFriendsUpdated(#friendsData)
end
local friendsLoader = LoadingWidget(
{ Parent = FriendActivityContainer }, { setFriendItems } )
-- Don't Block
spawn(function()
friendsLoader:AwaitFinished()
friendsLoader:Cleanup()
end)
local SortsContainer = Utility.Create'Frame'
{
Name = 'SortsContainer';
BackgroundTransparency = 1;
Parent = HomePaneContainer;
}
local populateSortsDebounce = false
local function PopulateSorts()
if populateSortsDebounce then return end
populateSortsDebounce = true
local function loadGameSorts()
while #sortsObjects > 0 do
local sortObject = table.remove(sortsObjects)
if sortObject then
if GuiService.SelectedCoreObject and GuiService.SelectedCoreObject:IsDescendantOf(sortObject:GetContainer()) then
if inFocus then
Utility.SetSelectedCoreObject(this:GetDefaultSelectionObject())
end
end
sortObject:Destroy()
end
end
local favoriteGamesSort = SortsData:GetUserFavorites()
local favoritesPage1 = favoriteGamesSort:GetSortAsync(0, 4)
local recentGamesSort = SortsData:GetUserRecent()
local recentlyPage1 = recentGamesSort:GetSortAsync(0, 4)
local showRecent = recentlyPage1 and #recentlyPage1 > 2
local showFavorites = favoritesPage1 and #favoritesPage1 > 2
local function setGridView(view, page, title, collection)
if page then
view:SetPlaceIds(page, title, collection)
end
view:SetTitle(title)
view:SetVisible(false)
view:SetParent(SortsContainer)
table.insert(sortsObjects, view)
end
local function createMainSortGrid(title, page, collection)
local view = GameSort:CreateMainGridView(UDim2.new(0, 378, 1, 0), Vector2.new(10, 10),
UDim2.new(1, 0, 0, 378), UDim2.new(0, 184, 0, 184))
setGridView(view, page, title, collection)
return view
end
local function createGridSortView(size, imageSize, spacing, rows, columns, page, title, collection)
local view = GameSort:CreateGridView(size, imageSize, spacing, rows, columns)
setGridView(view, page, title, collection)
return view
end
local currentPosition = UDim2.new(0, 0, 0, 0)
local margin = (showFavorites and showRecent) and 50 or 28
if showFavorites then
local view = createMainSortGrid(Strings:LocalizedString('FavoritesSortTitle'), favoritesPage1, favoriteGamesSort)
view:SetPosition(currentPosition)
currentPosition = currentPosition + UDim2.new(0, view:GetContainer().Size.X.Offset + margin, 0, 0)
end
if showRecent then
local view = createMainSortGrid(Strings:LocalizedString('RecentlyPlayedSortTitle'), recentlyPage1, recentGamesSort)
view:SetPosition(currentPosition)
currentPosition = currentPosition + UDim2.new(0, view:GetContainer().Size.X.Offset + margin, 0, 0)
end
local featuredGamesSort = SortsData:GetSort(SortsData.DefaultSortId.Featured)
if featuredGamesSort then
--Currently, assume SortsData.DefaultSortId.Featured corresponds to the feature sort Id
local featuredTitle = Strings:LocalizedString('FeaturedTitle')
local recommendedView;
if showRecent and showFavorites then
local page = featuredGamesSort:GetSortAsync(0, 4)
recommendedView = createMainSortGrid(featuredTitle, page, featuredGamesSort)
elseif showRecent or showFavorites then
local page = featuredGamesSort:GetSortAsync(0, 7)
recommendedView = createGridSortView(UDim2.new(0, 858, 1, 0), UDim2.new(0, 276, 0, 276), Vector2.new(15, 20),
2, 3, page, featuredTitle, featuredGamesSort)
else
local page = featuredGamesSort:GetSortAsync(0, 9)
recommendedView = createGridSortView(UDim2.new(0, 1236, 0, 648), UDim2.new(0, 300, 0, 300), Vector2.new(12, 12),
2, 4, page, featuredTitle, featuredGamesSort)
end
recommendedView:SetPosition(currentPosition)
end
end
local loader = LoadingWidget(
{Parent = SortsContainer}, {loadGameSorts})
spawn(function()
loader:AwaitFinished()
loader:Cleanup()
loader = nil
populateSortsDebounce = false
for i = 1, #sortsObjects do
sortsObjects[i]:SetVisible(true)
end
end)
end
local function UpdateLayout()
local guiRootSize = GuiRoot.AbsoluteSize
ProfileContainer.Size = Utility.CalculateRelativeDimensions(ProfileContainer, PROFILE_SIZE, MOCKUP_SIZE, guiRootSize)
NameLabel.Size = Utility.CalculateRelativeDimensions(NameLabel, PROFILE_NAME_SIZE, MOCKUP_SIZE, guiRootSize)
ProfileButton.Size = Utility.CalculateRelativeDimensions(ProfileButton, PROFILE_BUTTON_SIZE, MOCKUP_SIZE, guiRootSize)
ProfileButton.AnchorPoint = Vector2.new(0, 1)
ProfileButton.Position = UDim2.new(0, 0, 1, -6)
ProfileImage.Size = Utility.CalculateRelativeDimensions(ProfileImage, PROFILE_IMAGE_SIZE, MOCKUP_SIZE, guiRootSize)
AvatarBrushBackground.Size = UDim2.new(1 - ProfileImage.Size.X.Scale, -ProfileImage.Size.X.Offset, 1, 0)
AvatarBrushBackground.Position = UDim2.new(1 - AvatarBrushBackground.Size.X.Scale, AvatarBrushBackground.Size.X.Offset, 0, 0)
AvatarBrushImage.AnchorPoint = Vector2.new(0.5, 0.5)
AvatarBrushImage.Position = UDim2.new(0.5, 0, 0.42, 0)
AvatarTextLabel.AnchorPoint = Vector2.new(0.5, 0.5)
AvatarTextLabel.Position = UDim2.new(0.5, 0, 0.7, 0)
FriendActivityContainer.Size = UDim2.new(ProfileContainer.Size.X.Scale, 0, 0, 300);
FriendActivityContainer.Position = UDim2.new(0,0,ProfileContainer.Size.Y.Scale,0);
SortsContainer.Size = Utility.CalculateRelativeDimensions(SortsContainer, SORTS_SIZE, MOCKUP_SIZE, guiRootSize)
SortsContainer.Position = UDim2.new(1 - SortsContainer.Size.X.Scale, 0, 0, 0)
end
UpdateLayout()
local screenResolutionChangedConn = nil
local profileButtonSelectedConn = nil
local profileButtonDeselectedConn = nil
function this:GetName()
return Strings:LocalizedString('HomeWord')
end
function this:GetAnalyticsInfo()
return {[Analytics.WidgetNames('WidgetId')] = Analytics.WidgetNames('HomePaneId')}
end
function this:IsFocused()
return inFocus
end
function this:GetDefaultSelectionObject()
return ProfileButton
end
function this:SetSelectionObject()
Utility.SetSelectedCoreObject(self:GetDefaultSelectionObject())
-- TODO: Remember selection while staying in Pane. Pressing A on the Home tab should remember
-- last selection only while in pane.
end
function this:Show(fromAppHub)
HomePaneContainer.Visible = true
PopulateSorts()
UpdateLayout()
Utility.DisconnectEvent(screenResolutionChangedConn)
screenResolutionChangedConn = GuiRoot:GetPropertyChangedSignal('AbsoluteSize'):connect(function()
RunService.RenderStepped:wait()
UpdateLayout()
end)
Utility.DisconnectEvent(profileButtonSelectedConn)
Utility.DisconnectEvent(profileButtonDeselectedConn)
profileButtonSelectedConn = ProfileButton.SelectionGained:connect(OnProfileButtonSelectionChanged)
profileButtonDeselectedConn = ProfileButton.SelectionLost:connect(OnProfileButtonSelectionChanged)
OnProfileButtonSelectionChanged()
UpdateProfileInfo()
ScreenManager:DefaultCancelFade(self.TransitionTweens)
self.TransitionTweens = ScreenManager:DefaultFadeIn(HomePaneContainer)
delay(0.5, function()
if inFocus and GuiService.SelectedCoreObject == nil then
self:SetSelectionObject()
end
end)
if XboxRecommendedPeople then
--Suspend Friends BG Update whenever we are on GamesPane
FriendsData:SuspendUpdate()
end
ScreenManager:PlayDefaultOpenSound()
end
function this:Hide(fromAppHub)
HomePaneContainer.Visible = false
profileButtonSelectedConn = Utility.DisconnectEvent(profileButtonSelectedConn)
profileButtonDeselectedConn = Utility.DisconnectEvent(profileButtonDeselectedConn)
screenResolutionChangedConn = Utility.DisconnectEvent(screenResolutionChangedConn)
ScreenManager:DefaultCancelFade(self.TransitionTweens)
self.TransitionTweens = nil
if XboxRecommendedPeople then
if fromAppHub then
--We resume Friends Update only if we navigate to other tabs
FriendsData:ResumeUpdate()
end
end
end
function this:Focus()
inFocus = true
UpdateLayout()
self:SetSelectionObject()
OnProfileButtonSelectionChanged()
end
function this:RemoveFocus()
inFocus = false
local selectedObject = GuiService.SelectedCoreObject
if selectedObject and selectedObject:IsDescendantOf(HomePaneContainer) then
Utility.SetSelectedCoreObject(nil)
end
end
function this:SetPosition(newPosition)
HomePaneContainer.Position = newPosition
end
function this:SetParent(newParent)
HomePaneContainer.Parent = newParent
end
function this:IsAncestorOf(object)
return HomePaneContainer and HomePaneContainer:IsAncestorOf(object)
end
return this
end
return CreateHomePane