Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Rojo breaking when users undo/redo in Studio #708

Merged
merged 11 commits into from
Jul 5, 2023
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
* Skip confirming patches that contain only a datamodel name change. ([#688])
* 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])

[#668]: https://github.com/rojo-rbx/rojo/pull/668
[#674]: https://github.com/rojo-rbx/rojo/pull/674
[#675]: https://github.com/rojo-rbx/rojo/pull/675
[#688]: https://github.com/rojo-rbx/rojo/pull/688
[#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

## [7.3.0] - April 22, 2023
* Added `$attributes` to project format. ([#574])
Expand Down Expand Up @@ -579,4 +581,4 @@ This is a general maintenance release for the Rojo 0.5.x release series.
* More robust syncing with a new reconciler

## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017)
* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs)
* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs)
105 changes: 95 additions & 10 deletions plugin/src/App/init.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
local ChangeHistoryService = game:GetService("ChangeHistoryService")
local Players = game:GetService("Players")
local ServerStorage = game:GetService("ServerStorage")
local RunService = game:GetService("RunService")
Expand Down Expand Up @@ -57,6 +58,64 @@ function App:init()
self.confirmationEvent = self.confirmationBindable.Event
self.notifId = 0

self.waypointConnection = ChangeHistoryService.OnUndo:Connect(function(action: string)
if not string.find(action, "^Rojo: Patch") then
return
end

local undoConnection, redoConnection = nil, nil
local function cleanup()
undoConnection:Disconnect()
redoConnection:Disconnect()
end

Log.warn(
string.format(
"You've undone '%s'.\nIf this was not intended, please Redo in the topbar or with Ctrl/⌘+Y.",
action
)
)
local dismissNotif = self:addNotification(
string.format("You've undone '%s'.\nIf this was not intended, please restore.", action),
10,
{
Restore = {
text = "Restore",
style = "Solid",
layoutOrder = 1,
onClick = function(notification)
cleanup()
notification:dismiss()
ChangeHistoryService:Redo()
end,
},
Dismiss = {
text = "Dismiss",
style = "Bordered",
layoutOrder = 2,
onClick = function(notification)
cleanup()
notification:dismiss()
end,
},
}
)

undoConnection = ChangeHistoryService.OnUndo:Once(function()
-- Our notif is now out of date- redoing will not restore the patch
-- since we've undone even further. Dismiss the notif.
cleanup()
dismissNotif()
end)
redoConnection = ChangeHistoryService.OnRedo:Once(function(redoneAction: string)
if redoneAction == action then
-- The user has restored the patch, so we can dismiss the notif
cleanup()
dismissNotif()
end
end)
end)

self:setState({
appStatus = AppStatus.NotConnected,
guiEnabled = false,
Expand All @@ -83,7 +142,7 @@ function App:init()
onClick = function(notification)
notification:dismiss()
self:startSession()
end
end,
},
Dismiss = {
text = "Dismiss",
Expand All @@ -97,7 +156,16 @@ function App:init()
end
end

function App:addNotification(text: string, timeout: number?, actions: { [string]: {text: string, style: string, layoutOrder: number, onClick: (any) -> ()} }?)
function App:willUnmount()
self.waypointConnection:Disconnect()
self.confirmationBindable:Destroy()
end

function App:addNotification(
text: string,
timeout: number?,
actions: { [string]: { text: string, style: string, layoutOrder: number, onClick: (any) -> () } }?
)
if not Settings:get("showNotifications") then
return
end
Expand All @@ -123,6 +191,10 @@ function App:addNotification(text: string, timeout: number?, actions: { [string]
end

function App:closeNotification(id: number)
if not self.state.notifications[id] then
return
end

local notifications = table.clone(self.state.notifications)
notifications[id] = nil

Expand All @@ -133,26 +205,38 @@ end

function App:getPriorEndpoint()
local priorEndpoints = Settings:get("priorEndpoints")
if not priorEndpoints then return end
if not priorEndpoints then
return
end

local id = tostring(game.PlaceId)
if ignorePlaceIds[id] then return end
if ignorePlaceIds[id] then
return
end

local place = priorEndpoints[id]
if not place then return end
if not place then
return
end

return place.host, place.port
end

function App:getLastSyncTimestamp()
local priorEndpoints = Settings:get("priorEndpoints")
if not priorEndpoints then return end
if not priorEndpoints then
return
end

local id = tostring(game.PlaceId)
if ignorePlaceIds[id] then return end
if ignorePlaceIds[id] then
return
end

local place = priorEndpoints[id]
if not place then return end
if not place then
return
end

return place.timestamp
end
Expand All @@ -172,7 +256,9 @@ function App:setPriorEndpoint(host: string, port: string)
end

local id = tostring(game.PlaceId)
if ignorePlaceIds[id] then return end
if ignorePlaceIds[id] then
return
end

priorEndpoints[id] = {
host = if host ~= Config.defaultHost then host else nil,
Expand All @@ -181,7 +267,6 @@ function App:setPriorEndpoint(host: string, port: string)
}
Log.trace("Saved last used endpoint for {}", game.PlaceId)


Settings:set("priorEndpoints", priorEndpoints)
end

Expand Down
6 changes: 6 additions & 0 deletions plugin/src/Reconciler/applyPatch.lua
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
Patches can come from the server or be generated by the client.
]]

local ChangeHistoryService = game:GetService("ChangeHistoryService")

local Packages = script.Parent.Parent.Parent.Packages
local Log = require(Packages.Log)

Expand All @@ -17,6 +19,8 @@ local reify = require(script.Parent.reify)
local setProperty = require(script.Parent.setProperty)

local function applyPatch(instanceMap, patch)
local patchTimestamp = DateTime.now():FormatLocalTime("LTS", "en-us")

-- Tracks any portions of the patch that could not be applied to the DOM.
local unappliedPatch = PatchSet.newEmpty()

Expand Down Expand Up @@ -199,6 +203,8 @@ local function applyPatch(instanceMap, patch)
end
end

ChangeHistoryService:SetWaypoint("Rojo: Patch " .. patchTimestamp)

return unappliedPatch
end

Expand Down