display_name: DisplayName,
password_hash: PasswordHash,
posts: PostList,
- replies: PostList,
following: UserList,
followers: UserList,
.display_name = display_name,
.password_hash = try hash_password(password),
.posts = try PostList.init(txn),
- .replies = try PostList.init(txn),
.following = try UserList.init(txn),
.followers = try UserList.init(txn),
.post_lists = try PostListList.init(txn),
txn.abort();
const post_id = try append_post(env, user_id, user.posts, null, null, text);
-
- txn = try env.txn();
- var replies_view = try user.replies.open(txn);
- try replies_view.append(post_id);
- try txn.commit();
+ _ = post_id;
}
fn comment(env: lmdb.Env, user_id: UserId, parent_post_id: PostId, text: []const u8) !void {
const post_id = try append_post(env, user_id, parent_post.comments, parent_post_id, null, text);
txn = try env.txn();
- var replies_view = try user.replies.open(txn);
+ var replies_view = try user.posts.open(txn);
try replies_view.append(post_id);
try txn.commit();
}
txn.abort();
const post_id = try append_post(env, user_id, user.posts, null, quote_post_id, text);
-
- txn = try env.txn();
- var replies_view = try user.replies.open(txn);
- try replies_view.append(post_id);
- try txn.commit();
+ _ = post_id;
}
fn vote(env: lmdb.Env, post_id: PostId, user_id: UserId, kind: Vote.Kind) !void {
\\<input type="text" name="username" />
\\<input type="password" name="password" />
\\<input type="submit" value="Register" />
- \\</form>
+ \\</form><br />
\\<form action="/login" method="post">
\\<input type="text" name="username" />
\\<input type="password" name="password" />
\\<input type="submit" value="Login" />
- \\</form>
+ \\</form><br /><br />
, .{});
- try html_form(res, "/quit", .{
- \\type="submit" value="Quit"
- });
- try res.write("<br /><br />", .{});
}
}
fn write_start(res: *http.Response) !void {
\\<html>
\\<head>
\\<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🐣</text></svg>">
+ \\<meta name="viewport" content="width=device-width, initial-scale=1.0" />
\\<style>
\\ form {
\\ display: inline-block;
// Quote
try res.write(
- \\<a href="/quotes/{x}">🔁 {}</a>
+ \\<a href="/quoted/{x}">🔁 {}</a>
, .{ @intFromEnum(post.id), quotes_view.len() });
// Save to List
while (it.next()) |kv| {
const name = kv.val.name;
const id = kv.val.list.idx.?;
- try res.write("<option value=\"{x}\">{s}</option>", .{ id, name.constSlice() });
+ const list_view = try kv.val.list.open(txn);
+ try res.write("<option value=\"{x}\">{s}{s}</option>", .{ id, name.constSlice(), if (list_view.has(post_id) catch false) " *" else "" });
}
try res.write("</select>", .{});
try res.write("<input type=\"hidden\" name=\"post_id\" value=\"{x}\"></input>", .{@intFromEnum(post_id)});
while (it.next()) |kv| {
const name = kv.val.name;
const id = kv.val.list.idx.?;
- try res.write("<option value=\"{x}\">{s}</option>", .{ id, name.constSlice() });
+ const list_view = try kv.val.list.open(txn);
+ try res.write("<option value=\"{x}\">{s}{s}</option>", .{ id, name.constSlice(), if (list_view.has(user.id) catch false) " *" else "" });
}
try res.write("</select>", .{});
- try res.write("<input type=\"hidden\" name=\"user.id\" value=\"{x}\"></input>", .{@intFromEnum(user.id)});
+ try res.write("<input type=\"hidden\" name=\"user_id\" value=\"{x}\"></input>", .{@intFromEnum(user.id)});
try res.write("<input type=\"submit\" value=\"Add to feed\"></input>", .{});
try res.write("</form>", .{});
}
user.name.constSlice(), followers.len(),
});
- try res.write("<a href=\"/replies/{s}\">Replies</a><br />", .{
+ try res.write(
+ \\<a href="/all/{0s}">All Posts</a>
+ \\ <a href="/comments/{0s}">Comments</a>
+ \\ <a href="/quotes/{0s}">Quotes</a><br />
+ , .{
user.name.constSlice(),
});
try res.write("<br />", .{});
}
-fn write_posts(res: *http.Response, txn: lmdb.Txn, logged_in: ?Login, post_list: PostList) !void {
+fn write_posts(res: *http.Response, txn: lmdb.Txn, logged_in: ?Login, post_list: PostList, options: struct {
+ show_posts: bool,
+ show_quotes: bool,
+ show_comments: bool,
+}) !void {
const posts_view = try post_list.open(txn);
var it = posts_view.reverse_iterator();
while (it.next()) |post_id| {
- try write_post(res, txn, logged_in, post_id, .{ .recurse = 1 });
- try res.write("<br />", .{});
+ const posts = try Db.posts(txn);
+ const post = try posts.get(post_id);
+ if ((options.show_posts and (post.parent_id == null and post.quote_id == null)) or
+ (options.show_quotes and (post.quote_id != null)) or
+ (options.show_comments and (post.parent_id != null)))
+ {
+ try write_post(res, txn, logged_in, post_id, .{ .recurse = 1 });
+ try res.write("<br />", .{});
+ }
}
}
fn write_timeline(res: *http.Response, txn: lmdb.Txn, logged_in: ?Login, user_list: UserList) !void {
try write_profile(self.res, self.txn, self.logged_in, user);
- try write_posts(self.res, self.txn, self.logged_in, user.posts);
+ try write_posts(self.res, self.txn, self.logged_in, user.posts, .{
+ .show_posts = true,
+ .show_quotes = false,
+ .show_comments = false,
+ });
} else |err| {
try self.res.write(
\\<p>User not found [{}]</p>
, .{err});
}
}
- pub fn @"/replies/"(self: Self, args: struct { username: []const u8 }) !void {
+ pub fn @"/comments/"(self: Self, args: struct { username: []const u8 }) !void {
const user_ids = try Db.user_ids(self.txn);
if (user_ids.get(try Username.fromSlice(args.username))) |user_id| {
const users = try Db.users(self.txn);
try write_profile(self.res, self.txn, self.logged_in, user);
- try write_posts(self.res, self.txn, self.logged_in, user.replies);
+ try write_posts(self.res, self.txn, self.logged_in, user.posts, .{
+ .show_posts = false,
+ .show_quotes = false,
+ .show_comments = true,
+ });
+ } else |err| {
+ try self.res.write(
+ \\<p>User not found [{}]</p>
+ , .{err});
+ }
+ }
+ pub fn @"/quotes/"(self: Self, args: struct { username: []const u8 }) !void {
+ const user_ids = try Db.user_ids(self.txn);
+ if (user_ids.get(try Username.fromSlice(args.username))) |user_id| {
+ const users = try Db.users(self.txn);
+ const user = try users.get(user_id);
+
+ try write_profile(self.res, self.txn, self.logged_in, user);
+
+ try write_posts(self.res, self.txn, self.logged_in, user.posts, .{
+ .show_posts = false,
+ .show_quotes = true,
+ .show_comments = false,
+ });
+ } else |err| {
+ try self.res.write(
+ \\<p>User not found [{}]</p>
+ , .{err});
+ }
+ }
+ pub fn @"/all/"(self: Self, args: struct { username: []const u8 }) !void {
+ const user_ids = try Db.user_ids(self.txn);
+ if (user_ids.get(try Username.fromSlice(args.username))) |user_id| {
+ const users = try Db.users(self.txn);
+ const user = try users.get(user_id);
+
+ try write_profile(self.res, self.txn, self.logged_in, user);
+
+ try write_posts(self.res, self.txn, self.logged_in, user.posts, .{
+ .show_posts = true,
+ .show_quotes = true,
+ .show_comments = true,
+ });
} else |err| {
try self.res.write(
\\<p>User not found [{}]</p>
.show_comment_field = true,
});
}
- pub fn @"/quotes/"(self: Self, args: struct { post_id: PostId }) !void {
+ pub fn @"/quoted/"(self: Self, args: struct { post_id: PostId }) !void {
const posts = try Db.posts(self.txn);
const post = try posts.get(args.post_id);
}
}
pub fn @"/list/"(self: Self, args: struct { list_id: PostList.Index }) !void {
- try write_posts(self.res, self.txn, self.logged_in, PostList{ .idx = args.list_id });
+ try write_posts(self.res, self.txn, self.logged_in, PostList{ .idx = args.list_id }, .{
+ .show_posts = true,
+ .show_quotes = true,
+ .show_comments = true,
+ });
}
pub fn @"/lists"(self: Self) !void {
if (self.logged_in) |login| {
const name = kv.val.name;
const post_list = kv.val.list;
try self.res.write(
- \\<a href="/list/{x}">{s}</a>
+ \\<a href="/list/{x}">{s}</a>
, .{ post_list.idx.?, name.constSlice() });
try html_form(self.res, "/delete_list", .{
.{ "type=\"hidden\" name=\"list_id\" value=\"{x}\"", .{kv.key} },
const name = kv.val.name;
const user_list = kv.val.list;
try self.res.write(
- \\<a href="/feed/{x}">{s}</a>
+ \\<a href="/feed/{x}">{s}</a>
, .{ user_list.idx.?, name.constSlice() });
try html_form(self.res, "/delete_feed", .{
.{ "type=\"hidden\" name=\"list_id\" value=\"{x}\"", .{kv.key} },