╭ changed ─╮ │src/ui.zig│ ╰──────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭────────────────────────────────────────────────────────────────────────╮ │35 pub const NewRepo = @import("./ui/NewRepo.zig"); │ │36 pub const NewUser = @import("./ui/NewUser.zig"); │ │37 pub const UserSettings = @import("./ui/UserSettings.zig"); │ │38 +pub const UserKeys = @import("./ui/UserKeys.zig"); │ │39 pub const UserNotifications = @import("./ui/UserNotifications.zig");│ │40 pub const UserLogin = @import("./ui/UserLogin.zig"); │ │41 pub const widget = @import("./ui/widget.zig"); │ ╰────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────╮ │216 │ │217 pub const EventsView = enum { active, removed }; │ │218 │ │218 - pub const UserView = enum { notifications, settings }; │ │219 + pub const UserView = enum { notifications, settings, keys }; │ │220 │ │221 // the user tab's sub tab and the notifications window it shows│ │222 pub const UserTab = struct { │ ╰────────────────────────────────────────────────────────────────────────╯ ╭────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1300 fn userTabUrl(arena: *std.heap.ArenaAllocator, prefix: []const u8, tab: UserTab) ![]const u8 {│ │1301 return switch (tab.view) { │ │1302 .settings => try arena.allocator().print("{s}/user/settings", .{prefix}), │ │1303 + .keys => try arena.allocator().print("{s}/user/keys", .{prefix}), │ │1304 .notifications => if (tab.start == 0) │ │1305 try arena.allocator().print("{s}/user/notifications", .{prefix}) │ │1306 else │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1505 } │ │1506 │ │1507 // the tail after a page's "user": none or "notifications" with an optional │ │1506 - // "start:<n>", "settings", or "new" │ │1508 + // "start:<n>", "settings", "keys", or "new" │ │1509 fn userTail(segments: *std.mem.SplitIterator(u8, .scalar)) ?union(enum) { new, tab: UserTab } {│ │1510 const word = segments.next() orelse return .{ .tab = .{} }; │ │1511 if (std.mem.eql(u8, word, "new")) return if (segments.next() == null) .new else null; │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │1512 return switch (std.meta.stringToEnum(UserView, word) orelse return null) { │ │1511 - .settings => if (segments.next() == null) .{ .tab = .{ .view = .settings } } else null, │ │1513 + inline .settings, .keys => |view| if (segments.next() == null) .{ .tab = .{ .view = view } } else null,│ │1514 .notifications => .{ .tab = .{ .start = listStart(segments) orelse return null } }, │ │1515 }; │ │1516 } │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────────────────────────────────────────────╮ │2322 │ │2323 pub const AssignmentFailure = enum { not_found, not_an_email, already_assigned };│ │2324 │ │2325 + pub const KeyFailure = enum { │ │2326 + invalid, │ │2327 + unsupported, │ │2328 + already_added, │ │2329 + │ │2330 + pub fn fromError(err: anyerror) ?KeyFailure { │ │2331 + return switch (err) { │ │2332 + error.InvalidKey => .invalid, │ │2333 + error.UnsupportedKey => .unsupported, │ │2334 + error.KeyAdded => .already_added, │ │2335 + else => null, │ │2336 + }; │ │2337 + } │ │2338 + }; │ │2339 + │ │2340 pub const UserFailure = enum { │ │2341 required_name, │ │2342 invalid_name, │ ╰───────────────────────────────────────────────────────────────────────────────────────────────╯ ╭───────────────────────────────────────────────────────╮ │2378 failure: UserFailure, │ │2379 // passwords are never retained │ │2380 fields: struct { email: []const u8 },│ │2381 + }, │ │2382 + user_keys: struct { │ │2383 + failure: KeyFailure, │ │2384 + key: []const u8, │ │2385 }, │ │2386 repo: struct { │ │2387 failure: RepoFailure, │ ╰───────────────────────────────────────────────────────╯