╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────╮ │← previous│ ╰──────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1244 // and reloading keep the label and the query │ │1245 if (t.selected.len != 0) { │ │1246 try out.writer.print("{s}/" ++ discuss_seg ++ "{s}", .{ prefix, t.selected.slice() }); │ │1229 - try writeListFilters(&out.writer, t.label.slice(), t.search.slice()); │ │1247 + try writeListFilters(&out.writer, t.label.slice(), "", t.search.slice()); │ │1248 if (t.comments_start != 0) try out.writer.print("/" ++ start_seg ++ "{d}", .{t.comments_start});│ │1249 break :blk out.written(); │ │1250 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────╮ │1251 try out.writer.print("{s}/discussions/{s}", .{ prefix, @tagName(t.view) });│ │1234 - try writeListFilters(&out.writer, t.label.slice(), t.search.slice()); │ │1252 + try writeListFilters(&out.writer, t.label.slice(), "", t.search.slice()); │ │1253 break :blk out.written(); │ │1254 }, │ │1255 .repo_undo => |u| blk: { │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1578 } │ │1579 return null; │ │1580 } │ │1563 - if (!params.only(&.{ .start, .label, .search })) return null; │ │1564 - return withEncodedFilters(repoThreadCommentsRoute(.issue, pair, issue_id, params.start() orelse return null), params.values.get(.label) orelse "", params.values.get(.search) orelse ""); │ │1581 + if (!params.only(&.{ .start, .label, .assignee, .search })) return null; │ │1582 + return withEncodedAssignee(withEncodedFilters(repoThreadCommentsRoute(.issue, pair, issue_id, params.start() orelse return null), params.values.get(.label) orelse "", params.values.get(.search) orelse ""), params.values.get(.assignee) orelse "");│ │1583 } │ │1584 if (std.mem.startsWith(u8, tab, patch_seg)) { │ │1585 const patch_id = tab[patch_seg.len..]; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1660 if (!params.only(&.{.start})) return null; │ │1661 return repoIssuesConflictsRoute(pair, params.values.get(.start) orelse ""); │ │1662 } │ │1645 - if (!params.only(&.{ .label, .search })) return null; │ │1663 + if (!params.only(&.{ .label, .assignee, .search })) return null; │ │1664 const search_value = params.values.get(.search) orelse ""; │ │1647 - if (std.meta.stringToEnum(evt.Issue.Status, w)) |status| return withEncodedSearch(repoIssuesRoute(pair, status, label_value, ""), search_value); │ │1648 - if (std.mem.eql(u8, w, "labels")) return withEncodedSearch(repoThreadLabelsRoute(.issue, pair, label_value), search_value); │ │1649 - if (std.mem.eql(u8, w, "new")) return if (label_value.len == 0 and search_value.len == 0) repoThreadNewRoute(.issue, pair) else null; │ │1665 + const assignee_value = params.values.get(.assignee) orelse ""; │ │1666 + if (std.meta.stringToEnum(evt.Issue.Status, w)) |status| return withEncodedAssignee(withEncodedSearch(repoIssuesRoute(pair, status, label_value, ""), search_value), assignee_value);│ │1667 + if (std.mem.eql(u8, w, "labels")) return withEncodedAssignee(withEncodedSearch(repoThreadLabelsRoute(.issue, pair, label_value), search_value), assignee_value); │ │1668 + if (std.mem.eql(u8, w, "new")) return if (label_value.len == 0 and assignee_value.len == 0 and search_value.len == 0) repoThreadNewRoute(.issue, pair) else null; │ │1669 return null; │ │1670 } │ │1671 if (std.mem.eql(u8, tab, "patches")) { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1819 .repo_refs => |a_r| std.mem.eql(u8, a_r.name.slice(), b.repo_refs.name.slice()) and a_r.kind == b.repo_refs.kind and std.mem.eql(u8, a_r.from.slice(), b.repo_refs.from.slice()) and std.mem.eql(u8, a_r.search.slice(), b.repo_refs.search.slice()),│ │1820 .repo_issues => |a_i| std.mem.eql(u8, a_i.name.slice(), b.repo_issues.name.slice()) and │ │1821 std.mem.eql(u8, a_i.label.slice(), b.repo_issues.label.slice()) and │ │1822 + std.mem.eql(u8, a_i.assignee.slice(), b.repo_issues.assignee.slice()) and │ │1823 std.mem.eql(u8, a_i.search.slice(), b.repo_issues.search.slice()) and │ │1824 std.mem.eql(u8, a_i.selected.slice(), b.repo_issues.selected.slice()) and │ │1825 std.mem.eql(u8, a_i.theirs.slice(), b.repo_issues.theirs.slice()) and │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │2810 return if (data.host_kind == .local) RoutablePage.fromUrlLocal(path) else RoutablePage.fromUrl(path);│ │2811 } │ │2812 │ │2813 +// an assignee as the detail view shows it: the stored email, and the name of │ │2814 +// the user holding it on this instance when there is one │ │2815 +pub const Assignee = struct { │ │2816 + email: []const u8, │ │2817 + name: ?[]const u8 = null, │ │2818 + │ │2819 + pub fn display(self: Assignee) []const u8 { │ │2820 + return self.name orelse self.email; │ │2821 + } │ │2822 +}; │ │2823 + │ │2824 // a display author, resolved against the admin db at read time │ │2825 pub const Author = union(enum) { │ │2826 unknown, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────╯