Fix the diff visualizer of connected sessions (#674)

Clicking on the "X changes X ago" message opens up a handy diff
visualizer to see what those changes were. However, it had quite a few
issues that needed fixing.

- Disconnecting a session with it expanded caused an error as it tried
to read the serveSession that no longer exists during the page fade
transition. (#671)
- Resolved by converting to stateful component and holding the
serveSession during the lifetime to ensure it can render the last known
changes during the fade transition
- Leaving it open while new changes are synced did not update the
visualizer
- The patch data was piggybacking on an existing binding, which meant
that new patches did not trigger rerender.
    - Resolved by converting to state
    - Also made some improvements to that old binding
- Moved from app to connected page for better organization and
separation of duties
      - No more useless updates causing rerenders with no real change
- Scroll window child component wouldn't actually display the updated
visuals
    - Resolved by making major improvements to VirtualScroller
      - Made more robust against edge case states
      - Made smarter about knowing when it needs to refresh

As you can see in this slow motion GIF, it works now.

![slowedDemo](https://github.com/rojo-rbx/rojo/assets/40185666/c9fc8489-72a9-47be-ae45-9c420e1535d4)
This commit is contained in:
boatbomber
2023-06-04 01:46:16 -04:00
committed by GitHub
parent 6b0f7f94b6
commit 6542304340
4 changed files with 98 additions and 56 deletions

View File

@@ -51,10 +51,6 @@ function App:init()
self.host, self.setHost = Roact.createBinding(priorHost or "")
self.port, self.setPort = Roact.createBinding(priorPort or "")
self.patchInfo, self.setPatchInfo = Roact.createBinding({
patch = PatchSet.newEmpty(),
timestamp = os.time(),
})
self.confirmationBindable = Instance.new("BindableEvent")
self.confirmationEvent = self.confirmationBindable.Event
@@ -62,6 +58,10 @@ function App:init()
appStatus = AppStatus.NotConnected,
guiEnabled = false,
confirmData = {},
patchData = {
patch = PatchSet.newEmpty(),
timestamp = os.time(),
},
notifications = {},
toolbarIcon = Assets.Images.PluginButton,
})
@@ -227,21 +227,25 @@ function App:startSession()
local now = os.time()
local old = self.patchInfo:getValue()
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.setPatchInfo({
patch = merged,
timestamp = now,
self:setState({
patchData = {
patch = merged,
timestamp = now,
},
})
else
self.setPatchInfo({
patch = patch,
timestamp = now,
self:setState({
patchData = {
patch = patch,
timestamp = now,
},
})
end
end)
@@ -318,16 +322,6 @@ function App:startSession()
serveSession:start()
self.serveSession = serveSession
task.defer(function()
while self.serveSession == serveSession do
-- Trigger rerender to update timestamp text
local patchInfo = table.clone(self.patchInfo:getValue())
self.setPatchInfo(patchInfo)
local elapsed = os.time() - patchInfo.timestamp
task.wait(elapsed < 60 and 1 or elapsed / 5)
end
end)
end
function App:endSession()
@@ -429,7 +423,7 @@ function App:render()
Connected = createPageElement(AppStatus.Connected, {
projectName = self.state.projectName,
address = self.state.address,
patchInfo = self.patchInfo,
patchData = self.state.patchData,
serveSession = self.serveSession,
onDisconnect = function()