refactor: internationalise pagination and clean up related code
This commit is contained in:
parent
c6bdeecb2a
commit
614bd26cb3
7 changed files with 191 additions and 158 deletions
|
|
@ -15,6 +15,30 @@ static char *build_images_request_cache_key(const char *query, int page,
|
|||
return cache_compute_key(query, page, scope_key);
|
||||
}
|
||||
|
||||
static char *build_images_href(const char *query, int page) {
|
||||
const char *safe_query = query ? query : "";
|
||||
size_t needed = strlen("/images?q=") + strlen(safe_query) + 1;
|
||||
if (page > 1)
|
||||
needed += strlen("&p=") + 16;
|
||||
|
||||
char *href = (char *)malloc(needed);
|
||||
if (!href)
|
||||
return NULL;
|
||||
|
||||
snprintf(href, needed, "/images?q=%s", safe_query);
|
||||
if (page > 1) {
|
||||
char page_buf[16];
|
||||
snprintf(page_buf, sizeof(page_buf), "%d", page);
|
||||
strcat(href, "&p=");
|
||||
strcat(href, page_buf);
|
||||
}
|
||||
return href;
|
||||
}
|
||||
|
||||
static char *images_href_builder(int page, void *data) {
|
||||
return build_images_href((const char *)data, page);
|
||||
}
|
||||
|
||||
int images_handler(UrlParams *params) {
|
||||
extern Config global_config;
|
||||
TemplateContext ctx = new_context();
|
||||
|
|
@ -33,14 +57,6 @@ int images_handler(UrlParams *params) {
|
|||
}
|
||||
}
|
||||
|
||||
char page_str[16], prev_str[16], next_str[16], two_prev_str[16],
|
||||
two_next_str[16];
|
||||
|
||||
snprintf(page_str, sizeof(page_str), "%d", page);
|
||||
snprintf(prev_str, sizeof(prev_str), "%d", page > 1 ? page - 1 : 0);
|
||||
snprintf(next_str, sizeof(next_str), "%d", page + 1);
|
||||
snprintf(two_prev_str, sizeof(two_prev_str), "%d", page > 2 ? page - 2 : 0);
|
||||
snprintf(two_next_str, sizeof(two_next_str), "%d", page + 2);
|
||||
context_set(&ctx, "query", raw_query);
|
||||
|
||||
char *theme = get_theme("");
|
||||
|
|
@ -55,11 +71,15 @@ int images_handler(UrlParams *params) {
|
|||
const char *error_images_msg = beaker_get_locale_value(locale, "error_images");
|
||||
if (!error_images_msg) error_images_msg = "Error fetching images";
|
||||
|
||||
context_set(&ctx, "page", page_str);
|
||||
context_set(&ctx, "prev_page", prev_str);
|
||||
context_set(&ctx, "next_page", next_str);
|
||||
context_set(&ctx, "two_prev_page", two_prev_str);
|
||||
context_set(&ctx, "two_next_page", two_next_str);
|
||||
char ***pager_matrix = NULL;
|
||||
int *pager_inner_counts = NULL;
|
||||
int pager_count = build_pagination(page, locale, images_href_builder,
|
||||
(void *)raw_query, &pager_matrix,
|
||||
&pager_inner_counts);
|
||||
if (pager_count > 0) {
|
||||
context_set_array_of_arrays(&ctx, "pagination_links", pager_matrix,
|
||||
pager_count, pager_inner_counts);
|
||||
}
|
||||
|
||||
char *display_query = url_decode_query(raw_query);
|
||||
context_set(&ctx, "query", display_query);
|
||||
|
|
@ -170,6 +190,16 @@ int images_handler(UrlParams *params) {
|
|||
free(image_matrix);
|
||||
free(inner_counts);
|
||||
|
||||
if (pager_count > 0) {
|
||||
for (int i = 0; i < pager_count; i++) {
|
||||
for (int j = 0; j < LINK_FIELD_COUNT; j++)
|
||||
free(pager_matrix[i][j]);
|
||||
free(pager_matrix[i]);
|
||||
}
|
||||
free(pager_matrix);
|
||||
free(pager_inner_counts);
|
||||
}
|
||||
|
||||
free_image_results(results, result_count);
|
||||
free(request_cache_key);
|
||||
free(display_query);
|
||||
|
|
|
|||
|
|
@ -32,8 +32,6 @@ typedef struct {
|
|||
|
||||
enum {
|
||||
RESULT_FIELD_COUNT = 6,
|
||||
LINK_FIELD_COUNT = 3,
|
||||
PAGER_WINDOW_SIZE = 5,
|
||||
};
|
||||
|
||||
static InfoBox fetch_wiki_wrapper(char *query) {
|
||||
|
|
@ -189,66 +187,6 @@ static int add_infobox_to_collection(InfoBox *infobox, char ****collection,
|
|||
return current_count + 1;
|
||||
}
|
||||
|
||||
static int add_link_to_collection(const char *href, const char *label,
|
||||
const char *class_name, char ****collection,
|
||||
int **inner_counts, int current_count) {
|
||||
char ***old_collection = *collection;
|
||||
int *old_inner_counts = *inner_counts;
|
||||
char ***new_collection =
|
||||
(char ***)malloc(sizeof(char **) * (current_count + 1));
|
||||
int *new_inner_counts =
|
||||
(int *)malloc(sizeof(int) * (current_count + 1));
|
||||
|
||||
if (!new_collection || !new_inner_counts) {
|
||||
free(new_collection);
|
||||
free(new_inner_counts);
|
||||
return current_count;
|
||||
}
|
||||
|
||||
if (*collection && current_count > 0) {
|
||||
memcpy(new_collection, *collection, sizeof(char **) * current_count);
|
||||
}
|
||||
if (*inner_counts && current_count > 0) {
|
||||
memcpy(new_inner_counts, *inner_counts, sizeof(int) * current_count);
|
||||
}
|
||||
|
||||
*collection = new_collection;
|
||||
*inner_counts = new_inner_counts;
|
||||
|
||||
(*collection)[current_count] =
|
||||
(char **)malloc(sizeof(char *) * LINK_FIELD_COUNT);
|
||||
if (!(*collection)[current_count]) {
|
||||
*collection = old_collection;
|
||||
*inner_counts = old_inner_counts;
|
||||
free(new_collection);
|
||||
free(new_inner_counts);
|
||||
return current_count;
|
||||
}
|
||||
|
||||
(*collection)[current_count][0] = strdup(href ? href : "");
|
||||
(*collection)[current_count][1] = strdup(label ? label : "");
|
||||
(*collection)[current_count][2] = strdup(class_name ? class_name : "");
|
||||
|
||||
if (!(*collection)[current_count][0] || !(*collection)[current_count][1] ||
|
||||
!(*collection)[current_count][2]) {
|
||||
free((*collection)[current_count][0]);
|
||||
free((*collection)[current_count][1]);
|
||||
free((*collection)[current_count][2]);
|
||||
free((*collection)[current_count]);
|
||||
*collection = old_collection;
|
||||
*inner_counts = old_inner_counts;
|
||||
free(new_collection);
|
||||
free(new_inner_counts);
|
||||
return current_count;
|
||||
}
|
||||
|
||||
(*inner_counts)[current_count] = LINK_FIELD_COUNT;
|
||||
|
||||
free(old_collection);
|
||||
free(old_inner_counts);
|
||||
return current_count + 1;
|
||||
}
|
||||
|
||||
static int add_warning_to_collection(const char *engine_name,
|
||||
const char *warning_message,
|
||||
char ****collection, int **inner_counts,
|
||||
|
|
@ -385,6 +323,16 @@ static char *build_search_href(const char *query, const char *engine_id,
|
|||
return href;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
const char *query;
|
||||
const char *engine_id;
|
||||
} SearchHrefData;
|
||||
|
||||
static char *search_href_builder(int page, void *data) {
|
||||
SearchHrefData *d = (SearchHrefData *)data;
|
||||
return build_search_href(d->query, d->engine_id, page);
|
||||
}
|
||||
|
||||
static char *build_search_request_cache_key(const char *query,
|
||||
const char *engine_id, int page,
|
||||
const char *client_key) {
|
||||
|
|
@ -436,6 +384,16 @@ int results_handler(UrlParams *params) {
|
|||
snprintf(page_str, sizeof(page_str), "%d", page);
|
||||
context_set(&ctx, "page", page_str);
|
||||
|
||||
char prev_str[16], next_str[16], two_prev_str[16], two_next_str[16];
|
||||
snprintf(prev_str, sizeof(prev_str), "%d", page > 1 ? page - 1 : 0);
|
||||
snprintf(next_str, sizeof(next_str), "%d", page + 1);
|
||||
snprintf(two_prev_str, sizeof(two_prev_str), "%d", page > 2 ? page - 2 : 0);
|
||||
snprintf(two_next_str, sizeof(two_next_str), "%d", page + 2);
|
||||
context_set(&ctx, "prev_page", prev_str);
|
||||
context_set(&ctx, "next_page", next_str);
|
||||
context_set(&ctx, "two_prev_page", two_prev_str);
|
||||
context_set(&ctx, "two_next_page", two_next_str);
|
||||
|
||||
if (!raw_query || strlen(raw_query) == 0) {
|
||||
send_redirect("/");
|
||||
free_context(&ctx);
|
||||
|
|
@ -810,43 +768,10 @@ int results_handler(UrlParams *params) {
|
|||
|
||||
char ***pager_matrix = NULL;
|
||||
int *pager_inner_counts = NULL;
|
||||
int pager_count = 0;
|
||||
int pager_start = page <= 3 ? 1 : page - 2;
|
||||
int pager_end = pager_start + PAGER_WINDOW_SIZE - 1;
|
||||
|
||||
if (page > 3) {
|
||||
char *first_href = build_search_href(raw_query, selected_engine_id, 1);
|
||||
pager_count = add_link_to_collection(first_href, "First", "pagination-btn",
|
||||
&pager_matrix, &pager_inner_counts,
|
||||
pager_count);
|
||||
free(first_href);
|
||||
}
|
||||
|
||||
if (page > 1) {
|
||||
char *prev_href =
|
||||
build_search_href(raw_query, selected_engine_id, page - 1);
|
||||
pager_count = add_link_to_collection(prev_href, "Prev", "pagination-btn",
|
||||
&pager_matrix, &pager_inner_counts,
|
||||
pager_count);
|
||||
free(prev_href);
|
||||
}
|
||||
|
||||
for (int i = pager_start; i <= pager_end; i++) {
|
||||
char label[16];
|
||||
snprintf(label, sizeof(label), "%d", i);
|
||||
char *page_href = build_search_href(raw_query, selected_engine_id, i);
|
||||
pager_count = add_link_to_collection(
|
||||
page_href, label,
|
||||
i == page ? "pagination-btn pagination-current" : "pagination-btn",
|
||||
&pager_matrix, &pager_inner_counts, pager_count);
|
||||
free(page_href);
|
||||
}
|
||||
|
||||
char *next_href = build_search_href(raw_query, selected_engine_id, page + 1);
|
||||
pager_count = add_link_to_collection(next_href, "Next", "pagination-btn",
|
||||
&pager_matrix, &pager_inner_counts,
|
||||
pager_count);
|
||||
free(next_href);
|
||||
SearchHrefData href_data = { .query = raw_query, .engine_id = selected_engine_id };
|
||||
int pager_count = build_pagination(page, locale, search_href_builder,
|
||||
&href_data, &pager_matrix,
|
||||
&pager_inner_counts);
|
||||
|
||||
if (pager_count > 0) {
|
||||
context_set_array_of_arrays(&ctx, "pagination_links", pager_matrix,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include "Utility.h"
|
||||
#include <beaker.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -32,3 +33,101 @@ char *get_locale(const char *default_locale) {
|
|||
free(cookie);
|
||||
return strdup(default_locale);
|
||||
}
|
||||
|
||||
int add_link_to_collection(const char *href, const char *label,
|
||||
const char *class_name, char ****collection,
|
||||
int **inner_counts, int current_count) {
|
||||
char ***old_collection = *collection;
|
||||
int *old_inner_counts = *inner_counts;
|
||||
char ***new_collection =
|
||||
(char ***)malloc(sizeof(char **) * (current_count + 1));
|
||||
int *new_inner_counts =
|
||||
(int *)malloc(sizeof(int) * (current_count + 1));
|
||||
|
||||
if (!new_collection || !new_inner_counts) {
|
||||
free(new_collection);
|
||||
free(new_inner_counts);
|
||||
return current_count;
|
||||
}
|
||||
|
||||
if (*collection && current_count > 0) {
|
||||
memcpy(new_collection, *collection, sizeof(char **) * current_count);
|
||||
}
|
||||
if (*inner_counts && current_count > 0) {
|
||||
memcpy(new_inner_counts, *inner_counts, sizeof(int) * current_count);
|
||||
}
|
||||
|
||||
*collection = new_collection;
|
||||
*inner_counts = new_inner_counts;
|
||||
|
||||
(*collection)[current_count] =
|
||||
(char **)malloc(sizeof(char *) * LINK_FIELD_COUNT);
|
||||
if (!(*collection)[current_count]) {
|
||||
*collection = old_collection;
|
||||
*inner_counts = old_inner_counts;
|
||||
free(new_collection);
|
||||
free(new_inner_counts);
|
||||
return current_count;
|
||||
}
|
||||
|
||||
(*collection)[current_count][0] = strdup(href ? href : "");
|
||||
(*collection)[current_count][1] = strdup(label ? label : "");
|
||||
(*collection)[current_count][2] = strdup(class_name ? class_name : "");
|
||||
|
||||
if (!(*collection)[current_count][0] || !(*collection)[current_count][1] ||
|
||||
!(*collection)[current_count][2]) {
|
||||
free((*collection)[current_count][0]);
|
||||
free((*collection)[current_count][1]);
|
||||
free((*collection)[current_count][2]);
|
||||
free((*collection)[current_count]);
|
||||
*collection = old_collection;
|
||||
*inner_counts = old_inner_counts;
|
||||
free(new_collection);
|
||||
free(new_inner_counts);
|
||||
return current_count;
|
||||
}
|
||||
|
||||
(*inner_counts)[current_count] = LINK_FIELD_COUNT;
|
||||
|
||||
free(old_collection);
|
||||
free(old_inner_counts);
|
||||
return current_count + 1;
|
||||
}
|
||||
|
||||
int build_pagination(int page, const char *locale,
|
||||
char *(*href_builder)(int page, void *data), void *data,
|
||||
char ****out_matrix, int **out_inner_counts) {
|
||||
enum { PAGER_WINDOW_SIZE = 5 };
|
||||
|
||||
*out_matrix = NULL;
|
||||
*out_inner_counts = NULL;
|
||||
int count = 0;
|
||||
|
||||
int pager_start = page <= 3 ? 1 : page - 2;
|
||||
int pager_end = pager_start + PAGER_WINDOW_SIZE - 1;
|
||||
|
||||
if (page > 1) {
|
||||
char *href = href_builder(page - 1, data);
|
||||
count = add_link_to_collection(href, "<", "pagination-btn prev",
|
||||
out_matrix, out_inner_counts, count);
|
||||
free(href);
|
||||
}
|
||||
|
||||
for (int i = pager_start; i <= pager_end; i++) {
|
||||
char label[16];
|
||||
snprintf(label, sizeof(label), "%d", i);
|
||||
char *href = href_builder(i, data);
|
||||
count = add_link_to_collection(
|
||||
href, label,
|
||||
i == page ? "pagination-btn pagination-current" : "pagination-btn",
|
||||
out_matrix, out_inner_counts, count);
|
||||
free(href);
|
||||
}
|
||||
|
||||
char *href = href_builder(page + 1, data);
|
||||
count = add_link_to_collection(href, ">", "pagination-btn next",
|
||||
out_matrix, out_inner_counts, count);
|
||||
free(href);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,18 @@
|
|||
|
||||
#include <beaker.h>
|
||||
|
||||
#define LINK_FIELD_COUNT 3
|
||||
|
||||
int hex_to_int(char c);
|
||||
char *get_theme(const char *default_theme);
|
||||
char *get_locale(const char *default_locale);
|
||||
|
||||
int add_link_to_collection(const char *href, const char *label,
|
||||
const char *class_name, char ****collection,
|
||||
int **inner_counts, int current_count);
|
||||
|
||||
int build_pagination(int page, const char *locale,
|
||||
char *(*href_builder)(int page, void *data), void *data,
|
||||
char ****out_matrix, int **out_inner_counts);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -927,3 +927,5 @@ header .logo-link:hover {
|
|||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -65,48 +65,15 @@
|
|||
</div>
|
||||
{{endfor}}
|
||||
</div>
|
||||
<nav class="pagination">
|
||||
<a class="pagination-btn prev" href="/images?q={{query}}&p={{prev_page}}">
|
||||
←
|
||||
</a>
|
||||
|
||||
{{if two_prev_page != 0}}
|
||||
<a class="pagination-btn prev" href="/images?q={{query}}&p={{two_prev_page}}">
|
||||
{{two_prev_page}}
|
||||
</a>
|
||||
{{endif}}
|
||||
|
||||
{{if prev_page != 0}}
|
||||
<a class="pagination-btn prev" href="/images?q={{query}}&p={{prev_page}}">
|
||||
{{prev_page}}
|
||||
</a>
|
||||
{{endif}}
|
||||
|
||||
<a class="pagination-btn pagination-current" href="/images?q={{query}}&p={{page}}">
|
||||
{{page}}
|
||||
</a>
|
||||
<a class="pagination-btn next" href="/images?q={{query}}&p={{next_page}}">
|
||||
{{next_page}}
|
||||
</a>
|
||||
<a class="pagination-btn next" href="/images?q={{query}}&p={{two_next_page}}">
|
||||
{{two_next_page}}
|
||||
</a>
|
||||
|
||||
{{if prev_page == 0}}
|
||||
<a class="pagination-btn prev" href="/images?q={{query}}&p=4">
|
||||
4
|
||||
</a>
|
||||
{{endif}}
|
||||
|
||||
{{if two_prev_page == 0}}
|
||||
<a class="pagination-btn prev" href="/images?q={{query}}&p=5">
|
||||
5
|
||||
</a>
|
||||
{{endif}}
|
||||
<a class="pagination-btn next" href="/images?q={{query}}&p={{next_page}}">
|
||||
→
|
||||
</a>
|
||||
</nav>
|
||||
{{if exists pagination_links}}
|
||||
<nav class="pagination">
|
||||
{{for link in pagination_links}}
|
||||
<a class="{{link[2]}}" href="{{link[0]}}">
|
||||
{{link[1]}}
|
||||
</a>
|
||||
{{endfor}}
|
||||
</nav>
|
||||
{{endif}}
|
||||
</main>
|
||||
</body>
|
||||
|
||||
|
|
|
|||
|
|
@ -118,8 +118,8 @@
|
|||
{{info[2]|safe}}
|
||||
</p>
|
||||
<a class="read-more" href="{{info[3]}}">
|
||||
{{l("read_more")}}
|
||||
</a>
|
||||
{{l("read_more")}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue