diff options
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | include/Body.hpp | 7 | ||||
-rw-r--r-- | src/Body.cpp | 32 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 26 | ||||
-rw-r--r-- | src/plugins/Youtube.cpp | 7 |
5 files changed, 42 insertions, 33 deletions
@@ -174,4 +174,5 @@ Add option to view dead link in 4chan with 4chan archive and navigate to crossbo Show latest message before sync is done for a room when the latest message is an edit. Right now it has to fetch previous messages until the first non-edit message. Allow resuming downloads. Support downloading live youtube videos. -Youtube broke age restricted video again. Need to find a fix. It kinda works in yt-dlp, but not always.
\ No newline at end of file +Youtube broke age restricted video again. Need to find a fix. It kinda works in yt-dlp, but not always. +Youtube broke copyrighted videos again...
\ No newline at end of file diff --git a/include/Body.hpp b/include/Body.hpp index da54ee5..43fdf22 100644 --- a/include/Body.hpp +++ b/include/Body.hpp @@ -179,7 +179,7 @@ namespace QuickMedia { }; using BodyItems = std::vector<std::shared_ptr<BodyItem>>; - using BodyItemRenderCallback = std::function<void(BodyItem *body_item)>; + using BodyItemRenderCallback = std::function<void(std::shared_ptr<BodyItem> &body_item)>; // Return true to merge using BodyItemMergeHandler = std::function<bool(BodyItem *prev_item, BodyItem *this_item)>; @@ -236,7 +236,7 @@ namespace QuickMedia { // This happens because of |draw| sets thumbnails as unreferenced at the beginning and cleans them up at the end if they are not drawn in the same function call. // TODO: Right now drawing an item that also exists in the body will cause the text to update geometry every frame if the text is wrapping text and the items are drawn at different sizes, // because of Text::setMaxWidth - void draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item = true, bool is_embedded = false); + void draw_item(sf::RenderWindow &window, std::shared_ptr<BodyItem> &item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item = true, bool is_embedded = false); float get_item_height(BodyItem *item, float width, bool load_texture = true, bool include_embedded_item = true, bool merge_with_previous = false, int item_index = -1); @@ -264,6 +264,7 @@ namespace QuickMedia { bool can_move_left() const { return selected_column > 0; } bool can_move_right() const { return selected_column + 1 < num_columns; } + // TODO: Prevent items from being removed when render is in progress. That would invalidate references and cause a crash BodyItems items; bool draw_thumbnails; // Set to {0, 0} to disable resizing @@ -287,7 +288,7 @@ namespace QuickMedia { // Returns the the body total drawn height float draw_list_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const int prev_num_visible_items, const Json::Value &content_progress); void draw_card_view(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, sf::Vector2u window_size, float scissor_y); - void draw_item(sf::RenderWindow &window, BodyItem *item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress, bool include_embedded_item = true, bool merge_with_previous = false); + void draw_item(sf::RenderWindow &window, std::shared_ptr<BodyItem> &item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress, bool include_embedded_item = true, bool merge_with_previous = false); void update_dirty_state(BodyItem *body_item, float width); void clear_body_item_cache(BodyItem *body_item); sf::Vector2i get_item_thumbnail_size(BodyItem *item) const; diff --git a/src/Body.cpp b/src/Body.cpp index b11cb51..10911e4 100644 --- a/src/Body.cpp +++ b/src/Body.cpp @@ -922,10 +922,10 @@ namespace QuickMedia { return -1; } - void Body::draw_item(sf::RenderWindow &window, BodyItem *item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item, bool is_embedded) { + void Body::draw_item(sf::RenderWindow &window, std::shared_ptr<BodyItem> &item, sf::Vector2f pos, sf::Vector2f size, bool include_embedded_item, bool is_embedded) { // TODO: What about when |card_view| is used? item->keep_alive_frames = 3; - get_item_height(item, size.x, true, false, false, -1); + get_item_height(item.get(), size.x, true, false, false, -1); draw_item(window, item, pos, size, size.y + body_spacing[body_theme].spacing_y, -1, Json::Value::nullSingleton(), include_embedded_item); } @@ -1001,7 +1001,7 @@ namespace QuickMedia { // TODO: Improve performance. Skip items that are obviously not visible or anywhere near the body. Limit loop to 100-200 items around the selected item while(index != -1) { - BodyItem *item = items[index].get(); + std::shared_ptr<BodyItem> &item = items[index]; assert(item->visible); int prev_index; @@ -1013,11 +1013,11 @@ namespace QuickMedia { prev_body_item = items[prev_index].get(); } - const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item, item); + const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item, item.get()); if(attach_side == AttachSide::TOP && merge_with_previous) pos.y -= body_spacing[body_theme].spacing_y; - get_item_height(item, size.x, false, true, merge_with_previous, index); + get_item_height(item.get(), size.x, false, true, merge_with_previous, index); float top_y; if(attach_side == AttachSide::TOP) @@ -1039,7 +1039,7 @@ namespace QuickMedia { const bool is_item_visible_in_body = top_y + item->loaded_height >= 0.0f && top_y <= size.y; if(is_item_visible_in_body || index == selected_item) { - get_item_height(item, size.x, true, true, merge_with_previous, index); + get_item_height(item.get(), size.x, true, true, merge_with_previous, index); if(attach_side == AttachSide::BOTTOM) pos.y -= (item->loaded_height + body_spacing[body_theme].spacing_y); //page_scroll += add_height; @@ -1075,7 +1075,7 @@ namespace QuickMedia { pos.y -= (item->loaded_height + body_spacing[body_theme].spacing_y); if(item->keep_alive_frames == 0) { - clear_body_item_cache(item); + clear_body_item_cache(item.get()); // TODO: Make sure the embedded item is not referencing another item in the |items| list if(item->embedded_item) clear_body_item_cache(item->embedded_item.get()); @@ -1088,7 +1088,7 @@ namespace QuickMedia { pos.y += body_spacing[body_theme].spacing_y; if(attach_side == AttachSide::TOP) { - prev_body_item = item; + prev_body_item = item.get(); index = get_next_visible_item(index); } else { index = prev_index; @@ -1136,9 +1136,9 @@ namespace QuickMedia { sf::Vector2f pos_offset(space_left_column_each, page_scroll); while(item_index < num_items) { - BodyItem *item = items[item_index].get(); + std::shared_ptr<BodyItem> &item = items[item_index]; - get_item_height(item, card_max_image_size.x, false, false, false, item_index); + get_item_height(item.get(), card_max_image_size.x, false, false, false, item_index); int item_height = item->loaded_height; item_height = std::min(card_height, item_height + ((draw_thumbnails && !item->thumbnail_url.empty()) ? card_image_text_padding : 0) + card_padding_y * 2 + 5); row_max_height = std::max(row_max_height, item_height); @@ -1164,12 +1164,12 @@ namespace QuickMedia { if(body_item_render_callback) body_item_render_callback(item); - sf::Vector2i thumbnail_size = get_item_thumbnail_size(item); + sf::Vector2i thumbnail_size = get_item_thumbnail_size(item.get()); std::shared_ptr<ThumbnailData> item_thumbnail; if(draw_thumbnails && !item->thumbnail_url.empty()) item_thumbnail = AsyncImageLoader::get_instance().get_thumbnail(item->thumbnail_url, item->thumbnail_is_local, thumbnail_size); - get_item_height(item, card_max_image_size.x, true, false, false, item_index); + get_item_height(item.get(), card_max_image_size.x, true, false, false, item_index); item_height = item->loaded_height; item_height = std::min(card_height, item_height + (item_thumbnail ? card_image_text_padding : 0) + card_padding_y * 2 + 5); row_max_height = std::max(row_max_height, item_height); @@ -1274,7 +1274,7 @@ namespace QuickMedia { handle_item_render(pos + pos_offset, card_width, item_height, item_index); if(item->keep_alive_frames == 0) { - clear_body_item_cache(item); + clear_body_item_cache(item.get()); // TODO: Make sure the embedded item is not referencing another item in the |items| list if(item->embedded_item) clear_body_item_cache(item->embedded_item.get()); @@ -1307,8 +1307,8 @@ namespace QuickMedia { item_background_target_size = sf::Vector2f(card_width, row_max_height); } - void Body::draw_item(sf::RenderWindow &window, BodyItem *item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress, bool include_embedded_item, bool merge_with_previous) { - sf::Vector2i thumbnail_size = get_item_thumbnail_size(item); + void Body::draw_item(sf::RenderWindow &window, std::shared_ptr<BodyItem> &item, const sf::Vector2f &pos, const sf::Vector2f &size, const float item_height, const int item_index, const Json::Value &content_progress, bool include_embedded_item, bool merge_with_previous) { + sf::Vector2i thumbnail_size = get_item_thumbnail_size(item.get()); std::shared_ptr<ThumbnailData> item_thumbnail; if(draw_thumbnails && !merge_with_previous && !item->thumbnail_url.empty()) item_thumbnail = AsyncImageLoader::get_instance().get_thumbnail(item->thumbnail_url, item->thumbnail_is_local, thumbnail_size); @@ -1422,7 +1422,7 @@ namespace QuickMedia { if(item->embedded_item) { sf::Vector2f embedded_item_pos(std::floor(item_pos.x + text_offset_x + embedded_item_border_width + body_spacing[body_theme].padding_x), std::floor(item_pos.y + body_spacing[body_theme].embedded_item_padding_y + 6.0f)); sf::Vector2f embedded_item_size(embedded_item_width, embedded_item_height); - draw_item(window, item->embedded_item.get(), embedded_item_pos, embedded_item_size, false, true); + draw_item(window, item->embedded_item, embedded_item_pos, embedded_item_size, false, true); } else { embedded_item_load_text.setString(embedded_item_status_to_string(item->embedded_item_status)); embedded_item_load_text.setPosition(std::floor(item_pos.x + text_offset_x + embedded_item_border_width + body_spacing[body_theme].padding_x), std::floor(item_pos.y + embedded_item_height * 0.5f - (body_spacing[body_theme].embedded_item_font_size + 5.0f) * 0.5f + 6.0f)); diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index 161ea1a..dfb7770 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -5215,11 +5215,11 @@ namespace QuickMedia { AsyncTask<bool> fetch_users_future; AsyncTask<FetchMessageResult> fetch_message_future; Message *fetch_message = nullptr; - BodyItem *fetch_body_item = nullptr; + std::shared_ptr<BodyItem> fetch_body_item = nullptr; int fetch_message_tab = -1; // TODO: How about instead fetching all messages we have, not only the visible ones? also fetch with multiple threads. - tabs[PINNED_TAB_INDEX].body->body_item_render_callback = [this, ¤t_room, &me, &fetch_message_future, &tabs, &fetch_body_item, &fetch_message_tab, PINNED_TAB_INDEX, MESSAGES_TAB_INDEX](BodyItem *body_item) { + tabs[PINNED_TAB_INDEX].body->body_item_render_callback = [this, ¤t_room, &me, &fetch_message_future, &tabs, &fetch_body_item, &fetch_message_tab, PINNED_TAB_INDEX, MESSAGES_TAB_INDEX](std::shared_ptr<BodyItem> &body_item) { if(fetch_message_future.valid()) return; @@ -5232,7 +5232,7 @@ namespace QuickMedia { if(event_data->message->related_event_id.empty() || event_data->message->related_event_type != RelatedEventType::REPLY || (body_item->embedded_item_status != FetchStatus::NONE && body_item->embedded_item_status != FetchStatus::QUEUED_LOADING)) return; - if(load_cached_related_embedded_item(body_item, event_data->message, me, current_room, tabs[MESSAGES_TAB_INDEX].body->items)) + if(load_cached_related_embedded_item(body_item.get(), event_data->message, me, current_room, tabs[MESSAGES_TAB_INDEX].body->items)) return; std::string message_event_id = event_data->message->related_event_id; @@ -5277,7 +5277,7 @@ namespace QuickMedia { }; // TODO: How about instead fetching all messages we have, not only the visible ones? also fetch with multiple threads. - tabs[MESSAGES_TAB_INDEX].body->body_item_render_callback = [this, ¤t_room, &me, &fetch_message_future, &tabs, &fetch_body_item, &fetch_message_tab, MESSAGES_TAB_INDEX](BodyItem *body_item) { + tabs[MESSAGES_TAB_INDEX].body->body_item_render_callback = [this, ¤t_room, &me, &fetch_message_future, &tabs, &fetch_body_item, &fetch_message_tab, MESSAGES_TAB_INDEX](std::shared_ptr<BodyItem> &body_item) { Message *message = static_cast<Message*>(body_item->userdata); if(!message) return; @@ -5290,7 +5290,7 @@ namespace QuickMedia { return; } - if(load_cached_related_embedded_item(body_item, message, me, current_room, tabs[MESSAGES_TAB_INDEX].body->items)) + if(load_cached_related_embedded_item(body_item.get(), message, me, current_room, tabs[MESSAGES_TAB_INDEX].body->items)) return; std::string message_event_id = message->related_event_id; @@ -5356,7 +5356,7 @@ namespace QuickMedia { float prev_chat_height = chat_input.get_height(); float chat_input_height_full = 0.0f; - const float logo_padding_x = std::floor(15.0f * get_ui_scale()); + const float logo_padding_x = std::floor(10.0f * get_ui_scale()); const float chat_input_padding_x = std::floor(10.0f * get_ui_scale()); const float chat_input_padding_y = std::floor(10.0f * get_ui_scale()); @@ -6111,7 +6111,7 @@ namespace QuickMedia { update_pinned_messages_author(fetch_message->user); update_messages_author(fetch_message->user); fetch_message = nullptr; - } else if(fetch_message_result.type == FetchMessageType::MESSAGE) { + } else if(fetch_message_result.type == FetchMessageType::MESSAGE && fetch_body_item) { fprintf(stderr, "Finished fetching message: %s\n", fetch_message_result.message ? fetch_message_result.message->event_id.c_str() : "(null)"); if(fetch_message_tab == PINNED_TAB_INDEX) { PinnedEventData *event_data = static_cast<PinnedEventData*>(fetch_body_item->userdata); @@ -6134,6 +6134,7 @@ namespace QuickMedia { fetch_body_item->embedded_item_status = FetchStatus::FAILED_TO_LOAD; } } + fetch_body_item = nullptr; } fetch_message_tab = -1; } @@ -6232,8 +6233,9 @@ namespace QuickMedia { overlay.setFillColor(sf::Color(0, 0, 0, 240)); window.draw(overlay); - sf::Vector2f body_item_pos(body_pos.x, window_size.y - chat_input_height_full - item_height); - sf::Vector2f body_item_size(body_size.x, item_height); + const float padding_x = std::floor(10.0f * QuickMedia::get_ui_scale()); + sf::Vector2f body_item_pos(body_pos.x + padding_x, window_size.y - chat_input_height_full - item_height); + sf::Vector2f body_item_size(body_size.x - padding_x * 2.0f, item_height); 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))); @@ -6247,14 +6249,14 @@ namespace QuickMedia { window.draw(user_mention_background); tabs[USERS_TAB_INDEX].body->draw(window, - sf::Vector2f(body_pos.x, item_background.getPosition().y - user_mention_body_height), - sf::Vector2f(body_size.x, user_mention_body_height)); + sf::Vector2f(body_pos.x + padding_x, item_background.getPosition().y - user_mention_body_height), + sf::Vector2f(body_size.x - padding_x * 2.0f, user_mention_body_height)); } replying_to_text.setPosition(body_item_pos.x, body_item_pos.y - replying_to_text_height); window.draw(replying_to_text); - tabs[MESSAGES_TAB_INDEX].body->draw_item(window, currently_operating_on_item.get(), body_item_pos, body_item_size); + tabs[MESSAGES_TAB_INDEX].body->draw_item(window, currently_operating_on_item, body_item_pos, body_item_size); } if(selected_tab == MESSAGES_TAB_INDEX && current_room && current_room->body_item && !current_room->last_message_read && matrix->is_initial_sync_finished()) { diff --git a/src/plugins/Youtube.cpp b/src/plugins/Youtube.cpp index 167b201..4544a45 100644 --- a/src/plugins/Youtube.cpp +++ b/src/plugins/Youtube.cpp @@ -2463,9 +2463,14 @@ R"END( } const std::string &url = cipher_params["url"]; - if(cipher_params.empty() || url.empty()) + if(url.empty()) return false; + if(cipher_params.empty()) { + youtube_format.url = url; + return true; + } + std::string url_decoded = url_param_decode(url); url_decoded += "&alr=yes&cver=2.20210615.01.00&cpn=" + cpn; |