297 lines
7.2 KiB
Lua
297 lines
7.2 KiB
Lua
local GuiService = game:GetService("GuiService")
|
|
local Modules = game:GetService("CoreGui").RobloxGui.Modules
|
|
local PlayerService = game:GetService("Players")
|
|
|
|
local FlagSettings = require(Modules.LuaApp.FlagSettings)
|
|
local NotificationType = require(Modules.LuaApp.Enum.NotificationType)
|
|
|
|
local ScreenRouter = require(Modules.LuaChat.ScreenRouter)
|
|
local FormFactor = require(Modules.LuaApp.Enum.FormFactor)
|
|
local DialogFrame = require(Modules.LuaChat.Views.DialogFrame)
|
|
|
|
local UseLuaBottomBar = FlagSettings.IsLuaBottomBarEnabled()
|
|
local LuaHomeControlNativeBottomBar = settings():GetFFlag("LuaHomeControlNativeBottomBar")
|
|
|
|
local ScreenManager = {}
|
|
|
|
--[[
|
|
Create a new ScreenManager that uses the given 'root'
|
|
]]
|
|
function ScreenManager.new(root, appState)
|
|
local self = {
|
|
_stack = {},
|
|
_framesToViews = {},
|
|
rbx = root,
|
|
appState = appState,
|
|
route = nil,
|
|
routeMap = nil,
|
|
paused = false,
|
|
_analytics = appState.analytics,
|
|
}
|
|
|
|
local dialogFrame = DialogFrame.new(appState, nil)
|
|
dialogFrame.rbx.Parent = self.rbx
|
|
self.dialogFrame = dialogFrame
|
|
|
|
setmetatable(self, {
|
|
__index = ScreenManager
|
|
})
|
|
|
|
if self.appState then
|
|
self.appState.store.changed:connect(function(current, previous)
|
|
self:Update(current, previous)
|
|
end)
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
function ScreenManager:Update(current, previous)
|
|
if current == previous then
|
|
return
|
|
end
|
|
|
|
if self.paused ~= self.appState.store:getState().ChatAppReducer.ToggleChatPaused then
|
|
self.paused = self.appState.store:getState().ChatAppReducer.ToggleChatPaused
|
|
if self.paused then
|
|
self:DisableAllViews()
|
|
else
|
|
self:EnableAllViews()
|
|
self:SetTabBarVisible(current.TabBarVisible)
|
|
end
|
|
end
|
|
|
|
if LuaHomeControlNativeBottomBar then
|
|
if current.TabBarVisible ~= previous.TabBarVisible then
|
|
self:SetTabBarVisible(current.TabBarVisible)
|
|
end
|
|
|
|
if self.paused then
|
|
return
|
|
end
|
|
else
|
|
if self.paused then
|
|
return
|
|
end
|
|
|
|
if current.TabBarVisible ~= previous.TabBarVisible then
|
|
self:SetTabBarVisible(current.TabBarVisible)
|
|
end
|
|
end
|
|
|
|
if not next(current.ChatAppReducer.Location.current) then
|
|
for _, view in ipairs(self._stack) do
|
|
self:PopView(view)
|
|
end
|
|
return
|
|
end
|
|
|
|
if current.ChatAppReducer.Location.current == self.route then
|
|
|
|
return
|
|
end
|
|
|
|
if current.FormFactor == FormFactor.UNKNOWN then
|
|
return
|
|
end
|
|
|
|
local routeMap = ScreenRouter.RouteMaps[current.FormFactor]
|
|
|
|
if routeMap[current.ChatAppReducer.Location.current.intent] == nil then
|
|
return
|
|
end
|
|
|
|
--If a view representing this route already exists on the stack, we'll just pop down to it
|
|
local viewInStack = false
|
|
for _, view in ipairs(self._stack) do
|
|
if ScreenRouter:Compare(view.route, current.ChatAppReducer.Location.current) then
|
|
viewInStack = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if viewInStack then
|
|
while not ScreenRouter:Compare(self:GetCurrentView().route, current.ChatAppReducer.Location.current) do
|
|
self:PopView(self:GetCurrentView())
|
|
end
|
|
else
|
|
if current.ChatAppReducer.Location.current.popToIntent ~= nil then
|
|
while #self._stack > 1
|
|
and current.ChatAppReducer.Location.current.popToIntent ~= self:GetCurrentView().route.intent do
|
|
self:PopView(self:GetCurrentView())
|
|
end
|
|
end
|
|
local newView = ScreenRouter:GetView(self.appState, current.ChatAppReducer.Location.current, routeMap)
|
|
self:PushView(newView, current.ChatAppReducer.Location.current.intent)
|
|
end
|
|
|
|
self.route = current.ChatAppReducer.Location.current
|
|
end
|
|
|
|
function ScreenManager:GetViewOrderMap()
|
|
local indexMap = {}
|
|
|
|
for i = #self._stack, 1, -1 do
|
|
local view = self._stack[i]
|
|
if not indexMap[view] then
|
|
indexMap[view] = i
|
|
end
|
|
end
|
|
|
|
return indexMap
|
|
end
|
|
|
|
function ScreenManager:SortViews()
|
|
local indexMap = self:GetViewOrderMap()
|
|
|
|
for frame, view in pairs(self._framesToViews) do
|
|
local order = indexMap[view] or 0
|
|
-- TODO: CLIPLAYEREX-1051: We shoud set the frame sort order here. This is something that the player experience
|
|
-- team is working on. It should be fine for us not to do this for now.
|
|
frame.Name = ("LuaChat-layer%d"):format(order)
|
|
end
|
|
end
|
|
|
|
function ScreenManager:GetCurrentView()
|
|
return self._stack[#self._stack]
|
|
end
|
|
|
|
function ScreenManager:GetViewStack()
|
|
return self._stack
|
|
end
|
|
|
|
function ScreenManager:PushView(view, intent)
|
|
|
|
local current = self:GetCurrentView()
|
|
|
|
-- There are no reasons to push a view on top of itself!
|
|
if current == view then
|
|
error("Tried to push a view on top of itself!", 2)
|
|
end
|
|
|
|
local newViewIntent
|
|
if view then
|
|
newViewIntent = view.route.intent
|
|
end
|
|
local curIntent
|
|
if current then
|
|
curIntent = current.route.intent
|
|
end
|
|
|
|
if current then
|
|
current:Pause(view)
|
|
self.dialogFrame:TransitionDialogFrame(current, curIntent, newViewIntent, DialogFrame.TransitionType.Pause, nil)
|
|
end
|
|
|
|
table.insert(self._stack, view)
|
|
|
|
if view and view.rbx then
|
|
local frame = self.dialogFrame:AddDialogFrame(intent)
|
|
self._framesToViews[frame] = view
|
|
|
|
frame.ChildRemoved:Connect(function()
|
|
self._framesToViews[frame] = nil
|
|
frame:Destroy()
|
|
end)
|
|
|
|
view.rbx.Parent = frame
|
|
|
|
self:SortViews()
|
|
end
|
|
|
|
view:Start(current)
|
|
-- If we're the only view, we don't need to transition in.
|
|
if #self._stack > 1 then
|
|
self.dialogFrame:TransitionDialogFrame(view, newViewIntent, curIntent, DialogFrame.TransitionType.Start, nil)
|
|
end
|
|
end
|
|
|
|
--[[
|
|
Pop the view that's currently being shown.
|
|
|
|
Optionally, pass in a view to make the ScreenManager only pop if that view
|
|
is the one on top of the stack. This makes the pop operation idempotent.
|
|
]]
|
|
function ScreenManager:PopView(expectView)
|
|
if expectView and expectView ~= self:GetCurrentView() then
|
|
return
|
|
end
|
|
|
|
local last = self._stack[#self._stack]
|
|
local current = self._stack[#self._stack - 1]
|
|
local lastIntent
|
|
if last then
|
|
lastIntent = last.route.intent
|
|
end
|
|
local curIntent
|
|
if current then
|
|
curIntent = current.route.intent
|
|
end
|
|
|
|
if last then
|
|
self:SortViews()
|
|
|
|
last:Stop(current)
|
|
self.dialogFrame:TransitionDialogFrame(last, lastIntent, curIntent, DialogFrame.TransitionType.Stop,
|
|
function(playbackState)
|
|
if playbackState == Enum.PlaybackState.Completed then
|
|
last:Destruct()
|
|
if last.rbx then
|
|
last.rbx.Parent = nil
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
table.remove(self._stack, #self._stack)
|
|
|
|
if current then
|
|
current:Resume(last)
|
|
self.dialogFrame:TransitionDialogFrame(current, curIntent, lastIntent, DialogFrame.TransitionType.Resume, nil)
|
|
end
|
|
|
|
self.dialogFrame:ConfigureModalFrame()
|
|
|
|
return last
|
|
end
|
|
|
|
function ScreenManager:EnableAllViews()
|
|
self.dialogFrame.rbx.Enabled = true
|
|
end
|
|
|
|
function ScreenManager:DisableAllViews()
|
|
self.dialogFrame.rbx.Enabled = false
|
|
end
|
|
|
|
function ScreenManager:SetTabBarVisible(visible)
|
|
if UseLuaBottomBar then
|
|
return
|
|
end
|
|
|
|
if visible then
|
|
GuiService:BroadcastNotification("", NotificationType.SHOW_TAB_BAR)
|
|
else
|
|
GuiService:BroadcastNotification("", NotificationType.HIDE_TAB_BAR)
|
|
end
|
|
|
|
self:ReportLuaSettingOfBottomBarVisibility(visible)
|
|
end
|
|
|
|
function ScreenManager:ReportLuaSettingOfBottomBarVisibility(visible)
|
|
local eventContext = "broadcastBottomBarVisibilitySetting"
|
|
local eventName = "setBottomBarVisibilityFromLua"
|
|
|
|
local player = PlayerService.LocalPlayer
|
|
local userId = "UNKNOWN"
|
|
if player then
|
|
userId = tostring(player.UserId)
|
|
end
|
|
|
|
local additionalArgs = {
|
|
uid = userId,
|
|
visible = visible,
|
|
}
|
|
self._analytics.EventStream:setRBXEventStream(eventContext, eventName, additionalArgs)
|
|
end
|
|
|
|
return ScreenManager |