mirror of
https://github.com/rojo-rbx/rojo.git
synced 2026-04-25 23:26:19 +00:00
Visualize table changes (#834)
Implements a pop out diff view for table properties like Attributes and Tags
This commit is contained in:
@@ -1,10 +1,8 @@
|
|||||||
# Rojo Changelog
|
# Rojo Changelog
|
||||||
|
|
||||||
## Unreleased Changes
|
## Unreleased Changes
|
||||||
|
* Added popout diff visualizer for table properties like Attributes and Tags ([#834])
|
||||||
* Updated Theme to use Studio colors ([#838])
|
* 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])
|
* 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`:
|
This is specified via a new field on project files, `syncRules`:
|
||||||
|
|
||||||
@@ -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!
|
**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
|
[#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
|
## [7.4.0] - January 16, 2024
|
||||||
* Improved the visualization for array properties like Tags ([#829])
|
* Improved the visualization for array properties like Tags ([#829])
|
||||||
|
|||||||
@@ -14,6 +14,123 @@ local EMPTY_TABLE = {}
|
|||||||
|
|
||||||
local e = Roact.createElement
|
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")
|
local ChangeList = Roact.Component:extend("ChangeList")
|
||||||
|
|
||||||
function ChangeList:init()
|
function ChangeList:init()
|
||||||
@@ -36,6 +153,7 @@ function ChangeList:render()
|
|||||||
PaddingRight = UDim.new(0, 5),
|
PaddingRight = UDim.new(0, 5),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local headerRow = changes[1]
|
||||||
local headers = e("Frame", {
|
local headers = e("Frame", {
|
||||||
Size = UDim2.new(1, 0, 0, 30),
|
Size = UDim2.new(1, 0, 0, 30),
|
||||||
BackgroundTransparency = rowTransparency,
|
BackgroundTransparency = rowTransparency,
|
||||||
@@ -49,8 +167,8 @@ function ChangeList:render()
|
|||||||
HorizontalAlignment = Enum.HorizontalAlignment.Left,
|
HorizontalAlignment = Enum.HorizontalAlignment.Left,
|
||||||
VerticalAlignment = Enum.VerticalAlignment.Center,
|
VerticalAlignment = Enum.VerticalAlignment.Center,
|
||||||
}),
|
}),
|
||||||
A = e("TextLabel", {
|
ColumnA = e("TextLabel", {
|
||||||
Text = tostring(changes[1][1]),
|
Text = tostring(headerRow[1]),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamBold,
|
Font = Enum.Font.GothamBold,
|
||||||
TextSize = 14,
|
TextSize = 14,
|
||||||
@@ -61,8 +179,8 @@ function ChangeList:render()
|
|||||||
Size = UDim2.new(0.3, 0, 1, 0),
|
Size = UDim2.new(0.3, 0, 1, 0),
|
||||||
LayoutOrder = 1,
|
LayoutOrder = 1,
|
||||||
}),
|
}),
|
||||||
B = e("TextLabel", {
|
ColumnB = e("TextLabel", {
|
||||||
Text = tostring(changes[1][2]),
|
Text = tostring(headerRow[2]),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamBold,
|
Font = Enum.Font.GothamBold,
|
||||||
TextSize = 14,
|
TextSize = 14,
|
||||||
@@ -73,8 +191,8 @@ function ChangeList:render()
|
|||||||
Size = UDim2.new(0.35, 0, 1, 0),
|
Size = UDim2.new(0.35, 0, 1, 0),
|
||||||
LayoutOrder = 2,
|
LayoutOrder = 2,
|
||||||
}),
|
}),
|
||||||
C = e("TextLabel", {
|
ColumnC = e("TextLabel", {
|
||||||
Text = tostring(changes[1][3]),
|
Text = tostring(headerRow[3]),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamBold,
|
Font = Enum.Font.GothamBold,
|
||||||
TextSize = 14,
|
TextSize = 14,
|
||||||
@@ -95,89 +213,6 @@ function ChangeList:render()
|
|||||||
local metadata = values[4] or EMPTY_TABLE
|
local metadata = values[4] or EMPTY_TABLE
|
||||||
local isWarning = metadata.isWarning
|
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", {
|
rows[row] = e("Frame", {
|
||||||
Size = UDim2.new(1, 0, 0, 30),
|
Size = UDim2.new(1, 0, 0, 30),
|
||||||
BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1,
|
BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1,
|
||||||
@@ -192,7 +227,7 @@ function ChangeList:render()
|
|||||||
HorizontalAlignment = Enum.HorizontalAlignment.Left,
|
HorizontalAlignment = Enum.HorizontalAlignment.Left,
|
||||||
VerticalAlignment = Enum.VerticalAlignment.Center,
|
VerticalAlignment = Enum.VerticalAlignment.Center,
|
||||||
}),
|
}),
|
||||||
A = e("TextLabel", {
|
ColumnA = e("TextLabel", {
|
||||||
Text = (if isWarning then "⚠ " else "") .. tostring(values[1]),
|
Text = (if isWarning then "⚠ " else "") .. tostring(values[1]),
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamMedium,
|
Font = Enum.Font.GothamMedium,
|
||||||
@@ -204,32 +239,13 @@ function ChangeList:render()
|
|||||||
Size = UDim2.new(0.3, 0, 1, 0),
|
Size = UDim2.new(0.3, 0, 1, 0),
|
||||||
LayoutOrder = 1,
|
LayoutOrder = 1,
|
||||||
}),
|
}),
|
||||||
B = e(
|
Content = e(RowContent, {
|
||||||
"Frame",
|
values = values,
|
||||||
{
|
metadata = metadata,
|
||||||
BackgroundTransparency = 1,
|
transparency = props.transparency,
|
||||||
Size = UDim2.new(0.35, 0, 1, 0),
|
showStringDiff = props.showStringDiff,
|
||||||
LayoutOrder = 2,
|
showTableDiff = props.showTableDiff,
|
||||||
},
|
}),
|
||||||
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,
|
|
||||||
})
|
|
||||||
),
|
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ local function DisplayValue(props)
|
|||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
Label = e("TextLabel", {
|
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,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamMedium,
|
Font = Enum.Font.GothamMedium,
|
||||||
TextSize = 14,
|
TextSize = 14,
|
||||||
@@ -104,8 +104,13 @@ local function DisplayValue(props)
|
|||||||
-- Or special text handling tostring for some?
|
-- Or special text handling tostring for some?
|
||||||
-- Will add as needed, let's see what cases arise.
|
-- 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", {
|
return e("TextLabel", {
|
||||||
Text = string.gsub(tostring(props.value), "%s", " "),
|
Text = textRepresentation,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
Font = Enum.Font.GothamMedium,
|
Font = Enum.Font.GothamMedium,
|
||||||
TextSize = 14,
|
TextSize = 14,
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ function Expansion:render()
|
|||||||
ChangeList = e(ChangeList, {
|
ChangeList = e(ChangeList, {
|
||||||
changes = props.changeList,
|
changes = props.changeList,
|
||||||
transparency = props.transparency,
|
transparency = props.transparency,
|
||||||
showSourceDiff = props.showSourceDiff,
|
showStringDiff = props.showStringDiff,
|
||||||
|
showTableDiff = props.showTableDiff,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@@ -171,7 +172,8 @@ function DomLabel:render()
|
|||||||
indent = indent,
|
indent = indent,
|
||||||
transparency = props.transparency,
|
transparency = props.transparency,
|
||||||
changeList = props.changeList,
|
changeList = props.changeList,
|
||||||
showSourceDiff = props.showSourceDiff,
|
showStringDiff = props.showStringDiff,
|
||||||
|
showTableDiff = props.showTableDiff,
|
||||||
})
|
})
|
||||||
else nil,
|
else nil,
|
||||||
DiffIcon = if props.patchType
|
DiffIcon = if props.patchType
|
||||||
|
|||||||
@@ -76,7 +76,8 @@ function PatchVisualizer:render()
|
|||||||
changeList = node.changeList,
|
changeList = node.changeList,
|
||||||
depth = depth,
|
depth = depth,
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
showSourceDiff = self.props.showSourceDiff,
|
showStringDiff = self.props.showStringDiff,
|
||||||
|
showTableDiff = self.props.showTableDiff,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -10,6 +10,12 @@ local bindingUtil = require(Plugin.App.bindingUtil)
|
|||||||
|
|
||||||
local e = Roact.createElement
|
local e = Roact.createElement
|
||||||
|
|
||||||
|
local scrollDirToAutoSize = {
|
||||||
|
[Enum.ScrollingDirection.X] = Enum.AutomaticSize.X,
|
||||||
|
[Enum.ScrollingDirection.Y] = Enum.AutomaticSize.Y,
|
||||||
|
[Enum.ScrollingDirection.XY] = Enum.AutomaticSize.XY,
|
||||||
|
}
|
||||||
|
|
||||||
local function ScrollingFrame(props)
|
local function ScrollingFrame(props)
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
return e("ScrollingFrame", {
|
return e("ScrollingFrame", {
|
||||||
@@ -28,16 +34,21 @@ local function ScrollingFrame(props)
|
|||||||
Size = props.size,
|
Size = props.size,
|
||||||
Position = props.position,
|
Position = props.position,
|
||||||
AnchorPoint = props.anchorPoint,
|
AnchorPoint = props.anchorPoint,
|
||||||
CanvasSize = props.contentSize:map(function(value)
|
CanvasSize = if props.contentSize
|
||||||
return UDim2.new(
|
then props.contentSize:map(function(value)
|
||||||
0,
|
return UDim2.new(
|
||||||
if (props.scrollingDirection and props.scrollingDirection ~= Enum.ScrollingDirection.Y)
|
0,
|
||||||
then value.X
|
if (props.scrollingDirection and props.scrollingDirection ~= Enum.ScrollingDirection.Y)
|
||||||
else 0,
|
then value.X
|
||||||
0,
|
else 0,
|
||||||
value.Y
|
0,
|
||||||
)
|
value.Y
|
||||||
end),
|
)
|
||||||
|
end)
|
||||||
|
else UDim2.new(),
|
||||||
|
AutomaticCanvasSize = if props.contentSize == nil
|
||||||
|
then scrollDirToAutoSize[props.scrollingDirection or Enum.ScrollingDirection.XY]
|
||||||
|
else nil,
|
||||||
|
|
||||||
BorderSizePixel = 0,
|
BorderSizePixel = 0,
|
||||||
BackgroundTransparency = 1,
|
BackgroundTransparency = 1,
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ function StringDiffVisualizer:updateScriptBackground()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function StringDiffVisualizer:didUpdate(previousProps)
|
function StringDiffVisualizer:didUpdate(previousProps)
|
||||||
if previousProps.oldText ~= self.props.oldText or previousProps.newText ~= self.props.newText then
|
if previousProps.oldString ~= self.props.oldString or previousProps.newString ~= self.props.newString then
|
||||||
self:calculateContentSize()
|
self:calculateContentSize()
|
||||||
local add, remove = self:calculateDiffLines()
|
local add, remove = self:calculateDiffLines()
|
||||||
self:setState({
|
self:setState({
|
||||||
@@ -63,28 +63,28 @@ function StringDiffVisualizer:didUpdate(previousProps)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function StringDiffVisualizer:calculateContentSize()
|
function StringDiffVisualizer:calculateContentSize()
|
||||||
local oldText, newText = self.props.oldText, self.props.newText
|
local oldString, newString = self.props.oldString, self.props.newString
|
||||||
|
|
||||||
local oldTextBounds = TextService:GetTextSize(oldText, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999))
|
local oldStringBounds = TextService:GetTextSize(oldString, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999))
|
||||||
local newTextBounds = TextService:GetTextSize(newText, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999))
|
local newStringBounds = TextService:GetTextSize(newString, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999))
|
||||||
|
|
||||||
self.setContentSize(
|
self.setContentSize(
|
||||||
Vector2.new(math.max(oldTextBounds.X, newTextBounds.X), math.max(oldTextBounds.Y, newTextBounds.Y))
|
Vector2.new(math.max(oldStringBounds.X, newStringBounds.X), math.max(oldStringBounds.Y, newStringBounds.Y))
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function StringDiffVisualizer:calculateDiffLines()
|
function StringDiffVisualizer:calculateDiffLines()
|
||||||
local oldText, newText = self.props.oldText, self.props.newText
|
local oldString, newString = self.props.oldString, self.props.newString
|
||||||
|
|
||||||
-- Diff the two texts
|
-- Diff the two texts
|
||||||
local startClock = os.clock()
|
local startClock = os.clock()
|
||||||
local diffs = StringDiff.findDiffs(oldText, newText)
|
local diffs = StringDiff.findDiffs(oldString, newString)
|
||||||
local stopClock = os.clock()
|
local stopClock = os.clock()
|
||||||
|
|
||||||
Log.trace(
|
Log.trace(
|
||||||
"Diffing {} byte and {} byte strings took {} microseconds and found {} diff sections",
|
"Diffing {} byte and {} byte strings took {} microseconds and found {} diff sections",
|
||||||
#oldText,
|
#oldString,
|
||||||
#newText,
|
#newString,
|
||||||
math.round((stopClock - startClock) * 1000 * 1000),
|
math.round((stopClock - startClock) * 1000 * 1000),
|
||||||
#diffs
|
#diffs
|
||||||
)
|
)
|
||||||
@@ -137,7 +137,7 @@ function StringDiffVisualizer:calculateDiffLines()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function StringDiffVisualizer:render()
|
function StringDiffVisualizer:render()
|
||||||
local oldText, newText = self.props.oldText, self.props.newText
|
local oldString, newString = self.props.oldString, self.props.newString
|
||||||
|
|
||||||
return Theme.with(function(theme)
|
return Theme.with(function(theme)
|
||||||
return e(BorderedContainer, {
|
return e(BorderedContainer, {
|
||||||
@@ -175,7 +175,7 @@ function StringDiffVisualizer:render()
|
|||||||
Source = e(CodeLabel, {
|
Source = e(CodeLabel, {
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
position = UDim2.new(0, 0, 0, 0),
|
position = UDim2.new(0, 0, 0, 0),
|
||||||
text = oldText,
|
text = oldString,
|
||||||
lineBackground = theme.Diff.Remove,
|
lineBackground = theme.Diff.Remove,
|
||||||
markedLines = self.state.remove,
|
markedLines = self.state.remove,
|
||||||
}),
|
}),
|
||||||
@@ -190,7 +190,7 @@ function StringDiffVisualizer:render()
|
|||||||
Source = e(CodeLabel, {
|
Source = e(CodeLabel, {
|
||||||
size = UDim2.new(1, 0, 1, 0),
|
size = UDim2.new(1, 0, 1, 0),
|
||||||
position = UDim2.new(0, 0, 0, 0),
|
position = UDim2.new(0, 0, 0, 0),
|
||||||
text = newText,
|
text = newString,
|
||||||
lineBackground = theme.Diff.Add,
|
lineBackground = theme.Diff.Add,
|
||||||
markedLines = self.state.add,
|
markedLines = self.state.add,
|
||||||
}),
|
}),
|
||||||
|
|||||||
192
plugin/src/App/Components/TableDiffVisualizer/Array.lua
Normal file
192
plugin/src/App/Components/TableDiffVisualizer/Array.lua
Normal file
@@ -0,0 +1,192 @@
|
|||||||
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
|
local Plugin = Rojo.Plugin
|
||||||
|
local Packages = Rojo.Packages
|
||||||
|
|
||||||
|
local Roact = require(Packages.Roact)
|
||||||
|
|
||||||
|
local Assets = require(Plugin.Assets)
|
||||||
|
local Theme = require(Plugin.App.Theme)
|
||||||
|
|
||||||
|
local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame)
|
||||||
|
local DisplayValue = require(Plugin.App.Components.PatchVisualizer.DisplayValue)
|
||||||
|
|
||||||
|
local e = Roact.createElement
|
||||||
|
|
||||||
|
local Array = Roact.Component:extend("Array")
|
||||||
|
|
||||||
|
function Array:init()
|
||||||
|
self:setState({
|
||||||
|
diff = self:calculateDiff(),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:calculateDiff()
|
||||||
|
--[[
|
||||||
|
Find the indexes that are added or removed from the array,
|
||||||
|
and display them side by side with gaps for the indexes that
|
||||||
|
dont exist in the opposite array.
|
||||||
|
]]
|
||||||
|
local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {}
|
||||||
|
|
||||||
|
local i, j = 1, 1
|
||||||
|
local diff = {}
|
||||||
|
|
||||||
|
while i <= #oldTable and j <= #newTable do
|
||||||
|
if oldTable[i] == newTable[j] then
|
||||||
|
table.insert(diff, { oldTable[i], newTable[j] }) -- Unchanged
|
||||||
|
i += 1
|
||||||
|
j += 1
|
||||||
|
elseif not table.find(newTable, oldTable[i], j) then
|
||||||
|
table.insert(diff, { oldTable[i], nil }) -- Removal
|
||||||
|
i += 1
|
||||||
|
elseif not table.find(oldTable, newTable[j], i) then
|
||||||
|
table.insert(diff, { nil, newTable[j] }) -- Addition
|
||||||
|
j += 1
|
||||||
|
else
|
||||||
|
if table.find(newTable, oldTable[i], j) then
|
||||||
|
table.insert(diff, { nil, newTable[j] }) -- Addition
|
||||||
|
j += 1
|
||||||
|
else
|
||||||
|
table.insert(diff, { oldTable[i], nil }) -- Removal
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Handle remaining elements
|
||||||
|
while i <= #oldTable do
|
||||||
|
table.insert(diff, { oldTable[i], nil }) -- Remaining Removals
|
||||||
|
i += 1
|
||||||
|
end
|
||||||
|
while j <= #newTable do
|
||||||
|
table.insert(diff, { nil, newTable[j] }) -- Remaining Additions
|
||||||
|
j += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
return diff
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:didUpdate(previousProps)
|
||||||
|
if previousProps.oldTable ~= self.props.oldTable or previousProps.newTable ~= self.props.newTable then
|
||||||
|
self:setState({
|
||||||
|
diff = self:calculateDiff(),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Array:render()
|
||||||
|
return Theme.with(function(theme)
|
||||||
|
local diff = self.state.diff
|
||||||
|
local lines = table.create(#diff)
|
||||||
|
|
||||||
|
for i, element in diff do
|
||||||
|
local oldValue = element[1]
|
||||||
|
local newValue = element[2]
|
||||||
|
|
||||||
|
local patchType = if oldValue == nil then "Add" elseif newValue == nil then "Remove" else "Remain"
|
||||||
|
|
||||||
|
table.insert(
|
||||||
|
lines,
|
||||||
|
e("Frame", {
|
||||||
|
Size = UDim2.new(1, 0, 0, 25),
|
||||||
|
BackgroundTransparency = if patchType == "Remain" then 1 else self.props.transparency,
|
||||||
|
BackgroundColor3 = if patchType == "Remain" then theme.Diff.Row else theme.Diff[patchType],
|
||||||
|
BorderSizePixel = 0,
|
||||||
|
LayoutOrder = i,
|
||||||
|
}, {
|
||||||
|
DiffIcon = if patchType ~= "Remain"
|
||||||
|
then e("ImageLabel", {
|
||||||
|
Image = Assets.Images.Diff[patchType],
|
||||||
|
ImageColor3 = theme.AddressEntry.PlaceholderColor,
|
||||||
|
ImageTransparency = self.props.transparency,
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
Size = UDim2.new(0, 15, 0, 15),
|
||||||
|
Position = UDim2.new(0, 7, 0.5, 0),
|
||||||
|
AnchorPoint = Vector2.new(0, 0.5),
|
||||||
|
})
|
||||||
|
else nil,
|
||||||
|
Old = e("Frame", {
|
||||||
|
Size = UDim2.new(0.5, -30, 1, 0),
|
||||||
|
Position = UDim2.new(0, 30, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
}, {
|
||||||
|
Display = if oldValue ~= nil
|
||||||
|
then e(DisplayValue, {
|
||||||
|
value = oldValue,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
textColor = theme.Settings.Setting.DescriptionColor,
|
||||||
|
})
|
||||||
|
else nil,
|
||||||
|
}),
|
||||||
|
New = e("Frame", {
|
||||||
|
Size = UDim2.new(0.5, -10, 1, 0),
|
||||||
|
Position = UDim2.new(0.5, 5, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
}, {
|
||||||
|
Display = if newValue ~= nil
|
||||||
|
then e(DisplayValue, {
|
||||||
|
value = newValue,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
textColor = theme.Settings.Setting.DescriptionColor,
|
||||||
|
})
|
||||||
|
else nil,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Roact.createFragment({
|
||||||
|
Headers = e("Frame", {
|
||||||
|
Size = UDim2.new(1, 0, 0, 25),
|
||||||
|
BackgroundTransparency = self.props.transparency:map(function(t)
|
||||||
|
return 0.95 + (0.05 * t)
|
||||||
|
end),
|
||||||
|
BackgroundColor3 = theme.Diff.Row,
|
||||||
|
}, {
|
||||||
|
ColumnA = e("TextLabel", {
|
||||||
|
Size = UDim2.new(0.5, -30, 1, 0),
|
||||||
|
Position = UDim2.new(0, 30, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
Text = "Old",
|
||||||
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
Font = Enum.Font.GothamBold,
|
||||||
|
TextSize = 14,
|
||||||
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
|
}),
|
||||||
|
ColumnB = e("TextLabel", {
|
||||||
|
Size = UDim2.new(0.5, -10, 1, 0),
|
||||||
|
Position = UDim2.new(0.5, 5, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
Text = "New",
|
||||||
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
Font = Enum.Font.GothamBold,
|
||||||
|
TextSize = 14,
|
||||||
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
|
}),
|
||||||
|
Separator = e("Frame", {
|
||||||
|
Size = UDim2.new(1, 0, 0, 1),
|
||||||
|
Position = UDim2.new(0, 0, 1, 0),
|
||||||
|
BackgroundTransparency = 0,
|
||||||
|
BorderSizePixel = 0,
|
||||||
|
BackgroundColor3 = theme.BorderedContainer.BorderColor,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
KeyValues = e(ScrollingFrame, {
|
||||||
|
position = UDim2.new(0, 1, 0, 25),
|
||||||
|
size = UDim2.new(1, -2, 1, -27),
|
||||||
|
scrollingDirection = Enum.ScrollingDirection.Y,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
}, {
|
||||||
|
Layout = e("UIListLayout", {
|
||||||
|
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||||
|
VerticalAlignment = Enum.VerticalAlignment.Top,
|
||||||
|
}),
|
||||||
|
Lines = Roact.createFragment(lines),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Array
|
||||||
208
plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua
Normal file
208
plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
|
local Plugin = Rojo.Plugin
|
||||||
|
local Packages = Rojo.Packages
|
||||||
|
|
||||||
|
local Roact = require(Packages.Roact)
|
||||||
|
|
||||||
|
local Assets = require(Plugin.Assets)
|
||||||
|
local Theme = require(Plugin.App.Theme)
|
||||||
|
|
||||||
|
local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame)
|
||||||
|
local DisplayValue = require(Plugin.App.Components.PatchVisualizer.DisplayValue)
|
||||||
|
|
||||||
|
local e = Roact.createElement
|
||||||
|
|
||||||
|
local Dictionary = Roact.Component:extend("Dictionary")
|
||||||
|
|
||||||
|
function Dictionary:init()
|
||||||
|
self:setState({
|
||||||
|
diff = self:calculateDiff(),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dictionary:calculateDiff()
|
||||||
|
local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {}
|
||||||
|
|
||||||
|
-- Diff the two tables and find the added keys, removed keys, and changed keys
|
||||||
|
local diff = {}
|
||||||
|
|
||||||
|
for key, oldValue in oldTable do
|
||||||
|
local newValue = newTable[key]
|
||||||
|
if newValue == nil then
|
||||||
|
table.insert(diff, {
|
||||||
|
key = key,
|
||||||
|
patchType = "Remove",
|
||||||
|
})
|
||||||
|
elseif newValue ~= oldValue then
|
||||||
|
-- Note: should this do some sort of deep comparison for various types?
|
||||||
|
table.insert(diff, {
|
||||||
|
key = key,
|
||||||
|
patchType = "Edit",
|
||||||
|
})
|
||||||
|
else
|
||||||
|
table.insert(diff, {
|
||||||
|
key = key,
|
||||||
|
patchType = "Remain",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for key in newTable do
|
||||||
|
if oldTable[key] == nil then
|
||||||
|
table.insert(diff, {
|
||||||
|
key = key,
|
||||||
|
patchType = "Add",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
table.sort(diff, function(a, b)
|
||||||
|
return a.key < b.key
|
||||||
|
end)
|
||||||
|
|
||||||
|
return diff
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dictionary:didUpdate(previousProps)
|
||||||
|
if previousProps.oldTable ~= self.props.oldTable or previousProps.newTable ~= self.props.newTable then
|
||||||
|
self:setState({
|
||||||
|
diff = self:calculateDiff(),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Dictionary:render()
|
||||||
|
local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {}
|
||||||
|
local diff = self.state.diff
|
||||||
|
|
||||||
|
return Theme.with(function(theme)
|
||||||
|
local lines = table.create(#diff)
|
||||||
|
for order, line in diff do
|
||||||
|
local key = line.key
|
||||||
|
local oldValue = oldTable[key]
|
||||||
|
local newValue = newTable[key]
|
||||||
|
|
||||||
|
table.insert(
|
||||||
|
lines,
|
||||||
|
e("Frame", {
|
||||||
|
Size = UDim2.new(1, 0, 0, 25),
|
||||||
|
LayoutOrder = order,
|
||||||
|
BorderSizePixel = 0,
|
||||||
|
BackgroundTransparency = if line.patchType == "Remain" then 1 else self.props.transparency,
|
||||||
|
BackgroundColor3 = if line.patchType == "Remain"
|
||||||
|
then theme.Diff.Row
|
||||||
|
else theme.Diff[line.patchType],
|
||||||
|
}, {
|
||||||
|
DiffIcon = if line.patchType ~= "Remain"
|
||||||
|
then e("ImageLabel", {
|
||||||
|
Image = Assets.Images.Diff[line.patchType],
|
||||||
|
ImageColor3 = theme.AddressEntry.PlaceholderColor,
|
||||||
|
ImageTransparency = self.props.transparency,
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
Size = UDim2.new(0, 15, 0, 15),
|
||||||
|
Position = UDim2.new(0, 7, 0.5, 0),
|
||||||
|
AnchorPoint = Vector2.new(0, 0.5),
|
||||||
|
})
|
||||||
|
else nil,
|
||||||
|
KeyName = e("TextLabel", {
|
||||||
|
Size = UDim2.new(0.3, -15, 1, 0),
|
||||||
|
Position = UDim2.new(0, 30, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
Text = key,
|
||||||
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
Font = Enum.Font.GothamMedium,
|
||||||
|
TextSize = 14,
|
||||||
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
|
}),
|
||||||
|
OldValue = e("Frame", {
|
||||||
|
Size = UDim2.new(0.35, -7, 1, 0),
|
||||||
|
Position = UDim2.new(0.3, 15, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
}, {
|
||||||
|
e(DisplayValue, {
|
||||||
|
value = oldValue,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
textColor = theme.Settings.Setting.DescriptionColor,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
NewValue = e("Frame", {
|
||||||
|
Size = UDim2.new(0.35, -8, 1, 0),
|
||||||
|
Position = UDim2.new(0.65, 8, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
}, {
|
||||||
|
e(DisplayValue, {
|
||||||
|
value = newValue,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
textColor = theme.Settings.Setting.DescriptionColor,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Roact.createFragment({
|
||||||
|
Headers = e("Frame", {
|
||||||
|
Size = UDim2.new(1, 0, 0, 25),
|
||||||
|
BackgroundTransparency = self.props.transparency:map(function(t)
|
||||||
|
return 0.95 + (0.05 * t)
|
||||||
|
end),
|
||||||
|
BackgroundColor3 = theme.Diff.Row,
|
||||||
|
}, {
|
||||||
|
ColumnA = e("TextLabel", {
|
||||||
|
Size = UDim2.new(0.3, -15, 1, 0),
|
||||||
|
Position = UDim2.new(0, 30, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
Text = "Key",
|
||||||
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
Font = Enum.Font.GothamBold,
|
||||||
|
TextSize = 14,
|
||||||
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
|
}),
|
||||||
|
ColumnB = e("TextLabel", {
|
||||||
|
Size = UDim2.new(0.35, -7, 1, 0),
|
||||||
|
Position = UDim2.new(0.3, 15, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
Text = "Old",
|
||||||
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
Font = Enum.Font.GothamBold,
|
||||||
|
TextSize = 14,
|
||||||
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
|
}),
|
||||||
|
ColumnC = e("TextLabel", {
|
||||||
|
Size = UDim2.new(0.35, -8, 1, 0),
|
||||||
|
Position = UDim2.new(0.65, 8, 0, 0),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
Text = "New",
|
||||||
|
TextXAlignment = Enum.TextXAlignment.Left,
|
||||||
|
Font = Enum.Font.GothamBold,
|
||||||
|
TextSize = 14,
|
||||||
|
TextColor3 = theme.Settings.Setting.DescriptionColor,
|
||||||
|
TextTruncate = Enum.TextTruncate.AtEnd,
|
||||||
|
}),
|
||||||
|
Separator = e("Frame", {
|
||||||
|
Size = UDim2.new(1, 0, 0, 1),
|
||||||
|
Position = UDim2.new(0, 0, 1, 0),
|
||||||
|
BackgroundTransparency = 0,
|
||||||
|
BorderSizePixel = 0,
|
||||||
|
BackgroundColor3 = theme.BorderedContainer.BorderColor,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
KeyValues = e(ScrollingFrame, {
|
||||||
|
position = UDim2.new(0, 1, 0, 25),
|
||||||
|
size = UDim2.new(1, -2, 1, -27),
|
||||||
|
scrollingDirection = Enum.ScrollingDirection.Y,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
}, {
|
||||||
|
Layout = e("UIListLayout", {
|
||||||
|
SortOrder = Enum.SortOrder.LayoutOrder,
|
||||||
|
VerticalAlignment = Enum.VerticalAlignment.Top,
|
||||||
|
}),
|
||||||
|
Lines = Roact.createFragment(lines),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return Dictionary
|
||||||
48
plugin/src/App/Components/TableDiffVisualizer/init.lua
Normal file
48
plugin/src/App/Components/TableDiffVisualizer/init.lua
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
local Rojo = script:FindFirstAncestor("Rojo")
|
||||||
|
local Plugin = Rojo.Plugin
|
||||||
|
local Packages = Rojo.Packages
|
||||||
|
|
||||||
|
local Roact = require(Packages.Roact)
|
||||||
|
|
||||||
|
local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
||||||
|
local Array = require(script:FindFirstChild("Array"))
|
||||||
|
local Dictionary = require(script:FindFirstChild("Dictionary"))
|
||||||
|
|
||||||
|
local e = Roact.createElement
|
||||||
|
|
||||||
|
local TableDiffVisualizer = Roact.Component:extend("TableDiffVisualizer")
|
||||||
|
|
||||||
|
function TableDiffVisualizer:render()
|
||||||
|
local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {}
|
||||||
|
|
||||||
|
-- Ensure we're diffing tables, not mixing types
|
||||||
|
if type(oldTable) ~= "table" then
|
||||||
|
oldTable = {}
|
||||||
|
end
|
||||||
|
if type(newTable) ~= "table" then
|
||||||
|
newTable = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
local isArray = next(newTable) == 1 or next(oldTable) == 1
|
||||||
|
|
||||||
|
return e(BorderedContainer, {
|
||||||
|
size = self.props.size,
|
||||||
|
position = self.props.position,
|
||||||
|
anchorPoint = self.props.anchorPoint,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
}, {
|
||||||
|
Content = if isArray
|
||||||
|
then e(Array, {
|
||||||
|
oldTable = oldTable,
|
||||||
|
newTable = newTable,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
})
|
||||||
|
else e(Dictionary, {
|
||||||
|
oldTable = oldTable,
|
||||||
|
newTable = newTable,
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
return TableDiffVisualizer
|
||||||
@@ -14,6 +14,7 @@ local StudioPluginGui = require(Plugin.App.Components.Studio.StudioPluginGui)
|
|||||||
local Tooltip = require(Plugin.App.Components.Tooltip)
|
local Tooltip = require(Plugin.App.Components.Tooltip)
|
||||||
local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer)
|
local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer)
|
||||||
local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer)
|
local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer)
|
||||||
|
local TableDiffVisualizer = require(Plugin.App.Components.TableDiffVisualizer)
|
||||||
|
|
||||||
local e = Roact.createElement
|
local e = Roact.createElement
|
||||||
|
|
||||||
@@ -24,9 +25,12 @@ function ConfirmingPage:init()
|
|||||||
self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0))
|
self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0))
|
||||||
|
|
||||||
self:setState({
|
self:setState({
|
||||||
showingSourceDiff = false,
|
showingStringDiff = false,
|
||||||
oldSource = "",
|
oldString = "",
|
||||||
newSource = "",
|
newString = "",
|
||||||
|
showingTableDiff = false,
|
||||||
|
oldTable = {},
|
||||||
|
newTable = {},
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -63,11 +67,18 @@ function ConfirmingPage:render()
|
|||||||
patch = self.props.confirmData.patch,
|
patch = self.props.confirmData.patch,
|
||||||
instanceMap = self.props.confirmData.instanceMap,
|
instanceMap = self.props.confirmData.instanceMap,
|
||||||
|
|
||||||
showSourceDiff = function(oldSource: string, newSource: string)
|
showStringDiff = function(oldString: string, newString: string)
|
||||||
self:setState({
|
self:setState({
|
||||||
showingSourceDiff = true,
|
showingStringDiff = true,
|
||||||
oldSource = oldSource,
|
oldString = oldString,
|
||||||
newSource = newSource,
|
newString = newString,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
showTableDiff = function(oldTable: { [any]: any? }, newTable: { [any]: any? })
|
||||||
|
self:setState({
|
||||||
|
showingTableDiff = true,
|
||||||
|
oldTable = oldTable,
|
||||||
|
newTable = newTable,
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
}),
|
}),
|
||||||
@@ -136,10 +147,10 @@ function ConfirmingPage:render()
|
|||||||
PaddingRight = UDim.new(0, 20),
|
PaddingRight = UDim.new(0, 20),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
SourceDiff = e(StudioPluginGui, {
|
StringDiff = e(StudioPluginGui, {
|
||||||
id = "Rojo_ConfirmingSourceDiff",
|
id = "Rojo_ConfirmingStringDiff",
|
||||||
title = "Source diff",
|
title = "String diff",
|
||||||
active = self.state.showingSourceDiff,
|
active = self.state.showingStringDiff,
|
||||||
isEphemeral = true,
|
isEphemeral = true,
|
||||||
|
|
||||||
initDockState = Enum.InitialDockState.Float,
|
initDockState = Enum.InitialDockState.Float,
|
||||||
@@ -151,7 +162,7 @@ function ConfirmingPage:render()
|
|||||||
|
|
||||||
onClose = function()
|
onClose = function()
|
||||||
self:setState({
|
self:setState({
|
||||||
showingSourceDiff = false,
|
showingStringDiff = false,
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
}, {
|
}, {
|
||||||
@@ -167,8 +178,46 @@ function ConfirmingPage:render()
|
|||||||
anchorPoint = Vector2.new(0, 0),
|
anchorPoint = Vector2.new(0, 0),
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
oldText = self.state.oldSource,
|
oldString = self.state.oldString,
|
||||||
newText = self.state.newSource,
|
newString = self.state.newString,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
|
||||||
|
TableDiff = e(StudioPluginGui, {
|
||||||
|
id = "Rojo_ConfirmingTableDiff",
|
||||||
|
title = "Table diff",
|
||||||
|
active = self.state.showingTableDiff,
|
||||||
|
isEphemeral = true,
|
||||||
|
|
||||||
|
initDockState = Enum.InitialDockState.Float,
|
||||||
|
overridePreviousState = true,
|
||||||
|
floatingSize = Vector2.new(500, 350),
|
||||||
|
minimumSize = Vector2.new(400, 250),
|
||||||
|
|
||||||
|
zIndexBehavior = Enum.ZIndexBehavior.Sibling,
|
||||||
|
|
||||||
|
onClose = function()
|
||||||
|
self:setState({
|
||||||
|
showingTableDiff = false,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
}, {
|
||||||
|
TooltipsProvider = e(Tooltip.Provider, nil, {
|
||||||
|
Tooltips = e(Tooltip.Container, nil),
|
||||||
|
Content = e("Frame", {
|
||||||
|
Size = UDim2.fromScale(1, 1),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
}, {
|
||||||
|
e(TableDiffVisualizer, {
|
||||||
|
size = UDim2.new(1, -10, 1, -10),
|
||||||
|
position = UDim2.new(0, 5, 0, 5),
|
||||||
|
anchorPoint = Vector2.new(0, 0),
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
|
oldTable = self.state.oldTable,
|
||||||
|
newTable = self.state.newTable,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ local BorderedContainer = require(Plugin.App.Components.BorderedContainer)
|
|||||||
local Tooltip = require(Plugin.App.Components.Tooltip)
|
local Tooltip = require(Plugin.App.Components.Tooltip)
|
||||||
local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer)
|
local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer)
|
||||||
local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer)
|
local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer)
|
||||||
|
local TableDiffVisualizer = require(Plugin.App.Components.TableDiffVisualizer)
|
||||||
|
|
||||||
local e = Roact.createElement
|
local e = Roact.createElement
|
||||||
|
|
||||||
@@ -97,7 +98,8 @@ function ChangesDrawer:render()
|
|||||||
|
|
||||||
patchTree = self.props.patchTree,
|
patchTree = self.props.patchTree,
|
||||||
|
|
||||||
showSourceDiff = self.props.showSourceDiff,
|
showStringDiff = self.props.showStringDiff,
|
||||||
|
showTableDiff = self.props.showTableDiff,
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
@@ -239,9 +241,9 @@ function ConnectedPage:init()
|
|||||||
self:setState({
|
self:setState({
|
||||||
renderChanges = false,
|
renderChanges = false,
|
||||||
hoveringChangeInfo = false,
|
hoveringChangeInfo = false,
|
||||||
showingSourceDiff = false,
|
showingStringDiff = false,
|
||||||
oldSource = "",
|
oldString = "",
|
||||||
newSource = "",
|
newString = "",
|
||||||
})
|
})
|
||||||
|
|
||||||
self.changeInfoText, self.setChangeInfoText = Roact.createBinding("")
|
self.changeInfoText, self.setChangeInfoText = Roact.createBinding("")
|
||||||
@@ -258,7 +260,7 @@ function ConnectedPage:didUpdate(previousProps)
|
|||||||
-- New patch recieved
|
-- New patch recieved
|
||||||
self:startChangeInfoTextUpdater()
|
self:startChangeInfoTextUpdater()
|
||||||
self:setState({
|
self:setState({
|
||||||
showingSourceDiff = false,
|
showingStringDiff = false,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -387,11 +389,18 @@ function ConnectedPage:render()
|
|||||||
height = self.changeDrawerHeight,
|
height = self.changeDrawerHeight,
|
||||||
layoutOrder = 5,
|
layoutOrder = 5,
|
||||||
|
|
||||||
showSourceDiff = function(oldSource: string, newSource: string)
|
showStringDiff = function(oldString: string, newString: string)
|
||||||
self:setState({
|
self:setState({
|
||||||
showingSourceDiff = true,
|
showingStringDiff = true,
|
||||||
oldSource = oldSource,
|
oldString = oldString,
|
||||||
newSource = newSource,
|
newString = newString,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
showTableDiff = function(oldTable: { [any]: any? }, newTable: { [any]: any? })
|
||||||
|
self:setState({
|
||||||
|
showingTableDiff = true,
|
||||||
|
oldTable = oldTable,
|
||||||
|
newTable = newTable,
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
|
|
||||||
@@ -403,10 +412,10 @@ function ConnectedPage:render()
|
|||||||
end,
|
end,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
SourceDiff = e(StudioPluginGui, {
|
StringDiff = e(StudioPluginGui, {
|
||||||
id = "Rojo_ConnectedSourceDiff",
|
id = "Rojo_ConnectedStringDiff",
|
||||||
title = "Source diff",
|
title = "String diff",
|
||||||
active = self.state.showingSourceDiff,
|
active = self.state.showingStringDiff,
|
||||||
isEphemeral = true,
|
isEphemeral = true,
|
||||||
|
|
||||||
initDockState = Enum.InitialDockState.Float,
|
initDockState = Enum.InitialDockState.Float,
|
||||||
@@ -418,7 +427,7 @@ function ConnectedPage:render()
|
|||||||
|
|
||||||
onClose = function()
|
onClose = function()
|
||||||
self:setState({
|
self:setState({
|
||||||
showingSourceDiff = false,
|
showingStringDiff = false,
|
||||||
})
|
})
|
||||||
end,
|
end,
|
||||||
}, {
|
}, {
|
||||||
@@ -434,8 +443,46 @@ function ConnectedPage:render()
|
|||||||
anchorPoint = Vector2.new(0, 0),
|
anchorPoint = Vector2.new(0, 0),
|
||||||
transparency = self.props.transparency,
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
oldText = self.state.oldSource,
|
oldString = self.state.oldString,
|
||||||
newText = self.state.newSource,
|
newString = self.state.newString,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
|
||||||
|
TableDiff = e(StudioPluginGui, {
|
||||||
|
id = "Rojo_ConnectedTableDiff",
|
||||||
|
title = "Table diff",
|
||||||
|
active = self.state.showingTableDiff,
|
||||||
|
isEphemeral = true,
|
||||||
|
|
||||||
|
initDockState = Enum.InitialDockState.Float,
|
||||||
|
overridePreviousState = false,
|
||||||
|
floatingSize = Vector2.new(500, 350),
|
||||||
|
minimumSize = Vector2.new(400, 250),
|
||||||
|
|
||||||
|
zIndexBehavior = Enum.ZIndexBehavior.Sibling,
|
||||||
|
|
||||||
|
onClose = function()
|
||||||
|
self:setState({
|
||||||
|
showingTableDiff = false,
|
||||||
|
})
|
||||||
|
end,
|
||||||
|
}, {
|
||||||
|
TooltipsProvider = e(Tooltip.Provider, nil, {
|
||||||
|
Tooltips = e(Tooltip.Container, nil),
|
||||||
|
Content = e("Frame", {
|
||||||
|
Size = UDim2.fromScale(1, 1),
|
||||||
|
BackgroundTransparency = 1,
|
||||||
|
}, {
|
||||||
|
e(TableDiffVisualizer, {
|
||||||
|
size = UDim2.new(1, -10, 1, -10),
|
||||||
|
position = UDim2.new(0, 5, 0, 5),
|
||||||
|
anchorPoint = Vector2.new(0, 0),
|
||||||
|
transparency = self.props.transparency,
|
||||||
|
|
||||||
|
oldTable = self.state.oldTable,
|
||||||
|
newTable = self.state.newTable,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user