diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 12aac48d..5d097ef2 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -1,15 +1,154 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) +local Session = require(script.Parent.Parent.Session) +local Config = require(script.Parent.Parent.Config) +local Version = require(script.Parent.Parent.Version) +local Logging = require(script.Parent.Parent.Logging) +local DevSettings = require(script.Parent.Parent.DevSettings) + local ConnectPanel = require(script.Parent.ConnectPanel) +local ConnectionActivePanel = require(script.Parent.ConnectionActivePanel) local e = Roact.createElement +local function showUpgradeMessage(lastVersion) + local message = ( + "Rojo detected an upgrade from version %s to version %s." .. + "\nMake sure you have also upgraded your server!" .. + "\n\nRojo plugin version %s is intended for use with server version %s." + ):format( + Version.display(lastVersion), Version.display(Config.version), + Version.display(Config.version), Config.expectedServerVersionString + ) + + Logging.info(message) +end + +--[[ + Check if the user is using a newer version of Rojo than last time. If they + are, show them a reminder to make sure they check their server version. +]] +local function checkUpgrade(plugin) + -- When developing Rojo, there's no use in doing version checks + if DevSettings:isEnabled() then + return + end + + local lastVersion = plugin:GetSetting("LastRojoVersion") + + if lastVersion then + local wasUpgraded = Version.compare(Config.version, lastVersion) == 1 + + if wasUpgraded then + showUpgradeMessage(lastVersion) + end + end + + plugin:SetSetting("LastRojoVersion", Config.version) +end + +local SessionStatus = { + Disconnected = "Disconnected", + Connected = "Connected", + Configuring = "Configuring", + -- TODO: Error? +} + +setmetatable(SessionStatus, { + __index = function(_, key) + error(("%q is not a valid member of SessionStatus"):format(tostring(key)), 2) + end, +}) + local App = Roact.Component:extend("App") -function App:render() - return e("ScreenGui", nil, { - ConnectPanel = e(ConnectPanel), +function App:init() + self:setState({ + sessionStatus = SessionStatus.Disconnected, }) + + self.currentSession = nil + + self.displayedVersion = DevSettings:isEnabled() + and Config.codename + or Version.display(Config.version) +end + +function App:render() + local children + + if self.state.sessionStatus == SessionStatus.Connected then + children = { + ConnectionActivePanel = e(ConnectionActivePanel), + } + elseif self.state.sessionStatus == SessionStatus.Configuring then + children = { + ConnectPanel = e(ConnectPanel, { + startSession = function(address, port) + Logging.info("Starting new session") + + self.currentSession = Session.new({ + address = address, + port = port, + onError = function() + Logging.info("Session terminated") + self.currentSession = nil + + self:setState({ + sessionStatus = SessionStatus.Disconnected, + }) + end + }) + + self:setState({ + sessionStatus = SessionStatus.Connected, + }) + end, + cancel = function() + Logging.info("Canceling session configuration") + + self:setState({ + sessionStatus = SessionStatus.Disconnected, + }) + end, + }), + } + end + + return e("ScreenGui", nil, children) +end + +function App:didMount() + Logging.trace("Rojo %s initializing", self.displayedVersion) + + local toolbar = self.props.plugin:CreateToolbar("Rojo " .. self.displayedVersion) + + -- TODO: Icon! + local connectButton = toolbar:CreateButton("Connect", "Connect to Rojo Session", "") + connectButton.ClickableWhenViewportHidden = true + + connectButton.Click:Connect(function() + connectButton:SetActive(false) + checkUpgrade(self.props.plugin) + + if self.state.sessionStatus == SessionStatus.Connected then + Logging.info("Disconnecting session") + + error("NYI") + elseif self.state.sessionStatus == SessionStatus.Disconnected then + Logging.info("Starting session configuration") + + self:setState({ + sessionStatus = SessionStatus.Configuring, + }) + elseif self.state.sessionStatus == SessionStatus.Configuring then + Logging.info("Canceling session configuration") + + self:setState({ + sessionStatus = SessionStatus.Disconnected, + }) + end + end) end return App \ No newline at end of file diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index ce54da7f..1457fe9c 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -5,6 +5,8 @@ local FitText = require(script.Parent.FitText) local e = Roact.createElement +local FORM_TEXT_SIZE = 20 + local ConnectPanel = Roact.Component:extend("ConnectPanel") function ConnectPanel:init() @@ -37,7 +39,7 @@ function ConnectPanel:render() return e(FitList, { containerProps = { - BackgroundColor3 = Color3.fromRGB(8, 8, 8), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), Position = UDim2.new(0.5, 0, 0, 0), AnchorPoint = Vector2.new(0.5, 0), @@ -63,12 +65,13 @@ function ConnectPanel:render() }, }, { Label = e(FitText, { + MinSize = Vector2.new(0, 24), Kind = "TextLabel", LayoutOrder = 1, BackgroundTransparency = 1, TextXAlignment = Enum.TextXAlignment.Left, Font = Enum.Font.SourceSans, - TextSize = 16, + TextSize = FORM_TEXT_SIZE, Text = "Address", TextColor3 = Color3.fromRGB(245, 245, 245), @@ -81,23 +84,30 @@ function ConnectPanel:render() }), }), - Input = e("TextBox", { + InputOuter = e("Frame", { LayoutOrder = 2, - Size = UDim2.new(0, 300, 0, 20), - Font = Enum.Font.SourceSans, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Left, - TextSize = 16, - Text = self.state.address, - TextColor3 = Color3.fromRGB(245, 245, 245), - BackgroundColor3 = Color3.fromRGB(8, 8, 8), + Size = UDim2.new(0, 300, 0, 24), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -8, 1, -8), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = FORM_TEXT_SIZE, + Text = self.state.address, + TextColor3 = Color3.fromRGB(245, 245, 245), - [Roact.Change.Text] = function(rbx) - self:setState({ - address = rbx.Text, - }) - end, + [Roact.Change.Text] = function(rbx) + self:setState({ + address = rbx.Text, + }) + end, + }), }), }), @@ -112,12 +122,13 @@ function ConnectPanel:render() }, }, { Label = e(FitText, { + MinSize = Vector2.new(0, 24), Kind = "TextLabel", LayoutOrder = 1, BackgroundTransparency = 1, TextXAlignment = Enum.TextXAlignment.Left, Font = Enum.Font.SourceSans, - TextSize = 16, + TextSize = FORM_TEXT_SIZE, Text = "Port", TextColor3 = Color3.fromRGB(245, 245, 245), @@ -130,23 +141,30 @@ function ConnectPanel:render() }), }), - Input = e("TextBox", { + InputOuter = e("Frame", { LayoutOrder = 2, - Size = UDim2.new(0, 300, 0, 20), - Font = Enum.Font.SourceSans, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Left, - TextSize = 16, - Text = self.state.port, - TextColor3 = Color3.fromRGB(245, 245, 245), - BackgroundColor3 = Color3.fromRGB(8, 8, 8), + Size = UDim2.new(0, 300, 0, 24), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -8, 1, -8), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = FORM_TEXT_SIZE, + Text = self.state.port, + TextColor3 = Color3.fromRGB(245, 245, 245), - [Roact.Change.Text] = function(rbx) - self:setState({ - port = rbx.Text, - }) - end, + [Roact.Change.Text] = function(rbx) + self:setState({ + port = rbx.Text, + }) + end, + }), }), }), @@ -163,10 +181,13 @@ function ConnectPanel:render() e(FitText, { Kind = "TextButton", LayoutOrder = 1, - BackgroundColor3 = Color3.fromRGB(16, 16, 16), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), TextColor3 = Color3.fromRGB(245, 245, 245), Text = "Start", + Font = Enum.Font.SourceSans, + TextSize = FORM_TEXT_SIZE, + Padding = Vector2.new(12, 3), [Roact.Event.Activated] = function() if startSession ~= nil then @@ -178,10 +199,13 @@ function ConnectPanel:render() e(FitText, { Kind = "TextButton", LayoutOrder = 2, - BackgroundColor3 = Color3.fromRGB(16, 16, 16), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), TextColor3 = Color3.fromRGB(245, 245, 245), Text = "Cancel", + Font = Enum.Font.SourceSans, + TextSize = FORM_TEXT_SIZE, + Padding = Vector2.new(12, 3), [Roact.Event.Activated] = function() if cancel ~= nil then diff --git a/plugin/src/Components/ConnectionActivePanel.lua b/plugin/src/Components/ConnectionActivePanel.lua new file mode 100644 index 00000000..a63ea6aa --- /dev/null +++ b/plugin/src/Components/ConnectionActivePanel.lua @@ -0,0 +1,25 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local FitText = require(script.Parent.FitText) + +local e = Roact.createElement + +local ConnectionActivePanel = Roact.Component:extend("ConnectionActivePanel") + +function ConnectionActivePanel:render() + return e(FitText, { + Kind = "TextLabel", + Padding = Vector2.new(4, 4), + Font = Enum.Font.SourceSans, + TextSize = 16, + Text = "Rojo Connected", + TextColor3 = Color3.new(1, 1, 1), + BackgroundColor3 = Color3.new(0, 0, 0), + BorderSizePixel = 0, + BackgroundTransparency = 0.6, + Position = UDim2.new(0.5, 0, 0, 0), + AnchorPoint = Vector2.new(0.5, 0), + }) +end + +return ConnectionActivePanel \ No newline at end of file diff --git a/plugin/src/Components/FitText.lua b/plugin/src/Components/FitText.lua index 2ec0b51b..673bcf03 100644 --- a/plugin/src/Components/FitText.lua +++ b/plugin/src/Components/FitText.lua @@ -18,6 +18,7 @@ function FitText:render() local containerProps = Dictionary.merge(self.props, { Kind = Dictionary.None, Padding = Dictionary.None, + MinSize = Dictionary.None, Size = self.sizeBinding }) @@ -33,6 +34,7 @@ function FitText:didUpdate() 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 text = self.props.Text or "" @@ -41,8 +43,8 @@ function FitText:updateTextMeasurements() local measuredText = TextService:GetTextSize(text, textSize, font, Vector2.new(9e6, 9e6)) local totalSize = UDim2.new( - 0, padding.X * 2 + measuredText.X, - 0, padding.Y * 2 + measuredText.Y) + 0, math.max(minSize.X, padding.X * 2 + measuredText.X), + 0, math.max(minSize.Y, padding.Y * 2 + measuredText.Y)) self.setSize(totalSize) end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 32be9573..6117e46c 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -2,8 +2,6 @@ local ApiContext = require(script.Parent.ApiContext) local Config = require(script.Parent.Config) local Logging = require(script.Parent.Logging) -local REMOTE_URL = ("http://localhost:%d"):format(Config.port) - local function makeInstanceMap() local self = { fromIds = {}, @@ -249,12 +247,16 @@ end local Session = {} Session.__index = Session -function Session.new(onError) +function Session.new(config) local self = {} + self.onError = config.onError + local instanceMap = makeInstanceMap() - local api = ApiContext.new(REMOTE_URL) + local remoteUrl = ("http://%s:%s"):format(config.address, config.port) + + local api = ApiContext.new(remoteUrl) ApiContext:onMessage(function(message) local requestedIds = {} @@ -277,7 +279,7 @@ function Session.new(onError) end) :catch(function(message) Logging.warn("%s", tostring(message)) - onError() + self.onError() end) end) @@ -292,7 +294,7 @@ function Session.new(onError) end) :catch(function(message) Logging.warn("%s", tostring(message)) - onError() + self.onError() end) return setmetatable(self, Session) diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index b956cbf2..dc547c85 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -8,81 +8,12 @@ Roact.setGlobalConfig({ elementTracing = true, }) -local Session = require(script.Session) -local Config = require(script.Config) -local Version = require(script.Version) -local Logging = require(script.Logging) -local DevSettings = require(script.DevSettings) local App = require(script.Components.App) -local function showUpgradeMessage(lastVersion) - local message = ( - "Rojo detected an upgrade from version %s to version %s." .. - "\nMake sure you have also upgraded your server!" .. - "\n\nRojo plugin version %s is intended for use with server version %s." - ):format( - Version.display(lastVersion), Version.display(Config.version), - Version.display(Config.version), Config.expectedServerVersionString - ) +local app = Roact.createElement(App, { + plugin = plugin, +}) - Logging.info(message) -end +Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") ---[[ - Check if the user is using a newer version of Rojo than last time. If they - are, show them a reminder to make sure they check their server version. -]] -local function checkUpgrade() - -- When developing Rojo, there's no use in doing version checks - if DevSettings:isEnabled() then - return - end - - local lastVersion = plugin:GetSetting("LastRojoVersion") - - if lastVersion then - local wasUpgraded = Version.compare(Config.version, lastVersion) == 1 - - if wasUpgraded then - showUpgradeMessage(lastVersion) - end - end - - plugin:SetSetting("LastRojoVersion", Config.version) -end - -local function main() - local displayedVersion = DevSettings:isEnabled() - and Config.codename - or Version.display(Config.version) - - Logging.trace("Rojo %s initialized", displayedVersion) - - local toolbar = plugin:CreateToolbar("Rojo " .. displayedVersion) - - Roact.mount(Roact.createElement(App), game:GetService("CoreGui"), "Rojo UI") - - local currentSession - - -- TODO: Icon! - local connectButton = toolbar:CreateButton("Connect", "Connect to Rojo Session", "") - connectButton.ClickableWhenViewportHidden = true - - connectButton.Click:Connect(function() - connectButton:SetActive(false) - checkUpgrade() - - if currentSession ~= nil then - Logging.warn("A session is already running!") - return - end - - Logging.info("Started new session.") - currentSession = Session.new(function() - Logging.info("Session terminated.") - currentSession = nil - end) - end) -end - -main() \ No newline at end of file +-- TODO: Detect another instance of Rojo coming online and shut down this one. \ No newline at end of file