From 2cefd1bf2e9941c3eeb04a24fdf291c936f867ad Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 23:03:01 -0700 Subject: [PATCH] plugin: Add PluginSettings context item, render it in settings screen --- plugin/src/Components/App.lua | 9 +- plugin/src/Components/PluginSettings.lua | 119 +++++++++++++++++++++++ plugin/src/Components/SettingsPanel.lua | 55 ++++++----- plugin/src/init.server.lua | 12 ++- 4 files changed, 161 insertions(+), 34 deletions(-) create mode 100644 plugin/src/Components/PluginSettings.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index bef4973e..2736d950 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -18,7 +18,6 @@ local ConnectingPanel = require(Plugin.Components.ConnectingPanel) local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) local ErrorPanel = require(Plugin.Components.ErrorPanel) local SettingsPanel = require(Plugin.Components.SettingsPanel) -local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -214,11 +213,9 @@ function App:render() } end - return e(Theme.StudioProvider, nil, { - UI = e(Roact.Portal, { - target = self.dockWidget, - }, children), - }) + return e(Roact.Portal, { + target = self.dockWidget, + }, children) end function App:didMount() diff --git a/plugin/src/Components/PluginSettings.lua b/plugin/src/Components/PluginSettings.lua new file mode 100644 index 00000000..df90b10c --- /dev/null +++ b/plugin/src/Components/PluginSettings.lua @@ -0,0 +1,119 @@ +--[[ + Persistent plugin settings that can be accessed via Roact context. +]] + +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) + +local defaultSettings = { + openScriptsExternally = false, +} + +local Settings = {} +Settings.__index = Settings + +function Settings.fromPlugin(plugin) + local values = {} + + for name, defaultValue in pairs(defaultSettings) do + local savedValue = plugin:GetSetting("Rojo_" .. name) + + if savedValue == nil then + values[name] = defaultValue + else + values[name] = savedValue + end + end + + return setmetatable({ + __values = values, + __plugin = plugin, + __updateListeners = {}, + }, Settings) +end + +function Settings:get(name) + if defaultSettings[name] == nil then + error("Invalid setings name " .. tostring(name), 2) + end + + return self.__values[name] +end + +function Settings:set(name, value) + self.__plugin:SetSetting(name, value) + self.__values[name] = value + + for callback in pairs(self.__updateListeners) do + callback(name, value) + end +end + +function Settings:onUpdate(newCallback) + local newListeners = {} + for callback in pairs(self.__updateListeners) do + newListeners[callback] = true + end + + newListeners[newCallback] = true + self.__updateListeners = newListeners + + return function() + local newListeners = {} + for callback in pairs(self.__updateListeners) do + if callback ~= newCallback then + newListeners[callback] = true + end + end + + self.__updateListeners = newListeners + end +end + +local Context = Roact.createContext(nil) + +local StudioProvider = Roact.Component:extend("StudioProvider") + +function StudioProvider:init() + self.settings = Settings.fromPlugin(self.props.plugin) +end + +function StudioProvider:render() + return Roact.createElement(Context.Provider, { + value = self.settings, + }, self.props[Roact.Children]) +end + +local InternalConsumer = Roact.Component:extend("InternalConsumer") + +function InternalConsumer:render() + return self.props.render(self.props.settings) +end + +function InternalConsumer:didMount() + self.disconnect = self.props.settings:onUpdate(function() + -- Trigger a dummy state update to update the settings consumer. + self:setState({}) + end) +end + +function InternalConsumer:willUnmount() + self.disconnect() +end + +local function with(callback) + return Roact.createElement(Context.Consumer, { + render = function(settings) + return Roact.createElement(InternalConsumer, { + settings = settings, + render = callback, + }) + end, + }) +end + +return { + StudioProvider = StudioProvider, + with = with, +} \ No newline at end of file diff --git a/plugin/src/Components/SettingsPanel.lua b/plugin/src/Components/SettingsPanel.lua index 3f026d87..f11fff56 100644 --- a/plugin/src/Components/SettingsPanel.lua +++ b/plugin/src/Components/SettingsPanel.lua @@ -2,10 +2,11 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Theme = require(Plugin.Components.Theme) -local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) local FormButton = require(Plugin.Components.FormButton) +local Panel = require(Plugin.Components.Panel) +local PluginSettings = require(Plugin.Components.PluginSettings) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -15,32 +16,34 @@ function SettingsPanel:render() local back = self.props.back return Theme.with(function(theme) - 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), - }), + return PluginSettings.with(function(settings) + 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 = "This will be a settings panel.", - TextColor3 = theme.Text1, - BackgroundTransparency = 1, - }), + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = theme.ButtonFont, + TextSize = 18, + Text = "openScriptsExternally: " .. tostring(settings:get("openScriptsExternally")), + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), - DisconnectButton = e(FormButton, { - layoutOrder = 2, - text = "Okay", - secondary = true, - onClick = function() - back() - end, - }), - }) + DisconnectButton = e(FormButton, { + layoutOrder = 2, + text = "Okay", + secondary = true, + onClick = function() + back() + end, + }), + }) + end) end) end diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 2aaf4514..ca8d000f 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -14,9 +14,17 @@ local Roact = require(script.Parent.Roact) local Config = require(script.Config) local App = require(script.Components.App) +local Theme = require(script.Components.Theme) +local PluginSettings = require(script.Components.PluginSettings) -local app = Roact.createElement(App, { - plugin = plugin, +local app = Roact.createElement(Theme.StudioProvider, nil, { + Roact.createElement(PluginSettings.StudioProvider, { + plugin = plugin, + }, { + RojoUI = Roact.createElement(App, { + plugin = plugin, + }), + }) }) local tree = Roact.mount(app, nil, "Rojo UI")