Skip to content

Commit

Permalink
Visualize table changes (rojo-rbx#834)
Browse files Browse the repository at this point in the history
Implements a pop out diff view for table properties like Attributes and
Tags
  • Loading branch information
boatbomber authored Jan 22, 2024
1 parent 1cc720a commit 4018607
Show file tree
Hide file tree
Showing 12 changed files with 755 additions and 176 deletions.
6 changes: 3 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
# Rojo Changelog

## Unreleased Changes
* Added popout diff visualizer for table properties like Attributes and Tags ([#834])
* Updated Theme to use Studio colors ([#838])

[#838]: https://github.com/rojo-rbx/rojo/pull/838

* 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`:

Expand Down Expand Up @@ -53,6 +51,8 @@
**All** sync rules are reset between project files, so they must be specified in each one when nesting them. This is to ensure that nothing can break other projects by changing how files are synced!

[#813]: https://github.com/rojo-rbx/rojo/pull/813
[#834]: https://github.com/rojo-rbx/rojo/pull/834
[#838]: https://github.com/rojo-rbx/rojo/pull/838

## [7.4.0] - January 16, 2024
* Improved the visualization for array properties like Tags ([#829])
Expand Down
248 changes: 132 additions & 116 deletions plugin/src/App/Components/PatchVisualizer/ChangeList.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,123 @@ local EMPTY_TABLE = {}

local e = Roact.createElement

local function ViewDiffButton(props)
return Theme.with(function(theme)
return e("TextButton", {
Text = "",
Size = UDim2.new(0.7, 0, 1, -4),
LayoutOrder = 2,
BackgroundTransparency = 1,
[Roact.Event.Activated] = props.onClick,
}, {
e(BorderedContainer, {
size = UDim2.new(1, 0, 1, 0),
transparency = props.transparency:map(function(t)
return 0.5 + (0.5 * t)
end),
}, {
Layout = e("UIListLayout", {
FillDirection = Enum.FillDirection.Horizontal,
SortOrder = Enum.SortOrder.LayoutOrder,
HorizontalAlignment = Enum.HorizontalAlignment.Center,
VerticalAlignment = Enum.VerticalAlignment.Center,
Padding = UDim.new(0, 5),
}),
Label = e("TextLabel", {
Text = "View Diff",
BackgroundTransparency = 1,
Font = Enum.Font.GothamMedium,
TextSize = 14,
TextColor3 = theme.Settings.Setting.DescriptionColor,
TextXAlignment = Enum.TextXAlignment.Left,
TextTransparency = props.transparency,
TextTruncate = Enum.TextTruncate.AtEnd,
Size = UDim2.new(0, 65, 1, 0),
LayoutOrder = 1,
}),
Icon = e("ImageLabel", {
Image = Assets.Images.Icons.Expand,
ImageColor3 = theme.Settings.Setting.DescriptionColor,
ImageTransparency = props.transparency,

Size = UDim2.new(0, 16, 0, 16),
Position = UDim2.new(0.5, 0, 0.5, 0),
AnchorPoint = Vector2.new(0.5, 0.5),

BackgroundTransparency = 1,
LayoutOrder = 2,
}),
}),
})
end)
end

local function RowContent(props)
local values = props.values
local metadata = props.metadata

if props.showStringDiff and values[1] == "Source" then
-- Special case for .Source updates
return e(ViewDiffButton, {
transparency = props.transparency,
onClick = function()
if not props.showStringDiff then
return
end
props.showStringDiff(tostring(values[2]), tostring(values[3]))
end,
})
end

if props.showTableDiff and (type(values[2]) == "table" or type(values[3]) == "table") then
-- Special case for table properties (like Attributes/Tags)
return e(ViewDiffButton, {
transparency = props.transparency,
onClick = function()
if not props.showTableDiff then
return
end
props.showTableDiff(values[2], values[3])
end,
})
end

return Theme.with(function(theme)
return Roact.createFragment({
ColumnB = e(
"Frame",
{
BackgroundTransparency = 1,
Size = UDim2.new(0.35, 0, 1, 0),
LayoutOrder = 2,
},
e(DisplayValue, {
value = values[2],
transparency = props.transparency,
textColor = if metadata.isWarning
then theme.Diff.Warning
else theme.Settings.Setting.DescriptionColor,
})
),
ColumnC = e(
"Frame",
{
BackgroundTransparency = 1,
Size = UDim2.new(0.35, 0, 1, 0),
LayoutOrder = 3,
},
e(DisplayValue, {
value = values[3],
transparency = props.transparency,
textColor = if metadata.isWarning
then theme.Diff.Warning
else theme.Settings.Setting.DescriptionColor,
})
),
})
end)
end

local ChangeList = Roact.Component:extend("ChangeList")

function ChangeList:init()
Expand All @@ -36,6 +153,7 @@ function ChangeList:render()
PaddingRight = UDim.new(0, 5),
}

local headerRow = changes[1]
local headers = e("Frame", {
Size = UDim2.new(1, 0, 0, 30),
BackgroundTransparency = rowTransparency,
Expand All @@ -49,8 +167,8 @@ function ChangeList:render()
HorizontalAlignment = Enum.HorizontalAlignment.Left,
VerticalAlignment = Enum.VerticalAlignment.Center,
}),
A = e("TextLabel", {
Text = tostring(changes[1][1]),
ColumnA = e("TextLabel", {
Text = tostring(headerRow[1]),
BackgroundTransparency = 1,
Font = Enum.Font.GothamBold,
TextSize = 14,
Expand All @@ -61,8 +179,8 @@ function ChangeList:render()
Size = UDim2.new(0.3, 0, 1, 0),
LayoutOrder = 1,
}),
B = e("TextLabel", {
Text = tostring(changes[1][2]),
ColumnB = e("TextLabel", {
Text = tostring(headerRow[2]),
BackgroundTransparency = 1,
Font = Enum.Font.GothamBold,
TextSize = 14,
Expand All @@ -73,8 +191,8 @@ function ChangeList:render()
Size = UDim2.new(0.35, 0, 1, 0),
LayoutOrder = 2,
}),
C = e("TextLabel", {
Text = tostring(changes[1][3]),
ColumnC = e("TextLabel", {
Text = tostring(headerRow[3]),
BackgroundTransparency = 1,
Font = Enum.Font.GothamBold,
TextSize = 14,
Expand All @@ -95,89 +213,6 @@ function ChangeList:render()
local metadata = values[4] or EMPTY_TABLE
local isWarning = metadata.isWarning

-- Special case for .Source updates
-- because we want to display a syntax highlighted diff for better UX
if self.props.showSourceDiff and tostring(values[1]) == "Source" then
rows[row] = e("Frame", {
Size = UDim2.new(1, 0, 0, 30),
BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1,
BackgroundColor3 = theme.Diff.Row,
BorderSizePixel = 0,
LayoutOrder = row,
}, {
Padding = e("UIPadding", pad),
Layout = e("UIListLayout", {
FillDirection = Enum.FillDirection.Horizontal,
SortOrder = Enum.SortOrder.LayoutOrder,
HorizontalAlignment = Enum.HorizontalAlignment.Left,
VerticalAlignment = Enum.VerticalAlignment.Center,
}),
A = e("TextLabel", {
Text = (if isWarning then "" else "") .. tostring(values[1]),
BackgroundTransparency = 1,
Font = Enum.Font.GothamMedium,
TextSize = 14,
TextColor3 = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor,
TextXAlignment = Enum.TextXAlignment.Left,
TextTransparency = props.transparency,
TextTruncate = Enum.TextTruncate.AtEnd,
Size = UDim2.new(0.3, 0, 1, 0),
LayoutOrder = 1,
}),
Button = e("TextButton", {
Text = "",
Size = UDim2.new(0.7, 0, 1, -4),
LayoutOrder = 2,
BackgroundTransparency = 1,
[Roact.Event.Activated] = function()
if props.showSourceDiff then
props.showSourceDiff(tostring(values[2]), tostring(values[3]))
end
end,
}, {
e(BorderedContainer, {
size = UDim2.new(1, 0, 1, 0),
transparency = self.props.transparency:map(function(t)
return 0.5 + (0.5 * t)
end),
}, {
Layout = e("UIListLayout", {
FillDirection = Enum.FillDirection.Horizontal,
SortOrder = Enum.SortOrder.LayoutOrder,
HorizontalAlignment = Enum.HorizontalAlignment.Center,
VerticalAlignment = Enum.VerticalAlignment.Center,
Padding = UDim.new(0, 5),
}),
Label = e("TextLabel", {
Text = "View Diff",
BackgroundTransparency = 1,
Font = Enum.Font.GothamMedium,
TextSize = 14,
TextColor3 = theme.Settings.Setting.DescriptionColor,
TextXAlignment = Enum.TextXAlignment.Left,
TextTransparency = props.transparency,
TextTruncate = Enum.TextTruncate.AtEnd,
Size = UDim2.new(0, 65, 1, 0),
LayoutOrder = 1,
}),
Icon = e("ImageLabel", {
Image = Assets.Images.Icons.Expand,
ImageColor3 = theme.Settings.Setting.DescriptionColor,
ImageTransparency = self.props.transparency,

Size = UDim2.new(0, 16, 0, 16),
Position = UDim2.new(0.5, 0, 0.5, 0),
AnchorPoint = Vector2.new(0.5, 0.5),

BackgroundTransparency = 1,
LayoutOrder = 2,
}),
}),
}),
})
continue
end

rows[row] = e("Frame", {
Size = UDim2.new(1, 0, 0, 30),
BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1,
Expand All @@ -192,7 +227,7 @@ function ChangeList:render()
HorizontalAlignment = Enum.HorizontalAlignment.Left,
VerticalAlignment = Enum.VerticalAlignment.Center,
}),
A = e("TextLabel", {
ColumnA = e("TextLabel", {
Text = (if isWarning then "" else "") .. tostring(values[1]),
BackgroundTransparency = 1,
Font = Enum.Font.GothamMedium,
Expand All @@ -204,32 +239,13 @@ function ChangeList:render()
Size = UDim2.new(0.3, 0, 1, 0),
LayoutOrder = 1,
}),
B = e(
"Frame",
{
BackgroundTransparency = 1,
Size = UDim2.new(0.35, 0, 1, 0),
LayoutOrder = 2,
},
e(DisplayValue, {
value = values[2],
transparency = props.transparency,
textColor = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor,
})
),
C = e(
"Frame",
{
BackgroundTransparency = 1,
Size = UDim2.new(0.35, 0, 1, 0),
LayoutOrder = 3,
},
e(DisplayValue, {
value = values[3],
transparency = props.transparency,
textColor = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor,
})
),
Content = e(RowContent, {
values = values,
metadata = metadata,
transparency = props.transparency,
showStringDiff = props.showStringDiff,
showTableDiff = props.showTableDiff,
}),
})
end

Expand Down
9 changes: 7 additions & 2 deletions plugin/src/App/Components/PatchVisualizer/DisplayValue.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ local function DisplayValue(props)
}),
}),
Label = e("TextLabel", {
Text = string.format("%d,%d,%d", props.value.R * 255, props.value.G * 255, props.value.B * 255),
Text = string.format("%d, %d, %d", props.value.R * 255, props.value.G * 255, props.value.B * 255),
BackgroundTransparency = 1,
Font = Enum.Font.GothamMedium,
TextSize = 14,
Expand Down Expand Up @@ -104,8 +104,13 @@ local function DisplayValue(props)
-- Or special text handling tostring for some?
-- Will add as needed, let's see what cases arise.

local textRepresentation = string.gsub(tostring(props.value), "%s", " ")
if t == "string" then
textRepresentation = '"' .. textRepresentation .. '"'
end

return e("TextLabel", {
Text = string.gsub(tostring(props.value), "%s", " "),
Text = textRepresentation,
BackgroundTransparency = 1,
Font = Enum.Font.GothamMedium,
TextSize = 14,
Expand Down
6 changes: 4 additions & 2 deletions plugin/src/App/Components/PatchVisualizer/DomLabel.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ function Expansion:render()
ChangeList = e(ChangeList, {
changes = props.changeList,
transparency = props.transparency,
showSourceDiff = props.showSourceDiff,
showStringDiff = props.showStringDiff,
showTableDiff = props.showTableDiff,
}),
})
end
Expand Down Expand Up @@ -171,7 +172,8 @@ function DomLabel:render()
indent = indent,
transparency = props.transparency,
changeList = props.changeList,
showSourceDiff = props.showSourceDiff,
showStringDiff = props.showStringDiff,
showTableDiff = props.showTableDiff,
})
else nil,
DiffIcon = if props.patchType
Expand Down
3 changes: 2 additions & 1 deletion plugin/src/App/Components/PatchVisualizer/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ function PatchVisualizer:render()
changeList = node.changeList,
depth = depth,
transparency = self.props.transparency,
showSourceDiff = self.props.showSourceDiff,
showStringDiff = self.props.showStringDiff,
showTableDiff = self.props.showTableDiff,
})
)
end
Expand Down
Loading

0 comments on commit 4018607

Please sign in to comment.