╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ────────╮ │src/ui/widget.zig│ ╰─────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1809 }); │ │1810 errdefer text_input.deinit(allocator); │ │1811 text_input.getFocus().mode = .all; │ │1812 - try text_input.setContent(allocator, choices[0].text); │ │1812 + try text_input.setContent(allocator, choices[initial].text); │ │1813 box.getFocus().child_id = text_input.getFocus().id; │ │1814 try box.children.put(allocator, text_input.getFocus().id, .{ .widget = .{ .text_input = text_input }, .rect = null, .min_size = null, .flex = .shrink });│ │1815 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1816 - return .{ .box = box, .session = session, .choices = owned_choices }; │ │1816 + return .{ .box = box, .session = session, .choices = owned_choices, .selected = initial }; │ │1817 } │ │1818 │ │1819 - pub fn initClone(allocator: std.mem.Allocator, session: *ui.Session, location: ui.RoutablePage.RepoLocation) !?CopyableText {│ │1819 + pub fn initClone(allocator: std.mem.Allocator, session: *ui.Session, handle: ui.RepoHandle) !?CopyableText { │ │1820 const aa = session.page_arena.allocator(); │ │1821 var choices: [2]Choice = undefined; │ │1822 var count: usize = 0; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1823 - switch (location) { │ │1823 + var ssh_index: ?usize = null; │ │1824 + switch (handle.location) { │ │1825 .repo => |identity| { │ │1826 if (session.data.git_http_port) |port| { │ │1827 const url = try std.fmt.allocPrint(aa, "http://localhost:{d}/repo/{s}", .{ port, identity });│ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1834 count += 1; │ │1835 } │ │1836 if (session.data.git_ssh_port) |port| { │ │1837 + ssh_index = count; │ │1838 const url = try std.fmt.allocPrint(aa, "ssh://localhost:{d}/repo/{s}", .{ port, identity });│ │1839 choices[count] = .{ │ │1840 .selector = "ssh", │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────╮ │1856 }, │ │1857 } │ │1858 if (count == 0) return null; │ │1857 - return @as(?CopyableText, try init(allocator, session, choices[0..count])); │ │1859 + // a viewer who can push starts on the ssh url │ │1860 + const initial = if (handle.canWrite()) ssh_index orelse 0 else 0; │ │1861 + return @as(?CopyableText, try init(allocator, session, choices[0..count], initial));│ │1862 } │ │1863 │ │1864 pub fn minWidth(self: *const CopyableText) usize { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │236 comments_start: usize, │ │237 // the search the set is narrowed to, or null to list it whole │ │238 query: ?[]const u8, │ │239 - viewer: ?Comment.Viewer, │ │239 + viewer: ?ui.Viewer, │ │240 ) !Data.Window { │ │241 if (query) |text| return loadSearchWindow(Data, kind, hash_kind, arena, admin_moment, haxy_moment, records, set_maybe, root_key, conflict_set, selected_id, comments_start, text, viewer);│ │242 const set = set_maybe orelse return .empty; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────╮ │299 selected_id: []const u8, │ │300 comments_start: usize, │ │301 query_text: []const u8, │ │302 - viewer: ?Comment.Viewer, │ │302 + viewer: ?ui.Viewer, │ │303 ) !Data.Window { │ │304 const set = set_maybe orelse return .empty;│ │305 const DB = evt.EventDB(hash_kind); │ ╰────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────╮ │378 conflict_set: ?evt.EventDB(hash_kind).SortedSet(.read_only),│ │379 selected_id: []const u8, │ │380 comments_start: usize, │ │381 - viewer: ?Comment.Viewer, │ │381 + viewer: ?ui.Viewer, │ │382 ) !?Data.Entry { │ │383 const DB = evt.EventDB(hash_kind); │ │384 const aa = arena.allocator(); │ ╰─────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │806 errdefer back.deinit(allocator); │ │807 try inner_box.children.put(allocator, back.getFocus().id, .{ .widget = .{ .text_box = back }, .rect = null, .min_size = null }); │ │808 │ │809 - try Comment.appendComment(allocator, inner_box, self.session, self.data.identity, kind, self.data.can_reply, comment_view.selected); │ │809 + try Comment.appendComment(allocator, inner_box, self.session, self.data.identity, kind, self.data.viewer != null, comment_view.selected); │ │810 try Comment.appendCount(allocator, inner_box, comment_view.replies.count, "reply", "replies"); │ │811 - for (comment_view.replies.comments) |comment| try Comment.appendComment(allocator, inner_box, self.session, self.data.identity, kind, self.data.can_reply, comment); │ │811 + for (comment_view.replies.comments) |comment| try Comment.appendComment(allocator, inner_box, self.session, self.data.identity, kind, self.data.viewer != null, comment); │ │812 try Comment.appendWindowNav(allocator, inner_box, self.session, self.data.identity, kind, &comment_view.selected.comment.event.thread_id, &comment_view.selected.id, comment_view.replies);│ │813 │ │814 var spacer = try Spacer.init(allocator); │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │885 try Attachment.appendRows(allocator, inner_box, self.session, self.data.identity, try parent_route.toUrl(self.session.page_arena), entry.attachments); │ │886 │ │887 if (!description_page) { │ │888 - if (self.data.can_reply) { │ │888 + if (self.data.viewer != null) { │ │889 var reply = try Comment.linkBox(allocator, self.session, "new comment", ui.RoutablePage.repoThreadCommentNewRoute(kind, self.data.identity, entry.id, "") orelse return error.RouteTooLong);│ │890 errdefer reply.deinit(allocator); │ │891 try inner_box.children.put(allocator, reply.getFocus().id, .{ .widget = .{ .text_box = reply }, .rect = null, .min_size = null }); │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯