╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────╮ │21 pub const Patches = @import("./Repo/Patches.zig"); │ │22 pub const Discussions = @import("./Repo/Discussions.zig");│ │23 pub const Comment = @import("./Repo/Comment.zig"); │ │24 +pub const Undo = @import("./Repo/Undo.zig"); │ │25 pub const Events = @import("./Repo/Events.zig"); │ │26 pub const Settings = @import("./Settings.zig"); │ │27 pub const Auth = @import("./Auth.zig"); │ ╰──────────────────────────────────────────────────────────────╯ ╭─────────────────────────────╮ │36 patches: Patches, │ │37 discussions: Discussions,│ │38 events: Events, │ │39 +undo: ?Undo = null, │ │40 settings: Settings, │ │41 auth: Auth, │ │42 quit: Quit, │ ╰─────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │256 │ │257 // open the repo once for every tab. files and changes share a ref or revision. │ │258 // no filesystem (wasm), nowhere to look, or a failed open: empty tabs. │ │259 + const undo_allowed = if (session.local) |local| local.repo_kind == .xit else session.userId() != null and evt.Repo.roleOf(repo, session.userId()).atLeast(.write);│ │260 + if (route == .repo_undo and !undo_allowed) return error.NotFound; │ │261 + // a server shows events to whoever it shows undo to, so the route follows │ │262 + if (route == .repo_events and session.data.host_kind != .local and !undo_allowed) return error.NotFound; │ │263 + const undo_index = if (route == .repo_undo) route.repo_undo.index else null; │ │264 + var undo_data: ?Undo = null; │ │265 const files, const changes, const refs, var issues, var patches, var discussions, const events = blk: { │ │266 read: { │ │267 const io = session.io orelse break :read; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │278 try evt.consume(.local, .repo, repo_kind, opened.self_repo_opts, io, gpa, opened, evt.events_ref, &.{}); │ │279 try pch.refreshBranches(.local, repo_kind, opened.self_repo_opts, io, gpa, opened, null, null); │ │280 } │ │281 + if (repo_kind == .xit and undo_allowed) undo_data = try Undo.init(opened.self_repo_opts, arena, opened, repo_identity.identity, undo_index);│ │282 const files_data = if (patchrev_id.len != 0) │ │283 try Files.initPatchRev(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, location, patchrev_id, files_dir, files_line) │ │284 else │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │315 try Events.empty(aa, repo_identity.identity, events_view, session.local != null, session.data.sync_failure),│ │316 }; │ │317 }; │ │318 + if (route == .repo_undo and undo_data == null) return error.NotFound; │ │319 issues.repo_source = source; │ │320 patches.repo_source = source; │ │321 patches.repo_id = repo_id_maybe; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────╮ │332 .patches = patches, │ │333 .discussions = discussions, │ │334 .events = events, │ │335 + .undo = undo_data, │ │336 .settings = Settings.init(),│ │337 .auth = Auth.init(), │ │338 .quit = Quit.init(), │ ╰─────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │409 try stack.children.put(allocator, discussions_view.getFocus().id, .{ .repo_discussions = discussions_view });│ │410 } │ │411 │ │401 - { │ │412 + if (session.data.host_kind == .local or data.undo != null) { │ │413 var events_view = try Events.View.init(allocator, &data.events, session); │ │414 errdefer events_view.deinit(allocator); │ │415 try stack.children.put(allocator, events_view.getFocus().id, .{ .repo_events = events_view }); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │416 } │ │417 │ │418 + if (data.undo) |*undo| { │ │419 + var undo_view = try Undo.View.init(allocator, undo, session); │ │420 + errdefer undo_view.deinit(allocator); │ │421 + try stack.children.put(allocator, undo_view.getFocus().id, .{ .repo_undo = undo_view });│ │422 + } │ │423 + │ │424 // the header only shows the settings tab with a login and the auth │ │425 // tab outside local mode, so keep the stack's children 1:1 with │ │426 // the tabs by skipping the same views. │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯