╭ changed ──────────────╮ │src/ui/Repo/Threads.zig│ ╰───────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────────────╮ │369 detailed_index: [view_count]?usize, │ │370 description_id: [view_count]?usize, │ │371 author_id: [view_count]?usize, │ │372 - primary_button_id: [view_count]?usize,│ │372 │ │373 const header_index: usize = 0; │ │374 const stack_index: usize = 1; │ ╰───────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────╮ │388 const detail_index: usize = 1; │ │389 const list_max_width: usize = 40; │ │390 const detail_min_width: usize = 40; │ │392 - // indices within the issue form. │ │391 + // indices within the thread form. │ │392 const title_field_index: usize = 0; │ │393 const tags_field_index: usize = 1; │ │394 const description_field_index: usize = 2;│ ╰──────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │411 } │ │412 │ │413 // the status a status split lists; the conflicts split has none (its│ │415 - // issues carry their own). │ │414 + // threads carry their own). │ │415 fn splitStatus(index: usize) Status { │ │416 return @enumFromInt(index); │ │417 } │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────╮ │428 return if (has_drafts) entry.draft else false; │ │429 } │ │430 │ │432 - fn statusAction(status: Status) ?[]const u8 { │ │433 - const name = @tagName(status); │ │434 - if (std.mem.eql(u8, name, "open")) return "close"; │ │435 - if (std.mem.eql(u8, name, "closed")) return "open"; │ │436 - return null; │ │437 - } │ │431 + const StatusChange = struct { │ │432 + action: []const u8, │ │433 + status: Status, │ │434 + }; │ │435 │ │439 - fn toggledStatus(status: Status) ?Status { │ │436 + fn statusChange(status: Status) ?StatusChange { │ │437 const name = @tagName(status); │ │441 - if (std.mem.eql(u8, name, "open")) return std.meta.stringToEnum(Status, "closed");│ │442 - if (std.mem.eql(u8, name, "closed")) return std.meta.stringToEnum(Status, "open");│ │438 + if (std.mem.eql(u8, name, "open")) return .{ │ │439 + .action = "close", │ │440 + .status = std.meta.stringToEnum(Status, "closed") orelse return null, │ │441 + }; │ │442 + if (std.mem.eql(u8, name, "closed")) return .{ │ │443 + .action = "open", │ │444 + .status = std.meta.stringToEnum(Status, "open") orelse return null, │ │445 + }; │ │446 return null; │ │447 } │ │448 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │453 .discuss => ui.RoutablePage.repoDiscussionsRoute(identity, tag, selected), │ │454 else => @compileError("unsupported thread event kind"), │ │455 }; │ │453 - } │ │454 - │ │455 - fn commentsRoute(identity: []const u8, selected: []const u8, start: usize) ?ui.RoutablePage { │ │456 - return ui.RoutablePage.repoThreadCommentsRoute(kind, identity, selected, start); │ │457 - } │ │458 - │ │459 - fn commentRoute(identity: []const u8, thread_id: []const u8, comment_id: []const u8, start: usize) ?ui.RoutablePage {│ │460 - return ui.RoutablePage.repoThreadCommentRoute(kind, identity, thread_id, comment_id, start); │ │461 - } │ │462 - │ │463 - fn newCommentRoute(identity: []const u8, thread_id: []const u8, parent_id: []const u8) ?ui.RoutablePage { │ │464 - return ui.RoutablePage.repoThreadCommentNewRoute(kind, identity, thread_id, parent_id); │ │465 - } │ │466 - │ │467 - fn editCommentRoute(identity: []const u8, thread_id: []const u8, comment_id: []const u8) ?ui.RoutablePage { │ │468 - return ui.RoutablePage.repoThreadCommentEditRoute(kind, identity, thread_id, comment_id); │ │469 - } │ │470 - │ │471 - fn removeRoute(identity: []const u8, thread_id: []const u8, comment_id: []const u8) ?ui.RoutablePage { │ │472 - return ui.RoutablePage.repoThreadRemoveRoute(kind, identity, thread_id, comment_id); │ │473 - } │ │474 - │ │475 - fn editRoute(identity: []const u8, selected: []const u8) ?ui.RoutablePage { │ │476 - return ui.RoutablePage.repoThreadEditRoute(kind, identity, selected); │ │477 - } │ │478 - │ │479 - fn newRoute(identity: []const u8) ?ui.RoutablePage { │ │480 - return ui.RoutablePage.repoThreadNewRoute(kind, identity); │ │456 } │ │457 │ │458 fn draftsRoute(identity: []const u8) ?ui.RoutablePage { │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │460 .patch => ui.RoutablePage.repoPatchesDraftsRoute(identity), │ │461 else => null, │ │462 }; │ │488 - } │ │489 - │ │490 - fn descriptionRoute(identity: []const u8, selected: []const u8) ?ui.RoutablePage {│ │491 - return ui.RoutablePage.repoThreadDescriptionRoute(kind, identity, selected); │ │492 - } │ │493 - │ │494 - fn tagsRoute(identity: []const u8, tag: []const u8) ?ui.RoutablePage { │ │495 - return ui.RoutablePage.repoThreadTagsRoute(kind, identity, tag); │ │463 } │ │464 │ │465 fn conflictsRoute(identity: []const u8, selected: []const u8) ?ui.RoutablePage { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │498 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.toUrl(page_arena)}); │ │499 } │ │500 return listLink(page_arena, data.identity, status_maybe orelse @enumFromInt(0), data.tag, id); │ │534 - } │ │535 - │ │536 - fn descriptionLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, id: []const u8) ![]const u8 { │ │537 - const route = descriptionRoute(identity, id) orelse return error.RouteTooLong; │ │538 - return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.toUrl(page_arena)}); │ │501 } │ │502 │ │503 fn tagLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, status: Status, tag: []const u8) ![]const u8 {│ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────╮ │551 try stack.children.put(allocator, tf.getFocus().id, .{ .tag_flow = tf }); │ │552 } │ │553 │ │592 - // the new-issue form, or — on an edit, comment, or resolve url — that form in │ │593 - // its place, prefilled with the selected issue's content. a │ │554 + // the new-thread form, or — on an edit, comment, or resolve url — that form in│ │555 + // its place, prefilled with the selected thread's content. a │ │556 // logged-out session can't create events, so the unauthorized view │ │557 // stands in. │ │558 if (session.data.is_local or session.data.user_id != null) { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │559 if (data.view == .remove) { │ │560 const aa = session.page_arena.allocator(); │ │599 - const route = removeRoute(data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong; │ │561 + const route = ui.RoutablePage.repoThreadRemoveRoute(kind, data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong;│ │562 const action = try std.fmt.allocPrint(aa, "form:{s}", .{try route.toUrl(session.page_arena)}); │ │563 const event_name = if (data.comment_id.len == 0) thread_name else "comment"; │ │564 var label_buf: ["remove ".len + @max(thread_name.len, "comment".len)]u8 = undefined; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │569 } else if (data.view == .new_comment or data.view == .edit_comment) { │ │570 const editing = data.view == .edit_comment; │ │571 const route = if (editing) │ │610 - editCommentRoute(data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong │ │572 + ui.RoutablePage.repoThreadCommentEditRoute(kind, data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong│ │573 else │ │612 - newCommentRoute(data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong; │ │574 + ui.RoutablePage.repoThreadCommentNewRoute(kind, data.identity, data.selected_id, data.comment_id) orelse return error.RouteTooLong;│ │575 const page_url = try route.toUrl(session.page_arena); │ │576 const action = try std.fmt.allocPrint(session.page_arena.allocator(), "form:{s}", .{page_url}); │ │577 const page = data.comment_page; │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯