diff --git a/dist/treebird20.css b/dist/treebird20.css index 396397a..4270081 100644 --- a/dist/treebird20.css +++ b/dist/treebird20.css @@ -1680,6 +1680,11 @@ ul.large-list li a text-decoration: none; } +.menubar +{ + padding: 6px; +} + /****************************** * Scrobbles * ******************************/ diff --git a/src/query.c b/src/query.c index d177b40..893cccf 100644 --- a/src/query.c +++ b/src/query.c @@ -104,6 +104,8 @@ char* read_post_data(struct post_values* post) { "instance", &(post->instance), key_string }, { "visibility", &(post->visibility), key_string }, { "emojoindex", &(post->emojoindex), key_int }, + { "only_media", &(post->only_media), key_int }, + { "replies_only", &(post->replies_only), key_int }, { "js", &(post->js), key_int }, { "statattachments", &(post->stat_attachments), key_int }, { "statgreentexts", &(post->stat_greentexts), key_int }, diff --git a/src/query.h b/src/query.h index 0e14538..6f77992 100644 --- a/src/query.h +++ b/src/query.h @@ -48,6 +48,8 @@ struct post_values struct key instance_panel; // Int struct key notif_embed; // Int struct key set; // Int + struct key only_media; // Int + struct key replies_only; // Int struct key content; // String struct key itype; // String diff --git a/src/search.c b/src/search.c index fcaeb23..236380a 100644 --- a/src/search.c +++ b/src/search.c @@ -55,7 +55,6 @@ void search_page(struct session* ssn, mastodont_t* api, enum search_tab tab, cha // Output render_base_page(&b, ssn, api); - free(out_data); } diff --git a/src/status.c b/src/status.c index 9312244..7c0ca0d 100644 --- a/src/status.c +++ b/src/status.c @@ -634,12 +634,13 @@ char* construct_status(struct session* ssn, if (args && args->highlight_word && parse_content != status->content) { char* parse_content_tmp; - char* repl_str; + char* repl_str = NULL; easprintf(&repl_str, "%s", args->highlight_word); parse_content_tmp = parse_content; parse_content = strrepl(parse_content, args->highlight_word, repl_str, STRREPL_ALL); // Check if the old parse_content needed to be free'd - if (parse_content_tmp != status->content) + if (parse_content_tmp != status->content && + parse_content != parse_content_tmp) free(parse_content_tmp); else // No results, move back parse_content = parse_content_tmp; @@ -724,8 +725,8 @@ char* construct_status(struct session* ssn, if (notif) free(notif_info); free(delete_status); free(interactions_html); - if (parse_content != status->content && - parse_content) free(parse_content); + if (parse_content != status->content) + free(parse_content); return stat_html; } diff --git a/src/timeline.c b/src/timeline.c index 19d52cc..596009a 100644 --- a/src/timeline.c +++ b/src/timeline.c @@ -29,196 +29,72 @@ #include "error.h" #include "string_helpers.h" +#include "../static/timeline_options.ctmpl" #include "../static/navigation.ctmpl" -#include "../static/directs_page.ctmpl" -#include "../static/hashtag_page.ctmpl" -/* TODO Clean these up and make a meta function, i'm just lazy */ - -void tl_home(struct session* ssn, mastodont_t* api, int local) +void content_timeline(struct session* ssn, + mastodont_t* api, + struct mstdnt_storage* storage, + struct mstdnt_status* statuses, + size_t statuses_len, + enum base_category cat, + char* header_text, + int show_post_box) { - size_t status_count = 0, statuses_html_count = 0; - struct mstdnt_status* statuses = NULL; - struct mstdnt_storage storage = { 0 }; + size_t statuses_html_count = 0; char* status_format = NULL, - *post_box, - *navigation_box = NULL, - *output = NULL; - char* start_id; + * header = NULL, + * post_box = NULL, + * navigation_box = NULL, + * timeline_options, + * output = NULL, + * start_id; - struct mstdnt_timeline_args args = { - .with_muted = 1, - .local = local, - .max_id = keystr(ssn->post.max_id), - .since_id = NULL, - .min_id = keystr(ssn->post.min_id), - .limit = 20 - }; - - try_post_status(ssn, api); - - if (mastodont_timeline_home(api, &args, &storage, &statuses, &status_count)) + if (storage->error) + status_format = construct_error(storage->error, E_ERROR, 1, NULL); + else { - status_format = construct_error(storage.error, E_ERROR, 1, NULL); - } - else { // Construct statuses into HTML - status_format = construct_statuses(ssn, api, statuses, status_count, NULL, &statuses_html_count); + status_format = construct_statuses(ssn, api, statuses, statuses_len, NULL, &statuses_html_count); if (!status_format) - status_format = construct_error("Couldn't load posts", E_ERROR, 1, NULL); + status_format = construct_error("No statuses", E_NOTICE, 1, NULL); } // Create post box - post_box = construct_post_box(NULL, "", NULL); - if (statuses) + if (show_post_box) { - // If not set, set it - start_id = keystr(ssn->post.start_id) ? keystr(ssn->post.start_id) : statuses[0].id; - navigation_box = construct_navigation_box(start_id, - statuses[0].id, - statuses[status_count-1].id, - NULL); + post_box = construct_post_box(NULL, "", NULL); + if (statuses) + { + // If not set, set it + start_id = keystr(ssn->post.start_id) ? keystr(ssn->post.start_id) : statuses[0].id; + navigation_box = construct_navigation_box(start_id, + statuses[0].id, + statuses[statuses_len-1].id, + NULL); + } } - easprintf(&output, "%s%s%s", - post_box, - STR_NULL_EMPTY(status_format), - STR_NULL_EMPTY(navigation_box)); - struct base_page b = { - .category = BASE_CAT_HOME, - .content = output, - .sidebar_left = NULL + // Create timeline options/menubar + struct timeline_options_template todata = { + .only_media = "Only media?", + .replies = "Replies?", + .only_media_active = keyint(ssn->post.only_media) ? "checked" : NULL, }; - // Output - render_base_page(&b, ssn, api); + timeline_options = tmpl_gen_timeline_options(&todata, NULL); - // Cleanup - mastodont_storage_cleanup(&storage); - mstdnt_cleanup_statuses(statuses, status_count); - if (status_format) free(status_format); - if (post_box) free(post_box); - if (navigation_box) free(navigation_box); - if (output) free(output); -} - -void tl_direct(struct session* ssn, mastodont_t* api) -{ - size_t status_count = 0, statuses_html_count = 0; - struct mstdnt_status* statuses = NULL; - struct mstdnt_storage storage = { 0 }; - char* status_format = NULL, - *navigation_box = NULL, - *output = NULL, - *page = NULL; - char* start_id; - - struct mstdnt_timeline_args args = { - .with_muted = 1, - .max_id = keystr(ssn->post.max_id), - .since_id = NULL, - .min_id = keystr(ssn->post.min_id), - .limit = 20, - }; - - if (mastodont_timeline_direct(api, &args, &storage, &statuses, &status_count)) + // Display a header bar, usually customized for specific pages + if (header_text) { - status_format = construct_error(storage.error, E_ERROR, 1, NULL); - } - else { - // Construct statuses into HTML - status_format = construct_statuses(ssn, api, statuses, status_count, NULL, &statuses_html_count); - if (!status_format) - status_format = construct_error("Couldn't load posts", E_ERROR, 1, NULL); - } - - // Create post box - if (statuses) - { - // If not set, set it - start_id = keystr(ssn->post.start_id) ? keystr(ssn->post.start_id) : statuses[0].id; - navigation_box = construct_navigation_box(start_id, - statuses[0].id, - statuses[status_count-1].id, - NULL); + easprintf(&header, "

%s

", + header_text); } - easprintf(&page, "%s%s", - STR_NULL_EMPTY(status_format), - STR_NULL_EMPTY(navigation_box)); - - struct directs_page_template tdata = { - .direct_content = page, - }; - output = tmpl_gen_directs_page(&tdata, NULL); - - struct base_page b = { - .category = BASE_CAT_DIRECT, - .content = output, - .sidebar_left = NULL - }; - - // Output - render_base_page(&b, ssn, api); - - // Cleanup - mastodont_storage_cleanup(&storage); - mstdnt_cleanup_statuses(statuses, status_count); - if (status_format) free(status_format); - if (navigation_box) free(navigation_box); - if (output) free(output); - if (page) free(page); -} - -void tl_public(struct session* ssn, mastodont_t* api, int local, enum base_category cat) -{ - size_t status_count = 0, statuses_html_count = 0; - struct mstdnt_status* statuses = NULL; - struct mstdnt_storage storage = { 0 }; - char* status_format = NULL, - *post_box, - *navigation_box = NULL, - *output = NULL; - char* start_id; - - struct mstdnt_timeline_args args = { - .with_muted = 1, - .local = local, - .remote = 0, - .only_media = 0, - .max_id = keystr(ssn->post.max_id), - .since_id = NULL, - .min_id = keystr(ssn->post.min_id), - .limit = 20 - }; - - try_post_status(ssn, api); - - if (mastodont_timeline_public(api, &args, &storage, &statuses, &status_count)) - { - status_format = construct_error(storage.error, E_ERROR, 1, NULL); - } - else { - // Construct statuses into HTML - status_format = construct_statuses(ssn, api, statuses, status_count, NULL, &statuses_html_count); - if (!status_format) - status_format = construct_error("Couldn't load posts", E_ERROR, 1, NULL); - } - - // Create post box - post_box = construct_post_box(NULL, "", NULL); - if (statuses) - { - // If not set, set it - start_id = keystr(ssn->post.start_id) ? keystr(ssn->post.start_id) : statuses[0].id; - navigation_box = construct_navigation_box(start_id, - statuses[0].id, - statuses[status_count-1].id, - NULL); - } - - easprintf(&output, "%s%s%s", - post_box, + easprintf(&output, "%s%s%s%s%s", + STR_NULL_EMPTY(header), + STR_NULL_EMPTY(post_box), + STR_NULL_EMPTY(timeline_options), STR_NULL_EMPTY(status_format), STR_NULL_EMPTY(navigation_box)); @@ -232,140 +108,150 @@ void tl_public(struct session* ssn, mastodont_t* api, int local, enum base_categ render_base_page(&b, ssn, api); // Cleanup - mastodont_storage_cleanup(&storage); - mstdnt_cleanup_statuses(statuses, status_count); - if (status_format) free(status_format); - if (post_box) free(post_box); - if (navigation_box) free(navigation_box); - if (output) free(output); + mastodont_storage_cleanup(storage); + mstdnt_cleanup_statuses(statuses, statuses_len); + free(status_format); + free(post_box); + free(navigation_box); + free(output); +} + +void tl_home(struct session* ssn, mastodont_t* api, int local) +{ + size_t statuses_len = 0; + struct mstdnt_status* statuses = NULL; + struct mstdnt_storage storage = { 0 }; + + struct mstdnt_timeline_args args = { + .with_muted = 1, + .local = local, + // Converts to `enum mstdnt_reply_visibility' nicely + .reply_visibility = (ssn->post.replies_only.is_set ? + keyint(ssn->post.replies_only) : 0), + .only_media = (ssn->post.only_media.is_set ? + keyint(ssn->post.only_media) : 0), + .max_id = keystr(ssn->post.max_id), + .since_id = NULL, + .min_id = keystr(ssn->post.min_id), + .limit = 20 + }; + + try_post_status(ssn, api); + + mastodont_timeline_home(api, &args, &storage, &statuses, &statuses_len); + + content_timeline(ssn, api, &storage, statuses, statuses_len, BASE_CAT_HOME, NULL, 1); +} + +void tl_direct(struct session* ssn, mastodont_t* api) +{ + size_t statuses_len = 0; + struct mstdnt_status* statuses = NULL; + struct mstdnt_storage storage = { 0 }; + + struct mstdnt_timeline_args args = { + .with_muted = 1, + .max_id = keystr(ssn->post.max_id), + // Converts to `enum mstdnt_reply_visibility' nicely + .reply_visibility = (ssn->post.replies_only.is_set ? + keyint(ssn->post.replies_only) : 0), + .only_media = (ssn->post.only_media.is_set ? + keyint(ssn->post.only_media) : 0), + .since_id = NULL, + .min_id = keystr(ssn->post.min_id), + .limit = 20, + }; + + try_post_status(ssn, api); + + mastodont_timeline_direct(api, &args, &storage, &statuses, &statuses_len); + + content_timeline(ssn, api, &storage, statuses, statuses_len, BASE_CAT_DIRECT, NULL, 0); +} + +void tl_public(struct session* ssn, mastodont_t* api, int local, enum base_category cat) +{ + size_t statuses_len = 0; + struct mstdnt_status* statuses = NULL; + struct mstdnt_storage storage = { 0 }; + + struct mstdnt_timeline_args args = { + .with_muted = 1, + .local = local, + .remote = 0, + // Converts to `enum mstdnt_reply_visibility' nicely + .reply_visibility = (ssn->post.replies_only.is_set ? + keyint(ssn->post.replies_only) : 0), + .only_media = (ssn->post.only_media.is_set ? + keyint(ssn->post.only_media) : 0), + .max_id = keystr(ssn->post.max_id), + .since_id = NULL, + .min_id = keystr(ssn->post.min_id), + .limit = 20 + }; + + try_post_status(ssn, api); + + mastodont_timeline_public(api, &args, &storage, &statuses, &statuses_len); + + content_timeline(ssn, api, &storage, statuses, statuses_len, cat, NULL, 1); } void tl_list(struct session* ssn, mastodont_t* api, char* list_id) { - size_t status_count, statuses_html_count; + size_t statuses_len = 0; struct mstdnt_status* statuses = NULL; struct mstdnt_storage storage = { 0 }; - char* status_format, *post_box, *navigation_box = NULL, *start_id; - char* output = NULL; struct mstdnt_timeline_args args = { .max_id = keystr(ssn->post.max_id), .since_id = NULL, + // Converts to `enum mstdnt_reply_visibility' nicely + .reply_visibility = (ssn->post.replies_only.is_set ? + keyint(ssn->post.replies_only) : 0), + .only_media = (ssn->post.only_media.is_set ? + keyint(ssn->post.only_media) : 0), .min_id = keystr(ssn->post.min_id), .limit = 20, }; try_post_status(ssn, api); - if (mastodont_timeline_list(api, list_id, &args, &storage, &statuses, &status_count)) - { - status_format = construct_error(storage.error, E_ERROR, 1, NULL); - } - else { - // Construct statuses into HTML - status_format = construct_statuses(ssn, api, statuses, status_count, NULL, &statuses_html_count); - if (!status_format) - status_format = construct_error("No statuses", E_ERROR, 1, NULL); - } + mastodont_timeline_list(api, list_id, &args, &storage, &statuses, &statuses_len); - // Create post box - post_box = construct_post_box(NULL, "", NULL); - if (statuses) - { - // If not set, set it - start_id = keystr(ssn->post.start_id) ? keystr(ssn->post.start_id) : statuses[0].id; - navigation_box = construct_navigation_box(start_id, - statuses[0].id, - statuses[status_count-1].id, - NULL); - } - easprintf(&output, "%s%s%s", - post_box, - STR_NULL_EMPTY(status_format), - STR_NULL_EMPTY(navigation_box)); - - struct base_page b = { - .category = BASE_CAT_LISTS, - .content = output, - .sidebar_left = NULL - }; - - // Output - render_base_page(&b, ssn, api); - - // Cleanup - mastodont_storage_cleanup(&storage); - mstdnt_cleanup_statuses(statuses, status_count); - free(status_format); - if (post_box) free(post_box); - if (output) free(output); - if (navigation_box) free(navigation_box); + content_timeline(ssn, api, &storage, statuses, statuses_len, BASE_CAT_LISTS, NULL, 0); } void tl_tag(struct session* ssn, mastodont_t* api, char* tag_id) { - size_t status_count, statuses_html_count; + char* header; + size_t statuses_len = 0; struct mstdnt_status* statuses = NULL; struct mstdnt_storage storage = { 0 }; - char* status_format, *navigation_box = NULL, *start_id; - char* output = NULL; struct mstdnt_timeline_args args = { .max_id = keystr(ssn->post.max_id), .since_id = NULL, + // Converts to `enum mstdnt_reply_visibility' nicely + .reply_visibility = (ssn->post.replies_only.is_set ? + keyint(ssn->post.replies_only) : 0), + .only_media = (ssn->post.only_media.is_set ? + keyint(ssn->post.only_media) : 0), .min_id = keystr(ssn->post.min_id), .limit = 20, }; - if (mastodont_timeline_tag(api, tag_id, &args, &storage, &statuses, &status_count)) - status_format = construct_error(storage.error, E_ERROR, 1, NULL); - else { - // Construct statuses into HTML - status_format = construct_statuses(ssn, api, statuses, status_count, NULL, &statuses_html_count); - if (!status_format) - status_format = construct_error("No statuses", E_ERROR, 1, NULL); - } + mastodont_timeline_tag(api, tag_id, &args, &storage, &statuses, &statuses_len); - // Create post box - if (statuses) - { - // If not set, set it - start_id = keystr(ssn->post.start_id) ? keystr(ssn->post.start_id) : statuses[0].id; - navigation_box = construct_navigation_box(start_id, - statuses[0].id, - statuses[status_count-1].id, - NULL); - } + easprintf(&header, "Hashtag - #%s", tag_id); - struct hashtag_page_template tdata = { - .tag = tag_id, - .statuses = status_format, - .navigation = navigation_box - }; - - output = tmpl_gen_hashtag_page(&tdata, NULL); - - struct base_page b = { - .category = BASE_CAT_NONE, - .content = output, - .sidebar_left = NULL - }; - - // Output - render_base_page(&b, ssn, api); - - // Cleanup - mastodont_storage_cleanup(&storage); - mstdnt_cleanup_statuses(statuses, status_count); - free(status_format); - if (output) free(output); - if (navigation_box) free(navigation_box); + content_timeline(ssn, api, &storage, statuses, statuses_len, BASE_CAT_NONE, header, 0); + free(header); } void content_tl_home(struct session* ssn, mastodont_t* api, char** data) { - (void)data; if (keystr(ssn->cookies.logged_in)) tl_home(ssn, api, 0); else diff --git a/src/timeline.h b/src/timeline.h index b040397..3c7c96d 100644 --- a/src/timeline.h +++ b/src/timeline.h @@ -36,5 +36,13 @@ void content_tl_direct(struct session* ssn, mastodont_t* api, char** data); void content_tl_local(struct session* ssn, mastodont_t* api, char** data); void content_tl_list(struct session* ssn, mastodont_t* api, char** data); void content_tl_tag(struct session* ssn, mastodont_t* api, char** data); +void content_timeline(struct session* ssn, + mastodont_t* api, + struct mstdnt_storage* storage, + struct mstdnt_status* statuses, + size_t statuses_len, + enum base_category cat, + char* header, + int show_post_box); #endif // TIMELINE_H diff --git a/static/timeline_options.tmpl b/static/timeline_options.tmpl new file mode 100644 index 0000000..94afd7d --- /dev/null +++ b/static/timeline_options.tmpl @@ -0,0 +1,14 @@ +