diff --git a/CHANGELOG.md b/CHANGELOG.md
index 373eef77..17c7d27c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,7 @@
* Added sync reminder notification. ([#689])
* Added protection against syncing a model to a place. ([#691])
* Fix Rojo breaking when users undo/redo in Studio ([#708])
+* Improved sync info text on Connected page. ([#692])
[#668]: https://github.com/rojo-rbx/rojo/pull/668
[#674]: https://github.com/rojo-rbx/rojo/pull/674
@@ -16,6 +17,8 @@
[#689]: https://github.com/rojo-rbx/rojo/pull/689
[#691]: https://github.com/rojo-rbx/rojo/pull/691
[#708]: https://github.com/rojo-rbx/rojo/pull/708
+[#692]: https://github.com/rojo-rbx/rojo/pull/692
+
## [7.3.0] - April 22, 2023
* Added `$attributes` to project format. ([#574])
diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua
index af43e6a2..ac152ef1 100644
--- a/plugin/src/App/StatusPages/Connected.lua
+++ b/plugin/src/App/StatusPages/Connected.lua
@@ -170,9 +170,56 @@ function ConnectedPage:getChangeInfoText()
end
local elapsed = os.time() - patchData.timestamp
- local changes = PatchSet.countChanges(patchData.patch)
+ local unapplied = PatchSet.countChanges(patchData.unapplied)
- return string.format("Synced %d change%s %s", changes, changes == 1 and "" or "s", timeSinceText(elapsed))
+ return
+ "Synced "
+ .. timeSinceText(elapsed)
+ .. (if unapplied > 0 then
+ string.format(
+ ", but %d change%s failed to apply",
+ unapplied,
+ unapplied == 1 and "" or "s"
+ )
+ else "")
+ .. ""
+end
+
+function ConnectedPage:startChangeInfoTextUpdater()
+ -- Cancel any existing updater
+ self:stopChangeInfoTextUpdater()
+
+ -- Start a new updater
+ self.changeInfoTextUpdater = task.defer(function()
+ while true do
+ if self.state.hoveringChangeInfo then
+ self.setChangeInfoText("" .. self:getChangeInfoText() .. "")
+ else
+ self.setChangeInfoText(self:getChangeInfoText())
+ end
+
+ local elapsed = os.time() - self.props.patchData.timestamp
+ local updateInterval = 1
+
+ -- Update timestamp text as frequently as currently needed
+ for _, UnitData in ipairs(AGE_UNITS) do
+ local UnitSeconds = UnitData[1]
+ if elapsed > UnitSeconds then
+ updateInterval = UnitSeconds
+ break
+ end
+ end
+
+ task.wait(updateInterval)
+ end
+ end)
+end
+
+function ConnectedPage:stopChangeInfoTextUpdater()
+ if self.changeInfoTextUpdater then
+ task.cancel(self.changeInfoTextUpdater)
+ self.changeInfoTextUpdater = nil
+ end
end
function ConnectedPage:init()
@@ -195,34 +242,21 @@ function ConnectedPage:init()
self:setState({
renderChanges = false,
+ hoveringChangeInfo = false,
})
self.changeInfoText, self.setChangeInfoText = Roact.createBinding("")
- self.changeInfoTextUpdater = task.defer(function()
- while true do
- self.setChangeInfoText(self:getChangeInfoText())
-
- local elapsed = os.time() - self.props.patchData.timestamp
- local updateInterval = 1
-
- -- Update timestamp text as frequently as currently needed
- for _, UnitData in ipairs(AGE_UNITS) do
- local UnitSeconds = UnitData[1]
- if elapsed >= UnitSeconds then
- updateInterval = UnitSeconds
- break
- end
- end
-
- task.wait(updateInterval)
- end
- end)
+ self:startChangeInfoTextUpdater()
end
function ConnectedPage:willUnmount()
- if self.changeInfoTextUpdater then
- task.cancel(self.changeInfoTextUpdater)
+ self:stopChangeInfoTextUpdater()
+end
+
+function ConnectedPage:didUpdate(previousProps)
+ if self.props.patchData.timestamp ~= previousProps.patchData.timestamp then
+ self:startChangeInfoTextUpdater()
end
end
@@ -271,6 +305,20 @@ function ConnectedPage:render()
LayoutOrder = 3,
BackgroundTransparency = 1,
+ [Roact.Event.MouseEnter] = function()
+ self:setState({
+ hoveringChangeInfo = true,
+ })
+ self.setChangeInfoText("" .. self:getChangeInfoText() .. "")
+ end,
+
+ [Roact.Event.MouseLeave] = function()
+ self:setState({
+ hoveringChangeInfo = false,
+ })
+ self.setChangeInfoText(self:getChangeInfoText())
+ end,
+
[Roact.Event.Activated] = function()
if self.state.renderChanges then
self.changeDrawerMotor:setGoal(Flipper.Spring.new(0, {
@@ -284,6 +332,10 @@ function ConnectedPage:render()
}))
end
end,
+ }, {
+ Tooltip = e(Tooltip.Trigger, {
+ text = if self.state.renderChanges then "Hide the changes" else "View the changes",
+ }),
}),
ChangesDrawer = e(ChangesDrawer, {
diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua
index c7be7671..762f2bbd 100644
--- a/plugin/src/App/init.lua
+++ b/plugin/src/App/init.lua
@@ -122,6 +122,7 @@ function App:init()
confirmData = {},
patchData = {
patch = PatchSet.newEmpty(),
+ unapplied = PatchSet.newEmpty(),
timestamp = os.time(),
},
notifications = {},
@@ -357,35 +358,36 @@ function App:startSession()
twoWaySync = sessionOptions.twoWaySync,
})
- serveSession:onPatchApplied(function(patch, _unapplied)
+ serveSession:onPatchApplied(function(patch, unapplied)
+ local now = os.time()
+ local old = self.state.patchData
+
if PatchSet.isEmpty(patch) then
- -- Ignore empty patches
+ -- Ignore empty patch, but update timestamp
+ self:setState({
+ patchData = {
+ patch = old.patch,
+ unapplied = old.unapplied,
+ timestamp = now,
+ },
+ })
return
end
- local now = os.time()
-
- local old = self.state.patchData
if now - old.timestamp < 2 then
-- Patches that apply in the same second are
-- considered to be part of the same change for human clarity
- local merged = PatchSet.newEmpty()
- PatchSet.assign(merged, old.patch, patch)
-
- self:setState({
- patchData = {
- patch = merged,
- timestamp = now,
- },
- })
- else
- self:setState({
- patchData = {
- patch = patch,
- timestamp = now,
- },
- })
+ patch = PatchSet.assign(PatchSet.newEmpty(), old.patch, patch)
+ unapplied = PatchSet.assign(PatchSet.newEmpty(), old.unapplied, unapplied)
end
+
+ self:setState({
+ patchData = {
+ patch = patch,
+ unapplied = unapplied,
+ timestamp = now,
+ },
+ })
end)
serveSession:onStatusChanged(function(status, details)
@@ -409,6 +411,13 @@ function App:startSession()
elseif status == ServeSession.Status.Disconnected then
self.serveSession = nil
self:releaseSyncLock()
+ self:setState({
+ patchData = {
+ patch = PatchSet.newEmpty(),
+ unapplied = PatchSet.newEmpty(),
+ timestamp = os.time(),
+ },
+ })
-- Details being present indicates that this
-- disconnection was from an error.
diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua
index c9f621dc..a9bebd80 100644
--- a/plugin/src/PatchSet.lua
+++ b/plugin/src/PatchSet.lua
@@ -212,13 +212,24 @@ function PatchSet.countChanges(patch)
local count = 0
for _ in patch.added do
+ -- Adding an instance is 1 change
count += 1
end
for _ in patch.removed do
+ -- Removing an instance is 1 change
count += 1
end
- for _ in patch.updated do
- count += 1
+ for _, update in patch.updated do
+ -- Updating an instance is 1 change per property updated
+ for _ in update.changedProperties do
+ count += 1
+ end
+ if update.changedName ~= nil then
+ count += 1
+ end
+ if update.changedClassName ~= nil then
+ count += 1
+ end
end
return count