╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │154 }, │ │155 repo_issues: struct { │ │156 name: Array(repo_route_max_len), │ │157 - // the label the list is filtered to, url-encoded ("" = unfiltered). │ │158 - label: Array(issue_label_route_max_len) = .{}, │ │159 - // the assignee the list is filtered to, a url-encoded name or email as│ │160 - // typed ("" = unfiltered). │ │161 - assignee: Array(assignee_route_max_len) = .{}, │ │157 // the query the list is filtered to, url-encoded ("" = unfiltered). │ │158 search: Array(search_route_max_len) = .{}, │ │159 // the issue the route names: the list's window root, or the issue the │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────╮ │172 }, │ │173 repo_patches: struct { │ │174 name: Array(repo_route_max_len), │ │180 - label: Array(patch_label_route_max_len) = .{},│ │175 search: Array(search_route_max_len) = .{}, │ │176 selected: Array(evt.event_id_size * 2) = .{}, │ │177 theirs: Array(theirs_route_max_len) = .{}, │ ╰───────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────╮ │181 }, │ │182 repo_discussions: struct { │ │183 name: Array(repo_route_max_len), │ │190 - label: Array(discussion_label_route_max_len) = .{},│ │184 search: Array(search_route_max_len) = .{}, │ │185 selected: Array(evt.event_id_size * 2) = .{}, │ │186 view: DiscussionsView = .recent, │ ╰────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │231 │ │232 // the "key:value" segments of a url tail, collected in any order │ │233 const Params = struct { │ │241 - const ParamKey = enum { start, line, branch, tag, label, assignee, object, base, patchrev, theirs, find, search, from, moment, merge, user };│ │234 + const ParamKey = enum { start, line, branch, tag, object, base, patchrev, theirs, find, search, from, moment, merge, user }; │ │235 │ │236 // a branch:/tag:/object: param; the value stays url-encoded │ │237 const RefParam = struct { kind: RefOrOid, value: []const u8 }; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────╮ │316 // ends a commits route naming its commit's full message │ │317 const message_seg = "message"; │ │318 // the `Params` key spellings the url emitters use │ │326 - const label_filter_seg = @tagName(Params.ParamKey.label) ++ ":";│ │327 - const assignee_seg = @tagName(Params.ParamKey.assignee) ++ ":"; │ │319 const start_seg = @tagName(Params.ParamKey.start) ++ ":"; │ │320 const line_seg = @tagName(Params.ParamKey.line) ++ ":"; │ │321 const find_seg = @tagName(Params.ParamKey.find) ++ ":"; │ ╰─────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────╮ │345 fn identityElided(s: []const u8) bool { │ │346 return s.len == 0 or s[0] == '/'; │ │347 } │ │357 - │ │358 - // a url-encoded label can grow to three bytes per source byte. │ │359 - pub const issue_label_route_max_len = evt.Issue.label_max_len * 3; │ │360 - pub const patch_label_route_max_len = evt.Patch.label_max_len * 3; │ │361 - pub const discussion_label_route_max_len = evt.Discussion.label_max_len * 3;│ │348 │ │363 - // a url-encoded email can grow to three bytes per source byte. │ │364 - pub const assignee_route_max_len = evt.Assignment.email_max_len * 3; │ │365 - │ │349 // caps the resolve view's theirs: field list (a longer one doesn't route). │ │350 pub const theirs_route_max_len = 512; │ │351 │ ╰─────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │355 // caps the files tab's url-encoded search term. │ │356 pub const find_route_max_len = 100 * 3; │ │357 │ │375 - // caps the commits tab's url-encoded search query. │ │376 - pub const search_route_max_len = 100 * 3; │ │358 + // caps a url-encoded search query, room enough for an email assignee term.│ │359 + pub const search_route_max_len = 512 * 3; │ │360 │ │361 // the identity stored by every repo route. Local routes elide it. │ │362 pub const RepoIdentity = struct { │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │667 pub fn withSearch(self: RoutablePage, query: []const u8) ?RoutablePage { │ │668 const search = encodeParam(search_route_max_len, query) orelse return null; │ │669 return withEncodedSearch(self, search.slice()); │ │687 - } │ │688 - │ │689 - // the label, assignee and search segments of a thread list url, each optional │ │690 - fn writeListFilters(writer: *std.Io.Writer, label: []const u8, assignee: []const u8, search: []const u8) !void { │ │691 - if (label.len != 0) try writer.print("/" ++ label_filter_seg ++ "{s}", .{label}); │ │692 - if (assignee.len != 0) try writer.print("/" ++ assignee_seg ++ "{s}", .{assignee}); │ │693 - if (search.len != 0) try writer.print("/" ++ search_seg ++ "{s}", .{search}); │ │694 - } │ │695 - │ │696 - // carry the already-encoded list filters a selected thread's url names │ │697 - fn withEncodedFilters(self: ?RoutablePage, label: []const u8, search: []const u8) ?RoutablePage { │ │698 - var route = withEncodedSearch(self, search) orelse return null; │ │699 - switch (route) { │ │700 - inline .repo_issues, .repo_patches, .repo_discussions => |*thread| thread.label = @TypeOf(thread.label).from(label) orelse return null,│ │701 - else => return null, │ │702 - } │ │703 - return route; │ │704 - } │ │705 - │ │706 - // carry an already-encoded assignee filter on an issues route │ │707 - pub fn withEncodedAssignee(self: ?RoutablePage, value: []const u8) ?RoutablePage { │ │708 - var route = self orelse return null; │ │709 - switch (route) { │ │710 - .repo_issues => |*i| i.assignee = Array(assignee_route_max_len).from(value) orelse return null, │ │711 - else => return null, │ │712 - } │ │713 - return route; │ │670 } │ │671 │ │672 // carry an already-encoded search param, as a url hands it over │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │792 } │ │793 │ │794 // build a `.repo_issues` route for "owner:name" (identity) showing │ │839 - // `status`'s list, filtered to the url-encoded `label` ("" = unfiltered) and │ │840 - // rooted at the issue with hex event id `selected` ("" = the first window). │ │841 - pub fn repoIssuesRoute(identity: []const u8, status: evt.Issue.Status, label: []const u8, selected: []const u8) ?RoutablePage {│ │795 + // `status`'s list, rooted at the issue with hex event id `selected` ("" = │ │796 + // the first window). │ │797 + pub fn repoIssuesRoute(identity: []const u8, status: evt.Issue.Status, selected: []const u8) ?RoutablePage { │ │798 return .{ .repo_issues = .{ │ │799 .name = Array(repo_route_max_len).from(identity) orelse return null, │ │844 - .label = Array(issue_label_route_max_len).from(label) orelse return null, │ │800 .selected = Array(evt.event_id_size * 2).from(selected) orelse return null, │ │801 .view = switch (status) { │ │802 .open => .open, │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │805 } }; │ │806 } │ │807 │ │853 - pub fn repoPatchesRoute(identity: []const u8, status: evt.Patch.StatusKind, label: []const u8, selected: []const u8) ?RoutablePage {│ │808 + pub fn repoPatchesRoute(identity: []const u8, status: evt.Patch.StatusKind, selected: []const u8) ?RoutablePage { │ │809 return .{ .repo_patches = .{ │ │810 .name = Array(repo_route_max_len).from(identity) orelse return null, │ │856 - .label = Array(patch_label_route_max_len).from(label) orelse return null, │ │811 .selected = Array(evt.event_id_size * 2).from(selected) orelse return null, │ │812 .view = switch (status) { │ │813 .open => .open, │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯