Finish cleaning up template stuff
FossilOrigin-Name: 1fa9a720bfca80c96264c4f7263f6de710bee40da23d92f874070de5f32412a7
This commit is contained in:
parent
50e76ae712
commit
09ddb21d42
27 changed files with 38 additions and 1557 deletions
|
@ -31,7 +31,6 @@
|
|||
#include "base_page.h"
|
||||
#include "scrobble.h"
|
||||
#include "string_helpers.h"
|
||||
#include "navigation.h"
|
||||
#include "emoji.h"
|
||||
#include "timeline.h"
|
||||
|
||||
|
@ -504,36 +503,6 @@ AV* perlify_accounts(const struct mstdnt_account* accounts, size_t len)
|
|||
return av;
|
||||
}
|
||||
|
||||
HV* perlify_scrobble(const struct mstdnt_scrobble* scrobble)
|
||||
{
|
||||
if (!scrobble) return NULL;
|
||||
HV* scrobble_hv = newHV();
|
||||
|
||||
hvstores_ref(scrobble_hv, "account", perlify_account(&(scrobble->account)));
|
||||
hvstores_str(scrobble_hv, "album", scrobble->album);
|
||||
hvstores_str(scrobble_hv, "artist", scrobble->artist);
|
||||
hvstores_int(scrobble_hv, "created_at", scrobble->created_at);
|
||||
hvstores_str(scrobble_hv, "id", scrobble->id);
|
||||
hvstores_int(scrobble_hv, "length", scrobble->length);
|
||||
hvstores_str(scrobble_hv, "title", scrobble->title);
|
||||
|
||||
return scrobble_hv;
|
||||
}
|
||||
|
||||
AV* perlify_scrobbles(const struct mstdnt_scrobble* scrobbles, size_t len)
|
||||
{
|
||||
if (!(scrobbles && len)) return NULL;
|
||||
AV* av = newAV();
|
||||
av_extend(av, len-1);
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
av_store(av, i, newRV_inc((SV*)perlify_scrobble(scrobbles + i)));
|
||||
}
|
||||
|
||||
return av;
|
||||
}
|
||||
|
||||
HV* perlify_account(const struct mstdnt_account* acct)
|
||||
{
|
||||
if (!acct) return NULL;
|
||||
|
|
|
@ -72,8 +72,6 @@ void content_account_bookmarks(PATH_ARGS);
|
|||
|
||||
HV* perlify_account(const struct mstdnt_account* acct);
|
||||
AV* perlify_accounts(const struct mstdnt_account* accounts, size_t len);
|
||||
HV* perlify_scrobble(const struct mstdnt_scrobble* scrobble);
|
||||
AV* perlify_scrobbles(const struct mstdnt_scrobble* scrobbles, size_t len);
|
||||
HV* perlify_relationship(const struct mstdnt_relationship* rel);
|
||||
|
||||
#endif // ACCOUNT_H
|
||||
|
|
|
@ -109,7 +109,7 @@ char* construct_emoji_picker(char* status_id, size_t* size)
|
|||
AV* av = newAV();
|
||||
for (int i = 0; i < EMO_CAT_LEN; ++i)
|
||||
{
|
||||
av_store(av, i, newSVpv(emojis + i, len + i));
|
||||
av_store(av, i, newSVpv(emojis[i], len[i]));
|
||||
}
|
||||
XPUSHs(newRV_inc((SV*)av));
|
||||
PERL_STACK_SCALAR_CALL("emojis::emoji_picker");
|
||||
|
|
36
src/error.c
36
src/error.c
|
@ -21,46 +21,12 @@
|
|||
#include "easprintf.h"
|
||||
#include "l10n.h"
|
||||
|
||||
// Pages
|
||||
#include "../static/error_404.ctmpl"
|
||||
#include "../static/error.ctmpl"
|
||||
|
||||
char* construct_error(const char* error, enum error_type type, unsigned pad, size_t* size)
|
||||
{
|
||||
char* class;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case E_ERROR:
|
||||
class = "error"; break;
|
||||
case E_WARNING:
|
||||
class = "warning"; break;
|
||||
case E_NOTICE:
|
||||
class = "notice"; break;
|
||||
}
|
||||
|
||||
struct error_template data = {
|
||||
.err_type = class,
|
||||
.is_padded = pad ? "error-pad" : NULL,
|
||||
.error = error ? error : "An error occured",
|
||||
};
|
||||
|
||||
return tmpl_gen_error(&data, size);
|
||||
}
|
||||
|
||||
void content_not_found(FCGX_Request* req, struct session* ssn, mastodont_t* api, char* path)
|
||||
{
|
||||
char* page;
|
||||
struct error_404_template data = {
|
||||
.error = L10N[L10N_EN_US][L10N_PAGE_NOT_FOUND]
|
||||
};
|
||||
page = tmpl_gen_error_404(&data, NULL);
|
||||
|
||||
struct base_page b = {
|
||||
.content = page,
|
||||
.content = "Content not found",
|
||||
.sidebar_left = NULL
|
||||
};
|
||||
|
||||
render_base_page(&b, req, ssn, api);
|
||||
free(page);
|
||||
}
|
||||
|
|
|
@ -23,14 +23,6 @@
|
|||
#include "session.h"
|
||||
#include "path.h"
|
||||
|
||||
enum error_type
|
||||
{
|
||||
E_ERROR,
|
||||
E_WARNING,
|
||||
E_NOTICE
|
||||
};
|
||||
|
||||
char* construct_error(const char* error, enum error_type type, unsigned pad, size_t* size);
|
||||
void content_not_found(FCGX_Request* req, struct session* ssn, mastodont_t* api, char* path);
|
||||
|
||||
#endif // ERROR_H
|
||||
|
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Treebird - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "graphsnbars.h"
|
||||
#include "easprintf.h"
|
||||
#include "string_helpers.h"
|
||||
|
||||
// Pages
|
||||
#include "../static/bar.ctmpl"
|
||||
#include "../static/bar_graph.ctmpl"
|
||||
|
||||
struct hashtags_graph_args
|
||||
{
|
||||
struct mstdnt_tag* tags;
|
||||
size_t tags_len;
|
||||
unsigned max;
|
||||
time_t rel_day;
|
||||
size_t days;
|
||||
};
|
||||
|
||||
char* construct_bar_graph_container(char* bars, size_t* size)
|
||||
{
|
||||
struct bar_graph_template data = {
|
||||
.graph = bars,
|
||||
};
|
||||
return tmpl_gen_bar_graph(&data, size);
|
||||
}
|
||||
|
||||
char* construct_bar(float value, size_t* size)
|
||||
{
|
||||
struct bar_template data = {
|
||||
.value = value * 100
|
||||
};
|
||||
return tmpl_gen_bar(&data, size);
|
||||
}
|
||||
|
||||
static char* construct_hashgraph_voidwrap(void* passed, size_t index, size_t* res)
|
||||
{
|
||||
unsigned curr_sum = 0;
|
||||
struct hashtags_graph_args* args = passed;
|
||||
struct mstdnt_tag* tags = args->tags;
|
||||
size_t tags_len = args->tags_len;
|
||||
unsigned max = args->max;
|
||||
time_t rel_day = args->rel_day;
|
||||
size_t days = args->days;
|
||||
|
||||
for (int i = 0; i < tags_len; ++i)
|
||||
{
|
||||
for (int j = 0; j < tags[i].history_len; ++j)
|
||||
{
|
||||
if (tags[i].history[j].day == rel_day-((days-index-1)*86400))
|
||||
curr_sum += tags[i].history[j].uses;
|
||||
}
|
||||
}
|
||||
|
||||
return construct_bar((float)curr_sum / max, res);
|
||||
}
|
||||
|
||||
char* construct_hashtags_graph(struct mstdnt_tag* tags,
|
||||
size_t tags_len,
|
||||
size_t days,
|
||||
size_t* ret_size)
|
||||
{
|
||||
unsigned max_sum = 0;
|
||||
unsigned curr_sum = 0;
|
||||
size_t max_history_len = 0;
|
||||
|
||||
// Get current time at midnight for basis, copy over
|
||||
time_t t = time(NULL);
|
||||
struct tm* mn_ptr = gmtime(&t);
|
||||
struct tm mn;
|
||||
memcpy(&mn, mn_ptr, sizeof(mn));
|
||||
mn.tm_hour = 0;
|
||||
mn.tm_min = 0;
|
||||
mn.tm_sec = 0;
|
||||
time_t rel_day = timegm(&mn);
|
||||
|
||||
// Run a loop through all the hashtags, sum each set up,
|
||||
// then get the largest sum
|
||||
for (size_t i = 0; i < days; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < tags_len && i < tags[j].history_len; ++j)
|
||||
{
|
||||
if (tags[j].history_len > max_history_len)
|
||||
max_history_len = tags[j].history_len;
|
||||
if (tags[j].history[i].day >= rel_day-(i*86400))
|
||||
curr_sum += tags[j].history[i].uses;
|
||||
}
|
||||
|
||||
if (curr_sum > max_sum)
|
||||
max_sum = curr_sum;
|
||||
curr_sum = 0;
|
||||
}
|
||||
|
||||
struct hashtags_graph_args args = {
|
||||
.tags = tags,
|
||||
.tags_len = tags_len,
|
||||
.max = max_sum,
|
||||
.rel_day = rel_day,
|
||||
.days = max_history_len,
|
||||
};
|
||||
|
||||
return construct_func_strings(construct_hashgraph_voidwrap, &args, max_history_len, ret_size);
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/*
|
||||
* Treebird - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef GRAPHS_N_BARS_H
|
||||
#define GRAPHS_N_BARS_H
|
||||
#include <stddef.h>
|
||||
#include <mastodont.h>
|
||||
#include "session.h"
|
||||
|
||||
char* construct_bar_graph_container(char* bars, size_t* size);
|
||||
char* construct_bar(float value, size_t* size);
|
||||
char* construct_hashtags_graph(struct mstdnt_tag* tags,
|
||||
size_t tags_len,
|
||||
size_t days,
|
||||
size_t* ret_size);
|
||||
|
||||
#endif /* GRAPHS_N_BARS_H */
|
|
@ -22,44 +22,7 @@
|
|||
#include "easprintf.h"
|
||||
#include "../config.h"
|
||||
|
||||
// Pages
|
||||
#include "../static/hashtag.ctmpl"
|
||||
#include "../static/hashtag_page.ctmpl"
|
||||
|
||||
#define TAG_SIZE_INITIAL 12
|
||||
|
||||
static unsigned hashtag_history_daily_uses(size_t max, struct mstdnt_history* history, size_t history_len)
|
||||
{
|
||||
unsigned total = 0;
|
||||
|
||||
for (int i = 0; i < history_len && i < max; ++i)
|
||||
total += history[i].uses;
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
char* construct_hashtag(struct mstdnt_tag* hashtag, size_t* size)
|
||||
{
|
||||
// Lol!
|
||||
unsigned hash_size = TAG_SIZE_INITIAL +
|
||||
CLAMP(hashtag_history_daily_uses(7, hashtag->history, hashtag->history_len)*2, 0, 42);
|
||||
|
||||
struct hashtag_template data = {
|
||||
.prefix = config_url_prefix,
|
||||
.tag = hashtag->name,
|
||||
.tag_size = hash_size,
|
||||
};
|
||||
return tmpl_gen_hashtag(&data, size);
|
||||
}
|
||||
|
||||
static char* construct_hashtag_voidwrap(void* passed, size_t index, size_t* res)
|
||||
{
|
||||
return construct_hashtag((struct mstdnt_tag*)passed + index, res);
|
||||
}
|
||||
|
||||
char* construct_hashtags(struct mstdnt_tag* hashtags, size_t size, size_t* ret_size)
|
||||
{
|
||||
if (!(hashtags && size)) return NULL;
|
||||
return construct_func_strings(construct_hashtag_voidwrap, hashtags, size, ret_size);
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <stddef.h>
|
||||
#include <mastodont.h>
|
||||
|
||||
char* construct_hashtag(struct mstdnt_tag* hashtag, size_t* size);
|
||||
char* construct_hashtags(struct mstdnt_tag* hashtags, size_t size, size_t* ret_size);
|
||||
// TODO?
|
||||
|
||||
#endif /* HASHTAG_H */
|
||||
|
|
|
@ -29,10 +29,6 @@
|
|||
#include "lists.h"
|
||||
#include "string_helpers.h"
|
||||
#include "http.h"
|
||||
// Files
|
||||
#include "../static/account.ctmpl"
|
||||
#include "../static/list.ctmpl"
|
||||
#include "../static/lists.ctmpl"
|
||||
|
||||
void content_lists(PATH_ARGS)
|
||||
{
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
#include <curl/curl.h>
|
||||
#include <fcgi_stdio.h>
|
||||
|
||||
// Files
|
||||
#include "../static/login.ctmpl"
|
||||
|
||||
#define LOGIN_SCOPE "read+write+follow+push"
|
||||
|
||||
|
@ -163,7 +161,7 @@ void content_login(PATH_ARGS)
|
|||
|
||||
if (mastodont_register_app(api, &m_args, &args_app, &storage, &app) != 0)
|
||||
{
|
||||
error = construct_error(oauth_store.error, E_ERROR, 1, NULL);
|
||||
// error = construct_error(oauth_store.error, E_ERROR, 1, NULL);
|
||||
}
|
||||
else {
|
||||
struct mstdnt_application_args args_token = {
|
||||
|
@ -183,7 +181,7 @@ void content_login(PATH_ARGS)
|
|||
&oauth_store,
|
||||
&token) != 0 && oauth_store.error)
|
||||
{
|
||||
error = construct_error(oauth_store.error, E_ERROR, 1, NULL);
|
||||
//error = construct_error(oauth_store.error, E_ERROR, 1, NULL);
|
||||
}
|
||||
else {
|
||||
if (url_link)
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
/*
|
||||
* Treebird - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "navigation.h"
|
||||
#include "easprintf.h"
|
||||
|
||||
// Pages
|
||||
#include "../static/navigation.ctmpl"
|
||||
|
||||
#define SUBMIT_HTML "<input type=\"submit\" class=\"hidden\">"
|
||||
|
||||
char* construct_navigation_box(char* start_id,
|
||||
char* prev_id,
|
||||
char* next_id,
|
||||
size_t* size)
|
||||
{
|
||||
int is_start = start_id && prev_id ? strcmp(start_id, prev_id) == 0 : 0;
|
||||
|
||||
struct navigation_template tdata = {
|
||||
.start_id = start_id,
|
||||
.min_id = prev_id,
|
||||
.prev_active = is_start ? "btn-disabled" : NULL,
|
||||
.prev_submit = is_start ? "" : SUBMIT_HTML,
|
||||
.max_id = next_id
|
||||
};
|
||||
return tmpl_gen_navigation(&tdata, size);
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
* Treebird - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NAVIGATION_H
|
||||
#define NAVIGATION_H
|
||||
#include <stddef.h>
|
||||
#include <mastodont.h>
|
||||
|
||||
char* construct_navigation_box(char* start_id,
|
||||
char* prev_id,
|
||||
char* next_id,
|
||||
size_t* size);
|
||||
|
||||
#endif // NAVIGATION_H
|
|
@ -25,7 +25,6 @@
|
|||
#include "base_page.h"
|
||||
#include "string_helpers.h"
|
||||
#include "easprintf.h"
|
||||
#include "navigation.h"
|
||||
#include "http.h"
|
||||
#include "status.h"
|
||||
#include "error.h"
|
||||
|
@ -33,165 +32,6 @@
|
|||
#include "account.h"
|
||||
#include "../config.h"
|
||||
|
||||
// Pages
|
||||
#include "../static/notifications_page.ctmpl"
|
||||
#include "../static/notifications.ctmpl"
|
||||
#include "../static/notification_action.ctmpl"
|
||||
#include "../static/notification.ctmpl"
|
||||
#include "../static/notification_compact.ctmpl"
|
||||
#include "../static/like_svg.ctmpl"
|
||||
#include "../static/repeat_svg.ctmpl"
|
||||
#include "../static/notifications_embed.ctmpl"
|
||||
|
||||
struct notification_args
|
||||
{
|
||||
struct session* ssn;
|
||||
mastodont_t* api;
|
||||
struct mstdnt_notification* notifs;
|
||||
};
|
||||
|
||||
char* construct_notification(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_notification* notif,
|
||||
size_t* size)
|
||||
{
|
||||
char* notif_html;
|
||||
|
||||
if (notif->status)
|
||||
{
|
||||
// Construct status with notification_info
|
||||
notif_html = construct_status(ssn, api, notif->status, size, notif, NULL, 0);
|
||||
}
|
||||
else {
|
||||
notif_html = construct_notification_action(notif, size);
|
||||
}
|
||||
|
||||
return notif_html;
|
||||
}
|
||||
|
||||
char* construct_notification_action(struct mstdnt_notification* notif, size_t* size)
|
||||
{
|
||||
char* res;
|
||||
char* serialized_display_name = sanitize_html(notif->account->display_name);
|
||||
char* display_name = emojify(serialized_display_name,
|
||||
notif->account->emojis,
|
||||
notif->account->emojis_len);
|
||||
struct notification_action_template tdata = {
|
||||
.avatar = notif->account->avatar,
|
||||
.acct = notif->account->acct,
|
||||
.display_name = display_name,
|
||||
.prefix = config_url_prefix,
|
||||
.action = notification_type_compact_str(notif->type),
|
||||
.notif_svg = notification_type_svg(notif->type)
|
||||
};
|
||||
res = tmpl_gen_notification_action(&tdata, size);
|
||||
/* // Cleanup */
|
||||
if (display_name != notif->account->display_name &&
|
||||
display_name != serialized_display_name)
|
||||
free(display_name);
|
||||
if (serialized_display_name != notif->account->display_name)
|
||||
free(serialized_display_name);
|
||||
return res;
|
||||
}
|
||||
|
||||
char* construct_notification_compact(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_notification* notif,
|
||||
size_t* size)
|
||||
{
|
||||
char* notif_html;
|
||||
char* status_format = NULL;
|
||||
char* notif_stats = NULL;
|
||||
|
||||
const char* type_str = notification_type_compact_str(notif->type);
|
||||
const char* type_svg = notification_type_svg(notif->type);
|
||||
|
||||
if (notif->status)
|
||||
{
|
||||
if (notif->type == MSTDNT_NOTIFICATION_MENTION)
|
||||
notif_stats = construct_interaction_buttons(ssn, notif->status, NULL,
|
||||
STATUS_NO_LIKEBOOST | STATUS_NO_DOPAMEME);
|
||||
status_format = reformat_status(ssn,
|
||||
notif->status->content,
|
||||
notif->status->emojis,
|
||||
notif->status->emojis_len);
|
||||
}
|
||||
|
||||
char* serialized_display_name = sanitize_html(notif->account->display_name);
|
||||
char* display_name = emojify(serialized_display_name,
|
||||
notif->account->emojis,
|
||||
notif->account->emojis_len);
|
||||
struct notification_compact_template tdata = {
|
||||
.avatar = notif->account->avatar,
|
||||
.has_icon = strlen(type_svg) == 0 ? "" : "-with-icon",
|
||||
.acct = notif->account->acct,
|
||||
.display_name = display_name,
|
||||
.action = type_str,
|
||||
.notif_svg = type_svg,
|
||||
.is_status = (notif->type == MSTDNT_NOTIFICATION_STATUS ||
|
||||
notif->type == MSTDNT_NOTIFICATION_MENTION ? "is-mention" : NULL),
|
||||
/* Might show follower address */
|
||||
.content = (notif->type == MSTDNT_NOTIFICATION_FOLLOW ?
|
||||
notif->account->acct : status_format),
|
||||
.stats = notif_stats
|
||||
};
|
||||
|
||||
notif_html = tmpl_gen_notification_compact(&tdata, size);
|
||||
|
||||
if (status_format &&
|
||||
status_format != notif->status->content) free(status_format);
|
||||
if (notif_stats) free(notif_stats);
|
||||
if (serialized_display_name != notif->account->display_name)
|
||||
free(serialized_display_name);
|
||||
if (display_name != notif->account->display_name &&
|
||||
display_name != serialized_display_name)
|
||||
free(display_name);
|
||||
return notif_html;
|
||||
}
|
||||
|
||||
static char* construct_notification_voidwrap(void* passed, size_t index, size_t* res)
|
||||
{
|
||||
struct notification_args* args = passed;
|
||||
return construct_notification(args->ssn, args->api, args->notifs + index, res);
|
||||
}
|
||||
|
||||
static char* construct_notification_compact_voidwrap(void* passed, size_t index, size_t* res)
|
||||
{
|
||||
struct notification_args* args = passed;
|
||||
return construct_notification_compact(args->ssn, args->api, args->notifs + index, res);
|
||||
}
|
||||
|
||||
char* construct_notifications(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_notification* notifs,
|
||||
size_t size,
|
||||
size_t* ret_size)
|
||||
{
|
||||
struct notification_args args = {
|
||||
.ssn = ssn,
|
||||
.api = api,
|
||||
.notifs = notifs
|
||||
};
|
||||
return construct_func_strings(construct_notification_voidwrap, &args, size, ret_size);
|
||||
}
|
||||
|
||||
char* construct_notifications_compact(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_notification* notifs,
|
||||
size_t size,
|
||||
size_t* ret_size)
|
||||
{
|
||||
struct notification_args args = {
|
||||
.ssn = ssn,
|
||||
.api = api,
|
||||
.notifs = notifs
|
||||
};
|
||||
return construct_func_strings(construct_notification_compact_voidwrap,
|
||||
&args,
|
||||
size,
|
||||
ret_size);
|
||||
}
|
||||
|
||||
void content_notifications(PATH_ARGS)
|
||||
{
|
||||
struct mstdnt_args m_args;
|
||||
|
|
|
@ -23,29 +23,8 @@
|
|||
#include <fcgiapp.h>
|
||||
#include "session.h"
|
||||
#include "path.h"
|
||||
#include "type_string.h"
|
||||
#include "global_perl.h"
|
||||
|
||||
char* construct_notification(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_notification* notif,
|
||||
size_t* size);
|
||||
char* construct_notification_action(struct mstdnt_notification* notif, size_t* size);
|
||||
char* construct_notification_compact(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_notification* notif,
|
||||
size_t* size);
|
||||
char* construct_notifications(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_notification* notifs,
|
||||
size_t size,
|
||||
size_t* ret_size);
|
||||
char* construct_notifications_compact(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_notification* notifs,
|
||||
size_t size,
|
||||
size_t* ret_size);
|
||||
|
||||
// Page contents
|
||||
void content_notifications(PATH_ARGS);
|
||||
void content_notifications_compact(PATH_ARGS);
|
||||
|
|
|
@ -31,11 +31,6 @@
|
|||
#include "l10n.h"
|
||||
#include <fcgi_stdio.h>
|
||||
|
||||
// Pages
|
||||
#include "../static/config_general.ctmpl"
|
||||
#include "../static/config_appearance.ctmpl"
|
||||
#include "../static/config_sidebar.ctmpl"
|
||||
|
||||
#define bool_checked(key) (ssn->config.key ? "checked" : "")
|
||||
|
||||
enum config_category
|
||||
|
|
183
src/reply.c
183
src/reply.c
|
@ -1,183 +0,0 @@
|
|||
/*
|
||||
* Treebird - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define PCRE2_CODE_UNIT_WIDTH 8
|
||||
|
||||
#include <pcre2.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "reply.h"
|
||||
#include "easprintf.h"
|
||||
#include "../config.h"
|
||||
|
||||
// Pages
|
||||
#include "../static/post.ctmpl"
|
||||
|
||||
#define ID_REPLY_SIZE 256
|
||||
#define ID_RESPONSE "<input type=\"hidden\" name=\"replyid\" value=\"%s\">"
|
||||
|
||||
char* construct_post_box(struct mstdnt_status* reply_status,
|
||||
char* default_content,
|
||||
size_t* size)
|
||||
{
|
||||
#define C_S "checked"
|
||||
#define D_S "disabled"
|
||||
char* reply_html;
|
||||
char id_reply[ID_REPLY_SIZE];
|
||||
enum mstdnt_visibility_type vis = MSTDNT_VISIBILITY_PUBLIC;
|
||||
|
||||
// Put hidden post request and check visibility
|
||||
if (reply_status)
|
||||
{
|
||||
snprintf(id_reply, ID_REPLY_SIZE, ID_RESPONSE, reply_status->id);
|
||||
vis = reply_status->visibility;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mastodont-c orders the visibility type from smallest (PUBLIC) to
|
||||
* largest (LOCAL), so we take advantage of the enum values
|
||||
*/
|
||||
struct post_template tdata = {
|
||||
.prefix = config_url_prefix,
|
||||
.reply_input = reply_status ? id_reply : NULL,
|
||||
.content = default_content,
|
||||
.public_checked = vis == MSTDNT_VISIBILITY_PUBLIC ? C_S : NULL,
|
||||
// You can reply with public to unlisted posts
|
||||
.public_disabled = vis > MSTDNT_VISIBILITY_UNLISTED ? D_S : NULL,
|
||||
.unlisted_checked = vis == MSTDNT_VISIBILITY_UNLISTED ? C_S : NULL,
|
||||
.unlisted_disabled = vis > MSTDNT_VISIBILITY_UNLISTED ? D_S : NULL,
|
||||
.private_checked = vis == MSTDNT_VISIBILITY_PRIVATE ? C_S : NULL,
|
||||
.private_disabled = vis > MSTDNT_VISIBILITY_PRIVATE ? D_S : NULL,
|
||||
.direct_checked = vis == MSTDNT_VISIBILITY_DIRECT ? C_S : NULL,
|
||||
.local_checked = vis == MSTDNT_VISIBILITY_LOCAL ? C_S : NULL,
|
||||
};
|
||||
return tmpl_gen_post(&tdata, size);
|
||||
}
|
||||
|
||||
/* Some comments:
|
||||
* - Misskey does not return <span>, but we still regex to make sure it's a highlight
|
||||
* - The order of parameters in a tag can be changed (mastodon does this),
|
||||
* so we just grep for regex href
|
||||
* - Misskey/Mastodon adds an @ symbol in the href param, while pleroma adds /users and honk adds /u
|
||||
*/
|
||||
#define REGEX_REPLY "<a .*?href=\"https?:\\/\\/(.*?)\\/(?:@|users/|u/)?(.*?)?\".*?>@(?:<span>)?.*?(?:<\\/span>)?"
|
||||
|
||||
char* reply_status(struct session* ssn, char* id, struct mstdnt_status* status)
|
||||
{
|
||||
char* content = status->content;
|
||||
size_t content_len = strlen(status->content);
|
||||
char* stat_reply;
|
||||
// Regex
|
||||
pcre2_code* re;
|
||||
PCRE2_SIZE* re_results;
|
||||
pcre2_match_data* re_data;
|
||||
// Regex data
|
||||
int rc;
|
||||
int error;
|
||||
PCRE2_SIZE erroffset;
|
||||
int url_off, url_len, name_off, name_len;
|
||||
// Replies
|
||||
size_t replies_size = 0, replies_size_orig;
|
||||
char* replies = NULL;
|
||||
char* instance_domain = malloc(sizeof(config_instance_url)+sizeof("https:///")+1);
|
||||
|
||||
// sscanf instead of regex works here and requires less work, we just need to trim off the slash at the end
|
||||
if (sscanf(config_instance_url, "https://%s/", instance_domain) == 0)
|
||||
if (sscanf(config_instance_url, "http://%s/", instance_domain) == 0)
|
||||
{
|
||||
free(instance_domain);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
instance_domain[strlen(instance_domain)] = '\0';
|
||||
// Remove ports, if any. Needed for development or if
|
||||
// the server actually supports these
|
||||
char* port_val = strchr(instance_domain, ':');
|
||||
if (port_val) *port_val = '\0';
|
||||
|
||||
// Load first reply
|
||||
if (ssn->logged_in && strcmp(status->account.acct, ssn->acct.acct) != 0)
|
||||
{
|
||||
replies = malloc(replies_size = strlen(status->account.acct)+2);
|
||||
replies[0] = '@';
|
||||
strcpy(replies+1, status->account.acct);
|
||||
replies[replies_size-1] = ' ';
|
||||
}
|
||||
|
||||
// Compile regex
|
||||
re = pcre2_compile((PCRE2_SPTR)REGEX_REPLY, PCRE2_ZERO_TERMINATED, 0, &error, &erroffset, NULL);
|
||||
if (re == NULL)
|
||||
{
|
||||
fprintf(stderr, "Couldn't parse regex at offset %ld: %d\n", erroffset, error);
|
||||
free(replies);
|
||||
pcre2_code_free(re);
|
||||
}
|
||||
|
||||
re_data = pcre2_match_data_create_from_pattern(re, NULL);
|
||||
|
||||
for (int ind = 0;;)
|
||||
{
|
||||
rc = pcre2_match(re, (PCRE2_SPTR)content, content_len, ind, 0, re_data, NULL);
|
||||
if (rc < 0)
|
||||
break;
|
||||
|
||||
re_results = pcre2_get_ovector_pointer(re_data);
|
||||
|
||||
// Store to last result
|
||||
ind = re_results[5];
|
||||
|
||||
// Read out
|
||||
url_off = re_results[2];
|
||||
url_len = re_results[3] - url_off;
|
||||
name_off = re_results[4];
|
||||
name_len = re_results[5] - name_off;
|
||||
|
||||
int instance_cmp = strncmp(instance_domain, content+url_off, url_len);
|
||||
// Is this the same as us?
|
||||
// Cut off url_len by one to slice the '/' at the end
|
||||
if (instance_cmp == 0 &&
|
||||
strncmp(ssn->acct.acct, content+name_off, name_len) == 0)
|
||||
continue;
|
||||
|
||||
replies_size_orig = replies_size;
|
||||
replies_size += (instance_cmp!=0?url_len:0)+name_len+3-(instance_cmp==0); // Bool as int :^)
|
||||
|
||||
// Realloc string
|
||||
replies = realloc(replies, replies_size+1);
|
||||
|
||||
replies[replies_size_orig] = '@';
|
||||
memcpy(replies + replies_size_orig + 1, content + name_off, name_len);
|
||||
if (instance_cmp != 0)
|
||||
{
|
||||
replies[replies_size_orig+1+name_len] = '@';
|
||||
memcpy(replies + replies_size_orig + 1 + name_len + 1, content + url_off, url_len);
|
||||
}
|
||||
replies[replies_size-1] = ' ';
|
||||
}
|
||||
|
||||
if (replies)
|
||||
replies[replies_size-1] = '\0';
|
||||
|
||||
pcre2_match_data_free(re_data);
|
||||
|
||||
stat_reply = construct_post_box(status, replies, NULL);
|
||||
pcre2_code_free(re);
|
||||
free(replies);
|
||||
free(instance_domain);
|
||||
return stat_reply;
|
||||
}
|
34
src/reply.h
34
src/reply.h
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* Treebird - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef REPLY_H
|
||||
#define REPLY_H
|
||||
#include "session.h"
|
||||
#include <stddef.h>
|
||||
#include <mastodont.h>
|
||||
|
||||
char* construct_post_box(struct mstdnt_status* reply_id,
|
||||
char* default_content,
|
||||
size_t* size);
|
||||
|
||||
char* reply_status(struct session* ssn,
|
||||
char* id,
|
||||
struct mstdnt_status* status);
|
||||
|
||||
|
||||
#endif // REPLY_H
|
|
@ -19,35 +19,36 @@
|
|||
#include "scrobble.h"
|
||||
#include "easprintf.h"
|
||||
#include "string_helpers.h"
|
||||
#include "account.h"
|
||||
|
||||
#include "../static/scrobble.ctmpl"
|
||||
|
||||
char* construct_scrobble(struct mstdnt_scrobble* scrobble, size_t* size)
|
||||
// Converts it into a perl struct
|
||||
HV* perlify_scrobble(struct mstdnt_scrobble* scrobble)
|
||||
{
|
||||
struct scrobble_template tdata = {
|
||||
.scrobble_id = scrobble->id,
|
||||
.avatar = scrobble->account.avatar,
|
||||
.username = scrobble->account.display_name,
|
||||
.activity = "is listening to...",
|
||||
.title_key = "Title",
|
||||
.title = scrobble->title,
|
||||
.artist_key = "Artist",
|
||||
.artist = scrobble->artist,
|
||||
.album_key = "Album",
|
||||
.album = scrobble->album,
|
||||
.length_key = "Duration",
|
||||
.length = scrobble->length
|
||||
};
|
||||
if (!scrobble) return NULL;
|
||||
HV* scrobble_hv = newHV();
|
||||
|
||||
return tmpl_gen_scrobble(&tdata, size);
|
||||
hvstores_str(scrobble_hv, "album", scrobble->album);
|
||||
hvstores_str(scrobble_hv, "artist", scrobble->artist);
|
||||
hvstores_str(scrobble_hv, "id", scrobble->id);
|
||||
hvstores_str(scrobble_hv, "title", scrobble->title);
|
||||
hvstores_int(scrobble_hv, "created_at", scrobble->created_at);
|
||||
hvstores_int(scrobble_hv, "length", scrobble->created_at);
|
||||
hvstores_ref(scrobble_hv, "account", perlify_account(&(scrobble->account)));
|
||||
|
||||
return scrobble_hv;
|
||||
}
|
||||
|
||||
static char* construct_scrobble_voidwrap(void* passed, size_t index, size_t* res)
|
||||
// The same as above, but for multiple
|
||||
AV* perlify_scrobbles(struct mstdnt_scrobble* scrobble, size_t len)
|
||||
{
|
||||
return construct_scrobble((struct mstdnt_scrobble*)passed + index, res);
|
||||
}
|
||||
if (!(scrobble && len)) return NULL;
|
||||
AV* av = newAV();
|
||||
av_extend(av, len-1);
|
||||
|
||||
char* construct_scrobbles(struct mstdnt_scrobble* scrobbles, size_t scrobbles_len, size_t* ret_size)
|
||||
{
|
||||
return construct_func_strings(construct_scrobble_voidwrap, scrobbles, scrobbles_len, ret_size);
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
av_store(av, i, newRV_inc((SV*)perlify_scrobble(scrobble + i)));
|
||||
}
|
||||
|
||||
return av;
|
||||
}
|
||||
|
|
|
@ -19,8 +19,9 @@
|
|||
#ifndef SCROBBLE_H
|
||||
#define SCROBBLE_H
|
||||
#include <mastodont.h>
|
||||
#include "global_perl.h"
|
||||
|
||||
char* construct_scrobble(struct mstdnt_scrobble* scrobble, size_t* size);
|
||||
char* construct_scrobbles(struct mstdnt_scrobble* scrobbles, size_t scrobbles_len, size_t* ret_size);
|
||||
HV* perlify_scrobble(struct mstdnt_scrobble* scrobble);
|
||||
AV* perlify_scrobbles(struct mstdnt_scrobble* scrobble, size_t len);
|
||||
|
||||
#endif /* SCROBBLE_H */
|
||||
|
|
36
src/search.c
36
src/search.c
|
@ -28,42 +28,6 @@
|
|||
#include "hashtag.h"
|
||||
#include "error.h"
|
||||
#include "account.h"
|
||||
#include "graphsnbars.h"
|
||||
|
||||
// Pages
|
||||
#include "../static/search.ctmpl"
|
||||
#include "../static/search_all.ctmpl"
|
||||
|
||||
void search_page(FCGX_Request* req,
|
||||
struct session* ssn,
|
||||
mastodont_t* api,
|
||||
enum search_tab tab,
|
||||
char* content)
|
||||
{
|
||||
char* out_data;
|
||||
struct search_template tdata = {
|
||||
.prefix = config_url_prefix,
|
||||
.query = keystr(ssn->query.query),
|
||||
.accounts_active = MAKE_FOCUSED_IF(tab, SEARCH_ACCOUNTS),
|
||||
.accounts = "Accounts",
|
||||
.hashtags_active = MAKE_FOCUSED_IF(tab, SEARCH_HASHTAGS),
|
||||
.hashtags = "Hashtags",
|
||||
.statuses_active = MAKE_FOCUSED_IF(tab, SEARCH_STATUSES),
|
||||
.statuses = "Statuses",
|
||||
.results = content
|
||||
};
|
||||
out_data = tmpl_gen_search(&tdata, NULL);
|
||||
|
||||
struct base_page b = {
|
||||
.category = BASE_CAT_NONE,
|
||||
.content = out_data,
|
||||
.sidebar_left = NULL
|
||||
};
|
||||
|
||||
// Output
|
||||
render_base_page(&b, req, ssn, api);
|
||||
free(out_data);
|
||||
}
|
||||
|
||||
void content_search_all(PATH_ARGS)
|
||||
{
|
||||
|
|
12
src/search.h
12
src/search.h
|
@ -23,18 +23,6 @@
|
|||
#include "path.h"
|
||||
#include "global_perl.h"
|
||||
|
||||
enum search_tab
|
||||
{
|
||||
SEARCH_STATUSES,
|
||||
SEARCH_ACCOUNTS,
|
||||
SEARCH_HASHTAGS,
|
||||
};
|
||||
|
||||
void search_page(FCGX_Request* req,
|
||||
struct session* ssn,
|
||||
mastodont_t* api,
|
||||
enum search_tab tab,
|
||||
char* content);
|
||||
void content_search_all(PATH_ARGS);
|
||||
void content_search_statuses(PATH_ARGS);
|
||||
void content_search_accounts(PATH_ARGS);
|
||||
|
|
585
src/status.c
585
src/status.c
|
@ -30,50 +30,16 @@
|
|||
#include "cookie.h"
|
||||
#include "string_helpers.h"
|
||||
#include "error.h"
|
||||
#include "reply.h"
|
||||
#include "attachments.h"
|
||||
#include "emoji_reaction.h"
|
||||
#include "../config.h"
|
||||
#include "type_string.h"
|
||||
#include "string.h"
|
||||
#include "emoji.h"
|
||||
#include "account.h"
|
||||
|
||||
// Pages
|
||||
#include "../static/status.ctmpl"
|
||||
#include "../static/notification.ctmpl"
|
||||
#include "../static/in_reply_to.ctmpl"
|
||||
#include "../static/status_interactions_label.ctmpl"
|
||||
#include "../static/status_interactions.ctmpl"
|
||||
#include "../static/status_interaction_profile.ctmpl"
|
||||
#include "../static/interactions_page.ctmpl"
|
||||
#include "../static/likeboost.ctmpl"
|
||||
#include "../static/reactions_btn.ctmpl"
|
||||
#include "../static/interaction_buttons.ctmpl"
|
||||
#include "../static/reply_link.ctmpl"
|
||||
#include "../static/reply_checkbox.ctmpl"
|
||||
#include "../static/menu_item.ctmpl"
|
||||
#include "../static/like_btn.ctmpl"
|
||||
#include "../static/repeat_btn.ctmpl"
|
||||
#include "../static/reply_btn.ctmpl"
|
||||
#include "../static/expand_btn.ctmpl"
|
||||
#include "../static/like_btn_img.ctmpl"
|
||||
#include "../static/repeat_btn_img.ctmpl"
|
||||
#include "../static/reply_btn_img.ctmpl"
|
||||
#include "../static/expand_btn_img.ctmpl"
|
||||
#include "../static/thread_page_btn.ctmpl"
|
||||
|
||||
#define ACCOUNT_INTERACTIONS_LIMIT 11
|
||||
#define NUM_STR "%u"
|
||||
|
||||
struct status_args
|
||||
{
|
||||
mastodont_t* api;
|
||||
struct mstdnt_status* status;
|
||||
struct construct_statuses_args* args;
|
||||
struct session* ssn;
|
||||
};
|
||||
|
||||
int try_post_status(struct session* ssn, mastodont_t* api)
|
||||
{
|
||||
if (!(keystr(ssn->post.content))) return 1;
|
||||
|
@ -185,27 +151,6 @@ void content_status_react(PATH_ARGS)
|
|||
redirect(req, REDIRECT_303, referer);
|
||||
}
|
||||
|
||||
const char* status_visibility_str(enum l10n_locale loc,
|
||||
enum mstdnt_visibility_type vis)
|
||||
{
|
||||
switch (vis)
|
||||
{
|
||||
case MSTDNT_VISIBILITY_UNLISTED:
|
||||
return L10N[loc][L10N_VIS_UNLISTED];
|
||||
case MSTDNT_VISIBILITY_PRIVATE:
|
||||
return L10N[loc][L10N_VIS_PRIVATE];
|
||||
case MSTDNT_VISIBILITY_DIRECT:
|
||||
return L10N[loc][L10N_VIS_DIRECT];
|
||||
case MSTDNT_VISIBILITY_LOCAL:
|
||||
return L10N[loc][L10N_VIS_LOCAL];
|
||||
case MSTDNT_VISIBILITY_LIST:
|
||||
return L10N[loc][L10N_VIS_LIST];
|
||||
case MSTDNT_VISIBILITY_PUBLIC:
|
||||
default:
|
||||
return L10N[loc][L10N_VIS_PUBLIC];
|
||||
}
|
||||
}
|
||||
|
||||
int try_interact_status(struct session* ssn, mastodont_t* api, char* id)
|
||||
{
|
||||
struct mstdnt_args m_args;
|
||||
|
@ -245,127 +190,6 @@ int try_interact_status(struct session* ssn, mastodont_t* api, char* id)
|
|||
return res;
|
||||
}
|
||||
|
||||
char* construct_status_interactions_label(char* status_id,
|
||||
int is_favourites,
|
||||
char* header,
|
||||
int val,
|
||||
size_t* size)
|
||||
{
|
||||
struct status_interactions_label_template tdata = {
|
||||
.prefix = config_url_prefix,
|
||||
.status_id = status_id,
|
||||
.action = is_favourites ? "favourited_by" : "reblogged_by",
|
||||
.header = header,
|
||||
.value = val,
|
||||
};
|
||||
return tmpl_gen_status_interactions_label(&tdata, size);
|
||||
}
|
||||
|
||||
char* construct_interaction_buttons(struct session* ssn,
|
||||
struct mstdnt_status* status,
|
||||
size_t* size,
|
||||
uint8_t flags)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
char* construct_status_interactions(char* status_id,
|
||||
int fav_count,
|
||||
int reblog_count,
|
||||
struct mstdnt_account* fav_accounts,
|
||||
size_t fav_accounts_len,
|
||||
struct mstdnt_account* reblog_accounts,
|
||||
size_t reblog_accounts_len,
|
||||
size_t* size)
|
||||
{
|
||||
char* html;
|
||||
char* reblogs_label = reblog_count ?
|
||||
construct_status_interactions_label(status_id, 0, "Reblogs", reblog_count, NULL) : NULL;
|
||||
char* favourites_label = fav_count ?
|
||||
construct_status_interactions_label(status_id, 1, "Favorites", fav_count, NULL) : NULL;
|
||||
char* profiles = construct_status_interaction_profiles(reblog_accounts,
|
||||
fav_accounts,
|
||||
reblog_accounts_len,
|
||||
fav_accounts_len,
|
||||
NULL);
|
||||
struct status_interactions_template tdata = {
|
||||
.favourites_count = favourites_label,
|
||||
.reblogs_count = reblogs_label,
|
||||
.users = profiles
|
||||
};
|
||||
html = tmpl_gen_status_interactions(&tdata, size);
|
||||
if (reblogs_label) free(reblogs_label);
|
||||
if (favourites_label) free(favourites_label);
|
||||
if (profiles) free(profiles);
|
||||
return html;
|
||||
}
|
||||
|
||||
char* construct_status_interaction_profile(struct interact_profile_args* args, size_t index, size_t* size)
|
||||
{
|
||||
size_t s = 0;
|
||||
// Might change
|
||||
struct mstdnt_account* check_type = args->reblogs;
|
||||
char* profile_html = NULL;
|
||||
|
||||
// Loop through reblogs first, then favourites
|
||||
if (index >= args->reblogs_len)
|
||||
{
|
||||
index -= args->reblogs_len;
|
||||
check_type = args->favourites;
|
||||
}
|
||||
|
||||
// If favourites, loops through reblogs to verify no duplicates
|
||||
if (check_type == args->favourites)
|
||||
{
|
||||
for (size_t i = 0; i < args->reblogs_len; ++i)
|
||||
if (strcmp(check_type[index].id, args->reblogs[i].id) == 0)
|
||||
{
|
||||
if (size) *size = 0;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Usually means no reblogs if check_type is NULL
|
||||
if (check_type)
|
||||
{
|
||||
struct status_interaction_profile_template tdata = {
|
||||
.acct = check_type[index].acct,
|
||||
.avatar = check_type[index].avatar
|
||||
};
|
||||
profile_html = tmpl_gen_status_interaction_profile(&tdata, &s);
|
||||
}
|
||||
|
||||
if (size) *size = s;
|
||||
return profile_html;
|
||||
}
|
||||
|
||||
static char* construct_status_interaction_profiles_voidwrap(void* passed, size_t index, size_t* res)
|
||||
{
|
||||
struct interact_profile_args* args = passed;
|
||||
return construct_status_interaction_profile(args, index, res);
|
||||
}
|
||||
|
||||
char* construct_status_interaction_profiles(struct mstdnt_account* reblogs,
|
||||
struct mstdnt_account* favourites,
|
||||
size_t reblogs_len,
|
||||
size_t favourites_len,
|
||||
size_t* ret_size)
|
||||
{
|
||||
size_t arr_size = reblogs_len + favourites_len;
|
||||
// Set a limit to interactions
|
||||
if (arr_size > ACCOUNT_INTERACTIONS_LIMIT)
|
||||
arr_size = ACCOUNT_INTERACTIONS_LIMIT;
|
||||
|
||||
struct interact_profile_args args = {
|
||||
.reblogs = reblogs,
|
||||
.reblogs_len = reblogs_len,
|
||||
.favourites = favourites,
|
||||
.favourites_len = favourites_len
|
||||
};
|
||||
|
||||
return construct_func_strings(construct_status_interaction_profiles_voidwrap, &args, arr_size, ret_size);
|
||||
}
|
||||
|
||||
char* get_in_reply_to(mastodont_t* api,
|
||||
struct session* ssn,
|
||||
struct mstdnt_status* status,
|
||||
|
@ -383,418 +207,15 @@ char* get_in_reply_to(mastodont_t* api,
|
|||
&acct,
|
||||
&storage);
|
||||
|
||||
char* html = construct_in_reply_to(status, res == 0 ? &acct : NULL, size);
|
||||
char* html = "TODO";
|
||||
|
||||
// char* html = construct_in_reply_to(status, res == 0 ? &acct : NULL, size);
|
||||
|
||||
if (res == 0) mstdnt_cleanup_account(&acct);
|
||||
mastodont_storage_cleanup(&storage);
|
||||
return html;
|
||||
}
|
||||
|
||||
char* construct_in_reply_to(struct mstdnt_status* status,
|
||||
struct mstdnt_account* account,
|
||||
size_t* size)
|
||||
{
|
||||
struct in_reply_to_template tdata = {
|
||||
.prefix = config_url_prefix,
|
||||
.in_reply_to_text = L10N[L10N_EN_US][L10N_IN_REPLY_TO],
|
||||
.acct = account ? account->acct : status->in_reply_to_id,
|
||||
.status_id = status->in_reply_to_id
|
||||
};
|
||||
|
||||
return tmpl_gen_in_reply_to(&tdata, size);
|
||||
}
|
||||
|
||||
#define REGEX_GREENTEXT "((?:^|<br/?>|\\s)>.*?)(?:<br/?>|$)"
|
||||
|
||||
char* reformat_status(struct session* ssn,
|
||||
char* content,
|
||||
struct mstdnt_emoji* emos,
|
||||
size_t emos_len)
|
||||
{
|
||||
if (!content) return NULL;
|
||||
char* res = make_mentions_local(content);
|
||||
char* gt_res, *emo_res;
|
||||
|
||||
if (emos)
|
||||
{
|
||||
emo_res = emojify(res, emos, emos_len);
|
||||
if (emo_res != res && res != content)
|
||||
free(res);
|
||||
res = emo_res;
|
||||
}
|
||||
|
||||
if (ssn->config.stat_greentexts)
|
||||
{
|
||||
gt_res = greentextify(res);
|
||||
if (gt_res != res && res != content)
|
||||
free(res);
|
||||
res = gt_res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
#define REGEX_MENTION "(?=<a .*?mention.*?)<a .*?href=\"https?:\\/\\/(?<url>.*?)\\/(?:@|users\\/)?(?<>.*?)?\".*?>"
|
||||
|
||||
char* make_mentions_local(char* content)
|
||||
{
|
||||
char* url_format;
|
||||
int error;
|
||||
PCRE2_SIZE erroffset;
|
||||
int substitute_success = 0;
|
||||
// Initial size, will be increased by 30% if pcre2_substitute cannot fit into the size
|
||||
// ...why can't pcre2 just allocate a string with the size for us? Thanks...
|
||||
size_t res_len = 1024;
|
||||
char* res = malloc(res_len);
|
||||
pcre2_code* re = pcre2_compile((PCRE2_SPTR)REGEX_MENTION,
|
||||
PCRE2_ZERO_TERMINATED, PCRE2_MULTILINE,
|
||||
&error, &erroffset, NULL);
|
||||
if (re == NULL)
|
||||
{
|
||||
fprintf(stderr, "Couldn't parse regex at offset %d: %s\n", error, REGEX_MENTION + erroffset);
|
||||
pcre2_code_free(re);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int len = easprintf(&url_format,
|
||||
"<a target=\"_parent\" class=\"mention\" href=\"http%s://%s/@$2@$1\">",
|
||||
config_host_url_insecure ? "" : "s",
|
||||
getenv("HTTP_HOST"));
|
||||
|
||||
int rc = -1;
|
||||
PCRE2_SIZE res_len_str;
|
||||
while (rc < 0)
|
||||
{
|
||||
res_len_str = res_len;
|
||||
rc = pcre2_substitute(
|
||||
re,
|
||||
(PCRE2_SPTR)content,
|
||||
PCRE2_ZERO_TERMINATED,
|
||||
0,
|
||||
PCRE2_SUBSTITUTE_EXTENDED | PCRE2_SUBSTITUTE_GLOBAL,
|
||||
NULL,
|
||||
NULL,
|
||||
(PCRE2_SPTR)url_format,
|
||||
len,
|
||||
(PCRE2_UCHAR*)res,
|
||||
&res_len_str
|
||||
);
|
||||
if (rc < 0)
|
||||
{
|
||||
switch (rc)
|
||||
{
|
||||
case PCRE2_ERROR_NOMEMORY:
|
||||
// Increase by 30% and try again
|
||||
res_len = (float)res_len + ((float)res_len * .3);
|
||||
res = realloc(res, res_len);
|
||||
break;
|
||||
default:
|
||||
{
|
||||
char buf[256];
|
||||
pcre2_get_error_message(rc, buf, 256);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
substitute_success = 1;
|
||||
}
|
||||
|
||||
out:
|
||||
if (!substitute_success)
|
||||
free(res);
|
||||
free(url_format);
|
||||
pcre2_code_free(re);
|
||||
return substitute_success ? res : content;
|
||||
}
|
||||
|
||||
char* greentextify(char* content)
|
||||
{
|
||||
if (!content) return NULL;
|
||||
|
||||
int error;
|
||||
PCRE2_SIZE erroffset;
|
||||
int rc;
|
||||
int gt_off;
|
||||
int gt_len;
|
||||
char* res = content;
|
||||
|
||||
// Malloc'd strings
|
||||
char* reg_string;
|
||||
char* gt_string;
|
||||
|
||||
char* oldres = NULL;
|
||||
PCRE2_SIZE* re_results;
|
||||
pcre2_code* re = pcre2_compile((PCRE2_SPTR)REGEX_GREENTEXT, PCRE2_ZERO_TERMINATED, 0, &error, &erroffset, NULL);
|
||||
pcre2_match_data* re_data;
|
||||
if (re == NULL)
|
||||
{
|
||||
fprintf(stderr, "Couldn't parse regex at offset %ld: %d\n", erroffset, error);
|
||||
pcre2_code_free(re);
|
||||
return res;
|
||||
}
|
||||
|
||||
re_data = pcre2_match_data_create_from_pattern(re, NULL);
|
||||
|
||||
for (int ind = 0;;)
|
||||
{
|
||||
rc = pcre2_match(re, (PCRE2_SPTR)res, strlen(res), ind, 0, re_data, NULL);
|
||||
if (rc < 0)
|
||||
break;
|
||||
|
||||
re_results = pcre2_get_ovector_pointer(re_data);
|
||||
|
||||
// Store to last result
|
||||
gt_off = re_results[2];
|
||||
gt_len = re_results[3] - gt_off;
|
||||
|
||||
oldres = res;
|
||||
|
||||
// Malloc find/repl strings
|
||||
reg_string = malloc(gt_len + 1);
|
||||
strncpy(reg_string, res + gt_off, gt_len);
|
||||
reg_string[gt_len] = '\0';
|
||||
easprintf(>_string, "<span class=\"greentext\">%s</span>", reg_string);
|
||||
|
||||
res = strrepl(res, reg_string, gt_string, STRREPL_ALL );
|
||||
if (oldres != content) free(oldres);
|
||||
ind = re_results[2] + strlen(gt_string);
|
||||
free(reg_string);
|
||||
free(gt_string);
|
||||
}
|
||||
|
||||
pcre2_match_data_free(re_data);
|
||||
pcre2_code_free(re);
|
||||
return res;
|
||||
}
|
||||
|
||||
char* construct_status(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_status* local_status,
|
||||
size_t* size,
|
||||
struct mstdnt_notification* local_notif,
|
||||
struct construct_statuses_args* args,
|
||||
uint8_t flags)
|
||||
{
|
||||
struct mstdnt_args m_args;
|
||||
set_mstdnt_args(&m_args, ssn);
|
||||
char* stat_html;
|
||||
|
||||
// Counts
|
||||
char* formatted_display_name = NULL;
|
||||
char* attachments = NULL;
|
||||
char* emoji_reactions = NULL;
|
||||
char* serialized_display_name = NULL;
|
||||
char* interaction_btns = NULL;
|
||||
char* notif_info = NULL;
|
||||
char* post_response = NULL;
|
||||
char* in_reply_to_str = NULL;
|
||||
char* delete_status = NULL;
|
||||
char* pin_status = NULL;
|
||||
char* interactions_html = NULL;
|
||||
enum l10n_locale locale = l10n_normalize(ssn->config.lang);
|
||||
struct mstdnt_status* status = local_status;
|
||||
// Create a "fake" notification header which contains information for
|
||||
// the reblogged status
|
||||
struct mstdnt_notification notif_reblog;
|
||||
struct mstdnt_notification* notif = local_notif;
|
||||
struct mstdnt_account* favourites = NULL;
|
||||
struct mstdnt_account* reblogs = NULL;
|
||||
struct mstdnt_storage favourites_storage = { 0 };
|
||||
struct mstdnt_storage reblogs_storage = { 0 };
|
||||
size_t favourites_len = 0;
|
||||
size_t reblogs_len = 0;
|
||||
|
||||
if (!status) return NULL;
|
||||
|
||||
// If focused, show status interactions
|
||||
if ((flags & STATUS_FOCUSED) == STATUS_FOCUSED &&
|
||||
(status->reblogs_count || status->favourites_count))
|
||||
{
|
||||
if (status->favourites_count)
|
||||
mastodont_status_favourited_by(api,
|
||||
&m_args,
|
||||
status->id,
|
||||
&favourites_storage,
|
||||
&favourites,
|
||||
&favourites_len);
|
||||
if (status->reblogs_count)
|
||||
mastodont_status_reblogged_by(api,
|
||||
&m_args,
|
||||
status->id,
|
||||
&reblogs_storage,
|
||||
&reblogs,
|
||||
&reblogs_len);
|
||||
interactions_html = construct_status_interactions(status->id,
|
||||
status->favourites_count,
|
||||
status->reblogs_count,
|
||||
favourites,
|
||||
favourites_len,
|
||||
reblogs,
|
||||
reblogs_len,
|
||||
NULL);
|
||||
mastodont_storage_cleanup(&reblogs_storage);
|
||||
mastodont_storage_cleanup(&favourites_storage);
|
||||
|
||||
mstdnt_cleanup_accounts(favourites, favourites_len);
|
||||
mstdnt_cleanup_accounts(reblogs, reblogs_len);
|
||||
}
|
||||
|
||||
// Repoint value if it's a reblog
|
||||
if (status->reblog)
|
||||
{
|
||||
status = status->reblog;
|
||||
// Point to our account
|
||||
notif_reblog.account = &(local_status->account);
|
||||
notif_reblog.type = MSTDNT_NOTIFICATION_REBLOG;
|
||||
notif = ¬if_reblog;
|
||||
}
|
||||
|
||||
// Format username with emojis
|
||||
serialized_display_name = sanitize_html(status->account.display_name);
|
||||
formatted_display_name = emojify(serialized_display_name,
|
||||
status->account.emojis,
|
||||
status->account.emojis_len);
|
||||
// Format status
|
||||
char* parse_content = reformat_status(ssn, status->content, status->emojis, status->emojis_len);
|
||||
|
||||
interaction_btns = construct_interaction_buttons(ssn, status, NULL, flags);
|
||||
|
||||
// Find and replace
|
||||
if (args && args->highlight_word && parse_content != status->content)
|
||||
{
|
||||
char* parse_content_tmp;
|
||||
char* repl_str = NULL;
|
||||
easprintf(&repl_str, "<span class=\"search-highlight\">%s</span>", 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 &&
|
||||
parse_content != parse_content_tmp)
|
||||
free(parse_content_tmp);
|
||||
else // No results, move back
|
||||
parse_content = parse_content_tmp;
|
||||
|
||||
free(repl_str);
|
||||
}
|
||||
|
||||
if (ssn->logged_in)
|
||||
post_response = reply_status(ssn, status->in_reply_to_account_id , status);
|
||||
|
||||
// Delete status menu item and pinned, logged in only
|
||||
if (ssn->logged_in && strcmp(status->account.acct, ssn->acct.acct) == 0)
|
||||
{
|
||||
struct menu_item_template mdata = {
|
||||
.prefix = config_url_prefix,
|
||||
.status_id = status->id,
|
||||
.itype = "delete",
|
||||
.text = "Delete status"
|
||||
};
|
||||
delete_status = tmpl_gen_menu_item(&mdata, NULL);
|
||||
|
||||
mdata.itype = status->pinned ? "unpin" : "pin";
|
||||
mdata.text = status->pinned ? "Unpin status" : "Pin status";
|
||||
pin_status = tmpl_gen_menu_item(&mdata, NULL);
|
||||
}
|
||||
|
||||
if (status->media_attachments_len)
|
||||
attachments = construct_attachments(ssn, status->sensitive, status->media_attachments, status->media_attachments_len, NULL);
|
||||
if (status->pleroma.emoji_reactions_len)
|
||||
emoji_reactions = construct_emoji_reactions(status->id, status->pleroma.emoji_reactions, status->pleroma.emoji_reactions_len, NULL);
|
||||
if (notif && notif->type != MSTDNT_NOTIFICATION_MENTION)
|
||||
{
|
||||
char* notif_serialized_name = sanitize_html(notif->account->display_name);
|
||||
char* notif_display_name = emojify(notif_serialized_name,
|
||||
notif->account->emojis,
|
||||
notif->account->emojis_len);
|
||||
struct notification_template tdata = {
|
||||
.avatar = notif->account->avatar,
|
||||
.username = notif_display_name,
|
||||
.action = (local_status->reblog ? notification_type_compact_str(notif->type) : notification_type_str(notif->type)),
|
||||
.action_item = notification_type_svg(notif->type),
|
||||
};
|
||||
notif_info = tmpl_gen_notification(&tdata, NULL);
|
||||
if (notif_display_name != notif->account->display_name)
|
||||
free(notif_display_name);
|
||||
if (notif_serialized_name != notif_display_name &&
|
||||
notif_serialized_name != notif->account->display_name)
|
||||
free(notif_serialized_name);
|
||||
}
|
||||
|
||||
if (status->in_reply_to_id && status->in_reply_to_account_id)
|
||||
in_reply_to_str = get_in_reply_to(api, ssn, status, NULL);
|
||||
|
||||
struct status_template tmpl = {
|
||||
.status_id = status->id,
|
||||
.notif_info = notif_info,
|
||||
.thread_hidden = status->muted ? "checked" : "",
|
||||
// TODO doesn't even need to be a hashtag, this is a temporary hack
|
||||
.is_cat = status->account.note && strstr(status->account.note, "isCat") ? "is-cat" : NULL,
|
||||
.is_bun = status->account.note && strstr(status->account.note, "isBun") ? " is-bun" : NULL,
|
||||
.avatar = status->account.avatar,
|
||||
.username = formatted_display_name,
|
||||
.prefix = config_url_prefix,
|
||||
.acct = status->account.acct,
|
||||
.visibility = status_visibility_str(locale, status->visibility),
|
||||
.unmute = status->muted ? "un" : "",
|
||||
.unmute_btn = status->muted ? "Unmute thread" : "Mute thread",
|
||||
.unbookmark = status->bookmarked ? "un" : "",
|
||||
.unbookmark_btn = status->bookmarked ? "Remove Bookmark" : "Bookmark",
|
||||
.delete_status = delete_status,
|
||||
.pin_status = pin_status,
|
||||
.in_reply_to_str = in_reply_to_str,
|
||||
.status_content = parse_content,
|
||||
.attachments = attachments,
|
||||
.interactions = interactions_html,
|
||||
.emoji_reactions = emoji_reactions,
|
||||
.interaction_btns = interaction_btns,
|
||||
.reply = post_response,
|
||||
};
|
||||
|
||||
stat_html = tmpl_gen_status(&tmpl, size);
|
||||
|
||||
// Cleanup
|
||||
if (formatted_display_name != status->account.display_name &&
|
||||
formatted_display_name != serialized_display_name)
|
||||
free(formatted_display_name);
|
||||
if (serialized_display_name != status->account.display_name)
|
||||
free(serialized_display_name);
|
||||
free(in_reply_to_str);
|
||||
free(attachments);
|
||||
free(post_response);
|
||||
free(emoji_reactions);
|
||||
if (notif) free(notif_info);
|
||||
free(delete_status);
|
||||
free(pin_status);
|
||||
free(interactions_html);
|
||||
if (parse_content != status->content)
|
||||
free(parse_content);
|
||||
return stat_html;
|
||||
}
|
||||
|
||||
static char* construct_status_voidwrap(void* passed, size_t index, size_t* res)
|
||||
{
|
||||
struct status_args* args = passed;
|
||||
return construct_status(args->ssn, args->api, args->status + index, res, NULL, args->args, 0);
|
||||
}
|
||||
|
||||
char* construct_statuses(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_status* statuses,
|
||||
size_t size,
|
||||
struct construct_statuses_args* args,
|
||||
size_t* ret_size)
|
||||
{
|
||||
if (!(statuses && size)) return NULL;
|
||||
struct status_args stat_args = {
|
||||
.api = api,
|
||||
.status = statuses,
|
||||
.args = args,
|
||||
.ssn = ssn,
|
||||
};
|
||||
return construct_func_strings(construct_status_voidwrap, &stat_args, size, ret_size);
|
||||
}
|
||||
|
||||
void status_interact(PATH_ARGS)
|
||||
{
|
||||
char* referer = GET_ENV("HTTP_REFERER", req);
|
||||
|
|
51
src/status.h
51
src/status.h
|
@ -53,64 +53,17 @@ void content_status_create(PATH_ARGS);
|
|||
void content_status_react(PATH_ARGS);
|
||||
|
||||
// HTML Builders
|
||||
char* construct_status(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_status* status,
|
||||
size_t* size,
|
||||
struct mstdnt_notification* notif,
|
||||
struct construct_statuses_args* args,
|
||||
uint8_t flags);
|
||||
char* construct_statuses(struct session* ssn,
|
||||
mastodont_t* api,
|
||||
struct mstdnt_status* statuses,
|
||||
size_t size,
|
||||
struct construct_statuses_args* args,
|
||||
size_t* ret_size);
|
||||
char* construct_interaction_buttons(struct session* ssn,
|
||||
struct mstdnt_status* status,
|
||||
size_t* size,
|
||||
uint8_t flags);
|
||||
|
||||
// Reply to
|
||||
/** Deprecated: May be used in the future for Mastodon only */
|
||||
char* get_in_reply_to(mastodont_t* api,
|
||||
struct session* ssn,
|
||||
struct mstdnt_status* status,
|
||||
size_t* size);
|
||||
char* construct_in_reply_to(struct mstdnt_status* status,
|
||||
struct mstdnt_account* account,
|
||||
size_t* size);
|
||||
|
||||
char* construct_status_interactions(char* status_id,
|
||||
int fav_count,
|
||||
int reblog_count,
|
||||
struct mstdnt_account* fav_accounts,
|
||||
size_t fav_accounts_len,
|
||||
struct mstdnt_account* reblog_accounts,
|
||||
size_t reblog_accounts_len,
|
||||
size_t* size);
|
||||
|
||||
char* construct_status_interaction_profiles(struct mstdnt_account* reblogs,
|
||||
struct mstdnt_account* favourites,
|
||||
size_t reblogs_len,
|
||||
size_t favourites_len,
|
||||
size_t* ret_size);
|
||||
char* construct_status_interaction_profile(struct interact_profile_args* args, size_t index, size_t* size);
|
||||
char* construct_status_interactions_label(char* status_id,
|
||||
int is_favourites,
|
||||
char* header,
|
||||
int val,
|
||||
size_t* size);
|
||||
char* reformat_status(struct session* ssn,
|
||||
char* content,
|
||||
struct mstdnt_emoji* emos,
|
||||
size_t emos_len);
|
||||
char* greentextify(char* content);
|
||||
char* make_mentions_local(char* content);
|
||||
|
||||
void status_view_reblogs(PATH_ARGS);
|
||||
void status_view_favourites(PATH_ARGS);
|
||||
|
||||
const char* status_visibility_str(enum l10n_locale locale, enum mstdnt_visibility_type visibility);
|
||||
|
||||
void content_status_interactions(FCGX_Request* req,
|
||||
struct session* ssn,
|
||||
mastodont_t* api,
|
||||
|
|
|
@ -26,15 +26,10 @@
|
|||
#include "index.h"
|
||||
#include "status.h"
|
||||
#include "easprintf.h"
|
||||
#include "reply.h"
|
||||
#include "navigation.h"
|
||||
#include "query.h"
|
||||
#include "error.h"
|
||||
#include "string_helpers.h"
|
||||
|
||||
#include "../static/timeline_options.ctmpl"
|
||||
#include "../static/navigation.ctmpl"
|
||||
|
||||
void content_timeline(FCGX_Request* req,
|
||||
struct session* ssn,
|
||||
mastodont_t* api,
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
/*
|
||||
* Treebird - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "type_string.h"
|
||||
|
||||
// Icons
|
||||
#include "../static/like_svg.ctmpl"
|
||||
#include "../static/repeat_svg.ctmpl"
|
||||
#include "../static/follow_svg.ctmpl"
|
||||
|
||||
const char* notification_type_str(mstdnt_notification_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MSTDNT_NOTIFICATION_FOLLOW: return L10N[L10N_EN_US][L10N_NOTIF_FOLLOW];
|
||||
case MSTDNT_NOTIFICATION_FOLLOW_REQUEST: return L10N[L10N_EN_US][L10N_NOTIF_FOLLOW_REQUEST];
|
||||
case MSTDNT_NOTIFICATION_REBLOG: return L10N[L10N_EN_US][L10N_NOTIF_REPEATED];
|
||||
case MSTDNT_NOTIFICATION_FAVOURITE: return L10N[L10N_EN_US][L10N_NOTIF_LIKED];
|
||||
case MSTDNT_NOTIFICATION_POLL: return L10N[L10N_EN_US][L10N_NOTIF_POLL];
|
||||
case MSTDNT_NOTIFICATION_EMOJI_REACT: return L10N[L10N_EN_US][L10N_NOTIF_REACTED_WITH];
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
const char* notification_type_compact_str(mstdnt_notification_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MSTDNT_NOTIFICATION_FOLLOW: return L10N[L10N_EN_US][L10N_NOTIF_COMPACT_FOLLOW];
|
||||
case MSTDNT_NOTIFICATION_FOLLOW_REQUEST: return L10N[L10N_EN_US][L10N_NOTIF_COMPACT_FOLLOW_REQUEST];
|
||||
case MSTDNT_NOTIFICATION_REBLOG: return L10N[L10N_EN_US][L10N_NOTIF_COMPACT_REPEATED];
|
||||
case MSTDNT_NOTIFICATION_FAVOURITE: return L10N[L10N_EN_US][L10N_NOTIF_COMPACT_LIKED];
|
||||
case MSTDNT_NOTIFICATION_POLL: return L10N[L10N_EN_US][L10N_NOTIF_COMPACT_POLL];
|
||||
case MSTDNT_NOTIFICATION_EMOJI_REACT: return L10N[L10N_EN_US][L10N_NOTIF_COMPACT_REACTED_WITH];
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char* notification_type_svg(mstdnt_notification_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MSTDNT_NOTIFICATION_FOLLOW: return data_follow_svg;
|
||||
case MSTDNT_NOTIFICATION_FOLLOW_REQUEST: return "";
|
||||
case MSTDNT_NOTIFICATION_REBLOG: return data_repeat_svg;
|
||||
case MSTDNT_NOTIFICATION_FAVOURITE: return data_like_svg;
|
||||
case MSTDNT_NOTIFICATION_POLL: return "";
|
||||
case MSTDNT_NOTIFICATION_EMOJI_REACT: return "";
|
||||
default: return "";
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
* Treebird - Lightweight frontend for Pleroma
|
||||
* Copyright (C) 2022 Nekobit
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TYPE_STRING_H
|
||||
#define TYPE_STRING_H
|
||||
#include <mastodont.h>
|
||||
#include "l10n.h"
|
||||
|
||||
const char* notification_type_svg(mstdnt_notification_t type);
|
||||
const char* notification_type_str(mstdnt_notification_t type);
|
||||
const char* notification_type_compact_str(mstdnt_notification_t type);
|
||||
|
||||
#endif // TYPE_STRING_H
|
Loading…
Reference in a new issue