╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ──────╮ │src/ui/Repo.zig│ ╰───────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │362 changes_data, │ │363 try Refs.init(repo_kind, opened.self_repo_opts, arena, opened, io, gpa, repo_identity.identity, refs_kind, refs_from, refs_search), │ │364 try Discussions.init(repo_kind, opened.self_repo_opts, arena, opened, io, session.haxy_moment, repo_identity.identity, discussions_label, discussions_search, discussions_selected, discussions_comment, discussions_comments_start, discussions_view, tabViewer(handle, repo, .discuss)), │ │361 - try Issues.init(repo_kind, opened.self_repo_opts, arena, opened, io, session.haxy_moment, repo_identity.identity, issues_label, issues_search, issues_selected, issues_comment, issues_comments_start, issues_theirs, issues_view, tabViewer(handle, repo, .issue)), │ │365 + try Issues.init(repo_kind, opened.self_repo_opts, arena, opened, io, session.haxy_moment, repo_identity.identity, issues_label, issues_assignee, issues_search, issues_selected, issues_comment, issues_comments_start, issues_theirs, issues_view, tabViewer(handle, repo, .issue)), │ │366 try Patches.init(repo_kind, opened.self_repo_opts, arena, opened, io, session.haxy_moment, session, repo_id_maybe, repo_identity.identity, target_branch, patches_label, patches_search, patches_selected, patches_comment, patches_comments_start, patches_theirs, patches_view, tabViewer(handle, repo, .patch)),│ │367 try Events.init(repo_kind, opened.self_repo_opts, arena, opened, io, session.haxy_moment, repo_identity.identity, repo.event, events_view, events_kind, events_selected, events_moment, session.local != null, session.data.sync_failure), │ │368 }; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │377 Changes{ .commits = try Commits.emptyResult(aa, handle, requested_ref_or_oid orelse .branch, requested_ref_value, commits_base_oid) }, │ │378 try Refs.emptyResult(arena, repo_identity.identity, refs_kind, refs_from, refs_search), │ │379 try Discussions.emptyResult(aa, repo_identity.identity, discussions_label, discussions_search, discussions_selected, discussions_comment, discussions_comments_start, discussions_view),│ │376 - try Issues.emptyResult(aa, repo_identity.identity, issues_label, issues_search, issues_selected, issues_comment, issues_comments_start, issues_theirs, issues_view), │ │380 + try Issues.emptyResult(aa, repo_identity.identity, issues_label, issues_assignee, issues_search, issues_selected, issues_comment, issues_comments_start, issues_theirs, issues_view), │ │381 try Patches.emptyResult(aa, repo_identity.identity, patches_label, patches_search, patches_selected, patches_comment, patches_comments_start, patches_theirs, patches_view), │ │382 try Events.empty(aa, repo_identity.identity, events_view, session.local != null, session.data.sync_failure), │ │383 }; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ──────────────────╮ │src/ui/Repo/Discussions.zig│ ╰───────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │25 author: ui.Author = .unknown, │ │26 comments: Comment.Window = .empty, │ │27 attachments: []const Attachment.WithId = &.{}, │ │28 - assignees: []const []const u8 = &.{}, │ │28 + assignees: []const ui.Assignee = &.{}, │ │29 // whether the viewer may change the thread, computed here so the web ui has it│ │30 can_modify: bool = false, │ │31 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │174 } │ │175 │ │176 const discussion_comments_start = if (empty.comment_id.len == 0) comments_start else 0; │ │177 - const loaded_window = try thread.loadWindow(Self, .discuss, repo_opts.hash, arena, admin_moment, haxy_moment, records, set_maybe, root_key, null, empty.selected_id, discussion_comments_start, empty.search, viewer); │ │177 + const loaded_window = try thread.loadWindow(Self, .discuss, repo_opts.hash, arena, admin_moment, haxy_moment, records, set_maybe, root_key, null, empty.selected_id, discussion_comments_start, empty.search, null, viewer);│ │178 const comment_page = if (empty.comment_id.len == 0) │ │179 null │ │180 else │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────╮ │223 │ │224 // tabs switching between the discussions page's views │ │225 pub fn initHeader(allocator: std.mem.Allocator, session: *ui.Session, data: *const Self) !Header {│ │226 - var header = try Header.init(allocator, session, data.search); │ │226 + var header = try Header.init(allocator, session, data.search, null); │ │227 errdefer header.deinit(allocator); │ │228 const selected_index = View.viewIndex(data.view); │ │229 const page_selected = std.meta.activeTag(session.data.current_page) == .repo_discussions; │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────╮ │29 conflicted: bool = false, │ │30 comments: Comment.Window = .empty, │ │31 attachments: []const Attachment.WithId = &.{}, │ │32 - assignees: []const []const u8 = &.{}, │ │32 + assignees: []const ui.Assignee = &.{}, │ │33 // whether the viewer may change the thread, computed here so the web ui has it│ │34 can_modify: bool = false, │ │35 }; │ ╰───────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────╮ │80 identity: []const u8, │ │81 // the url-encoded label the lists are filtered to ("" = unfiltered). │ │82 label: []const u8, │ │83 +// the url-encoded name or email the lists are filtered to, as typed ("" = unfiltered).│ │84 +assignee: []const u8, │ │85 +// false when the assignee names no user or no assigned issue, which lists nothing │ │86 +assignee_found: bool = true, │ │87 // the decoded query the lists are filtered to, or null when unfiltered. │ │88 search: ?[]const u8 = null, │ │89 // the hex event id of the issue its status's window is rooted at ("" = the │ ╰───────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │171 } │ │172 │ │173 // an empty listing, for the wasm / no-repo paths. │ │170 -pub fn emptyResult(aa: std.mem.Allocator, identity: []const u8, label: []const u8, search: []const u8, selected_id: []const u8, comment_id: []const u8, comments_start: usize, theirs_picks: []const u8, view: ui.RoutablePage.IssuesView) !Self { │ │174 +pub fn emptyResult(aa: std.mem.Allocator, identity: []const u8, label: []const u8, assignee: []const u8, search: []const u8, selected_id: []const u8, comment_id: []const u8, comments_start: usize, theirs_picks: []const u8, view: ui.RoutablePage.IssuesView) !Self {│ │175 return .{ │ │176 .identity = try aa.dupe(u8, identity), │ │177 .label = try aa.dupe(u8, label), │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │178 + .assignee = try aa.dupe(u8, assignee), │ │179 .search = if (search.len == 0) null else std.Uri.percentDecodeInPlace(try aa.dupe(u8, search)),│ │180 .selected_id = try aa.dupe(u8, selected_id), │ │181 .comment_id = try aa.dupe(u8, comment_id), │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │197 } │ │198 │ │199 // read one window per status of an opened repo's issues (filtered to `label` │ │195 -// when set), ordered by creation (newest first). the window of the issue │ │196 -// `selected_id` names starts at it ("" = the beginning). a git repo reads the │ │200 +// and `assignee` when set), ordered by creation (newest first). the window of │ │201 +// the issue `selected_id` names starts at it ("" = the beginning). a git repo reads the│ │202 // event db next to it (synced from the events branch on each page build); a │ │203 // xit repo reads its own db. │ │204 pub fn init( │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯