╭ changed ─────────────╮ │src/ui/Repo/Issues.zig│ ╰──────────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭──────────────────────────────────────────╮ │1 const std = @import("std"); │ │2 +const builtin = @import("builtin"); │ │3 const evt = @import("../../event.zig");│ │4 const ui = @import("../../ui.zig"); │ │5 const xit = @import("xit"); │ ╰──────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────╮ │12 const Grid = xitui.grid.Grid; │ │13 const Focus = xitui.focus.Focus; │ │14 const inp = @import("../input.zig"); │ │15 + │ │16 +const wasm = builtin.target.cpu.arch == .wasm32; │ │17 │ │18 // how many issues one window shows before a "next" link appears.│ │19 pub const page_size = 20; │ ╰─────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────╮ │56 view: ui.RoutablePage.IssuesView, │ │57 // every tag in the repo, in sorted order, for the tags view. │ │58 tags: []const []const u8, │ │59 +// the on-disk repo this page was read from, for the terminal submit path│ │60 +// (the web posts the new-issue form to the issue route instead). │ │61 +repo_source: ?ui.RepoSource = null, │ │62 │ │63 const Self = @This(); │ │64 │ ╰─────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────╮ │84 } │ │85 │ │86 // read one window per status of an opened repo's issues (filtered to `tag` │ │81 -// when set), ordered by creation time (oldest first). the window of the issue│ │87 +// when set), ordered by creation time (newest first). the window of the issue│ │88 // `selected_id` names starts at it ("" = the beginning). a local session │ │89 // reads the event db next to the repo (synced from the events branch on each │ │90 // page build); a server repo reads its own db. │ ╰──────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │162 const issue_cursor = try event_id_to_issue.getCursor(hash.hashInt(repo_opts.hash, &id_bytes)) orelse return error.NotFound;│ │163 const issue_map = try DB.HashMap(.read_only).init(issue_cursor); │ │164 const issue_event = try evt.read(evt.Issue, DB, repo_opts.hash, arena, issue_map); │ │159 - const order_key = try aa.dupe(u8, &evt.orderKey(issue_event.created_ts, &id_bytes)); │ │165 + const order_key = try aa.dupe(u8, &evt.orderKeyDesc(issue_event.created_ts, &id_bytes)); │ │166 │ │167 // the named issue must be in its windowed set (a tag url can name an │ │168 // issue that doesn't carry the tag). │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────╮ │274 } else try set.iteratorFromIndex(0); │ │275 │ │276 // collect this window's issues, plus a peek at the one after it (its id is│ │271 - // the next window's start). the set's keys are orderKey │ │272 - // ([timestamp][event-id]); the trailing bytes of each key are the issue │ │273 - // event id. │ │277 + // the next window's start). the trailing bytes of each set key are the │ │278 + // issue event id. │ │279 var issues: std.ArrayList(IssueWithId) = .empty; │ │280 var next_id: ?[]const u8 = null; │ │281 while (try iter.next()) |id_cursor_val| { │ ╰────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────╮ │322 const open_view_index: usize = 0; │ │323 const closed_view_index: usize = 1; │ │324 const tags_view_index: usize = 2; │ │325 + const new_view_index: usize = 3; │ │326 const split_count: usize = 2; │ │327 // indices within a split (the horizontal box inside the stack).│ │328 const list_index: usize = 0; │ ╰─────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────╮ │329 const detail_index: usize = 1; │ │330 const list_max_width: usize = 40; │ │331 const detail_min_width: usize = 40; │ │332 + // indices within the new-issue form. │ │333 + const title_field_index: usize = 0; │ │334 + const tags_field_index: usize = 1; │ │335 + const description_field_index: usize = 2; │ │336 + const submit_field_index: usize = 3; │ │337 │ │338 fn viewIndex(view: ui.RoutablePage.IssuesView) usize {│ │339 return switch (view) { │ ╰───────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────╮ │340 .open => open_view_index, │ │341 .closed => closed_view_index,│ │342 .tags => tags_view_index, │ │343 + .new => new_view_index, │ │344 }; │ │345 } │ │346 │ ╰──────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │390 try stack.children.put(allocator, tf.getFocus().id, .{ .tag_flow = tf });│ │391 } │ │392 │ │393 + // the new-issue form │ │394 + { │ │395 + var form = try initNewForm(allocator, session, data); │ │396 + errdefer form.deinit(allocator); │ │397 + try stack.children.put(allocator, form.getFocus().id, .{ .box = form }); │ │398 + } │ │399 + │ │400 // the stack starts on the page's view. │ │401 stack.getFocus().child_id = stack.children.keys()[viewIndex(data.view)]; │ │402 │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯