╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │87 }; │ │88 }, │ │89 .repo => switch (route) { │ │90 - .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_settings, .repo_auth => .{ .repo = try Repo.init(arena, session, route) }, │ │90 + .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo, .repo_settings, .repo_auth => .{ .repo = try Repo.init(arena, session, route) },│ │91 else => return error.UnexpectedRoute, │ │92 }, │ │93 .fork => switch (route) { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────╮ │168 comment: Array(evt.event_id_size * 2) = .{},│ │169 }, │ │170 repo_events: RepoEventsRoute, │ │171 + repo_undo: RepoUndoRoute, │ │172 repo_settings: Array(repo_route_max_len), │ │173 repo_auth: Array(repo_route_max_len), │ │174 fork_patch: ForkRoute, │ ╰─────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │395 }; │ │396 }; │ │397 │ │398 + pub const RepoUndoRoute = struct { │ │399 + name: Array(repo_identity_max_len), │ │400 + index: ?u64 = null, │ │401 + }; │ │402 + │ │403 + pub fn repoUndoRoute(identity: []const u8, index: ?u64) ?RoutablePage { │ │404 + return .{ .repo_undo = .{ .name = Array(repo_identity_max_len).from(identity) orelse return null, .index = index } };│ │405 + } │ │406 + │ │407 pub const RepoEventsRoute = struct { │ │408 name: Array(repo_identity_max_len), │ │409 view: EventsView = .active, │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1146 try out.writer.print("{s}/discussions/{s}", .{ prefix, @tagName(t.view) }); │ │1147 try writeListFilters(&out.writer, t.tag.slice(), t.search.slice()); │ │1148 break :blk out.written(); │ │1149 + }, │ │1150 + .repo_undo => |u| blk: { │ │1151 + const prefix = try repoUrlPrefix(arena, u.name.slice()); │ │1152 + break :blk if (u.index) |index| try std.fmt.allocPrint(arena.allocator(), "{s}/undo/{d}", .{ prefix, index }) else try std.fmt.allocPrint(arena.allocator(), "{s}/undo", .{prefix});│ │1153 }, │ │1154 .repo_events => |e| blk: { │ │1155 const prefix = try repoUrlPrefix(arena, e.name.slice()); │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────╮ │1316 .repo_patches => |*p| p.name.slice(), │ │1317 .repo_discussions => |*t| t.name.slice(), │ │1318 .repo_events => |*e| e.name.slice(), │ │1319 + .repo_undo => |*u| u.name.slice(), │ │1320 .repo_settings, .repo_auth => |*name| name.slice(),│ │1321 else => null, │ │1322 }; │ ╰─────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1358 return switch (self) { │ │1359 .home_users, .home_repos, .home_settings, .home_auth => .home, │ │1360 .user_repos, .user_forks, .user_settings, .user_auth => .user, │ │1346 - .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_settings, .repo_auth => .repo, │ │1361 + .repo_files, .repo_commits, .repo_diff, .repo_refs, .repo_issues, .repo_patches, .repo_discussions, .repo_events, .repo_undo, .repo_settings, .repo_auth => .repo,│ │1362 .fork_patch, .fork_diff, .fork_files, .fork_commits, .fork_settings, .fork_auth => .fork, │ │1363 }; │ │1364 } │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1544 if (std.mem.eql(u8, view, "new")) return if (tag_value.len == 0 and search_value.len == 0) repoThreadNewRoute(.discuss, pair) else null;│ │1545 return null; │ │1546 } │ │1547 + if (std.mem.eql(u8, tab, "undo")) { │ │1548 + const index = if (segments.next()) |word| std.fmt.parseInt(u64, word, 10) catch return null else null; │ │1549 + return if (segments.next() == null) repoUndoRoute(pair, index) else null; │ │1550 + } │ │1551 if (std.mem.eql(u8, tab, "events")) { │ │1552 const view = if (segments.next()) |word| │ │1553 std.meta.stringToEnum(EventsView, word) orelse return null │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1687 a_p.view == b.repo_patches.view and │ │1688 a_p.comments_start == b.repo_patches.comments_start and │ │1689 std.mem.eql(u8, a_p.comment.slice(), b.repo_patches.comment.slice()), │ │1690 + .repo_undo => |a_u| std.mem.eql(u8, a_u.name.slice(), b.repo_undo.name.slice()) and a_u.index == b.repo_undo.index,│ │1691 .repo_events => |a_e| std.mem.eql(u8, a_e.name.slice(), b.repo_events.name.slice()) and │ │1692 a_e.view == b.repo_events.view and │ │1693 a_e.kind == b.repo_events.kind and │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────╮ │2037 pub const HostRequest = union(enum) { │ │2038 show_copyable_text: []const u8, │ │2039 sync_events, │ │2040 + undo: RoutablePage.RepoUndoRoute, │ │2041 }; │ │2042 │ │2043 pub const FormFeedback = union(enum) {│ ╰────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │2313 terminal_live = true; │ │2314 term.setActive(&terminal); │ │2315 }, │ │2316 + .undo => |target| try Repo.Undo.perform(allocator, session, target),│ │2317 .sync_events => { │ │2318 try nav.root.build(allocator, .{ │ │2319 .min_size = .{ .width = null, .height = null }, │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯