Redesign settings UI in plugin (#886)
@@ -7,6 +7,7 @@
|
||||
* Updated Theme to use Studio colors ([#838])
|
||||
* Improved patch visualizer UX ([#883])
|
||||
* Added experimental setting for Auto Connect in playtests ([#840])
|
||||
* Improved settings UI ([#886])
|
||||
* `Open Scripts Externally` option can now be changed while syncing ([#911])
|
||||
* Projects may now specify rules for syncing files as if they had a different file extension. ([#813])
|
||||
This is specified via a new field on project files, `syncRules`:
|
||||
@@ -60,6 +61,7 @@
|
||||
[#838]: https://github.com/rojo-rbx/rojo/pull/838
|
||||
[#840]: https://github.com/rojo-rbx/rojo/pull/840
|
||||
[#883]: https://github.com/rojo-rbx/rojo/pull/883
|
||||
[#886]: https://github.com/rojo-rbx/rojo/pull/886
|
||||
[#893]: https://github.com/rojo-rbx/rojo/pull/893
|
||||
[#903]: https://github.com/rojo-rbx/rojo/pull/903
|
||||
[#911]: https://github.com/rojo-rbx/rojo/pull/911
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<div align="center">
|
||||
<a href="https://rojo.space"><img src="assets/logo-512.png" alt="Rojo" height="217" /></a>
|
||||
<a href="https://rojo.space"><img src="assets/brand_images/logo-512.png" alt="Rojo" height="217" /></a>
|
||||
</div>
|
||||
|
||||
<div> </div>
|
||||
@@ -43,4 +43,4 @@ Pull requests are welcome!
|
||||
Rojo supports Rust 1.70.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has.
|
||||
|
||||
## License
|
||||
Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details.
|
||||
Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details.
|
||||
|
||||
|
Before Width: | Height: | Size: 975 B After Width: | Height: | Size: 975 B |
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 229 B After Width: | Height: | Size: 229 B |
|
Before Width: | Height: | Size: 584 B After Width: | Height: | Size: 584 B |
|
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 295 B |
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
BIN
assets/images/icons/debug.png
Normal file
|
After Width: | Height: | Size: 183 B |
BIN
assets/images/icons/expand.png
Normal file
|
After Width: | Height: | Size: 273 B |
BIN
assets/images/icons/reset.png
Normal file
|
After Width: | Height: | Size: 933 B |
BIN
assets/images/icons/warning.png
Normal file
|
After Width: | Height: | Size: 241 B |
|
Before Width: | Height: | Size: 175 B After Width: | Height: | Size: 175 B |
@@ -20,6 +20,7 @@ local function SlicedImage(props)
|
||||
Size = props.size,
|
||||
Position = props.position,
|
||||
AnchorPoint = props.anchorPoint,
|
||||
AutomaticSize = props.automaticSize,
|
||||
|
||||
ZIndex = props.zIndex,
|
||||
LayoutOrder = props.layoutOrder,
|
||||
|
||||
56
plugin/src/App/Components/Tag.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
local Rojo = script:FindFirstAncestor("Rojo")
|
||||
local Plugin = Rojo.Plugin
|
||||
local Packages = Rojo.Packages
|
||||
|
||||
local Roact = require(Packages.Roact)
|
||||
|
||||
local Assets = require(Plugin.Assets)
|
||||
|
||||
local SlicedImage = require(Plugin.App.Components.SlicedImage)
|
||||
|
||||
local e = Roact.createElement
|
||||
|
||||
return function(props)
|
||||
return e(SlicedImage, {
|
||||
slice = Assets.Slices.RoundedBackground,
|
||||
color = props.color,
|
||||
transparency = props.transparency:map(function(transparency)
|
||||
return 0.9 + (0.1 * transparency)
|
||||
end),
|
||||
layoutOrder = props.layoutOrder,
|
||||
position = props.position,
|
||||
anchorPoint = props.anchorPoint,
|
||||
size = UDim2.new(0, 0, 0, 16),
|
||||
automaticSize = Enum.AutomaticSize.X,
|
||||
}, {
|
||||
Padding = e("UIPadding", {
|
||||
PaddingLeft = UDim.new(0, 4),
|
||||
PaddingRight = UDim.new(0, 4),
|
||||
PaddingTop = UDim.new(0, 2),
|
||||
PaddingBottom = UDim.new(0, 2),
|
||||
}),
|
||||
Icon = if props.icon
|
||||
then e("ImageLabel", {
|
||||
Size = UDim2.new(0, 12, 0, 12),
|
||||
Position = UDim2.new(0, 0, 0.5, 0),
|
||||
AnchorPoint = Vector2.new(0, 0.5),
|
||||
Image = props.icon,
|
||||
BackgroundTransparency = 1,
|
||||
ImageColor3 = props.color,
|
||||
ImageTransparency = props.transparency,
|
||||
})
|
||||
else nil,
|
||||
Text = e("TextLabel", {
|
||||
Text = props.text,
|
||||
Font = Enum.Font.GothamMedium,
|
||||
TextSize = 12,
|
||||
TextColor3 = props.color,
|
||||
TextXAlignment = Enum.TextXAlignment.Center,
|
||||
TextTransparency = props.transparency,
|
||||
Size = UDim2.new(0, 0, 1, 0),
|
||||
Position = UDim2.new(0, if props.icon then 15 else 0, 0, 0),
|
||||
AutomaticSize = Enum.AutomaticSize.X,
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
})
|
||||
end
|
||||
@@ -13,10 +13,23 @@ local Theme = require(Plugin.App.Theme)
|
||||
local Checkbox = require(Plugin.App.Components.Checkbox)
|
||||
local Dropdown = require(Plugin.App.Components.Dropdown)
|
||||
local IconButton = require(Plugin.App.Components.IconButton)
|
||||
local Tag = require(Plugin.App.Components.Tag)
|
||||
|
||||
local e = Roact.createElement
|
||||
|
||||
local DIVIDER_FADE_SIZE = 0.1
|
||||
local TAG_TYPES = {
|
||||
unstable = {
|
||||
text = "UNSTABLE",
|
||||
icon = Assets.Images.Icons.Warning,
|
||||
color = { "Settings", "Setting", "UnstableColor" },
|
||||
},
|
||||
debug = {
|
||||
text = "DEBUG",
|
||||
icon = Assets.Images.Icons.Debug,
|
||||
color = { "Settings", "Setting", "DebugColor" },
|
||||
},
|
||||
}
|
||||
|
||||
local function getTextBounds(text, textSize, font, lineHeight, bounds)
|
||||
local textBounds = TextService:GetTextSize(text, textSize, font, bounds)
|
||||
@@ -27,6 +40,17 @@ local function getTextBounds(text, textSize, font, lineHeight, bounds)
|
||||
return Vector2.new(textBounds.X, lineHeightAbsolute * lineCount - (lineHeightAbsolute - textSize))
|
||||
end
|
||||
|
||||
local function getThemeColorFromPath(theme, path)
|
||||
local color = theme
|
||||
for _, key in path do
|
||||
if color[key] == nil then
|
||||
return theme.BrandColor
|
||||
end
|
||||
color = color[key]
|
||||
end
|
||||
return color
|
||||
end
|
||||
|
||||
local Setting = Roact.Component:extend("Setting")
|
||||
|
||||
function Setting:init()
|
||||
@@ -51,11 +75,11 @@ end
|
||||
|
||||
function Setting:render()
|
||||
return Theme.with(function(theme)
|
||||
theme = theme.Settings
|
||||
local settingsTheme = theme.Settings
|
||||
|
||||
return e("Frame", {
|
||||
Size = self.contentSize:map(function(value)
|
||||
return UDim2.new(1, 0, 0, 20 + value.Y + 20)
|
||||
return UDim2.new(1, 0, 0, value.Y + 20)
|
||||
end),
|
||||
LayoutOrder = self.props.layoutOrder,
|
||||
ZIndex = -self.props.layoutOrder,
|
||||
@@ -106,7 +130,7 @@ function Setting:render()
|
||||
then e(IconButton, {
|
||||
icon = Assets.Images.Icons.Reset,
|
||||
iconSize = 24,
|
||||
color = theme.BackButtonColor,
|
||||
color = settingsTheme.BackButtonColor,
|
||||
transparency = self.props.transparency,
|
||||
visible = self.props.showReset,
|
||||
layoutOrder = -1,
|
||||
@@ -120,37 +144,49 @@ function Setting:render()
|
||||
Size = UDim2.new(1, 0, 1, 0),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
Name = e("TextLabel", {
|
||||
Text = (
|
||||
if self.props.experimental
|
||||
then '<font color="#FF8E3C">⚠ </font>'
|
||||
elseif
|
||||
self.props.developerDebug
|
||||
then '<font family="rbxasset://fonts/families/Guru.json" color="#35B5FF">⚑ </font>' -- Guru is the only font with the flag emoji
|
||||
else ""
|
||||
) .. self.props.name,
|
||||
Font = Enum.Font.GothamBold,
|
||||
TextSize = 17,
|
||||
TextColor3 = theme.Setting.NameColor,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
TextTransparency = self.props.transparency,
|
||||
RichText = true,
|
||||
|
||||
Size = UDim2.new(1, 0, 0, 17),
|
||||
|
||||
LayoutOrder = 1,
|
||||
Heading = e("Frame", {
|
||||
Size = UDim2.new(1, 0, 0, 16),
|
||||
BackgroundTransparency = 1,
|
||||
}, {
|
||||
Layout = e("UIListLayout", {
|
||||
VerticalAlignment = Enum.VerticalAlignment.Center,
|
||||
FillDirection = Enum.FillDirection.Horizontal,
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
Padding = UDim.new(0, 5),
|
||||
}),
|
||||
Tag = if self.props.tag and TAG_TYPES[self.props.tag]
|
||||
then e(Tag, {
|
||||
layoutOrder = 1,
|
||||
transparency = self.props.transparency,
|
||||
text = TAG_TYPES[self.props.tag].text,
|
||||
icon = TAG_TYPES[self.props.tag].icon,
|
||||
color = getThemeColorFromPath(theme, TAG_TYPES[self.props.tag].color),
|
||||
})
|
||||
else nil,
|
||||
Name = e("TextLabel", {
|
||||
Text = self.props.name,
|
||||
Font = Enum.Font.GothamBold,
|
||||
TextSize = 16,
|
||||
TextColor3 = if self.props.tag and TAG_TYPES[self.props.tag]
|
||||
then getThemeColorFromPath(theme, TAG_TYPES[self.props.tag].color)
|
||||
else settingsTheme.Setting.NameColor,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
TextTransparency = self.props.transparency,
|
||||
RichText = true,
|
||||
|
||||
Size = UDim2.new(1, 0, 0, 16),
|
||||
|
||||
LayoutOrder = 2,
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
}),
|
||||
|
||||
Description = e("TextLabel", {
|
||||
Text = (if self.props.experimental
|
||||
then '<font color="#FF8E3C">[Experimental] </font>'
|
||||
elseif self.props.developerDebug then '<font color="#35B5FF">[Dev Debug] </font>'
|
||||
else "") .. self.props.description,
|
||||
Text = self.props.description,
|
||||
Font = Enum.Font.Gotham,
|
||||
LineHeight = 1.2,
|
||||
TextSize = 14,
|
||||
TextColor3 = theme.Setting.DescriptionColor,
|
||||
TextColor3 = settingsTheme.Setting.DescriptionColor,
|
||||
TextXAlignment = Enum.TextXAlignment.Left,
|
||||
TextTransparency = self.props.transparency,
|
||||
TextWrapped = true,
|
||||
@@ -160,11 +196,9 @@ function Setting:render()
|
||||
containerSize = self.containerSize,
|
||||
inputSize = self.inputSize,
|
||||
}):map(function(values)
|
||||
local desc = (if self.props.experimental then "[Experimental] " else "")
|
||||
.. self.props.description
|
||||
local offset = values.inputSize.X + 5
|
||||
local textBounds = getTextBounds(
|
||||
desc,
|
||||
self.props.description,
|
||||
14,
|
||||
Enum.Font.Gotham,
|
||||
1.2,
|
||||
@@ -173,7 +207,7 @@ function Setting:render()
|
||||
return UDim2.new(1, -offset, 0, textBounds.Y)
|
||||
end),
|
||||
|
||||
LayoutOrder = 2,
|
||||
LayoutOrder = 3,
|
||||
BackgroundTransparency = 1,
|
||||
}),
|
||||
|
||||
@@ -181,21 +215,16 @@ function Setting:render()
|
||||
VerticalAlignment = Enum.VerticalAlignment.Center,
|
||||
FillDirection = Enum.FillDirection.Vertical,
|
||||
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||
Padding = UDim.new(0, 6),
|
||||
Padding = UDim.new(0, 5),
|
||||
|
||||
[Roact.Change.AbsoluteContentSize] = function(object)
|
||||
self.setContentSize(object.AbsoluteContentSize)
|
||||
end,
|
||||
}),
|
||||
|
||||
Padding = e("UIPadding", {
|
||||
PaddingTop = UDim.new(0, 20),
|
||||
PaddingBottom = UDim.new(0, 20),
|
||||
}),
|
||||
}),
|
||||
|
||||
Divider = e("Frame", {
|
||||
BackgroundColor3 = theme.DividerColor,
|
||||
BackgroundColor3 = settingsTheme.DividerColor,
|
||||
BackgroundTransparency = self.props.transparency,
|
||||
Size = UDim2.new(1, 0, 0, 1),
|
||||
BorderSizePixel = 0,
|
||||
|
||||
@@ -166,7 +166,7 @@ function SettingsPage:render()
|
||||
id = "autoConnectPlaytestServer",
|
||||
name = "Auto Connect Playtest Server",
|
||||
description = "Automatically connect game server to Rojo when playtesting while connected in Edit",
|
||||
experimental = true,
|
||||
tag = "unstable",
|
||||
transparency = self.props.transparency,
|
||||
layoutOrder = layoutIncrement(),
|
||||
}),
|
||||
@@ -175,7 +175,7 @@ function SettingsPage:render()
|
||||
id = "openScriptsExternally",
|
||||
name = "Open Scripts Externally",
|
||||
description = "Attempt to open scripts in an external editor",
|
||||
experimental = true,
|
||||
tag = "unstable",
|
||||
transparency = self.props.transparency,
|
||||
layoutOrder = layoutIncrement(),
|
||||
}),
|
||||
@@ -185,7 +185,7 @@ function SettingsPage:render()
|
||||
name = "Two-Way Sync",
|
||||
description = "Editing files in Studio will sync them into the filesystem",
|
||||
locked = self.props.syncActive,
|
||||
experimental = true,
|
||||
tag = "unstable",
|
||||
transparency = self.props.transparency,
|
||||
layoutOrder = layoutIncrement(),
|
||||
}),
|
||||
@@ -194,7 +194,7 @@ function SettingsPage:render()
|
||||
id = "logLevel",
|
||||
name = "Log Level",
|
||||
description = "Plugin output verbosity level",
|
||||
developerDebug = true,
|
||||
tag = "debug",
|
||||
transparency = self.props.transparency,
|
||||
layoutOrder = layoutIncrement(),
|
||||
|
||||
@@ -211,7 +211,7 @@ function SettingsPage:render()
|
||||
id = "typecheckingEnabled",
|
||||
name = "Typechecking",
|
||||
description = "Toggle typechecking on the API surface",
|
||||
developerDebug = true,
|
||||
tag = "debug",
|
||||
transparency = self.props.transparency,
|
||||
layoutOrder = layoutIncrement(),
|
||||
}),
|
||||
@@ -220,7 +220,7 @@ function SettingsPage:render()
|
||||
id = "timingLogsEnabled",
|
||||
name = "Timing Logs",
|
||||
description = "Toggle logging timing of internal actions for benchmarking Rojo performance",
|
||||
developerDebug = true,
|
||||
tag = "debug",
|
||||
transparency = self.props.transparency,
|
||||
layoutOrder = layoutIncrement(),
|
||||
}),
|
||||
|
||||
@@ -35,6 +35,7 @@ function StudioProvider:updateTheme()
|
||||
local isDark = studioTheme.Name == "Dark"
|
||||
|
||||
local theme = strict(studioTheme.Name .. "Theme", {
|
||||
BrandColor = BRAND_COLOR,
|
||||
BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainBackground),
|
||||
TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText),
|
||||
SubTextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.SubText),
|
||||
@@ -166,6 +167,8 @@ function StudioProvider:updateTheme()
|
||||
Setting = {
|
||||
NameColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText),
|
||||
DescriptionColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText),
|
||||
UnstableColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.WarningText),
|
||||
DebugColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.InfoText),
|
||||
},
|
||||
},
|
||||
Header = {
|
||||
|
||||
@@ -25,6 +25,8 @@ local Assets = {
|
||||
Back = "rbxassetid://6017213752",
|
||||
Reset = "rbxassetid://10142422327",
|
||||
Expand = "rbxassetid://12045401097",
|
||||
Warning = "rbxassetid://16571019891",
|
||||
Debug = "rbxassetid://16588411361",
|
||||
Checkmark = "rbxassetid://16571012729",
|
||||
Exclamation = "rbxassetid://16571172190",
|
||||
SyncSuccess = "rbxassetid://16565035221",
|
||||
|
||||
@@ -29,13 +29,13 @@ macro_rules! declare_asset {
|
||||
declare_asset!(css, "../../assets/index.css");
|
||||
|
||||
pub fn logo() -> &'static [u8] {
|
||||
static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png");
|
||||
static LOGO: &[u8] = include_bytes!("../../assets/brand_images/logo-512.png");
|
||||
|
||||
LOGO
|
||||
}
|
||||
|
||||
pub fn icon() -> &'static [u8] {
|
||||
static ICON: &[u8] = include_bytes!("../../assets/icon-32.png");
|
||||
static ICON: &[u8] = include_bytes!("../../assets/brand_images/icon-32.png");
|
||||
|
||||
ICON
|
||||
}
|
||||
|
||||