From 0ca16103cb5e3bbb7c69a83544cf96aedeab8ff7 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 2 Jul 2022 20:45:29 -0700 Subject: [PATCH 1/8] Rough prototype of patch info display --- plugin/src/App/StatusPages/Connected.lua | 103 +++++++++++++++++------ plugin/src/App/init.lua | 39 +++++++++ plugin/src/ServeSession.lua | 13 +++ 3 files changed, 127 insertions(+), 28 deletions(-) diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 5793c6bae..5444e1f40 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -12,6 +12,26 @@ local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local e = Roact.createElement +local AGE_UNITS = { {31556909, "year"}, {2629743, "month"}, {604800, "week"}, {86400, "day"}, {3600, "hour"}, {60, "minute"}, } +function timeSinceText(elapsed: number): string + if elapsed < 3 then + return "just now" + end + + local ageText = string.format("%d seconds ago", elapsed) + + for _,UnitData in ipairs(AGE_UNITS) do + local UnitSeconds, UnitName = UnitData[1], UnitData[2] + if elapsed > UnitSeconds then + local c = math.floor(elapsed/UnitSeconds) + ageText = string.format("%d %s%s ago", c, UnitName, c>1 and "s" or "") + break + end + end + + return ageText +end + local function ConnectionDetails(props) return Theme.with(function(theme) return e(BorderedContainer, { @@ -82,33 +102,60 @@ end local ConnectedPage = Roact.Component:extend("ConnectedPage") function ConnectedPage:render() - return Roact.createFragment({ - Header = e(Header, { - transparency = self.props.transparency, - layoutOrder = 1, - }), - - ConnectionDetails = e(ConnectionDetails, { - projectName = self.state.projectName, - address = self.state.address, - transparency = self.props.transparency, - layoutOrder = 2, - - onDisconnect = self.props.onDisconnect, - }), - - Layout = e("UIListLayout", { - VerticalAlignment = Enum.VerticalAlignment.Center, - FillDirection = Enum.FillDirection.Vertical, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 10), - }), - - Padding = e("UIPadding", { - PaddingLeft = UDim.new(0, 20), - PaddingRight = UDim.new(0, 20), - }), - }) + return Theme.with(function(theme) + local patchInfo = self.props.patchInfo + + return Roact.createFragment({ + Header = e(Header, { + transparency = self.props.transparency, + layoutOrder = 1, + }), + + ConnectionDetails = e(ConnectionDetails, { + projectName = self.state.projectName, + address = self.state.address, + transparency = self.props.transparency, + layoutOrder = 2, + + onDisconnect = self.props.onDisconnect, + }), + + + Info = e("TextLabel", { + Text = string.format( + "Synced %d change%s %s", + patchInfo.updates, + patchInfo.updates == 1 and "" or "s", + timeSinceText(os.time() - patchInfo.timestamp) + ), + Font = Enum.Font.Gotham, + TextSize = 14, + TextWrapped = true, + RichText = true, + TextColor3 = theme.Header.VersionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextYAlignment = Enum.TextYAlignment.Top, + TextTransparency = self.props.transparency, + + Size = UDim2.new(1, 0, 0, 28), + + LayoutOrder = 3, + BackgroundTransparency = 1, + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), + }) + end) end function ConnectedPage.getDerivedStateFromProps(props) @@ -122,4 +169,4 @@ function ConnectedPage.getDerivedStateFromProps(props) } end -return ConnectedPage \ No newline at end of file +return ConnectedPage diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 9b4b60fb1..9e88d4002 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -48,6 +48,10 @@ function App:init() guiEnabled = false, notifications = {}, toolbarIcon = Assets.Images.PluginButton, + patchInfo = { + updates = 0, + timestamp = os.time(), + }, }) end @@ -104,6 +108,30 @@ function App:startSession() twoWaySync = sessionOptions.twoWaySync, }) + serveSession:onPatchApplied(function(patch, unapplied) + local count = 0 + + for _, set in patch do + for _ in set do + count += 1 + end + end + for _, set in unapplied do + for _ in set do + count -= 1 + end + end + + if count == 0 then return end + + self:setState({ + patchInfo = { + updates = count, + timestamp = os.time(), + }, + }) + end) + serveSession:onStatusChanged(function(status, details) if status == ServeSession.Status.Connecting then self:setState({ @@ -147,6 +175,16 @@ function App:startSession() serveSession:start() self.serveSession = serveSession + + task.defer(function() + while self.serveSession == serveSession do + -- Trigger rerender to update timestamp text + self:setState({ + patchInfo = table.clone(self.state.patchInfo), + }) + task.wait(3) + end + end) end function App:endSession() @@ -230,6 +268,7 @@ function App:render() Connected = createPageElement(AppStatus.Connected, { projectName = self.state.projectName, address = self.state.address, + patchInfo = self.state.patchInfo, onDisconnect = function() self:endSession() diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index f9a3bd9b4..30c5127db 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -94,6 +94,7 @@ function ServeSession.new(options) __instanceMap = instanceMap, __changeBatcher = changeBatcher, __statusChangedCallback = nil, + __patchAppliedCallback = nil, __connections = connections, } @@ -121,6 +122,10 @@ function ServeSession:onStatusChanged(callback) self.__statusChangedCallback = callback end +function ServeSession:onPatchApplied(callback) + self.__patchAppliedCallback = callback +end + function ServeSession:start() self:__setStatus(Status.Connecting) @@ -231,6 +236,10 @@ function ServeSession:__initialSync(rootInstanceId) Log.warn("Could not apply all changes requested by the Rojo server:\n{}", PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) end + + if self.__patchAppliedCallback then + pcall(self.__patchAppliedCallback, catchUpPatch, unappliedPatch) + end end) end @@ -244,6 +253,10 @@ function ServeSession:__mainSyncLoop() Log.warn("Could not apply all changes requested by the Rojo server:\n{}", PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) end + + if self.__patchAppliedCallback then + pcall(self.__patchAppliedCallback, message, unappliedPatch) + end end if self.__status ~= Status.Disconnected then From ff09a14970288d485f2f69716d6b19b2cb9d602f Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 2 Jul 2022 20:49:07 -0700 Subject: [PATCH 2/8] Remove extra newline --- plugin/src/App/StatusPages/Connected.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 5444e1f40..b23e50288 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -120,7 +120,6 @@ function ConnectedPage:render() onDisconnect = self.props.onDisconnect, }), - Info = e("TextLabel", { Text = string.format( "Synced %d change%s %s", From d4106acd216050ed42a745c5ca553ee4a509584f Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 2 Jul 2022 21:08:18 -0700 Subject: [PATCH 3/8] Switch to binding --- plugin/src/App/StatusPages/Connected.lua | 16 ++++++++-------- plugin/src/App/init.lua | 23 +++++++++-------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index b23e50288..108646098 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -103,8 +103,6 @@ local ConnectedPage = Roact.Component:extend("ConnectedPage") function ConnectedPage:render() return Theme.with(function(theme) - local patchInfo = self.props.patchInfo - return Roact.createFragment({ Header = e(Header, { transparency = self.props.transparency, @@ -121,12 +119,14 @@ function ConnectedPage:render() }), Info = e("TextLabel", { - Text = string.format( - "Synced %d change%s %s", - patchInfo.updates, - patchInfo.updates == 1 and "" or "s", - timeSinceText(os.time() - patchInfo.timestamp) - ), + Text = self.props.patchInfo:map(function(info) + return string.format( + "Synced %d change%s %s", + info.updates, + info.updates == 1 and "" or "s", + timeSinceText(os.time() - info.timestamp) + ) + end), Font = Enum.Font.Gotham, TextSize = 14, TextWrapped = true, diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 9e88d4002..3f38500b0 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -42,16 +42,16 @@ function App:init() self.host, self.setHost = Roact.createBinding("") self.port, self.setPort = Roact.createBinding("") + self.patchInfo, self.setPatchInfo = Roact.createBinding({ + updates = 0, + timestamp = os.time(), + }) self:setState({ appStatus = AppStatus.NotConnected, guiEnabled = false, notifications = {}, toolbarIcon = Assets.Images.PluginButton, - patchInfo = { - updates = 0, - timestamp = os.time(), - }, }) end @@ -123,12 +123,9 @@ function App:startSession() end if count == 0 then return end - - self:setState({ - patchInfo = { - updates = count, - timestamp = os.time(), - }, + self.setPatchInfo({ + updates = count, + timestamp = os.time(), }) end) @@ -179,9 +176,7 @@ function App:startSession() task.defer(function() while self.serveSession == serveSession do -- Trigger rerender to update timestamp text - self:setState({ - patchInfo = table.clone(self.state.patchInfo), - }) + self.setPatchInfo(table.clone(self.patchInfo:getValue())) task.wait(3) end end) @@ -268,7 +263,7 @@ function App:render() Connected = createPageElement(AppStatus.Connected, { projectName = self.state.projectName, address = self.state.address, - patchInfo = self.state.patchInfo, + patchInfo = self.patchInfo, onDisconnect = function() self:endSession() From 5d1077bf8579900b92d0df80a1e342045c6353aa Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 2 Jul 2022 21:20:23 -0700 Subject: [PATCH 4/8] Update slower for older timestamps --- plugin/src/App/init.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 3f38500b0..44854a4b3 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -176,8 +176,9 @@ function App:startSession() task.defer(function() while self.serveSession == serveSession do -- Trigger rerender to update timestamp text - self.setPatchInfo(table.clone(self.patchInfo:getValue())) - task.wait(3) + local patchInfo = table.clone(self.patchInfo:getValue()) + self.setPatchInfo(patchInfo) + task.wait((os.time() - patchInfo.timestamp) / 10) end end) end From df232075b25e5ee372c7ef63ae78602e7aed32bc Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sun, 3 Jul 2022 14:53:03 -0700 Subject: [PATCH 5/8] Batch patches within a second of each other --- plugin/src/App/init.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 44854a4b3..7bffba67e 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -109,6 +109,7 @@ function App:startSession() }) serveSession:onPatchApplied(function(patch, unapplied) + local now = os.time() local count = 0 for _, set in patch do @@ -123,9 +124,15 @@ function App:startSession() end if count == 0 then return end + + local old = self.patchInfo:getValue() + if now - old.timestamp < 2 then + count += old.updates + end + self.setPatchInfo({ updates = count, - timestamp = os.time(), + timestamp = now, }) end) From 367afa5eda78c9b065d63718750f936b94ca0760 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sun, 3 Jul 2022 22:17:53 -0700 Subject: [PATCH 6/8] Fix indentation --- plugin/src/App/init.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 7bffba67e..1622bb46d 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -127,8 +127,8 @@ function App:startSession() local old = self.patchInfo:getValue() if now - old.timestamp < 2 then - count += old.updates - end + count += old.updates + end self.setPatchInfo({ updates = count, From 8169d1848f075fbeb858dc9188730a36e1070c6a Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 4 Jul 2022 12:05:30 -0700 Subject: [PATCH 7/8] Less wasteful refresh hz --- plugin/src/App/init.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 1622bb46d..a813880fe 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -185,7 +185,8 @@ function App:startSession() -- Trigger rerender to update timestamp text local patchInfo = table.clone(self.patchInfo:getValue()) self.setPatchInfo(patchInfo) - task.wait((os.time() - patchInfo.timestamp) / 10) + local elapsed = os.time() - patchInfo.timestamp + task.wait(elapsed < 60 and 1 or elapsed/5) end end) end From b6017fafd9dfe2266a7e5528d04b9df92c135a9a Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 4 Jul 2022 12:12:02 -0700 Subject: [PATCH 8/8] More apt variable name --- plugin/src/App/StatusPages/Connected.lua | 4 ++-- plugin/src/App/init.lua | 14 +++++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 108646098..d055c5f26 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -122,8 +122,8 @@ function ConnectedPage:render() Text = self.props.patchInfo:map(function(info) return string.format( "Synced %d change%s %s", - info.updates, - info.updates == 1 and "" or "s", + info.changes, + info.changes == 1 and "" or "s", timeSinceText(os.time() - info.timestamp) ) end), diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index a813880fe..800039858 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -43,7 +43,7 @@ function App:init() self.host, self.setHost = Roact.createBinding("") self.port, self.setPort = Roact.createBinding("") self.patchInfo, self.setPatchInfo = Roact.createBinding({ - updates = 0, + changes = 0, timestamp = os.time(), }) @@ -110,28 +110,28 @@ function App:startSession() serveSession:onPatchApplied(function(patch, unapplied) local now = os.time() - local count = 0 + local changes = 0 for _, set in patch do for _ in set do - count += 1 + changes += 1 end end for _, set in unapplied do for _ in set do - count -= 1 + changes -= 1 end end - if count == 0 then return end + if changes == 0 then return end local old = self.patchInfo:getValue() if now - old.timestamp < 2 then - count += old.updates + changes += old.changes end self.setPatchInfo({ - updates = count, + changes = changes, timestamp = now, }) end)