╭ changed ─────────╮ │src/event/User.zig│ ╰──────────────────╯ ╭───────────╮ │← all files│ ╰───────────╯ ╭───────────────────────────────────────────╮ │1 const std = @import("std"); │ │2 const evt = @import("../event.zig"); │ │3 const xit = @import("xit"); │ │4 +const rp = xit.repo; │ │5 const hash = xit.hash; │ │6 const bcrypt = std.crypto.pwhash.bcrypt;│ │7 │ ╰───────────────────────────────────────────╯ ╭──────────────────────────────╮ │ 9 display_name: []const u8, │ │10 email: []const u8, │ │11 password_hash: []const u8,│ │12 +enable_ansi: bool = false,│ │13 │ │14 pub fn consume( │ │15 comptime DB: type, │ ╰──────────────────────────────╯ ╭─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │109 }; │ │110 │ │111 return .{ .success = user_id }; │ │112 +} │ │113 + │ │114 +// read a user by event id via the event-id->user index, or null if the id │ │115 +// isn't a known user. field byte slices are allocated in `arena`. │ │116 +pub fn readById( │ │117 + comptime DB: type, │ │118 + comptime hash_kind: hash.HashKind, │ │119 + haxy_moment: DB.HashMap(.read_only), │ │120 + arena: *std.heap.ArenaAllocator, │ │121 + user_id: []const u8, │ │122 +) !?@This() { │ │123 + const event_id_to_user_cursor = try haxy_moment.getCursor(hash.hashInt(hash_kind, "event-id->user")) orelse return null;│ │124 + const event_id_to_user = try DB.HashMap(.read_only).init(event_id_to_user_cursor); │ │125 + const user_cursor = try event_id_to_user.getCursor(hash.hashInt(hash_kind, user_id)) orelse return null; │ │126 + const user_map = try DB.HashMap(.read_only).init(user_cursor); │ │127 + return try evt.read(@This(), DB, hash_kind, arena, user_map); │ │128 +} │ │129 + │ │130 +// flip a user's ANSI-art preference by re-emitting their User event with │ │131 +// enable_ansi negated. a no-op for an unknown user. `repo` must be writable. │ │132 +pub fn toggleAnsi( │ │133 + comptime repo_opts: rp.RepoOpts(.xit), │ │134 + io: std.Io, │ │135 + allocator: std.mem.Allocator, │ │136 + repo: *rp.Repo(.xit, repo_opts), │ │137 + user_id: []const u8, │ │138 +) !void { │ │139 + const DB = rp.Repo(.xit, repo_opts).DB; │ │140 + var arena = std.heap.ArenaAllocator.init(allocator); │ │141 + defer arena.deinit(); │ │142 + │ │143 + const moment = try evt.currentMoment(repo_opts, repo); │ │144 + const user = (try readById(DB, repo_opts.hash, moment, &arena, user_id)) orelse return; │ │145 + │ │146 + var updated = user; │ │147 + updated.enable_ansi = !user.enable_ansi; │ │148 + try evt.commitAndConsume(repo_opts, io, allocator, repo, evt.events_ref, &[_]evt.EventWithId{.{ │ │149 + .id = std.fmt.bytesToHex(user_id[0..evt.event_id_size].*, .lower), │ │150 + .event = .{ .user = updated }, │ │151 + }}); │ │152 } │ │153 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯