Start rewriting plugin on top of new sync protocol

This commit is contained in:
Lucien Greathouse
2019-10-02 18:41:52 -07:00
parent b562d11994
commit 923f661428
12 changed files with 591 additions and 710 deletions

View File

@@ -4,15 +4,20 @@ local Plugin = Rojo.Plugin
local Roact = require(Rojo.Roact)
local Log = require(Rojo.Log)
local ApiContext = require(Plugin.ApiContext)
local Assets = require(Plugin.Assets)
local Config = require(Plugin.Config)
local DevSettings = require(Plugin.DevSettings)
local Session = require(Plugin.Session)
local Reconciler = require(Plugin.Reconciler)
local ServeSession = require(Plugin.ServeSession)
local Version = require(Plugin.Version)
local preloadAssets = require(Plugin.preloadAssets)
local strict = require(Plugin.strict)
local ConnectPanel = require(Plugin.Components.ConnectPanel)
local ConnectingPanel = require(Plugin.Components.ConnectingPanel)
local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel)
local ErrorPanel = require(Plugin.Components.ErrorPanel)
local e = Roact.createElement
@@ -52,26 +57,23 @@ local function checkUpgrade(plugin)
plugin:SetSetting("LastRojoVersion", Config.version)
end
local SessionStatus = {
Disconnected = "Disconnected",
local AppStatus = strict("AppStatus", {
NotStarted = "NotStarted",
Connecting = "Connecting",
Connected = "Connected",
}
setmetatable(SessionStatus, {
__index = function(_, key)
error(("%q is not a valid member of SessionStatus"):format(tostring(key)), 2)
end,
Error = "Error",
})
local App = Roact.Component:extend("App")
function App:init()
self:setState({
sessionStatus = SessionStatus.Disconnected,
appStatus = AppStatus.NotStarted,
errorMessage = nil,
})
self.signals = {}
self.currentSession = nil
self.serveSession = nil
self.displayedVersion = DevSettings:isEnabled()
and Config.codename
@@ -96,7 +98,7 @@ function App:init()
360, 190 -- Minimum size
)
self.dockWidget = self.props.plugin:CreateDockWidgetPluginGui("Rojo-0.5.x", widgetInfo)
self.dockWidget = self.props.plugin:CreateDockWidgetPluginGui("Rojo-" .. self.displayedVersion, widgetInfo)
self.dockWidget.Name = "Rojo " .. self.displayedVersion
self.dockWidget.Title = "Rojo " .. self.displayedVersion
self.dockWidget.AutoLocalize = false
@@ -107,56 +109,92 @@ function App:init()
end)
end
function App:startSession(address, port)
Log.trace("Starting new session")
local baseUrl = ("http://%s:%s"):format(address, port)
self.serveSession = ServeSession.new({
apiContext = ApiContext.new(baseUrl),
reconciler = Reconciler.new(),
})
self.serveSession:onStatusChanged(function(status, details)
if status == ServeSession.Status.Connecting then
self:setState({
appStatus = AppStatus.Connecting,
})
elseif status == ServeSession.Status.Connected then
self:setState({
appStatus = AppStatus.Connected,
})
elseif status == ServeSession.Status.Disconnected then
self.serveSession = nil
-- Details being present indicates that this
-- disconnection was from an error.
if details ~= nil then
Log.warn(tostring(details))
self:setState({
appStatus = AppStatus.Error,
errorMessage = tostring(details),
})
else
self:setState({
appStatus = AppStatus.NotStarted,
})
end
end
end)
self.serveSession:start()
end
function App:render()
local children
if self.state.sessionStatus == SessionStatus.Connected then
if self.state.appStatus == AppStatus.NotStarted then
children = {
ConnectPanel = e(ConnectPanel, {
startSession = function(address, port)
self:startSession(address, port)
end,
cancel = function()
Log.trace("Canceling session configuration")
self:setState({
appStatus = AppStatus.NotStarted,
})
end,
}),
}
elseif self.state.appStatus == AppStatus.Connecting then
children = {
ConnectingPanel = Roact.createElement(ConnectingPanel),
}
elseif self.state.appStatus == AppStatus.Connected then
children = {
ConnectionActivePanel = e(ConnectionActivePanel, {
stopSession = function()
Log.trace("Disconnecting session")
self.currentSession:disconnect()
self.currentSession = nil
self.serveSession:stop()
self.serveSession = nil
self:setState({
sessionStatus = SessionStatus.Disconnected,
appStatus = AppStatus.NotStarted,
})
Log.trace("Session terminated by user")
end,
}),
}
elseif self.state.sessionStatus == SessionStatus.Disconnected then
elseif self.state.appStatus == AppStatus.Error then
children = {
ConnectPanel = e(ConnectPanel, {
startSession = function(address, port)
Log.trace("Starting new session")
local success, session = Session.new({
address = address,
port = port,
onError = function(message)
Log.warn("Rojo session terminated because of an error:\n%s", tostring(message))
self.currentSession = nil
self:setState({
sessionStatus = SessionStatus.Disconnected,
})
end
})
if success then
self.currentSession = session
self:setState({
sessionStatus = SessionStatus.Connected,
})
end
end,
cancel = function()
Log.trace("Canceling session configuration")
ErrorPanel = Roact.createElement(ErrorPanel, {
errorMessage = self.state.errorMessage,
onDismiss = function()
self:setState({
sessionStatus = SessionStatus.Disconnected,
appStatus = AppStatus.NotStarted,
})
end,
}),
@@ -176,9 +214,9 @@ function App:didMount()
end
function App:willUnmount()
if self.currentSession ~= nil then
self.currentSession:disconnect()
self.currentSession = nil
if self.serveSession ~= nil then
self.serveSession:stop()
self.serveSession = nil
end
for _, signal in pairs(self.signals) do

View File

@@ -0,0 +1,34 @@
local Roact = require(script:FindFirstAncestor("Rojo").Roact)
local Plugin = script:FindFirstAncestor("Plugin")
local Theme = require(Plugin.Theme)
local Panel = require(Plugin.Components.Panel)
local FitText = require(Plugin.Components.FitText)
local e = Roact.createElement
local ConnectingPanel = Roact.Component:extend("ConnectingPanel")
function ConnectingPanel:render()
return e(Panel, nil, {
Layout = Roact.createElement("UIListLayout", {
HorizontalAlignment = Enum.HorizontalAlignment.Center,
VerticalAlignment = Enum.VerticalAlignment.Center,
SortOrder = Enum.SortOrder.LayoutOrder,
Padding = UDim.new(0, 8),
}),
Text = e(FitText, {
Padding = Vector2.new(12, 6),
Font = Theme.ButtonFont,
TextSize = 18,
Text = "Connecting...",
TextColor3 = Theme.PrimaryColor,
BackgroundTransparency = 1,
}),
})
end
return ConnectingPanel

View File

@@ -0,0 +1,51 @@
local Roact = require(script:FindFirstAncestor("Rojo").Roact)
local Plugin = script:FindFirstAncestor("Plugin")
local Theme = require(Plugin.Theme)
local Panel = require(Plugin.Components.Panel)
local FitText = require(Plugin.Components.FitText)
local FormButton = require(Plugin.Components.FormButton)
local e = Roact.createElement
local ErrorPanel = Roact.Component:extend("ErrorPanel")
function ErrorPanel:render()
local errorMessage = self.props.errorMessage
local onDismiss = self.props.onDismiss
return e(Panel, nil, {
Layout = Roact.createElement("UIListLayout", {
HorizontalAlignment = Enum.HorizontalAlignment.Center,
VerticalAlignment = Enum.VerticalAlignment.Center,
SortOrder = Enum.SortOrder.LayoutOrder,
Padding = UDim.new(0, 8),
}),
Text = e(FitText, {
LayoutOrder = 1,
FitAxis = "Y",
Size = UDim2.new(1, 0, 0, 0),
Padding = Vector2.new(12, 6),
Font = Theme.ButtonFont,
TextSize = 18,
Text = errorMessage,
TextWrap = true,
TextColor3 = Theme.PrimaryColor,
BackgroundTransparency = 1,
}),
DismissButton = e(FormButton, {
layoutOrder = 2,
text = "Dismiss",
secondary = true,
onClick = function()
onDismiss()
end,
}),
})
end
return ErrorPanel

View File

@@ -9,6 +9,7 @@ local e = Roact.createElement
local FitText = Roact.Component:extend("FitText")
function FitText:init()
self.ref = Roact.createRef()
self.sizeBinding, self.setSize = Roact.createBinding(UDim2.new())
end
@@ -16,10 +17,15 @@ function FitText:render()
local kind = self.props.Kind or "TextLabel"
local containerProps = Dictionary.merge(self.props, {
FitAxis = Dictionary.None,
Kind = Dictionary.None,
Padding = Dictionary.None,
MinSize = Dictionary.None,
Size = self.sizeBinding
Size = self.sizeBinding,
[Roact.Ref] = self.ref,
[Roact.Change.AbsoluteSize] = function()
self:updateTextMeasurements()
end
})
return e(kind, containerProps)
@@ -36,15 +42,45 @@ end
function FitText:updateTextMeasurements()
local minSize = self.props.MinSize or Vector2.new(0, 0)
local padding = self.props.Padding or Vector2.new(0, 0)
local fitAxis = self.props.FitAxis or "XY"
local baseSize = self.props.Size
local text = self.props.Text or ""
local font = self.props.Font or Enum.Font.Legacy
local textSize = self.props.TextSize or 12
local measuredText = TextService:GetTextSize(text, textSize, font, Vector2.new(9e6, 9e6))
local totalSize = UDim2.new(
0, math.max(minSize.X, padding.X * 2 + measuredText.X),
0, math.max(minSize.Y, padding.Y * 2 + measuredText.Y))
local containerSize = self.ref.current.AbsoluteSize
local textBounds
if fitAxis == "XY" then
textBounds = Vector2.new(9e6, 9e6)
elseif fitAxis == "X" then
textBounds = Vector2.new(9e6, containerSize.Y - padding.Y * 2)
elseif fitAxis == "Y" then
textBounds = Vector2.new(containerSize.X - padding.X * 2, 9e6)
end
local measuredText = TextService:GetTextSize(text, textSize, font, textBounds)
local computedX = math.max(minSize.X, padding.X * 2 + measuredText.X)
local computedY = math.max(minSize.Y, padding.Y * 2 + measuredText.Y)
local totalSize
if fitAxis == "XY" then
totalSize = UDim2.new(
0, computedX,
0, computedY)
elseif fitAxis == "X" then
totalSize = UDim2.new(
0, computedX,
baseSize.Y.Scale, baseSize.Y.Offset)
elseif fitAxis == "Y" then
totalSize = UDim2.new(
baseSize.X.Scale, baseSize.X.Offset,
0, computedY)
end
self.setSize(totalSize)
end