From a221237637191d70c2e1d18aec82056501f8140f Mon Sep 17 00:00:00 2001 From: Alex Schroeder Date: Sun, 4 Dec 2022 21:28:29 +0100 Subject: [PATCH] Pagination of the public and private page Use the query parameters skip and show to control what you can see, e.g. /alex/admin?skip=0&show=4 Don't use or save the timeline cache if either is set. The following functions were changed from accepting a single max parameter to accepting both skip and show: timeline_simple_list, timeline_list, index_list_desc. --- activitypub.c | 2 +- data.c | 20 ++++++++++---------- html.c | 37 ++++++++++++++++++++++++++++++------- main.c | 2 +- snac.h | 6 +++--- 5 files changed, 45 insertions(+), 22 deletions(-) diff --git a/activitypub.c b/activitypub.c index 252c084..7017899 100644 --- a/activitypub.c +++ b/activitypub.c @@ -1094,7 +1094,7 @@ int activitypub_get_handler(d_char *req, char *q_path, else if (strcmp(p_path, "outbox") == 0) { xs *id = xs_fmt("%s/outbox", snac.actor); - xs *elems = timeline_simple_list(&snac, "public", 20); + xs *elems = timeline_simple_list(&snac, "public", 0, 20); xs *list = xs_list_new(); msg = msg_collection(&snac, id); char *p, *v; diff --git a/data.c b/data.c index f36c01d..c545535 100644 --- a/data.c +++ b/data.c @@ -359,7 +359,7 @@ d_char *index_list(const char *fn, int max) } -d_char *index_list_desc(const char *fn, int max) +d_char *index_list_desc(const char *fn, int skip, int show) /* returns an index as a list, in reverse order */ { d_char *list = NULL; @@ -372,9 +372,9 @@ d_char *index_list_desc(const char *fn, int max) char line[256]; list = xs_list_new(); - /* move to the end minus one entry */ - if (!fseek(f, 0, SEEK_END) && !fseek(f, -33, SEEK_CUR)) { - while (n < max && fgets(line, sizeof(line), f) != NULL) { + /* move to the end minus one entry (or more, if skipping entries) */ + if (!fseek(f, 0, SEEK_END) && !fseek(f, (skip + 1) * -33, SEEK_CUR)) { + while (n < show && fgets(line, sizeof(line), f) != NULL) { line[32] = '\0'; list = xs_list_append(list, line); n++; @@ -856,7 +856,7 @@ d_char *timeline_top_level(d_char *list) } -d_char *timeline_simple_list(snac *snac, const char *idx_name, int max) +d_char *timeline_simple_list(snac *snac, const char *idx_name, int skip, int show) /* returns a timeline (with all entries) */ { int c_max; @@ -865,19 +865,19 @@ d_char *timeline_simple_list(snac *snac, const char *idx_name, int max) c_max = xs_number_get(xs_dict_get(srv_config, "max_timeline_entries")); /* never more timeline entries than the configured maximum */ - if (max > c_max) - max = c_max; + if (show > c_max) + show = c_max; xs *idx = xs_fmt("%s/%s.idx", snac->basedir, idx_name); - return index_list_desc(idx, max); + return index_list_desc(idx, skip, show); } -d_char *timeline_list(snac *snac, const char *idx_name, int max) +d_char *timeline_list(snac *snac, const char *idx_name, int skip, int show) /* returns a timeline (only top level entries) */ { - xs *list = timeline_simple_list(snac, idx_name, max); + xs *list = timeline_simple_list(snac, idx_name, skip, show); return timeline_top_level(list); } diff --git a/html.c b/html.c index 78c6aed..5614956 100644 --- a/html.c +++ b/html.c @@ -967,6 +967,7 @@ int html_get_handler(d_char *req, char *q_path, char **body, int *b_size, char * xs *uid = NULL; char *p_path; int cache = 1; + int save = 1; char *v; xs *l = xs_split_n(q_path, "/", 2); @@ -1004,6 +1005,14 @@ int html_get_handler(d_char *req, char *q_path, char **body, int *b_size, char * if ((v = xs_dict_get(srv_config, "disable_cache")) && xs_type(v) == XSTYPE_TRUE) cache = 0; + int skip = 0; + int show = 50; + char *q_vars = xs_dict_get(req, "q_vars"); + if ((v = xs_dict_get(q_vars, "skip")) != NULL) + skip = atoi(v), cache = 0, save = 0; + if ((v = xs_dict_get(q_vars, "show")) != NULL) + show = atoi(v), cache = 0, save = 0; + if (p_path == NULL) { /* public timeline */ xs *h = xs_str_localtime(0, "%Y-%m.html"); @@ -1016,13 +1025,20 @@ int html_get_handler(d_char *req, char *q_path, char **body, int *b_size, char * status = 200; } else { - xs *list = timeline_list(&snac, "public", XS_ALL); + xs *list = timeline_list(&snac, "public", skip, show); - *body = html_timeline(&snac, list, 1); + *body = html_timeline(&snac, list, 1); + if (xs_list_len(list) == show) + *body = xs_str_cat( + *body, xs_fmt( + "

" + "More…" + "

\n", snac.actor, skip + show, show)); *b_size = strlen(*body); status = 200; - history_add(&snac, h, *body, *b_size); + if (save) + history_add(&snac, h, *body, *b_size); } } else @@ -1042,13 +1058,20 @@ int html_get_handler(d_char *req, char *q_path, char **body, int *b_size, char * else { snac_debug(&snac, 1, xs_fmt("building timeline")); - xs *list = timeline_list(&snac, "private", XS_ALL); + xs *list = timeline_list(&snac, "private", skip, show); *body = html_timeline(&snac, list, 0); + if (xs_list_len(list) == show) + *body = xs_str_cat( + *body, xs_fmt( + "

" + "More…" + "

\n", snac.actor, skip + show, show)); *b_size = strlen(*body); status = 200; - history_add(&snac, "timeline.html_", *body, *b_size); + if (save) + history_add(&snac, "timeline.html_", *body, *b_size); } } } @@ -1109,7 +1132,7 @@ int html_get_handler(d_char *req, char *q_path, char **body, int *b_size, char * if (strcmp(p_path, ".rss") == 0) { /* public timeline in RSS format */ d_char *rss; - xs *elems = timeline_simple_list(&snac, "public", 20); + xs *elems = timeline_simple_list(&snac, "public", 0, 20); xs *bio = not_really_markdown(xs_dict_get(snac.config, "bio")); char *p, *v; @@ -1202,7 +1225,7 @@ int html_post_handler(d_char *req, char *q_path, d_char *payload, int p_size, uid = xs_list_get(l, 1); if (!uid || !user_open(&snac, uid)) { /* invalid user */ - srv_log(xs_fmt("html_get_handler bad user %s", uid)); + srv_log(xs_fmt("html_post_handler bad user %s", uid)); return 404; } diff --git a/main.c b/main.c index 7048426..d3a461e 100644 --- a/main.c +++ b/main.c @@ -159,7 +159,7 @@ int main(int argc, char *argv[]) #endif xs *idx = xs_fmt("%s/private.idx", snac.basedir); - xs *list = index_list_desc(idx, 256); + xs *list = index_list_desc(idx, 0, 256); xs *tl = timeline_top_level(list); xs *j = xs_json_dumps_pp(tl, 4); diff --git a/snac.h b/snac.h index 6f3899b..a6215b1 100644 --- a/snac.h +++ b/snac.h @@ -58,7 +58,7 @@ int index_add(const char *fn, const char *md5); int index_del(const char *fn, const char *md5); int index_first(const char *fn, char *buf, int size); d_char *index_list(const char *fn, int max); -d_char *index_list_desc(const char *fn, int max); +d_char *index_list_desc(const char *fn, int skip, int show); int object_add(const char *id, d_char *obj); int object_add_ow(const char *id, d_char *obj); @@ -85,8 +85,8 @@ d_char *follower_list(snac *snac); double timeline_mtime(snac *snac); int timeline_del(snac *snac, char *id); -d_char *timeline_simple_list(snac *snac, const char *idx_name, int max); -d_char *timeline_list(snac *snac, const char *idx_name, int max); +d_char *timeline_simple_list(snac *snac, const char *idx_name, int skip, int show); +d_char *timeline_list(snac *snac, const char *idx_name, int skip, int show); int timeline_add(snac *snac, char *id, char *o_msg, char *parent, char *referrer); void timeline_admire(snac *snac, char *o_msg, char *id, char *admirer, int like);