feat(wip): load themes dynamically from static/themes/*.css
This commit is contained in:
@@ -88,6 +88,7 @@ int main() {
|
||||
}
|
||||
|
||||
set_default_locale(cfg.default_locale);
|
||||
init_themes("static");
|
||||
|
||||
global_config = cfg;
|
||||
|
||||
|
||||
@@ -2,12 +2,17 @@
|
||||
#include "../Utility/Utility.h"
|
||||
#include <beaker.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
int home_handler(UrlParams *params) {
|
||||
(void)params;
|
||||
char *theme = get_theme("");
|
||||
char *locale = get_locale(NULL);
|
||||
|
||||
char **themes = NULL;
|
||||
int themes_count = 0;
|
||||
get_available_themes(&themes, &themes_count);
|
||||
|
||||
TemplateContext ctx = new_context();
|
||||
context_set(&ctx, "theme", theme);
|
||||
context_set(&ctx, "version", VERSION);
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#include "../Utility/Utility.h"
|
||||
#include "Config.h"
|
||||
#include <beaker.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char *build_images_request_cache_key(const char *query, int page,
|
||||
const char *client_key) {
|
||||
@@ -67,15 +69,18 @@ int images_handler(UrlParams *params) {
|
||||
beaker_set_locale(&ctx, locale);
|
||||
|
||||
const char *rate_limit_msg = beaker_get_locale_value(locale, "rate_limit");
|
||||
if (!rate_limit_msg) rate_limit_msg = "Slow down! Too many image searches from you!";
|
||||
const char *error_images_msg = beaker_get_locale_value(locale, "error_images");
|
||||
if (!error_images_msg) error_images_msg = "Error fetching images";
|
||||
if (!rate_limit_msg)
|
||||
rate_limit_msg = "Slow down! Too many image searches from you!";
|
||||
const char *error_images_msg =
|
||||
beaker_get_locale_value(locale, "error_images");
|
||||
if (!error_images_msg)
|
||||
error_images_msg = "Error fetching images";
|
||||
|
||||
char ***pager_matrix = NULL;
|
||||
int *pager_inner_counts = NULL;
|
||||
int pager_count = build_pagination(page, images_href_builder,
|
||||
(void *)raw_query, &pager_matrix,
|
||||
&pager_inner_counts);
|
||||
int pager_count =
|
||||
build_pagination(page, 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);
|
||||
|
||||
@@ -32,7 +32,8 @@ int settings_handler(UrlParams *params) {
|
||||
|
||||
char **user_engines = NULL;
|
||||
int user_engine_count = 0;
|
||||
int has_user_pref = (get_user_engines(&user_engines, &user_engine_count) == 0);
|
||||
int has_user_pref =
|
||||
(get_user_engines(&user_engines, &user_engine_count) == 0);
|
||||
|
||||
int enabled_count = 0;
|
||||
for (int i = 0; i < ENGINE_COUNT; i++) {
|
||||
@@ -77,7 +78,34 @@ int settings_handler(UrlParams *params) {
|
||||
context_set(&ctx, "query", query);
|
||||
context_set(&ctx, "theme", theme);
|
||||
context_set(&ctx, "locale", locale);
|
||||
context_set_array_of_arrays(&ctx, "locales", locale_data, locale_count, inner_counts);
|
||||
context_set_array_of_arrays(&ctx, "locales", locale_data, locale_count,
|
||||
inner_counts);
|
||||
|
||||
char **themes = NULL;
|
||||
int themes_count = 0;
|
||||
get_available_themes(&themes, &themes_count);
|
||||
|
||||
if (themes_count > 0) {
|
||||
char ***theme_ptrs = malloc(sizeof(char **) * themes_count);
|
||||
int *theme_inner = malloc(sizeof(int) * themes_count);
|
||||
for (int i = 0; i < themes_count; i++) {
|
||||
theme_ptrs[i] = malloc(sizeof(char *) * 2);
|
||||
theme_ptrs[i][0] = themes[i];
|
||||
theme_ptrs[i][1] = strdup(themes[i]);
|
||||
if (theme_ptrs[i][1][0] >= 'a' && theme_ptrs[i][1][0] <= 'z') {
|
||||
theme_ptrs[i][1][0] = theme_ptrs[i][1][0] - 'a' + 'A';
|
||||
}
|
||||
theme_inner[i] = 2;
|
||||
}
|
||||
context_set_array_of_arrays(&ctx, "themes", theme_ptrs, themes_count,
|
||||
theme_inner);
|
||||
for (int i = 0; i < themes_count; i++) {
|
||||
free(theme_ptrs[i][1]);
|
||||
free(theme_ptrs[i]);
|
||||
}
|
||||
free(theme_ptrs);
|
||||
free(theme_inner);
|
||||
}
|
||||
|
||||
if (enabled_count > 0) {
|
||||
context_set_array_of_arrays(&ctx, "enabled_engines", engine_data,
|
||||
|
||||
@@ -1,11 +1,80 @@
|
||||
#include "Utility.h"
|
||||
#include "../Scraping/Scraping.h"
|
||||
#include <beaker.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static char global_default_locale[32] = "en_gb";
|
||||
static char **themes_list = NULL;
|
||||
static int themes_count = 0;
|
||||
static int themes_initialized = 0;
|
||||
|
||||
void init_themes(const char *static_path) {
|
||||
if (themes_initialized)
|
||||
return;
|
||||
themes_initialized = 1;
|
||||
|
||||
char themes_dir[512];
|
||||
snprintf(themes_dir, sizeof(themes_dir), "%s/themes", static_path);
|
||||
|
||||
DIR *dir = opendir(themes_dir);
|
||||
if (!dir)
|
||||
return;
|
||||
|
||||
struct dirent *entry;
|
||||
int capacity = 4;
|
||||
themes_list = malloc(sizeof(char *) * capacity);
|
||||
themes_count = 0;
|
||||
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
size_t len = strlen(entry->d_name);
|
||||
if (len > 4 && strcmp(entry->d_name + len - 4, ".css") == 0) {
|
||||
if (themes_count >= capacity) {
|
||||
capacity *= 2;
|
||||
themes_list = realloc(themes_list, sizeof(char *) * capacity);
|
||||
}
|
||||
themes_list[themes_count] = strndup(entry->d_name, len - 4);
|
||||
themes_count++;
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
for (int i = 0; i < themes_count; i++) {
|
||||
for (int j = i + 1; j < themes_count; j++) {
|
||||
int priority_i = 0, priority_j = 0;
|
||||
if (strcmp(themes_list[i], "system") == 0)
|
||||
priority_i = 0;
|
||||
else if (strcmp(themes_list[i], "light") == 0)
|
||||
priority_i = 1;
|
||||
else if (strcmp(themes_list[i], "dark") == 0)
|
||||
priority_i = 2;
|
||||
else
|
||||
priority_i = 3;
|
||||
if (strcmp(themes_list[j], "system") == 0)
|
||||
priority_j = 0;
|
||||
else if (strcmp(themes_list[j], "light") == 0)
|
||||
priority_j = 1;
|
||||
else if (strcmp(themes_list[j], "dark") == 0)
|
||||
priority_j = 2;
|
||||
else
|
||||
priority_j = 3;
|
||||
if (priority_i > priority_j ||
|
||||
(priority_i == priority_j &&
|
||||
strcmp(themes_list[i], themes_list[j]) > 0)) {
|
||||
char *tmp = themes_list[i];
|
||||
themes_list[i] = themes_list[j];
|
||||
themes_list[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void get_available_themes(char ***out_themes, int *out_count) {
|
||||
*out_themes = themes_list;
|
||||
*out_count = themes_count;
|
||||
}
|
||||
|
||||
void set_default_locale(const char *locale) {
|
||||
if (locale && strlen(locale) > 0) {
|
||||
@@ -26,13 +95,16 @@ int hex_to_int(char c) {
|
||||
|
||||
char *get_theme(const char *default_theme) {
|
||||
char *cookie = get_cookie("theme");
|
||||
if (cookie &&
|
||||
(strcmp(cookie, "light") == 0 ||
|
||||
strcmp(cookie, "dark") == 0)) {
|
||||
return cookie;
|
||||
if (cookie && strlen(cookie) > 0) {
|
||||
for (int i = 0; i < themes_count; i++) {
|
||||
if (strcmp(cookie, themes_list[i]) == 0) {
|
||||
return cookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
free(cookie);
|
||||
return strdup(default_theme);
|
||||
return strdup(default_theme && strlen(default_theme) > 0 ? default_theme
|
||||
: "system");
|
||||
}
|
||||
|
||||
char *get_locale(const char *default_locale) {
|
||||
@@ -41,7 +113,8 @@ char *get_locale(const char *default_locale) {
|
||||
return cookie;
|
||||
}
|
||||
free(cookie);
|
||||
const char *fallback = default_locale ? default_locale : global_default_locale;
|
||||
const char *fallback =
|
||||
default_locale ? default_locale : global_default_locale;
|
||||
return strdup(fallback);
|
||||
}
|
||||
|
||||
@@ -49,9 +122,12 @@ static int engine_id_casecmp(const char *a, const char *b) {
|
||||
while (*a && *b) {
|
||||
char la = *a;
|
||||
char lb = *b;
|
||||
if (la >= 'A' && la <= 'Z') la = la - 'A' + 'a';
|
||||
if (lb >= 'A' && lb <= 'Z') lb = lb - 'A' + 'a';
|
||||
if (la != lb) return 0;
|
||||
if (la >= 'A' && la <= 'Z')
|
||||
la = la - 'A' + 'a';
|
||||
if (lb >= 'A' && lb <= 'Z')
|
||||
lb = lb - 'A' + 'a';
|
||||
if (la != lb)
|
||||
return 0;
|
||||
a++;
|
||||
b++;
|
||||
}
|
||||
@@ -59,7 +135,8 @@ static int engine_id_casecmp(const char *a, const char *b) {
|
||||
}
|
||||
|
||||
int is_engine_id_enabled(const char *engine_id) {
|
||||
if (!engine_id) return 0;
|
||||
if (!engine_id)
|
||||
return 0;
|
||||
for (int i = 0; i < ENGINE_COUNT; i++) {
|
||||
if (ENGINE_REGISTRY[i].enabled &&
|
||||
engine_id_casecmp(ENGINE_REGISTRY[i].id, engine_id)) {
|
||||
@@ -120,7 +197,8 @@ int get_user_engines(char ***out_ids, int *out_count) {
|
||||
}
|
||||
|
||||
int user_engines_contains(const char *engine_id, char **ids, int count) {
|
||||
if (!engine_id || !ids) return 0;
|
||||
if (!engine_id || !ids)
|
||||
return 0;
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (engine_id_casecmp(ids[i], engine_id))
|
||||
return 1;
|
||||
@@ -135,8 +213,7 @@ int add_link_to_collection(const char *href, const char *label,
|
||||
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));
|
||||
int *new_inner_counts = (int *)malloc(sizeof(int) * (current_count + 1));
|
||||
|
||||
if (!new_collection || !new_inner_counts) {
|
||||
free(new_collection);
|
||||
@@ -188,9 +265,8 @@ int add_link_to_collection(const char *href, const char *label,
|
||||
return current_count + 1;
|
||||
}
|
||||
|
||||
int build_pagination(int page,
|
||||
char *(*href_builder)(int page, void *data), void *data,
|
||||
char ****out_matrix, int **out_inner_counts) {
|
||||
int build_pagination(int page, char *(*href_builder)(int page, void *data),
|
||||
void *data, char ****out_matrix, int **out_inner_counts) {
|
||||
enum { PAGER_WINDOW_SIZE = 5 };
|
||||
|
||||
*out_matrix = NULL;
|
||||
@@ -202,8 +278,8 @@ int build_pagination(int page,
|
||||
|
||||
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);
|
||||
count = add_link_to_collection(href, "←", "pagination-btn prev", out_matrix,
|
||||
out_inner_counts, count);
|
||||
free(href);
|
||||
}
|
||||
|
||||
@@ -219,8 +295,8 @@ int build_pagination(int page,
|
||||
}
|
||||
|
||||
char *href = href_builder(page + 1, data);
|
||||
count = add_link_to_collection(href, "→", "pagination-btn next",
|
||||
out_matrix, out_inner_counts, count);
|
||||
count = add_link_to_collection(href, "→", "pagination-btn next", out_matrix,
|
||||
out_inner_counts, count);
|
||||
free(href);
|
||||
|
||||
return count;
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
int hex_to_int(char c);
|
||||
char *get_theme(const char *default_theme);
|
||||
void init_themes(const char *static_path);
|
||||
void get_available_themes(char ***out_themes, int *out_count);
|
||||
void set_default_locale(const char *locale);
|
||||
char *get_locale(const char *default_locale);
|
||||
|
||||
@@ -26,8 +28,7 @@ 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,
|
||||
char *(*href_builder)(int page, void *data), void *data,
|
||||
char ****out_matrix, int **out_inner_counts);
|
||||
int build_pagination(int page, char *(*href_builder)(int page, void *data),
|
||||
void *data, char ****out_matrix, int **out_inner_counts);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,26 +1,3 @@
|
||||
:root {
|
||||
--bg-main: #ffffff;
|
||||
--bg-card: #f8f9fa;
|
||||
--border: #e0e0e0;
|
||||
--text-primary: #1a1a1a;
|
||||
--text-secondary: #5f6368;
|
||||
--text-muted: #757575;
|
||||
--accent: #202124;
|
||||
--accent-glow: rgba(0,0,0,0.05);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-main: #121212;
|
||||
--bg-card: #1e1e1e;
|
||||
--border: #333333;
|
||||
--text-primary: #ffffff;
|
||||
--text-secondary: #a0a0a0;
|
||||
--text-muted: #d1d1d1;
|
||||
--accent: #e2e2e2;
|
||||
--accent-glow: rgba(255,255,255,0.1);
|
||||
}
|
||||
}
|
||||
|
||||
*, *::before, *::after {
|
||||
box-sizing: border-box;
|
||||
font-family: sans-serif;
|
||||
|
||||
22
static/themes/system.css
Normal file
22
static/themes/system.css
Normal file
@@ -0,0 +1,22 @@
|
||||
:root {
|
||||
--bg-main: #ffffff;
|
||||
--bg-card: #f8f9fa;
|
||||
--border: #e0e0e0;
|
||||
--text-primary: #1a1a1a;
|
||||
--text-secondary: #5f6368;
|
||||
--text-muted: #757575;
|
||||
--accent: #202124;
|
||||
--accent-glow: rgba(0,0,0,0.05);
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--bg-main: #121212;
|
||||
--bg-card: #1e1e1e;
|
||||
--border: #333333;
|
||||
--text-primary: #ffffff;
|
||||
--text-secondary: #a0a0a0;
|
||||
--text-muted: #d1d1d1;
|
||||
--accent: #e2e2e2;
|
||||
--accent-glow: rgba(255,255,255,0.1);
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,7 @@
|
||||
OmniSearch
|
||||
</title>
|
||||
<link rel="stylesheet" href="static/main.css">
|
||||
{{if theme == "light"}}<link rel="preload" href="static/theme-light.css" as="style"><link rel="stylesheet" href="static/theme-light.css">{{endif}}
|
||||
{{if theme == "dark"}}<link rel="preload" href="static/theme-dark.css" as="style"><link rel="stylesheet" href="static/theme-dark.css">{{endif}}
|
||||
<link rel="stylesheet" href="static/themes/{{theme}}.css">
|
||||
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
||||
<link rel="search"
|
||||
type="application/opensearchdescription+xml"
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
</title>
|
||||
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="static/main.css">
|
||||
{{if theme == "light"}}<link rel="preload" href="static/theme-light.css" as="style"><link rel="stylesheet" href="static/theme-light.css">{{endif}}
|
||||
{{if theme == "dark"}}<link rel="preload" href="static/theme-dark.css" as="style"><link rel="stylesheet" href="static/theme-dark.css">{{endif}}
|
||||
<link rel="stylesheet" href="static/themes/{{theme}}.css">
|
||||
</head>
|
||||
|
||||
<body class="images-view">
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
OmniSearch - {{query}}
|
||||
</title>
|
||||
<link rel="stylesheet" href="static/main.css">
|
||||
{{if theme == "light"}}<link rel="preload" href="static/theme-light.css" as="style"><link rel="stylesheet" href="static/theme-light.css">{{endif}}
|
||||
{{if theme == "dark"}}<link rel="preload" href="static/theme-dark.css" as="style"><link rel="stylesheet" href="static/theme-dark.css">{{endif}}
|
||||
<link rel="stylesheet" href="static/themes/{{theme}}.css">
|
||||
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
||||
<link rel="search"
|
||||
type="application/opensearchdescription+xml"
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
OmniSearch - {{l("settings_title")}}
|
||||
</title>
|
||||
<link rel="stylesheet" href="static/main.css">
|
||||
{{if theme == "light"}}<link rel="preload" href="static/theme-light.css" as="style"><link rel="stylesheet" href="static/theme-light.css">{{endif}}
|
||||
{{if theme == "dark"}}<link rel="preload" href="static/theme-dark.css" as="style"><link rel="stylesheet" href="static/theme-dark.css">{{endif}}
|
||||
<link rel="stylesheet" href="static/themes/{{theme}}.css">
|
||||
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
|
||||
<link rel="search"
|
||||
type="application/opensearchdescription+xml"
|
||||
@@ -58,9 +57,9 @@
|
||||
<div class="settings-field">
|
||||
<label class="settings-label" for="theme">{{l("theme_label")}}</label>
|
||||
<select id="theme" name="theme" class="settings-select">
|
||||
<option value="system" {{if theme == "system"}}selected{{endif}}>{{l("theme_system")}}</option>
|
||||
<option value="light" {{if theme == "light"}}selected{{endif}}>{{l("theme_light")}}</option>
|
||||
<option value="dark" {{if theme == "dark"}}selected{{endif}}>{{l("theme_dark")}}</option>
|
||||
{{for t in themes}}
|
||||
<option value="{{t[0]}}" {{if theme == t[0]}}selected{{endif}}>{{t[1]}}</option>
|
||||
{{endfor}}
|
||||
</select>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
Reference in New Issue
Block a user