From da2988c4356d2756e86037b1c7e859f49583c109 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Wed, 8 Sep 2021 17:04:31 +0200 Subject: Load theme from file (~/.config/quickmedia/themes/.json and /usr/share/quickmedia/themes/.json) --- src/Body.cpp | 28 +++---- src/BodyItem.cpp | 6 +- src/Config.cpp | 9 ++- src/Entry.cpp | 4 +- src/QuickMedia.cpp | 149 +++++++++++++++++------------------ src/SearchBar.cpp | 10 +-- src/Storage.cpp | 2 +- src/Tabs.cpp | 8 +- src/Text.cpp | 4 +- src/Theme.cpp | 183 ++++++++++++++++++++++++------------------- src/gui/Button.cpp | 2 +- src/plugins/AniList.cpp | 2 +- src/plugins/FileManager.cpp | 2 +- src/plugins/HotExamples.cpp | 4 +- src/plugins/MangaGeneric.cpp | 2 +- src/plugins/Mangadex.cpp | 4 +- src/plugins/Manganelo.cpp | 4 +- src/plugins/Matrix.cpp | 20 ++--- src/plugins/MyAnimeList.cpp | 6 +- src/plugins/Page.cpp | 2 +- src/plugins/Soundcloud.cpp | 2 +- src/plugins/Youtube.cpp | 6 +- 22 files changed, 244 insertions(+), 215 deletions(-) (limited to 'src') diff --git a/src/Body.cpp b/src/Body.cpp index 68e34e8..10e31dd 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -106,16 +106,16 @@ namespace QuickMedia { num_visible_items(0), top_cut_off(false), bottom_cut_off(false), - item_background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_current_theme().selected_color, rounded_rectangle_shader), - reaction_background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_current_theme().shade_color, rounded_rectangle_shader), + item_background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_theme().selected_color, rounded_rectangle_shader), + reaction_background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_theme().shade_color, rounded_rectangle_shader), rounded_rectangle_mask_shader(rounded_rectangle_mask_shader) { assert(rounded_rectangle_shader); assert(rounded_rectangle_mask_shader); init_body_themes(); embedded_item_load_text = sf::Text("", *FontLoader::get_font(FontLoader::FontType::LATIN), body_spacing[body_theme].embedded_item_font_size); - progress_text.setFillColor(get_current_theme().text_color); - replies_text.setFillColor(get_current_theme().replies_text_color); + progress_text.setFillColor(get_theme().text_color); + replies_text.setFillColor(get_theme().replies_text_color); thumbnail_max_size.x = 600; thumbnail_max_size.y = 337; sf::Vector2f loading_icon_size(loading_icon.getTexture()->getSize().x, loading_icon.getTexture()->getSize().y); @@ -905,7 +905,7 @@ namespace QuickMedia { body_item->timestamp_text = std::make_unique(time_str, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(get_config().body.timestamp_font_size * get_config().scale * get_config().font_scale)); } - body_item->timestamp_text->setFillColor(get_current_theme().timestamp_text_color); + body_item->timestamp_text->setFillColor(get_theme().timestamp_text_color); } } } @@ -1006,7 +1006,7 @@ namespace QuickMedia { if(prev_num_visible_items > 0 && render_selected_item_bg && body_theme == BODY_THEME_MINIMAL) { item_background.set_position(sf::Vector2f(pos.x, item_background_prev_pos.y)); item_background.set_size(item_background_prev_size); - item_background.set_color(get_current_theme().selected_color); + item_background.set_color(get_theme().selected_color); item_background.set_band(sf::Vector2f(0.0f, 0.0f), sf::Vector2f(0.0f, 0.0f)); item_background.draw(window); } @@ -1218,9 +1218,9 @@ namespace QuickMedia { item_background.set_position(pos + pos_offset); item_background.set_size(sf::Vector2f(card_width, item_height)); - item_background.set_color(get_current_theme().card_item_background_color); + item_background.set_color(get_theme().card_item_background_color); item_background.set_band(item_background_prev_pos - (pos + pos_offset), item_background_prev_size); - item_background.set_band_color(get_current_theme().selected_color); + item_background.set_band_color(get_theme().selected_color); item_background.draw(window); { @@ -1290,7 +1290,7 @@ namespace QuickMedia { const float gradient_height = 5.0f; if(text_offset_y >= text_height - gradient_height && std::abs(item_height - card_height) < 1) { const sf::Vector2f card_bottom(text_pos.x, text_height); - const sf::Color color = item_index == selected_item ? get_current_theme().selected_color : get_current_theme().card_item_background_color; + const sf::Color color = item_index == selected_item ? get_theme().selected_color : get_theme().card_item_background_color; sf::Vertex gradient_points[4]; gradient_points[0] = sf::Vertex(card_bottom + sf::Vector2f(0.0f, -gradient_height), sf::Color(color.r, color.g, color.b, 0)); @@ -1362,9 +1362,9 @@ namespace QuickMedia { if(item_index != -1 && body_theme == BODY_THEME_MODERN_SPACIOUS) { item_background.set_size(sf::Vector2f(size.x, item_height)); item_background.set_position(item_pos); - item_background.set_color(get_current_theme().shade_color); + item_background.set_color(get_theme().shade_color); item_background.set_band(item_background_prev_pos - pos, item_background_prev_size); - item_background.set_band_color(get_current_theme().selected_color); + item_background.set_band_color(get_theme().selected_color); item_background.draw(window); } @@ -1403,12 +1403,12 @@ namespace QuickMedia { // shapes dont have texture coordinates. // TODO: Cache circle shape sf::CircleShape circle_shape(content_size.x * 0.5f); - circle_shape.setFillColor(get_current_theme().image_loading_background_color); + circle_shape.setFillColor(get_theme().image_loading_background_color); circle_shape.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y)); window.draw(circle_shape); } else { image_fallback.setSize(content_size); - image_fallback.setFillColor(get_current_theme().image_loading_background_color); + image_fallback.setFillColor(get_theme().image_loading_background_color); image_fallback.setPosition(item_pos + sf::Vector2f(body_spacing[body_theme].image_padding_x, padding_y)); window.draw(image_fallback); } @@ -1452,7 +1452,7 @@ namespace QuickMedia { const float embedded_item_width = std::floor(size.x - text_offset_x - embedded_item_border_width - body_spacing[body_theme].padding_x); float embedded_item_height = item->embedded_item ? get_item_height(item->embedded_item.get(), embedded_item_width, true, false) : ((body_spacing[body_theme].embedded_item_font_size + 5.0f) + body_spacing[body_theme].embedded_item_padding_y * 2.0f); sf::RectangleShape border_left(sf::Vector2f(embedded_item_border_width, std::floor(embedded_item_height))); - border_left.setFillColor(get_current_theme().embedded_item_border_color); + border_left.setFillColor(get_theme().embedded_item_border_color); border_left.setPosition(std::floor(item_pos.x + text_offset_x), std::floor(item_pos.y + body_spacing[body_theme].embedded_item_padding_y + 2.0f)); window.draw(border_left); diff --git a/src/BodyItem.cpp b/src/BodyItem.cpp index 70d9d45..0b41893 100644 --- a/src/BodyItem.cpp +++ b/src/BodyItem.cpp @@ -13,9 +13,9 @@ namespace QuickMedia { thumbnail_is_local(false), userdata(nullptr), timestamp(0), - title_color(get_current_theme().text_color), - author_color(get_current_theme().text_color), - description_color(get_current_theme().text_color) + title_color(get_theme().text_color), + author_color(get_theme().text_color), + description_color(get_theme().text_color) { if(!_title.empty()) set_title(std::move(_title)); diff --git a/src/Config.cpp b/src/Config.cpp index b481374..31f8df9 100644 --- a/src/Config.cpp +++ b/src/Config.cpp @@ -58,7 +58,7 @@ namespace QuickMedia { } // No-op if this has already been called before - void init_config() { + static void init_config() { if(config_initialized) return; @@ -66,11 +66,16 @@ namespace QuickMedia { // Wtf? can't use static non-pointer config because it causes a segfault when setting config.theme. // It looks like a libc bug??? crashes for both gcc and clang. config = new Config(); + config->scale = get_ui_scale(); + Path config_path = get_storage_dir().join("config.json"); + if(get_file_type(config_path) != FileType::REGULAR) { + return; + } + Json::Value json_root; if(!read_file_as_json(config_path, json_root) || !json_root.isObject()) { fprintf(stderr, "Warning: failed to parse config file: %s\n", config_path.data.c_str()); - config->scale = get_ui_scale(); return; } diff --git a/src/Entry.cpp b/src/Entry.cpp index f35e34f..8f63945 100644 --- a/src/Entry.cpp +++ b/src/Entry.cpp @@ -18,12 +18,12 @@ namespace QuickMedia { draw_background(true), text("", false, std::floor(get_config().input.font_size * get_config().scale * get_config().font_scale), 0.0f), width(0.0f), - background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_current_theme().selected_color, rounded_rectangle_shader), + background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_theme().selected_color, rounded_rectangle_shader), placeholder(placeholder_text, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(get_config().input.font_size * get_config().scale * get_config().font_scale)), mouse_left_inside(false) { text.setEditable(true); - placeholder.setFillColor(get_current_theme().placeholder_text_color); + placeholder.setFillColor(get_theme().placeholder_text_color); } void Entry::process_event(sf::Event &event) { diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 640ec16..6b85d34 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -247,7 +247,7 @@ namespace QuickMedia { auto body_item = BodyItem::create(std::move(title)); if(!description.empty()) { body_item->set_description(std::move(description)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); } body_item->url = std::to_string(handlers.size()); handlers.push_back(std::move(handler)); @@ -593,7 +593,6 @@ namespace QuickMedia { set_resource_loader_root_path(resources_root.c_str()); set_use_system_fonts(get_config().use_system_fonts); - init_themes(); if(!is_touch_enabled()) { if(!circle_mask_shader.loadFromFile(resources_root + "shaders/circle_mask.glsl", sf::Shader::Type::Fragment)) { @@ -601,7 +600,7 @@ namespace QuickMedia { abort(); } - if(get_current_theme().blur_enabled) { + if(get_theme().drop_shadow) { if(!rounded_rectangle_shader.loadFromFile(resources_root + "shaders/rounded_rectangle.glsl", sf::Shader::Type::Fragment)) { show_notification("QuickMedia", "Failed to load " + resources_root + "/shaders/rounded_rectangle.glsl", Urgency::CRITICAL); abort(); @@ -1329,7 +1328,7 @@ namespace QuickMedia { body_item->url = "https://www.youtube.com/watch?v=" + video_id_str; body_item->thumbnail_url = "https://img.youtube.com/vi/" + video_id_str + "/mqdefault.jpg"; body_item->set_description("Watched " + seconds_to_relative_time_str(time_now - timestamp.asInt64())); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); body_item->thumbnail_size = sf::Vector2i(192, 108); history_items.push_back(std::move(body_item)); } @@ -1406,7 +1405,7 @@ namespace QuickMedia { // TODO: Add thumbnail auto body_item = BodyItem::create(manga_name.asString()); body_item->set_description("Last read " + seconds_to_relative_time_str(now - last_modified_time)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); if(strcmp(plugin_name, "manganelo") == 0) body_item->url = "https://manganelo.com/manga/" + base64_url_decode(filename.string()); @@ -1634,7 +1633,7 @@ namespace QuickMedia { if(!tabs[selected_tab].search_bar) { shade_extra_height = std::floor(10.0f * get_config().scale); sf::RectangleShape shade_top(sf::Vector2f(window_size.x, shade_extra_height)); - shade_top.setFillColor(get_current_theme().shade_color); + shade_top.setFillColor(get_theme().shade_color); window.draw(shade_top); } @@ -2043,10 +2042,10 @@ namespace QuickMedia { } sf::RectangleShape more_items_above_rect; - more_items_above_rect.setFillColor(get_current_theme().more_items_color); + more_items_above_rect.setFillColor(get_theme().more_items_color); sf::RectangleShape more_items_below_rect; - more_items_below_rect.setFillColor(get_current_theme().more_items_color); + more_items_below_rect.setFillColor(get_theme().more_items_color); sf::Event event; sf::Clock frame_timer; @@ -2170,18 +2169,18 @@ namespace QuickMedia { if(tab_associated_data[selected_tab].fetching_next_page_running) { double progress = 0.5 + std::sin(std::fmod(gradient_inc, 360.0) * 0.017453292519943295 - 1.5707963267948966*0.5) * 0.5; gradient_inc += (frame_time_ms * 0.5); - sf::Color bottom_color = interpolate_colors(get_current_theme().background_color, get_current_theme().loading_bar_color, progress); + sf::Color bottom_color = interpolate_colors(get_theme().background_color, get_theme().loading_bar_color, progress); if(tabs[selected_tab].body->attach_side == AttachSide::TOP) { - gradient_points[0].color = get_current_theme().background_color; - gradient_points[1].color = get_current_theme().background_color; + gradient_points[0].color = get_theme().background_color; + gradient_points[1].color = get_theme().background_color; gradient_points[2].color = bottom_color; gradient_points[3].color = bottom_color; } else if(tabs[selected_tab].body->attach_side == AttachSide::BOTTOM) { gradient_points[0].color = bottom_color; gradient_points[1].color = bottom_color; - gradient_points[2].color = get_current_theme().background_color; - gradient_points[3].color = get_current_theme().background_color; + gradient_points[2].color = get_theme().background_color; + gradient_points[3].color = get_theme().background_color; } } @@ -2335,7 +2334,7 @@ namespace QuickMedia { ui_tabs.set_text(i, tab.page->get_title()); } - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); page_loop_render(window, tabs, selected_tab, tab_associated_data[selected_tab], json_chapters, ui_tabs); if(tabs[selected_tab].body->get_num_items() > 0) { @@ -2511,7 +2510,7 @@ namespace QuickMedia { goto task_end; } - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f); load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0); window.draw(load_sprite); @@ -3229,7 +3228,7 @@ namespace QuickMedia { matrix->update(); if(!video_loaded) { - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f); load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0); window.draw(load_sprite); @@ -3483,7 +3482,7 @@ namespace QuickMedia { break; } - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); load_sprite.setPosition(window_size.x * 0.5f, window_size.y * 0.5f); load_sprite.setRotation(load_sprite_timer.getElapsedTime().asSeconds() * 400.0); window.draw(load_sprite); @@ -3506,7 +3505,7 @@ namespace QuickMedia { sf::Texture image_texture; sf::Sprite image; sf::Text error_message("", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(30 * get_config().scale * get_config().font_scale)); - error_message.setFillColor(get_current_theme().text_color); + error_message.setFillColor(get_theme().text_color); bool download_in_progress = false; sf::Event event; @@ -3676,7 +3675,7 @@ namespace QuickMedia { image.setPosition(std::floor(content_size.x * 0.5f - image_size.x * 0.5f), std::floor(content_size.y * 0.5f - image_size.y * 0.5f)); } - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); if(error) { window.draw(error_message); @@ -3753,7 +3752,7 @@ namespace QuickMedia { while(current_page == PageType::IMAGES_CONTINUOUS && window.isOpen()) { handle_x11_events(); - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); ImageViewerAction action = image_viewer.draw(); switch(action) { case ImageViewerAction::NONE: @@ -3822,12 +3821,12 @@ namespace QuickMedia { const float captcha_slide_padding_x = std::floor(4.0f * get_config().scale); const float captcha_slide_padding_y = std::floor(4.0f * get_config().scale); - sf::Color background_color_darker = get_current_theme().background_color; + sf::Color background_color_darker = get_theme().background_color; background_color_darker.r = std::max(0, (int)background_color_darker.r - 20); background_color_darker.g = std::max(0, (int)background_color_darker.g - 20); background_color_darker.b = std::max(0, (int)background_color_darker.b - 20); RoundedRectangle captcha_slide_bg(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale), background_color_darker, &rounded_rectangle_shader); - RoundedRectangle captcha_slide_fg(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale - captcha_slide_padding_y), get_current_theme().loading_bar_color, &rounded_rectangle_shader); + RoundedRectangle captcha_slide_fg(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale - captcha_slide_padding_y), get_theme().loading_bar_color, &rounded_rectangle_shader); auto attached_image_texture = std::make_unique(); sf::Sprite attached_image_sprite; @@ -3934,7 +3933,7 @@ namespace QuickMedia { }; sf::RectangleShape comment_input_shade; - comment_input_shade.setFillColor(get_current_theme().shade_color); + comment_input_shade.setFillColor(get_theme().shade_color); sf::Sprite logo_sprite(plugin_logo); logo_sprite.setScale(0.8f * get_config().scale, 0.8f * get_config().scale); @@ -3953,10 +3952,10 @@ namespace QuickMedia { const float chat_input_padding_y = std::floor(10.0f * get_config().scale); sf::RectangleShape more_items_above_rect; - more_items_above_rect.setFillColor(get_current_theme().more_items_color); + more_items_above_rect.setFillColor(get_theme().more_items_color); sf::RectangleShape more_items_below_rect; - more_items_below_rect.setFillColor(get_current_theme().more_items_color); + more_items_below_rect.setFillColor(get_theme().more_items_color); sf::Vector2f body_pos; sf::Vector2f body_size; @@ -4336,7 +4335,7 @@ namespace QuickMedia { //comment_input.update(); - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); if(navigation_stage == NavigationStage::SOLVING_POST_CAPTCHA && captcha_texture.getNativeHandle() != 0) { const float slide_speed = 0.5f; const bool window_has_focus = window.hasFocus(); @@ -4386,7 +4385,7 @@ namespace QuickMedia { // TODO: Cut off ends with sf::View instead sf::RectangleShape cut_off_rectangle(captcha_image_size); - cut_off_rectangle.setFillColor(get_current_theme().background_color); + cut_off_rectangle.setFillColor(get_theme().background_color); cut_off_rectangle.setPosition(captcha_sprite.getPosition() - sf::Vector2f(cut_off_rectangle.getSize().x, 0.0f)); window.draw(cut_off_rectangle); @@ -4426,7 +4425,7 @@ namespace QuickMedia { window.draw(attached_image_sprite); } else { sf::RectangleShape rect(sf::Vector2f(640.0f, 480.0f)); - rect.setFillColor(get_current_theme().image_loading_background_color); + rect.setFillColor(get_theme().image_loading_background_color); auto content_size = window_size; auto rect_size = clamp_to_size(rect.getSize(), content_size); rect.setSize(rect_size); @@ -4494,7 +4493,7 @@ namespace QuickMedia { SearchBar *inputs[num_inputs] = { &login_input, &password_input, &homeserver_input }; int focused_input = 0; - RoundedRectangle background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_current_theme().shade_color, &rounded_rectangle_shader); + RoundedRectangle background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_theme().shade_color, &rounded_rectangle_shader); auto text_submit_callback = [this, inputs](const sf::String&) { for(int i = 0; i < num_inputs; ++i) { @@ -4582,7 +4581,7 @@ namespace QuickMedia { } } - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); background.draw(window); for(int i = 0; i < num_inputs; ++i) { inputs[i]->update(); @@ -4646,9 +4645,9 @@ namespace QuickMedia { body_item->embedded_item->embedded_item = nullptr; body_item->embedded_item->reactions.clear(); if(message->user->user_id != my_user_id && ((related_body_item->userdata && static_cast(related_body_item->userdata)->user.get() == me) || message_contains_user_mention(body_item->get_description(), my_display_name) || message_contains_user_mention(body_item->get_description(), my_user_id))) - body_item->set_description_color(get_current_theme().attention_alert_text_color); + body_item->set_description_color(get_theme().attention_alert_text_color); else - body_item->set_description_color(get_current_theme().text_color); + body_item->set_description_color(get_theme().text_color); body_item->embedded_item_status = FetchStatus::FINISHED_LOADING; return true; } @@ -4686,12 +4685,12 @@ namespace QuickMedia { body_item->visible = false; if(is_system_message_type(message->type)) { body_item->set_author("Server"); - body_item->set_author_color(get_current_theme().text_color); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_author_color(get_theme().text_color); + body_item->set_description_color(get_theme().faded_text_color); body_item->thumbnail_url.clear(); } if(message->user->user_id != my_user_id && (message_contains_user_mention(body_item->get_description(), my_display_name) || message_contains_user_mention(body_item->get_description(), my_user_id))) - body_item->set_description_color(get_current_theme().attention_alert_text_color); + body_item->set_description_color(get_theme().attention_alert_text_color); return body_item; } @@ -4810,7 +4809,7 @@ namespace QuickMedia { tab.body->show_drop_shadow = false; } - Tabs ui_tabs(&rounded_rectangle_shader, is_touch_enabled() ? sf::Color::Transparent : get_current_theme().background_color); + Tabs ui_tabs(&rounded_rectangle_shader, is_touch_enabled() ? sf::Color::Transparent : get_theme().background_color); const int PINNED_TAB_INDEX = ui_tabs.add_tab("Pinned messages (0)", tabs[0].body.get()); const int MESSAGES_TAB_INDEX = ui_tabs.add_tab("Messages", tabs[1].body.get()); const int USERS_TAB_INDEX = ui_tabs.add_tab("Users (0)", tabs[2].body.get()); @@ -4893,7 +4892,7 @@ namespace QuickMedia { const float room_topic_text_height = std::floor(12.0f * get_config().scale * get_config().font_scale); sf::Text room_topic_text("", *FontLoader::get_font(FontLoader::FontType::LATIN), room_topic_text_height); - room_topic_text.setFillColor(get_current_theme().faded_text_color); + room_topic_text.setFillColor(get_theme().faded_text_color); sf::Text room_label(matrix_chat_page->rooms_page->get_title(), *FontLoader::get_font(FontLoader::FontType::LATIN_BOLD), std::floor(18 * get_config().scale * get_config().font_scale)); room_label.setPosition(15.0f, room_name_text_padding_y + 4.0f); @@ -4923,9 +4922,9 @@ namespace QuickMedia { } body_item->set_description("Message deleted"); if(original_message && is_system_message_type(original_message->type)) - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); else - body_item->set_description_color(get_current_theme().text_color); + body_item->set_description_color(get_theme().text_color); body_item->thumbnail_size = AVATAR_THUMBNAIL_SIZE; body_item->url.clear(); }; @@ -4953,9 +4952,9 @@ namespace QuickMedia { Message *reply_to_message = static_cast(body_item->userdata); body_item->set_description(strip(message_get_body_remove_formatting(message.get()))); if(message->user != me && (message_contains_user_mention(reply_to_message->body, my_display_name) || message_contains_user_mention(reply_to_message->body, me->user_id))) - body_item->set_description_color(get_current_theme().attention_alert_text_color); + body_item->set_description_color(get_theme().attention_alert_text_color); else - body_item->set_description_color(get_current_theme().text_color); + body_item->set_description_color(get_theme().text_color); message->replaces = reply_to_message; reply_to_message->replaced_by = message; } @@ -4992,9 +4991,9 @@ namespace QuickMedia { Message *reply_to_message = static_cast(body_item->userdata); body_item->set_description(strip(message_get_body_remove_formatting(message.get()))); if(message->user != me && (message_contains_user_mention(reply_to_message->body, my_display_name) || message_contains_user_mention(reply_to_message->body, me->user_id))) - body_item->set_description_color(get_current_theme().attention_alert_text_color); + body_item->set_description_color(get_theme().attention_alert_text_color); else - body_item->set_description_color(get_current_theme().text_color); + body_item->set_description_color(get_theme().text_color); message->replaces = reply_to_message; reply_to_message->replaced_by = message; } @@ -5405,7 +5404,7 @@ namespace QuickMedia { }); } else { auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id); - body_item->set_description_color(get_current_theme().provisional_message_color); + body_item->set_description_color(get_theme().provisional_message_color); load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items()); tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item}); post_task_queue.push([this, ¤t_room, text, msgtype, body_item, message]() { @@ -5430,7 +5429,7 @@ namespace QuickMedia { message->related_event_type = RelatedEventType::REPLY; message->related_event_id = static_cast(related_to_message)->event_id; auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id); - body_item->set_description_color(get_current_theme().provisional_message_color); + body_item->set_description_color(get_theme().provisional_message_color); load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items()); tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item}); post_task_queue.push([this, ¤t_room, text, related_to_message, body_item, message, transaction_id]() { @@ -5456,7 +5455,7 @@ namespace QuickMedia { if(body_item) { auto body_item_shared_ptr = tabs[MESSAGES_TAB_INDEX].body->get_item_by_index(body_item_index); body_item_shared_ptr->set_description(text); - body_item_shared_ptr->set_description_color(get_current_theme().provisional_message_color); + body_item_shared_ptr->set_description_color(get_theme().provisional_message_color); auto edit_body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id); edit_body_item->visible = false; @@ -5550,9 +5549,9 @@ namespace QuickMedia { *body_item = *related_body_item; body_item->reactions.clear(); if(message_contains_user_mention(related_body_item->get_description(), current_room->get_user_display_name(me)) || message_contains_user_mention(related_body_item->get_description(), me->user_id)) - body_item->set_description_color(get_current_theme().attention_alert_text_color); + body_item->set_description_color(get_theme().attention_alert_text_color); else - body_item->set_description_color(get_current_theme().text_color); + body_item->set_description_color(get_theme().text_color); event_data->status = FetchStatus::FINISHED_LOADING; event_data->message = static_cast(related_body_item->userdata); body_item->userdata = event_data; @@ -5634,10 +5633,10 @@ namespace QuickMedia { bool has_unread_messages = false; sf::RectangleShape more_messages_below_rect; - more_messages_below_rect.setFillColor(get_current_theme().new_items_alert_color); + more_messages_below_rect.setFillColor(get_theme().new_items_alert_color); sf::RectangleShape chat_input_shade; - chat_input_shade.setFillColor(get_current_theme().shade_color); + chat_input_shade.setFillColor(get_theme().shade_color); float tab_vertical_offset = 0.0f; @@ -6377,11 +6376,11 @@ namespace QuickMedia { if(!provisional_message->event_id.empty()) { provisional_message->message->event_id = std::move(provisional_message->event_id); - provisional_message->body_item->set_description_color(get_current_theme().text_color); + provisional_message->body_item->set_description_color(get_theme().text_color); sent_messages[provisional_message->message->event_id] = std::move(provisional_message.value()); } else if(provisional_message->body_item) { provisional_message->body_item->set_description("Failed to send: " + provisional_message->body_item->get_description()); - provisional_message->body_item->set_description_color(get_current_theme().failed_text_color); + provisional_message->body_item->set_description_color(get_theme().failed_text_color); provisional_message->body_item->userdata = nullptr; } } @@ -6628,7 +6627,7 @@ namespace QuickMedia { fetch_body_item->embedded_item = message_to_body_item(current_room, fetch_message_result.message.get(), current_room->get_user_display_name(me), me->user_id); fetch_body_item->embedded_item_status = FetchStatus::FINISHED_LOADING; if(fetch_message_result.message->user == me) - fetch_body_item->set_description_color(get_current_theme().attention_alert_text_color); + fetch_body_item->set_description_color(get_theme().attention_alert_text_color); } else { fetch_body_item->embedded_item_status = FetchStatus::FAILED_TO_LOAD; } @@ -6638,7 +6637,7 @@ namespace QuickMedia { fetch_message_tab = -1; } - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); if(chat_state == ChatState::URL_SELECTION) { url_selection_body.draw(window, body_pos, body_size); @@ -6647,7 +6646,7 @@ namespace QuickMedia { if(selected_tab == MESSAGES_TAB_INDEX && mention.visible && chat_state == ChatState::TYPING_MESSAGE) { sf::RectangleShape user_mention_background(sf::Vector2f(body_size.x, user_mention_body_height)); user_mention_background.setPosition(sf::Vector2f(body_pos.x, body_pos.y + body_size.y - user_mention_body_height)); - user_mention_background.setFillColor(get_current_theme().shade_color); + user_mention_background.setFillColor(get_theme().shade_color); window.draw(user_mention_background); tabs[USERS_TAB_INDEX].body->draw(window, user_mention_background.getPosition(), user_mention_background.getSize()); @@ -6679,7 +6678,7 @@ namespace QuickMedia { if(draw_room_list) { sf::RectangleShape room_list_background(sf::Vector2f(this->body_size.x, window_size.y)); //room_list_background.setPosition(this->body_pos); - room_list_background.setFillColor(get_current_theme().shade_color); + room_list_background.setFillColor(get_theme().shade_color); window.draw(room_list_background); window.draw(room_label); const float tab_y = std::floor(tab_vertical_offset) + room_name_padding_y; @@ -6710,13 +6709,13 @@ namespace QuickMedia { sf::RectangleShape item_background(sf::Vector2f(window_size.x, body_item_size.y + chat_input_height_full + replying_to_text_height + margin)); item_background.setPosition(sf::Vector2f(0.0f, window_size.y - (body_item_size.y + chat_input_height_full + replying_to_text_height + margin))); - item_background.setFillColor(get_current_theme().background_color); + item_background.setFillColor(get_theme().background_color); window.draw(item_background); if(mention.visible) { sf::RectangleShape user_mention_background(sf::Vector2f(window_size.x, user_mention_body_height)); user_mention_background.setPosition(sf::Vector2f(0.0f, item_background.getPosition().y - user_mention_body_height)); - user_mention_background.setFillColor(get_current_theme().shade_color); + user_mention_background.setFillColor(get_theme().shade_color); window.draw(user_mention_background); tabs[USERS_TAB_INDEX].body->draw(window, @@ -6753,9 +6752,9 @@ namespace QuickMedia { room_desc.erase(room_desc.begin() + last_line_start - 1, room_desc.end()); } current_room->body_item->set_description(std::move(room_desc)); - current_room->body_item->set_description_color(get_current_theme().faded_text_color); + current_room->body_item->set_description_color(get_theme().faded_text_color); // TODO: Show a line like nheko instead for unread messages, or something else - current_room->body_item->set_title_color(get_current_theme().text_color); + current_room->body_item->set_title_color(get_theme().text_color); current_room->last_message_read = true; // TODO: Maybe set this instead when the mention is visible on the screen? current_room->unread_notification_count = 0; @@ -6789,7 +6788,7 @@ namespace QuickMedia { // TODO: fetch_messages_dir double progress = 0.5 + std::sin(std::fmod(gradient_inc, 360.0) * 0.017453292519943295 - 1.5707963267948966*0.5) * 0.5; gradient_inc += (frame_time_ms * 0.5); - sf::Color top_color = interpolate_colors(get_current_theme().background_color, get_current_theme().loading_page_color, progress); + sf::Color top_color = interpolate_colors(get_theme().background_color, get_theme().loading_page_color, progress); gradient_points[0].position.x = chat_input_shade.getPosition().x; gradient_points[0].position.y = tab_shade_height; @@ -6805,8 +6804,8 @@ namespace QuickMedia { gradient_points[0].color = top_color; gradient_points[1].color = top_color; - gradient_points[2].color = get_current_theme().background_color; - gradient_points[3].color = get_current_theme().background_color; + gradient_points[2].color = get_theme().background_color; + gradient_points[3].color = get_theme().background_color; if(fetch_messages_dir == MessageDirection::AFTER) { gradient_points[0].position.y = more_messages_below_rect.getPosition().y; @@ -6814,8 +6813,8 @@ namespace QuickMedia { gradient_points[2].position.y = more_messages_below_rect.getPosition().y + gradient_height; gradient_points[3].position.y = more_messages_below_rect.getPosition().y + gradient_height; - gradient_points[0].color = get_current_theme().background_color; - gradient_points[1].color = get_current_theme().background_color; + gradient_points[0].color = get_theme().background_color; + gradient_points[1].color = get_theme().background_color; gradient_points[2].color = top_color; gradient_points[3].color = top_color; } @@ -7190,13 +7189,13 @@ namespace QuickMedia { } idle_active_handler(); - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); window.display(); const float loading_bar_padding_x = std::floor(4.0f * get_config().scale); const float loading_bar_padding_y = std::floor(4.0f * get_config().scale); - RoundedRectangle loading_bar_background(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale), get_current_theme().background_color, &rounded_rectangle_shader); - RoundedRectangle loading_bar(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale - loading_bar_padding_y), get_current_theme().loading_bar_color, &rounded_rectangle_shader); + RoundedRectangle loading_bar_background(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale), get_theme().background_color, &rounded_rectangle_shader); + RoundedRectangle loading_bar(sf::Vector2f(1.0f, 1.0f), std::floor(10.0f * get_config().scale - loading_bar_padding_y), get_theme().loading_bar_color, &rounded_rectangle_shader); const float padding_x = std::floor(30.0f * get_config().scale); const float spacing_y = std::floor(15.0f * get_config().scale); @@ -7205,9 +7204,9 @@ namespace QuickMedia { sf::Text progress_text("0kb/Unknown", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(20.0f * get_config().scale * get_config().font_scale)); sf::Text status_text("Downloading", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(20.0f * get_config().scale * get_config().font_scale)); sf::Text filename_text(filename.c_str(), *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14.0f * get_config().scale * get_config().font_scale)); - filename_text.setFillColor(get_current_theme().faded_text_color); + filename_text.setFillColor(get_theme().faded_text_color); sf::Text download_speed_text("0 bytes/s", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(14.0f * get_config().scale * get_config().font_scale)); - download_speed_text.setFillColor(get_current_theme().faded_text_color); + download_speed_text.setFillColor(get_theme().faded_text_color); bool redraw = true; sf::Event event; @@ -7313,7 +7312,7 @@ namespace QuickMedia { std::floor((loading_bar_background.get_size().x - loading_bar_padding_x * 2.0f) * ui_progress), loading_bar_height - loading_bar_padding_y * 2.0f)); - window.clear(get_current_theme().shade_color); + window.clear(get_theme().shade_color); loading_bar_background.draw(window); loading_bar.draw(window); window.draw(progress_text); @@ -7389,10 +7388,10 @@ namespace QuickMedia { const float bottom_panel_spacing = 10.0f; Button cancel_button("Cancel", FontLoader::get_font(FontLoader::FontType::LATIN), 16, 100.0f, &rounded_rectangle_shader, get_config().scale * get_config().font_scale); - cancel_button.set_background_color(get_current_theme().cancel_button_background_color); + cancel_button.set_background_color(get_theme().cancel_button_background_color); Button save_button("Save", FontLoader::get_font(FontLoader::FontType::LATIN), 16, 100.0f, &rounded_rectangle_shader, get_config().scale * get_config().font_scale); - save_button.set_background_color(get_current_theme().confirm_button_background_color); + save_button.set_background_color(get_theme().confirm_button_background_color); sf::Text file_name_label("File name:", *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(16.0f * get_config().scale * get_config().font_scale)); @@ -7402,7 +7401,7 @@ namespace QuickMedia { file_name_entry.set_editable(false); sf::RectangleShape bottom_panel_background; - bottom_panel_background.setFillColor(get_current_theme().shade_color); + bottom_panel_background.setFillColor(get_theme().shade_color); const float gradient_height = 5.0f; sf::Vertex gradient_points[4]; @@ -7517,7 +7516,7 @@ namespace QuickMedia { gradient_points[3] = sf::Vertex(bottom_panel_background.getPosition() + sf::Vector2f(0.0f, 0.0f), color); } - window.clear(get_current_theme().background_color); + window.clear(get_theme().background_color); ui_tabs.draw(window, sf::Vector2f(0.0f, search_bar->getBottomWithoutShadow()), window_size.x); search_bar->draw(window, window_size, true); diff --git a/src/SearchBar.cpp b/src/SearchBar.cpp index cc93169..085f23e 100644 --- a/src/SearchBar.cpp +++ b/src/SearchBar.cpp @@ -25,7 +25,7 @@ namespace QuickMedia { text_autosearch_delay(50), caret_visible(true), text(placeholder, *FontLoader::get_font(FontLoader::FontType::LATIN), std::floor(get_config().search.font_size * get_config().scale * get_config().font_scale)), - background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_current_theme().selected_color, rounded_rectangle_shader), + background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_theme().selected_color, rounded_rectangle_shader), placeholder_str(placeholder), show_placeholder(true), updated_search(false), @@ -40,8 +40,8 @@ namespace QuickMedia { { padding_top = padding_top_default; padding_bottom = padding_bottom_default; - text.setFillColor(get_current_theme().placeholder_text_color); - shade.setFillColor(get_current_theme().shade_color); + text.setFillColor(get_theme().placeholder_text_color); + shade.setFillColor(get_theme().shade_color); if(plugin_logo && plugin_logo->getNativeHandle() != 0) plugin_logo_sprite.setTexture(*plugin_logo, true); } @@ -186,7 +186,7 @@ namespace QuickMedia { if(str.getSize() == 0) { show_placeholder = true; text.setString(placeholder_str); - text.setFillColor(get_current_theme().placeholder_text_color); + text.setFillColor(get_theme().placeholder_text_color); } if(!updated_search) { typing = true; @@ -216,7 +216,7 @@ namespace QuickMedia { return; show_placeholder = true; text.setString(placeholder_str); - text.setFillColor(get_current_theme().placeholder_text_color); + text.setFillColor(get_theme().placeholder_text_color); needs_update = true; updated_search = false; backspace_pressed = false; diff --git a/src/Storage.cpp b/src/Storage.cpp index 35cf5f8..3ceb606 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -279,7 +279,7 @@ namespace QuickMedia { bool read_file_as_json(const Path &filepath, Json::Value &result) { std::string file_content; if(file_get_content(filepath, file_content) != 0) { - fprintf(stderr, "Failed to get content of file: %s\n", filepath.data.c_str()); + //fprintf(stderr, "Failed to get content of file: %s\n", filepath.data.c_str()); return false; } diff --git a/src/Tabs.cpp b/src/Tabs.cpp index 8965a85..2a4c2f0 100644 --- a/src/Tabs.cpp +++ b/src/Tabs.cpp @@ -23,11 +23,11 @@ namespace QuickMedia { return tab_height + std::floor(10.0f * get_config().scale); } - Tabs::Tabs(sf::Shader *rounded_rectangle_shader, sf::Color shade_color) : background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_current_theme().selected_color, rounded_rectangle_shader), shade_color(shade_color) { + Tabs::Tabs(sf::Shader *rounded_rectangle_shader, sf::Color shade_color) : background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_theme().selected_color, rounded_rectangle_shader), shade_color(shade_color) { shade.setFillColor(shade_color); } - Tabs::Tabs(sf::Shader *rounded_rectangle_shader) : Tabs(rounded_rectangle_shader, get_current_theme().shade_color) {} + Tabs::Tabs(sf::Shader *rounded_rectangle_shader) : Tabs(rounded_rectangle_shader, get_theme().shade_color) {} int Tabs::add_tab(const std::string &title, Body *body) { assert(body); @@ -173,7 +173,7 @@ namespace QuickMedia { window.draw(gradient_points, 4, sf::Quads); sf::RectangleShape line(sf::Vector2f(std::floor(10.0f * get_config().scale), std::floor(2.0f * get_config().scale))); - line.setFillColor(get_current_theme().arrow_color); + line.setFillColor(get_theme().arrow_color); line.setOrigin(line.getSize().x * 0.5f, line.getSize().y * 0.5f); line.rotate(-45.0f); @@ -200,7 +200,7 @@ namespace QuickMedia { window.draw(gradient_points, 4, sf::Quads); sf::RectangleShape line(sf::Vector2f(std::floor(10.0f * get_config().scale), std::floor(2.0f * get_config().scale))); - line.setFillColor(get_current_theme().arrow_color); + line.setFillColor(get_theme().arrow_color); line.setOrigin(line.getSize().x * 0.5f, line.getSize().y * 0.5f); line.rotate(45.0f); diff --git a/src/Text.cpp b/src/Text.cpp index c5f1ce2..14aebb1 100644 --- a/src/Text.cpp +++ b/src/Text.cpp @@ -37,7 +37,7 @@ namespace QuickMedia bold_font(bold_font), characterSize(characterSize), maxWidth(maxWidth), - color(get_current_theme().text_color), + color(get_theme().text_color), dirty(true), dirtyText(false), dirtyCaret(false), @@ -399,7 +399,7 @@ namespace QuickMedia const float vspace = font_get_real_height(latin_font); const float emoji_scale = vspace / 20.0f; - const sf::Color url_color = get_current_theme().url_text_color; + const sf::Color url_color = get_theme().url_text_color; size_t url_range_index = 0; diff --git a/src/Theme.cpp b/src/Theme.cpp index a197848..8f52240 100644 --- a/src/Theme.cpp +++ b/src/Theme.cpp @@ -1,97 +1,122 @@ #include "../include/Theme.hpp" #include "../include/Config.hpp" -#include -#include -#include +#include "../include/Storage.hpp" #include namespace QuickMedia { - enum { - THEME_DARK, // Default theme - THEME_NORD, - - __NUM_THEMES__ // This should always be the last item - }; - - static bool themes_initialized = false; - static int current_theme = THEME_DARK; - static Theme themes[__NUM_THEMES__]; - - static void init_theme_dark() { - themes[THEME_DARK].background_color = sf::Color(18, 21, 26); - themes[THEME_DARK].text_color = sf::Color(255, 255, 255); - themes[THEME_DARK].faded_text_color = sf::Color(255, 255, 255, 179); - themes[THEME_DARK].shade_color = sf::Color(28, 32, 39); - themes[THEME_DARK].selected_color = sf::Color(55, 60, 68); - themes[THEME_DARK].card_item_background_color = sf::Color(28, 32, 39); - themes[THEME_DARK].replies_text_color = sf::Color(129, 162, 190); - themes[THEME_DARK].placeholder_text_color = sf::Color(255, 255, 255, 100); - themes[THEME_DARK].image_loading_background_color = sf::Color(52, 58, 70); - themes[THEME_DARK].attention_alert_text_color = sf::Color(255, 100, 100); - themes[THEME_DARK].cancel_button_background_color = sf::Color(41, 45, 50); - themes[THEME_DARK].confirm_button_background_color = sf::Color(31, 117, 255); - themes[THEME_DARK].loading_bar_color = sf::Color(31, 117, 255); - themes[THEME_DARK].embedded_item_border_color = sf::Color(255, 255, 255); - themes[THEME_DARK].provisional_message_color = sf::Color(255, 255, 255, 150); - themes[THEME_DARK].failed_text_color = sf::Color(255, 0, 0); - themes[THEME_DARK].timestamp_text_color = sf::Color(185, 190, 198, 100); - themes[THEME_DARK].new_items_alert_color = sf::Color(128, 50, 50); - themes[THEME_DARK].arrow_color = sf::Color(255, 255, 255, 175); - themes[THEME_DARK].url_text_color = sf::Color(35, 140, 245); - themes[THEME_DARK].loading_page_color = sf::Color(175, 180, 188); - themes[THEME_DARK].more_items_color = sf::Color(150, 175, 255, 100); - themes[THEME_DARK].blur_enabled = false; + static bool theme_initialized = false; + static Theme *theme = nullptr; + + static bool get_theme_by_name(const std::string &theme_name, Json::Value &json_root) { + Path config_path = get_storage_dir().join("themes").join(theme_name).append(".json"); + if(read_file_as_json(config_path, json_root) && json_root.isObject()) + return true; + + config_path = Path("/usr/share/quickmedia/themes/").join(theme_name).append(".json"); + if(read_file_as_json(config_path, json_root) && json_root.isObject()) + return true; + + return false; } - static void init_theme_nord() { - themes[THEME_NORD].background_color = sf::Color(46, 52, 64); - themes[THEME_NORD].text_color = sf::Color(236, 239, 244); - themes[THEME_NORD].faded_text_color = sf::Color(229, 233, 240); - themes[THEME_NORD].shade_color = sf::Color(67, 76, 94); - themes[THEME_NORD].selected_color = sf::Color(59, 66, 82); - themes[THEME_NORD].card_item_background_color = sf::Color(76, 86, 106); - themes[THEME_NORD].replies_text_color = sf::Color(136, 192, 208); - themes[THEME_NORD].placeholder_text_color = sf::Color(236, 239, 244); - themes[THEME_NORD].image_loading_background_color = sf::Color(216, 222, 233); - themes[THEME_NORD].attention_alert_text_color = sf::Color(191, 97, 106); - themes[THEME_NORD].cancel_button_background_color = sf::Color(229, 233, 240); - themes[THEME_NORD].confirm_button_background_color = sf::Color(229, 233, 240); - themes[THEME_NORD].loading_bar_color = sf::Color(136, 192, 208); - themes[THEME_NORD].embedded_item_border_color = sf::Color(216, 222, 233); - themes[THEME_NORD].provisional_message_color = sf::Color(236, 239, 244); - themes[THEME_NORD].failed_text_color = sf::Color(191, 97, 106); - themes[THEME_NORD].timestamp_text_color = sf::Color(76, 86, 106); - themes[THEME_NORD].new_items_alert_color = sf::Color(235, 203, 139); - themes[THEME_NORD].arrow_color = sf::Color(236, 239, 244); - themes[THEME_NORD].url_text_color = sf::Color(136, 192, 208); - themes[THEME_NORD].loading_page_color = sf::Color(229, 233, 240); - themes[THEME_NORD].more_items_color = sf::Color(150, 175, 255, 100); - themes[THEME_NORD].blur_enabled = false; + // Returns -1 if its not a hex value + static int get_hex_value(char c) { + if(c >= '0' && c <= '9') + return c - '0'; + else if(c >= 'a' && c <= 'f') + return 10 + (c - 'a'); + else if(c >= 'A' && c <= 'F') + return 10 + (c - 'A'); + else + return -1; } - void init_themes() { - if(themes_initialized) + static void parse_hex_set_color(const Json::Value &json_obj, const char *field_name, sf::Color &color) { + const Json::Value &json_val = json_obj[field_name]; + if(!json_val.isString()) { + fprintf(stderr, "Warning: theme variable \"%s\" does not exists or is not a string\n", field_name); return; + } - themes_initialized = true; - init_theme_dark(); - init_theme_nord(); + // #RRGGBB(AA), case insensitive hex + const char *color_str = json_val.asCString(); + if(color_str[0] != '#') { + fprintf(stderr, "Warning: theme variable \"%s\" is an invalid color value. Expected #RRGGBB or #RRGGBBAA, was: %s\n", field_name, color_str); + return; + } - const char *theme = get_config().theme.c_str(); - if(strcmp(theme, "default") == 0) - current_theme = THEME_DARK; - else if(strcmp(theme, "nord") == 0) - current_theme = THEME_NORD; - else - fprintf(stderr, "Warning: Invalid theme %s, using the default theme\n", theme); + const int color_str_len = strlen(color_str); + if(color_str_len - 1 != 6 && color_str_len - 1 != 8) { + fprintf(stderr, "Warning: theme variable \"%s\" is an invalid color value. Expected #RRGGBB or #RRGGBBAA, was: %s\n", field_name, color_str); + return; + } + + sf::Color new_color; + for(int i = 1; i < color_str_len; i += 2) { + const int c1 = get_hex_value(color_str[i + 0]); + const int c2 = get_hex_value(color_str[i + 1]); + if(c1 == -1 || c2 == -1) { + fprintf(stderr, "Warning: theme variable \"%s\" is an invalid color value. Expected #RRGGBB or #RRGGBBAA, was: %s\n", field_name, color_str); + return; + } + + // TODO: Test on big endian systems + (&new_color.r)[(i - 1)/2] = (c1 << 4) | c2; + } + color = new_color; } - void set_current_theme(int theme) { - current_theme = theme; + static void get_bool_value(const Json::Value &json_obj, const char *field_name, bool &val) { + const Json::Value &json_val = json_obj[field_name]; + if(!json_val.isBool()) { + fprintf(stderr, "Warning: theme variable \"%s\" does not exists or is not a boolean\n", field_name); + return; + } + val = json_val.asBool(); + } + + static void init_theme() { + if(theme_initialized) + return; + + theme_initialized = true; + // Wtf? can't use static non-pointer config because it causes a segfault. + // It looks like a libc bug??? crashes for both gcc and clang. + theme = new Theme(); + + Json::Value json_root; + if(!get_theme_by_name(get_config().theme, json_root)) { + fprintf(stderr, "Warning: failed to load theme: \"%s\", using \"default\" theme\n", get_config().theme.c_str()); + return; + } + + parse_hex_set_color(json_root, "background_color", theme->background_color); + parse_hex_set_color(json_root, "text_color", theme->text_color); + parse_hex_set_color(json_root, "faded_text_color", theme->faded_text_color); + parse_hex_set_color(json_root, "shade_color", theme->shade_color); + parse_hex_set_color(json_root, "selected_color", theme->selected_color); + parse_hex_set_color(json_root, "card_item_background_color", theme->card_item_background_color); + parse_hex_set_color(json_root, "replies_text_color", theme->replies_text_color); + parse_hex_set_color(json_root, "placeholder_text_color", theme->placeholder_text_color); + parse_hex_set_color(json_root, "image_loading_background_color", theme->image_loading_background_color); + parse_hex_set_color(json_root, "attention_alert_text_color", theme->attention_alert_text_color); + parse_hex_set_color(json_root, "cancel_button_background_color", theme->cancel_button_background_color); + parse_hex_set_color(json_root, "confirm_button_background_color", theme->confirm_button_background_color); + parse_hex_set_color(json_root, "loading_bar_color", theme->loading_bar_color); + parse_hex_set_color(json_root, "embedded_item_border_color", theme->embedded_item_border_color); + parse_hex_set_color(json_root, "provisional_message_color", theme->provisional_message_color); + parse_hex_set_color(json_root, "failed_text_color", theme->failed_text_color); + parse_hex_set_color(json_root, "timestamp_text_color", theme->timestamp_text_color); + parse_hex_set_color(json_root, "new_items_alert_color", theme->new_items_alert_color); + parse_hex_set_color(json_root, "arrow_color", theme->arrow_color); + parse_hex_set_color(json_root, "url_text_color", theme->url_text_color); + parse_hex_set_color(json_root, "loading_page_color", theme->loading_page_color); + parse_hex_set_color(json_root, "more_items_color", theme->more_items_color); + get_bool_value(json_root, "drop_shadow", theme->drop_shadow); } - const Theme& get_current_theme() { - assert(themes_initialized); - return themes[current_theme]; + const Theme& get_theme() { + init_theme(); + return *theme; } } diff --git a/src/gui/Button.cpp b/src/gui/Button.cpp index 1f84335..63850d5 100644 --- a/src/gui/Button.cpp +++ b/src/gui/Button.cpp @@ -9,7 +9,7 @@ namespace QuickMedia { Button::Button(const std::string &label, sf::Font *font, unsigned int character_size, float width, sf::Shader *rounded_rectangle_shader, float scale) : label(label, *font, character_size * scale), - background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_current_theme().shade_color, rounded_rectangle_shader), + background(sf::Vector2f(1.0f, 1.0f), 10.0f, get_theme().shade_color, rounded_rectangle_shader), scale(scale) { background.set_size(sf::Vector2f(std::floor(width * scale), get_height())); diff --git a/src/plugins/AniList.cpp b/src/plugins/AniList.cpp index 1523129..0c7229f 100644 --- a/src/plugins/AniList.cpp +++ b/src/plugins/AniList.cpp @@ -385,7 +385,7 @@ query ($id: Int, $page: Int, $perPage: Int) { body_item->set_author(std::move(title)); if(!description.empty()) { body_item->set_description(std::move(description)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); } if(cover_image_json.isObject()) { const Json::Value &cover_img_sized_json = cover_image_json[thumbnail_size_to_cover_image_type(thumbnail_size)]; diff --git a/src/plugins/FileManager.cpp b/src/plugins/FileManager.cpp index 295b962..289a382 100644 --- a/src/plugins/FileManager.cpp +++ b/src/plugins/FileManager.cpp @@ -140,7 +140,7 @@ namespace QuickMedia { description += "\nDirectory"; } body_item->set_description(std::move(description)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); result_items.push_back(std::move(body_item)); } diff --git a/src/plugins/HotExamples.cpp b/src/plugins/HotExamples.cpp index 29e0110..a049101 100644 --- a/src/plugins/HotExamples.cpp +++ b/src/plugins/HotExamples.cpp @@ -72,7 +72,7 @@ namespace QuickMedia { html_unescape_sequences(desc); (*item_data->body_items)[item_data->index]->set_description(std::move(desc)); - (*item_data->body_items)[item_data->index]->set_description_color(get_current_theme().faded_text_color); + (*item_data->body_items)[item_data->index]->set_description_color(get_theme().faded_text_color); item_data->index++; } return 0; @@ -122,7 +122,7 @@ namespace QuickMedia { html_unescape_sequences(desc); (*item_data->body_items)[item_data->index]->set_description(std::move(desc)); - (*item_data->body_items)[item_data->index]->set_description_color(get_current_theme().text_color); + (*item_data->body_items)[item_data->index]->set_description_color(get_theme().text_color); // TODO: Use monospace item_data->index++; } diff --git a/src/plugins/MangaGeneric.cpp b/src/plugins/MangaGeneric.cpp index 87b4f1d..78a2c39 100644 --- a/src/plugins/MangaGeneric.cpp +++ b/src/plugins/MangaGeneric.cpp @@ -111,7 +111,7 @@ namespace QuickMedia { } else if(merge_userdata->type == MergeType::DESCRIPTION) { const char *prefix = merge_userdata->desc_prefix ? merge_userdata->desc_prefix : ""; (*body_item_image_context.body_items)[body_item_image_context.index]->set_description(prefix + std::move(field_stripped)); - (*body_item_image_context.body_items)[body_item_image_context.index]->set_description_color(get_current_theme().faded_text_color); + (*body_item_image_context.body_items)[body_item_image_context.index]->set_description_color(get_theme().faded_text_color); } body_item_image_context.index++; } diff --git a/src/plugins/Mangadex.cpp b/src/plugins/Mangadex.cpp index 1553d82..34bcfc7 100644 --- a/src/plugins/Mangadex.cpp +++ b/src/plugins/Mangadex.cpp @@ -216,7 +216,7 @@ namespace QuickMedia { const Json::Value &en_json = description_json["en"]; if(en_json.isString()) { body_item->set_description(en_json.asString()); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); } } @@ -306,7 +306,7 @@ namespace QuickMedia { time_t unix_time = iso_utc_to_unix_time(publish_at_json.asCString()); if(unix_time != 0) { body_item->set_description("Uploaded: " + unix_time_to_local_time_str(unix_time)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); } } diff --git a/src/plugins/Manganelo.cpp b/src/plugins/Manganelo.cpp index 90003cb..990a513 100644 --- a/src/plugins/Manganelo.cpp +++ b/src/plugins/Manganelo.cpp @@ -67,7 +67,7 @@ namespace QuickMedia { if(text.data && class_attr.data && string_view_contains(class_attr, "chapter-time") && item_data->index < item_data->body_items->size()) { std::string uploaded_date(text.data, text.size); (*item_data->body_items)[item_data->index]->set_description("Uploaded: " + std::move(uploaded_date)); - (*item_data->body_items)[item_data->index]->set_description_color(get_current_theme().faded_text_color); + (*item_data->body_items)[item_data->index]->set_description_color(get_theme().faded_text_color); item_data->index++; } return 0; @@ -134,7 +134,7 @@ namespace QuickMedia { item->url = "https://manganelo.com/manga/" + url_param_encode(nameunsigned.asString()); if(lastchapter.isString() && lastchapter.asCString()[0] != '\0') { item->set_description("Latest chapter: " + lastchapter.asString()); - item->set_description_color(get_current_theme().faded_text_color); + item->set_description_color(get_theme().faded_text_color); } Json::Value image = child.get("image", ""); if(image.isString() && image.asCString()[0] != '\0') diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 6d8148d..3f42437 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -630,20 +630,20 @@ namespace QuickMedia { if(!room_desc.empty()) room_desc += '\n'; room_desc += "** " + std::to_string(unread_notification_count) + " unread mention(s) **"; // TODO: Better notification? - room->body_item->set_description_color(get_current_theme().attention_alert_text_color); + room->body_item->set_description_color(get_theme().attention_alert_text_color); } else { - room->body_item->set_description_color(get_current_theme().faded_text_color); + room->body_item->set_description_color(get_theme().faded_text_color); } room->body_item->set_description(std::move(room_desc)); if(set_room_as_unread) - room->body_item->set_title_color(get_current_theme().attention_alert_text_color); + room->body_item->set_title_color(get_theme().attention_alert_text_color); room->last_message_read = false; rooms_page->move_room_to_top(room); room_tags_page->move_room_to_top(room); } else if(last_new_message) { room->body_item->set_description(extract_first_line_remove_newline_elipses(matrix->message_get_author_displayname(last_new_message.get()), AUTHOR_MAX_LENGTH) + ": " + message_to_room_description_text(last_new_message.get())); - room->body_item->set_description_color(get_current_theme().faded_text_color); + room->body_item->set_description_color(get_theme().faded_text_color); rooms_page->move_room_to_top(room); room_tags_page->move_room_to_top(room); @@ -904,7 +904,7 @@ namespace QuickMedia { body_item->set_author(extract_first_line_remove_newline_elipses(display_name, AUTHOR_MAX_LENGTH)); body_item->set_author_color(user_id_to_color(user_info.user_id)); body_item->set_description(user_info.user_id); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); if(user_info.avatar_url) body_item->thumbnail_url = user_info.avatar_url.value(); body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; @@ -1035,8 +1035,8 @@ namespace QuickMedia { body_item->url = notification.event_id; if(!notification.read) { - body_item->set_author_color(get_current_theme().attention_alert_text_color); - body_item->set_description_color(get_current_theme().attention_alert_text_color); + body_item->set_author_color(get_theme().attention_alert_text_color); + body_item->set_description_color(get_theme().attention_alert_text_color); } body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE; @@ -1128,8 +1128,8 @@ namespace QuickMedia { NotificationsExtraData *extra_data = static_cast(room_notification.second->extra.get()); if(!extra_data->read) { extra_data->read = true; - room_notification.second->set_author_color(get_current_theme().text_color); - room_notification.second->set_description_color(get_current_theme().text_color); + room_notification.second->set_author_color(get_theme().text_color); + room_notification.second->set_description_color(get_theme().text_color); } } } @@ -4410,7 +4410,7 @@ namespace QuickMedia { auto body_item = BodyItem::create(""); body_item->url.assign(user_id_json.GetString(), user_id_json.GetStringLength()); body_item->set_description(body_item->url); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); if(display_name_json.IsString()) body_item->set_author(std::string(display_name_json.GetString(), display_name_json.GetStringLength())); else diff --git a/src/plugins/MyAnimeList.cpp b/src/plugins/MyAnimeList.cpp index 5f5ae40..16f07f9 100644 --- a/src/plugins/MyAnimeList.cpp +++ b/src/plugins/MyAnimeList.cpp @@ -85,7 +85,7 @@ namespace QuickMedia { if(!description.empty()) { body_item->set_description(std::move(description)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); } return body_item; @@ -284,7 +284,7 @@ namespace QuickMedia { std::string description(text.data, text.size); html_unescape_sequences(description); (*item_data->body_items)[item_data->index]->set_description(std::move(description)); - (*item_data->body_items)[item_data->index]->set_description_color(get_current_theme().faded_text_color); + (*item_data->body_items)[item_data->index]->set_description_color(get_theme().faded_text_color); item_data->index++; } return 0; @@ -302,7 +302,7 @@ namespace QuickMedia { auto body_item = BodyItem::create(""); body_item->set_description(std::move(description)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); result_items->push_back(std::move(body_item)); } return 0; diff --git a/src/plugins/Page.cpp b/src/plugins/Page.cpp index 5c64183..b7ef30c 100644 --- a/src/plugins/Page.cpp +++ b/src/plugins/Page.cpp @@ -74,7 +74,7 @@ namespace QuickMedia { body_item->url = url_json.asString(); if(timestamp_json.isInt64()) { body_item->set_description("Bookmarked " + seconds_to_relative_time_str(time_now - timestamp_json.asInt64())); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); } result_items.push_back(std::move(body_item)); } diff --git a/src/plugins/Soundcloud.cpp b/src/plugins/Soundcloud.cpp index f20cf7d..a9b192e 100644 --- a/src/plugins/Soundcloud.cpp +++ b/src/plugins/Soundcloud.cpp @@ -204,7 +204,7 @@ namespace QuickMedia { } body_item->set_description(std::move(description)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); return body_item; } diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index d308346..b6dc2f7 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -504,7 +504,7 @@ namespace QuickMedia { desc += std::move(description_snippet_stripped); } body_item->set_description(std::move(desc)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); if(scheduled_text.empty()) body_item->url = "https://www.youtube.com/watch?v=" + video_id_str; @@ -563,7 +563,7 @@ namespace QuickMedia { desc += std::move(description_snippet_stripped); } body_item->set_description(std::move(desc)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); body_item->url = "https://www.youtube.com/channel/" + channel_id_json.asString(); if(thumbnail) { if(string_starts_with(thumbnail->url, "https:")) @@ -1745,7 +1745,7 @@ namespace QuickMedia { description += subscription_data.author; } body_item->set_description(std::move(description)); - body_item->set_description_color(get_current_theme().faded_text_color); + body_item->set_description_color(get_theme().faded_text_color); body_item->url = "https://www.youtube.com/watch?v=" + subscription_entry.video_id; body_item->thumbnail_url = "https://img.youtube.com/vi/" + subscription_entry.video_id + "/mqdefault.jpg"; body_item->thumbnail_size = sf::Vector2i(192, 108); -- cgit v1.2.3