╭──────────╮ │← previous│ ╰──────────╯ ╭ changed ───────────────╮ │src/ui/widget/thread.zig│ ╰────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │1424 const This = @This(); │ │1425 // a vertical box: the header tabs on top, then a stack holding a │ │1426 // master-detail split (thread list + description pane) per status list, │ │1427 - // plus the tags view. │ │1427 + // plus the labels view. │ │1428 box: wgt.Box(Widget), // vert: [header_index] = tabs, [stack_index] = stack│ │1429 data: *const Self, │ │1430 session: *ui.Session, │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────╮ │1433 const stack_index: usize = 1; │ │1434 // indices within the stack, 1:1 with the header tabs. │ │1435 const status_count = @typeInfo(Status).@"enum".fields.len; │ │1436 - const tags_view_index: usize = status_count; │ │1436 + const labels_view_index: usize = status_count; │ │1437 // the new-thread form, or the edit, comment, or resolve form when the page was│ │1438 // loaded at one of their urls. │ │1439 - const form_view_index: usize = tags_view_index + 1; │ │1439 + const form_view_index: usize = labels_view_index + 1; │ │1440 // the conflicts split; the tab and stack child exist only when the repo │ │1441 // has conflicted threads. │ │1442 const drafts_view_index: usize = form_view_index + 1; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1450 │ │1451 pub fn viewIndex(view: ViewKind) usize { │ │1452 const name = @tagName(view); │ │1453 - if (std.mem.eql(u8, name, "tags")) return tags_view_index; │ │1453 + if (std.mem.eql(u8, name, "labels")) return labels_view_index; │ │1454 if (std.mem.eql(u8, name, "new") or std.mem.eql(u8, name, "edit") or std.mem.eql(u8, name, "publish") or std.mem.eql(u8, name, "merge") or std.mem.eql(u8, name, "new_comment") or std.mem.eql(u8, name, "edit_comment") or std.mem.eql(u8, name, "remove") or std.mem.eql(u8, name, "resolve")) return form_view_index;│ │1455 if (std.mem.eql(u8, name, "conflicts")) return conflict_view_index; │ │1456 if (std.mem.eql(u8, name, "drafts")) return drafts_view_index; │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1489 return if (supports_drafts) entry.draft else false; │ │1490 } │ │1491 │ │1492 - fn listRoute(identity: []const u8, status: Status, tag: []const u8, selected: []const u8) ?ui.RoutablePage { │ │1493 - return Data.listRoute(identity, status, tag, selected); │ │1492 + fn listRoute(identity: []const u8, status: Status, label: []const u8, selected: []const u8) ?ui.RoutablePage {│ │1493 + return Data.listRoute(identity, status, label, selected); │ │1494 } │ │1495 │ │1496 fn draftsRoute(identity: []const u8) ?ui.RoutablePage { │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1513 return if (supports_conflicts) Data.resolveRoute(identity, selected, picks) else null; │ │1514 } │ │1515 │ │1516 - // a list link keeps the filters the page carries: the tag, and the │ │1516 + // a list link keeps the filters the page carries: the label, and the │ │1517 // search query when one is set │ │1518 - fn listLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, status: Status, tag: []const u8, id: []const u8, search: []const u8) ![]const u8 { │ │1519 - var route = listRoute(identity, status, tag, id) orelse return error.RouteTooLong; │ │1518 + fn listLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, status: Status, label: []const u8, id: []const u8, search: []const u8) ![]const u8 {│ │1519 + var route = listRoute(identity, status, label, id) orelse return error.RouteTooLong; │ │1520 if (search.len != 0) route = route.withSearch(search) orelse return error.RouteTooLong; │ │1521 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.toUrl(page_arena)}); │ │1522 } │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1544 const route = draftsRoute(data.identity) orelse return error.RouteTooLong; │ │1545 return std.fmt.allocPrint(page_arena.allocator(), "a:{s}", .{try route.toUrl(page_arena)}); │ │1546 } │ │1547 - return listLink(page_arena, data.identity, status_maybe orelse @enumFromInt(0), data.tag, id, data.search orelse ""); │ │1547 + return listLink(page_arena, data.identity, status_maybe orelse @enumFromInt(0), data.label, id, data.search orelse ""); │ │1548 } │ │1549 │ │1550 - fn tagLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, status: Status, tag: []const u8, search: []const u8) ![]const u8 { │ │1551 - const encoded = try ui.urlEncodeRef(page_arena.allocator(), tag); │ │1550 + fn labelLink(page_arena: *std.heap.ArenaAllocator, identity: []const u8, status: Status, label: []const u8, search: []const u8) ![]const u8 {│ │1551 + const encoded = try ui.urlEncodeRef(page_arena.allocator(), label); │ │1552 return listLink(page_arena, identity, status, encoded, "", search); │ │1553 } │ │1554 │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1578 try stack.children.put(allocator, split.getFocus().id, .{ .box = split }); │ │1579 } │ │1580 │ │1581 - // the tags view │ │1581 + // the labels view │ │1582 { │ │1583 - var tf = try TagFlow.init(allocator); │ │1583 + var tf = try WordFlow.init(allocator); │ │1584 errdefer tf.deinit(allocator); │ │1585 - var items: std.ArrayList(TagFlow.Item) = .empty; │ │1585 + var items: std.ArrayList(WordFlow.Item) = .empty; │ │1586 defer items.deinit(allocator); │ │1587 // when filtered, the first item clears the filter │ │1588 - if (data.tag.len != 0) │ │1588 + if (data.label.len != 0) │ │1589 try items.append(allocator, .{ .text = "✕", .link = try listLink(session.page_arena, data.identity, @enumFromInt(0), "", "", data.search orelse "") }); │ │1590 - for (data.tags) |tag| │ │1591 - try items.append(allocator, .{ .text = tag, .link = try tagLink(session.page_arena, data.identity, @enumFromInt(0), tag, data.search orelse "") }); │ │1590 + for (data.labels) |label| │ │1591 + try items.append(allocator, .{ .text = label, .link = try labelLink(session.page_arena, data.identity, @enumFromInt(0), label, data.search orelse "") });│ │1592 try tf.setItems(allocator, items.items); │ │1593 - try stack.children.put(allocator, tf.getFocus().id, .{ .tag_flow = tf }); │ │1593 + try stack.children.put(allocator, tf.getFocus().id, .{ .word_flow = tf }); │ │1594 } │ │1595 │ │1596 // the new-thread form, or — on an edit, comment, or resolve url — that form in │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1812 } │ │1813 │ │1814 { │ │1815 - var tags = try wgt.TextInput.init(allocator, .{ .label = " tags (separate with spaces) ", .name = "tags", .visible_width = null, .rounded_corners = true, .render_content = session.is_terminal }); │ │1816 - errdefer tags.deinit(allocator); │ │1817 - tags.getFocus().mode = .all; │ │1815 + var labels = try wgt.TextInput.init(allocator, .{ .label = " labels (separate with spaces) ", .name = "labels", .visible_width = null, .rounded_corners = true, .render_content = session.is_terminal });│ │1816 + errdefer labels.deinit(allocator); │ │1817 + labels.getFocus().mode = .all; │ │1818 if (saved_fields) |saved| │ │1819 - try tags.setContent(allocator, saved.tags) │ │1819 + try labels.setContent(allocator, saved.labels) │ │1820 else if (record) |r| │ │1821 - try tags.setContent(allocator, r.event.tags); │ │1822 - try box.children.put(allocator, tags.getFocus().id, .{ .widget = .{ .text_input = tags }, .rect = null, .min_size = .{ .width = null, .height = 3 } }); │ │1821 + try labels.setContent(allocator, r.event.labels); │ │1822 + try box.children.put(allocator, labels.getFocus().id, .{ .widget = .{ .text_input = labels }, .rect = null, .min_size = .{ .width = null, .height = 3 } }); │ │1823 } │ │1824 │ │1825 { │ ╰───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────╮ │1949 try addLabel(allocator, &box, "title conflict:"); │ │1950 try addFieldConflict(allocator, &box, session, data, "title", fc); │ │1951 } │ │1952 - if (conflict.tags) |*fc| { │ │1953 - try addLabel(allocator, &box, "tags conflict:"); │ │1954 - try addFieldConflict(allocator, &box, session, data, "tags", fc); │ │1952 + if (conflict.labels) |*fc| { │ │1953 + try addLabel(allocator, &box, "labels conflict:"); │ │1954 + try addFieldConflict(allocator, &box, session, data, "labels", fc);│ │1955 } │ │1956 if (comptime @hasField(Data.Conflict, "status")) { │ │1957 if (conflict.status) |*fc| { │ ╰─────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────────────────────────────────────────────────────────────────────────────────────────╮ │2147 return &self.viewStack().children.values()[index].box; │ │2148 } │ │2149 │ │2150 - // the tags view's flow inside the stack. │ │2151 - fn tagsView(self: *This) *TagFlow { │ │2152 - return &self.viewStack().children.values()[tags_view_index].tag_flow; │ │2150 + // the labels view's flow inside the stack. │ │2151 + fn labelsView(self: *This) *WordFlow { │ │2152 + return &self.viewStack().children.values()[labels_view_index].word_flow;│ │2153 } │ │2154 │ │2155 // the non-confirmation form inside the stack │ ╰──────────────────────────────────────────────────────────────────────────────────────────╯ ╭──────╮ │next →│ ╰──────╯