Clients/Client2018/content/internal/AppShell/Modules/Shell/Components/Common/SideBar.lua

260 lines
8.6 KiB
Lua

--[[
Creates a component for sidebar
Props:
buttons : array An array of the buttons to be added on the sidebar.
key - string The text to be shown on the sidebar button.
value - function() A callback which will be called when the button is activated.
text: string - The text to be shown on the sidebar.
inFocus: bool - The boolean which indicates whether the sidebar is open.
selectIndex: int - The button index we try to select when the sidebar is open.
paddingTop : UDim - The padding to apply on the top side relative to the sidebar's normal size.
paddingBottom : UDim - The padding to apply on the bottom side relative to the sidebar's normal size.
displayOrder: int - The order that the sidebar ScreenGui is drawn.
onRemoveFocus : function() - Callback function when the remove focus from sidebar
onClose: function() - Callback function when the sidebar is closed.
actionPriority : int - The action priority on sidebar.
]]
local CoreGui = game:GetService("CoreGui")
local Modules = CoreGui.RobloxGui.Modules
local Roact = require(Modules.Common.Roact)
local GlobalSettings = require(Modules.Shell.GlobalSettings)
local RoactMotion = require(Modules.LuaApp.RoactMotion)
local SoundManager = require(Modules.Shell.SoundManager)
local Components = Modules.Shell.Components
local SoundComponent = require(Modules.Shell.Components.Common.SoundComponent)
local ContextActionEvent = require(Components.ContextActionEvent)
local Utility = require(Modules.Shell.Utility)
local INSET_X = 65
local BUTTON_SIZE_Y = 75
local SIDEBAR_SELECTION_GROUP_NAME = "SideBar"
local SideBar = Roact.PureComponent:extend("SideBar")
function SideBar:init()
self.groupKey = SIDEBAR_SELECTION_GROUP_NAME
self.buttonImage = GlobalSettings.Images.ButtonDefault
self.selectionImageObject = Utility.Create "ImageLabel"({
Name = "SelectorImage",
BackgroundTransparency = 1,
Visible = false
})
self.defaultProps = {
buttonColor3 = GlobalSettings.Colors.WhiteButton,
buttonTransparency = 1,
textColor3 = GlobalSettings.Colors.WhiteText,
}
self.focusedProps = {
buttonColor3 = GlobalSettings.Colors.BlueButton,
buttonTransparency = 0,
textColor3 = GlobalSettings.Colors.TextSelected,
}
end
function SideBar:render()
local props = self.props
local onClose = function()
self.buttons = {}
Utility.RemoveSelectionGroup(self.groupKey)
if props.onClose then
props.onClose()
end
end
local contents = {
--Make it inside the title safe container
UIPadding = Roact.createElement("UIPadding", {
PaddingTop = props.paddingTop or UDim.new(0, 156),
PaddingBottom = props.paddingBottom or UDim.new(0, 39)
})
}
if props.buttons then
local index = 0
for _, buttonObj in ipairs(props.buttons) do
index = index + 1
local btIndex = index
local focused = self.state.selectedIndex and self.state.selectedIndex == btIndex
local currProps = focused and self.focusedProps or self.defaultProps
local btText = Roact.createElement("TextLabel", {
Size = UDim2.new(1, -INSET_X, 1, 0),
Position = UDim2.new(0, INSET_X, 0, 0),
AnchorPoint = Vector2.new(0, 0),
Text = buttonObj.text,
TextSize = GlobalSettings.TextSizes.Medium,
TextXAlignment = Enum.TextXAlignment.Left,
TextColor3 = currProps.textColor3,
Font = GlobalSettings.RegularFont,
BackgroundTransparency = 1,
})
local moveSelection = Roact.createElement(SoundComponent, {
SoundName = "MoveSelection",
})
contents["Button"..btIndex] = Roact.createElement("ImageButton", {
Image = self.buttonImage,
Position = UDim2.new(0.5, 0, 0.5, 0),
AnchorPoint = Vector2.new(0.5, 0.5),
Size = UDim2.new(1, -1, 0, BUTTON_SIZE_Y),
LayoutOrder = btIndex,
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] = function()
self:setState({
selectedIndex = btIndex
})
end,
[Roact.Event.SelectionLost] = function()
self:setState({
selectedIndex = Roact.None
})
end,
[Roact.Event.Activated] = function()
SoundManager:Play("ButtonPress")
onClose()
buttonObj.callback()
end,
[Roact.Ref] = function(bt)
self.buttons = self.buttons or {}
self.buttons[btIndex] = bt
end,
}, {
ButtonText = btText,
MoveSelection = moveSelection,
})
end
if index > 0 then
contents.UIListLayout = Roact.createElement("UIListLayout", {
Padding = UDim.new(0, 0),
SortOrder = Enum.SortOrder.LayoutOrder,
HorizontalAlignment = Enum.HorizontalAlignment.Left,
VerticalAlignment = Enum.VerticalAlignment.Top,
})
end
else
contents.TextLabel = Roact.createElement("TextLabel", {
Size = UDim2.new(1, -INSET_X - 100, 1, 0),
Position = UDim2.new(0, INSET_X, 0, 0),
BorderSizePixel = 0,
BackgroundTransparency = 1,
Text = props.text,
TextXAlignment = Enum.TextXAlignment.Left,
TextYAlignment = Enum.TextYAlignment.Top,
TextColor3 = GlobalSettings.WhiteTextColor,
Font = GlobalSettings.RegularFont,
FontSize = GlobalSettings.DescriptionSize,
TextWrapped = true,
})
end
local inFocus = props.inFocus
local modalBackgroundTransparency = inFocus and GlobalSettings.ModalBackgroundTransparency or 1
local containerPositionXScale = inFocus and 0.7 or 1
if not inFocus then
self.seenPressed = false
end
return Roact.createElement(RoactMotion.SimpleMotion, {
defaultStyle = {
modalBackgroundTransparency = 1,
containerPositionXScale = 1,
},
style = {
modalBackgroundTransparency = RoactMotion.spring(modalBackgroundTransparency, 600, 60),
containerPositionXScale = RoactMotion.spring(containerPositionXScale, 600, 60),
},
onRested = not inFocus and onClose,
render = function(values)
return Roact.createElement(Roact.Portal, { target = CoreGui }, {
SideBarGui = Roact.createElement("ScreenGui", {
ZIndexBehavior = Enum.ZIndexBehavior.Sibling,
DisplayOrder = props.displayOrder or 1
}, {
BackConnector = inFocus and Roact.createElement(ContextActionEvent, {
name = "CloseSideBar",
callback = function(actionName, inputState, inputObject)
if inputObject.KeyCode == Enum.KeyCode.ButtonB then
if inputState == Enum.UserInputState.Begin then
self.seenPressed = true
elseif inputState == Enum.UserInputState.End and self.seenPressed then
self:setState({
selectedIndex = Roact.None
})
if props.onRemoveFocus then
props.onRemoveFocus()
end
end
end
end,
binds = { Enum.UserInputType.Gamepad1, Enum.UserInputType.Gamepad2, Enum.UserInputType.Gamepad3, Enum.UserInputType.Gamepad4 },
actionPriority = props.actionPriority
}),
ModalOverlay = Roact.createElement("Frame", {
Size = UDim2.new(1, 0, 1, 0),
BackgroundTransparency = values.modalBackgroundTransparency,
BackgroundColor3 = GlobalSettings.ModalBackgroundColor,
BorderSizePixel = 0,
}, {
SideBarContainer = Roact.createElement("Frame", {
Size = UDim2.new(0.3, 0, 1, 0),
Position = UDim2.new(values.containerPositionXScale, 0, 0, 0),
BorderSizePixel = 0,
BackgroundColor3 = GlobalSettings.OverlayColor,
[Roact.Ref] = function(container)
self.container = container
end
}, contents)
})
}),
})
end
})
end
function SideBar:didMount()
delay(0, function()
if self.props.inFocus and self.container then
Utility.RemoveSelectionGroup(self.groupKey)
Utility.AddSelectionParent(self.groupKey, self.container)
local trySelectIndex = self.props.selectIndex or 1
if self.buttons and self.buttons[trySelectIndex] then
if not self.state.selectedIndex then
Utility.SetSelectedCoreObject(self.buttons[trySelectIndex])
end
else
Utility.SetSelectedCoreObject(nil)
end
end
end)
end
function SideBar:didUpdate(previousProps, previousState)
if self.props.inFocus == previousProps.inFocus then
return
end
if self.props.inFocus and self.container then
Utility.RemoveSelectionGroup(self.groupKey)
Utility.AddSelectionParent(self.groupKey, self.container)
local trySelectIndex = self.props.selectIndex or 1
if self.buttons and self.buttons[trySelectIndex] then
if not self.state.selectedIndex then
Utility.SetSelectedCoreObject(self.buttons[trySelectIndex])
end
else
Utility.SetSelectedCoreObject(nil)
end
else
Utility.RemoveSelectionGroup(self.groupKey)
end
end
function SideBar:willUnmount()
Utility.RemoveSelectionGroup(self.groupKey)
end
return SideBar