aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/Body.hpp10
-rw-r--r--src/Body.cpp214
-rw-r--r--src/QuickMedia.cpp13
3 files changed, 165 insertions, 72 deletions
diff --git a/include/Body.hpp b/include/Body.hpp
index 3d8167a..48eb45f 100644
--- a/include/Body.hpp
+++ b/include/Body.hpp
@@ -154,8 +154,6 @@ namespace QuickMedia {
sf::Vector2i thumbnail_size;
std::vector<Reaction> reactions; // TODO: Move to a different body item type
std::shared_ptr<BodyItemExtra> extra; // TODO: Remove
-
- float calculated_height = -1.0f;
private:
// TODO: Clean up these strings when set in text, and get_title for example should return |title_text.getString()|
// TODO: Use sf::String instead, removes the need to convert to utf32 every time the text is dirty (for example when resizing window)
@@ -272,8 +270,12 @@ namespace QuickMedia {
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;
- BodyItem* get_previous_visible_item(int start_index);
- BodyItem* get_next_visible_item(int start_index);
+ // Returns -1 if not found
+ int get_previous_visible_item(int start_index);
+ // Returns -1 if not found
+ int get_next_visible_item(int start_index);
+ float get_offset_to_first_visible_item(sf::Vector2f body_size);
+ float get_offset_to_last_visible_item(sf::Vector2f body_size);
private:
Program *program;
std::unordered_map<std::string, std::shared_ptr<ThumbnailData>> item_thumbnail_textures;
diff --git a/src/Body.cpp b/src/Body.cpp
index 9ea2e01..1f339ce 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -101,7 +101,6 @@ namespace QuickMedia {
author_color = other.author_color;
description_color = other.description_color;
extra = other.extra;
- calculated_height = other.calculated_height;
return *this;
}
@@ -377,8 +376,10 @@ namespace QuickMedia {
void Body::clamp_selection() {
int num_items = (int)items.size();
- if(items.empty())
+ if(items.empty()) {
+ selected_item = 0;
return;
+ }
if(selected_item < 0)
selected_item = 0;
@@ -612,7 +613,8 @@ namespace QuickMedia {
if(selected_item_diff > 0) {
int num_items_scrolled = 0;
int i = prev_selected_item;
- BodyItem *prev_body_item = get_previous_visible_item(i);
+ const int prev_body_item_index = get_previous_visible_item(i);
+ BodyItem *prev_body_item = prev_body_item_index == -1 ? nullptr : items[prev_body_item_index].get();
while(num_items_scrolled < selected_int_diff_abs && i < num_items) {
if(items[i]->visible) {
const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item, items[i].get());
@@ -632,7 +634,8 @@ namespace QuickMedia {
BodyItem *prev_body_item;
while(num_items_scrolled < selected_int_diff_abs && i >= 0) {
if(items[i]->visible) {
- prev_body_item = get_previous_visible_item(i);
+ const int prev_body_item_index = get_previous_visible_item(i);
+ prev_body_item = prev_body_item_index == -1 ? nullptr : items[prev_body_item_index].get();
const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item, items[i].get());
page_scroll -= get_item_height(items[i].get(), size.x, selected_int_diff_abs < 50, true, merge_with_previous, i);
if(merge_with_previous)
@@ -646,8 +649,32 @@ namespace QuickMedia {
}
bool merge_with_previous = false;
+ const int prev_body_item_index = get_previous_visible_item(selected_item);
+ merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item_index == -1 ? nullptr : items[prev_body_item_index].get(), items[selected_item].get());
+
+ if(keep_selected_inside_body) {
+ if(!first_item_fully_visible && !last_item_fully_visible) {
+ if(offset_to_top > 0.0f)
+ page_scroll -= offset_to_top;
+ else if(offset_to_bottom > 0.0f)
+ page_scroll += offset_to_bottom;
+ } else {
+ if(attach_side == AttachSide::TOP) {
+ if(first_item_fully_visible) {
+ page_scroll -= offset_to_top;
+ } else {
+ //page_scroll = get_offset_to_first_visible_item(size);
+ }
+ } else if(attach_side == AttachSide::BOTTOM) {
+ if(last_item_fully_visible) {
+ page_scroll += offset_to_bottom;
+ } else {
+ //page_scroll = get_offset_to_last_visible_item(size);
+ }
+ }
+ }
+ }
- merge_with_previous = body_item_merge_handler && body_item_merge_handler(get_previous_visible_item(selected_item), items[selected_item].get());
selected_item_height = get_item_height(items[selected_item].get(), size.x, true, true, merge_with_previous, selected_item);
selected_item_height += spacing_y;
bool selected_item_fits_on_screen = selected_item_height <= size.y;
@@ -665,25 +692,13 @@ namespace QuickMedia {
selected_line_bottom_visible |= selected_item_fits_on_screen;
if(keep_selected_inside_body) {
- if(!first_item_fully_visible && !last_item_fully_visible) {
- if(offset_to_top > 0.0f)
- page_scroll -= offset_to_top;
- else if(offset_to_bottom > 0.0f)
- page_scroll += offset_to_bottom;
- } else {
- if((attach_side == AttachSide::TOP && first_item_fully_visible)/* || (first_item_fully_visible && !last_item_fully_visible)*/)
- page_scroll -= offset_to_top;
- else if((attach_side == AttachSide::BOTTOM && last_item_fully_visible) || (last_item_fully_visible && !first_item_fully_visible))
- page_scroll += offset_to_bottom;
- }
-
if(page_scroll > size.y - selected_item_height && selected_item_fits_on_screen) {
page_scroll = size.y - selected_item_height;
if(merge_with_previous)
page_scroll += spacing_y*2.0f;
- BodyItem *next_body_item = get_next_visible_item(selected_item);
- const bool merge_with_next = next_body_item && body_item_merge_handler && body_item_merge_handler(items[selected_item].get(), next_body_item);
+ int next_body_item_index = get_next_visible_item(selected_item);
+ const bool merge_with_next = next_body_item_index != -1 && body_item_merge_handler && body_item_merge_handler(items[selected_item].get(), items[next_body_item_index].get());
if(!merge_with_previous && merge_with_next)
page_scroll += spacing_y;
} else if(page_scroll < (merge_with_previous ? spacing_y : 0.0f) && selected_line_top_visible && selected_item_fits_on_screen) {
@@ -705,22 +720,21 @@ namespace QuickMedia {
sf::Vector2f prev_pos = pos;
int i;
- for(i = selected_item - 1; i >= 0; --i) {
+ for(i = selected_item - 1; i >= 0;) {
auto &item = items[i];
// TODO: Find a better solution?
- if(!item->visible)
+ if(!item->visible) {
+ --i;
continue;
+ }
- BodyItem *prev_body_item = get_previous_visible_item(i);
- const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item, item.get());
+ int prev_body_item_index = get_previous_visible_item(i);
+ const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item_index == -1 ? nullptr : items[prev_body_item_index].get(), item.get());
item->last_drawn_time = elapsed_time_sec;
- float extra_page_scroll = page_scroll;
float item_height = get_item_height(item.get(), size.x, true, true, merge_with_previous, i);
- prev_pos.y += (page_scroll - extra_page_scroll);
- float item_height_with_merge = item_height;
- item_height_with_merge += spacing_y;
+ float item_height_with_merge = item_height + spacing_y;
prev_pos.y -= item_height_with_merge;
if(prev_pos.y < start_y) {
@@ -745,29 +759,30 @@ namespace QuickMedia {
if(merge_with_previous)
prev_pos.y += spacing_y;
+
+ i = prev_body_item_index;
}
offset_to_top = prev_pos.y - start_y;
- BodyItem *prev_body_item = get_previous_visible_item(selected_item);
- float prev_item_height = 0.0f;
+ BodyItem *prev_body_item = prev_body_item_index == -1 ? nullptr : items[prev_body_item_index].get();
merge_with_previous = false;
sf::Vector2f after_pos = pos;
- for(int i = selected_item; i < num_items; ++i) {
+ for(int i = selected_item; i < num_items;) {
auto &item = items[i];
// TODO: Find a better solution?
- if(!item->visible)
+ if(!item->visible) {
+ ++i;
continue;
+ }
merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item, item.get());
if(merge_with_previous)
after_pos.y -= spacing_y;
- float extra_page_scroll = page_scroll;
float item_height = get_item_height(item.get(), size.x, true, true, merge_with_previous, i);
- after_pos.y += (page_scroll - extra_page_scroll);
if(after_pos.y < start_y) {
items_cut_off = true;
@@ -796,8 +811,8 @@ namespace QuickMedia {
++num_visible_items;
last_visible_item = i;
- BodyItem *next_body_item = get_next_visible_item(i);
- const bool merge_with_next = next_body_item && body_item_merge_handler && body_item_merge_handler(item.get(), next_body_item);
+ int next_body_item_index = get_next_visible_item(i);
+ const bool merge_with_next = next_body_item_index != -1 && body_item_merge_handler && body_item_merge_handler(item.get(), next_body_item_index == -1 ? nullptr : items[next_body_item_index].get());
if(after_pos.y - start_y - (merge_with_next ? 0.0f : spacing_y) > size.y) {
last_item_fully_visible = false;
@@ -812,7 +827,10 @@ namespace QuickMedia {
first_fully_visible_item = i;
prev_body_item = items[i].get();
- prev_item_height = item_height;
+
+ i = next_body_item_index;
+ if(i == -1)
+ break;
}
if(first_fully_visible_item == -1)
@@ -955,21 +973,108 @@ namespace QuickMedia {
}
// TODO: Cache, and take into consideration updated items and visibility change
- BodyItem* Body::get_previous_visible_item(int start_index) {
+ int Body::get_previous_visible_item(int start_index) {
for(int i = start_index - 1; i >= 0; --i) {
if(items[i]->visible)
- return items[i].get();
+ return i;
}
- return nullptr;
+ return -1;
}
// TODO: Cache, and take into consideration updated items and visibility change
- BodyItem* Body::get_next_visible_item(int start_index) {
+ int Body::get_next_visible_item(int start_index) {
for(int i = start_index + 1; i < (int)items.size(); ++i) {
if(items[i]->visible)
- return items[i].get();
+ return i;
+ }
+ return -1;
+ }
+
+ // TODO: Remove
+ float Body::get_offset_to_first_visible_item(sf::Vector2f body_size) {
+ float start_pos = page_scroll;
+ float pos = start_pos;
+ for(int i = selected_item - 1; i >= 0;) {
+ auto &item = items[i];
+
+ // TODO: Find a better solution?
+ if(!item->visible) {
+ --i;
+ continue;
+ }
+
+ int prev_body_item_index = get_previous_visible_item(i);
+ const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item_index == -1 ? nullptr : items[prev_body_item_index].get(), item.get());
+
+ float item_height = get_item_height(item.get(), body_size.x, true, true, merge_with_previous, i);
+ float item_height_with_merge = item_height + spacing_y;
+ pos -= item_height_with_merge;
+
+ if(start_pos - (pos + item_height_with_merge) >= body_size.y) {
+ pos = start_pos - body_pos.y;
+ break;
+ //return body_pos.y;
+ }
+
+ if(merge_with_previous)
+ pos += spacing_y;
+
+ i = prev_body_item_index;
+ }
+
+ //int prev_body_item_index = get_previous_visible_item(selected_item);
+ //const bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item_index == -1 ? nullptr : items[prev_body_item_index].get(), items[selected_item].get());
+//
+ //pos -= selected_item_height;
+ //if(merge_with_previous)
+ // pos += spacing_y*2.0f;
+//
+ //int next_body_item_index = get_next_visible_item(selected_item);
+ //const bool merge_with_next = next_body_item_index != -1 && body_item_merge_handler && body_item_merge_handler(items[selected_item].get(), items[next_body_item_index].get());
+ //if(!merge_with_previous && merge_with_next)
+ // pos += spacing_y;
+
+ return start_pos - pos;
+ }
+
+ // TODO: Remove
+ float Body::get_offset_to_last_visible_item(sf::Vector2f body_size) {
+ const int prev_body_item_index = get_previous_visible_item(selected_item);
+ BodyItem *prev_body_item = prev_body_item_index == -1 ? nullptr : items[prev_body_item_index].get();
+
+ float start_pos = page_scroll;
+ float pos = start_pos;
+ const int num_items = (int)items.size();
+ for(int i = selected_item; i < num_items;) {
+ auto &item = items[i];
+
+ // TODO: Find a better solution?
+ if(!item->visible) {
+ ++i;
+ continue;
+ }
+
+ bool merge_with_previous = body_item_merge_handler && body_item_merge_handler(prev_body_item, item.get());
+ if(merge_with_previous)
+ pos -= spacing_y;
+
+ if(pos - start_pos >= body_size.y)
+ return body_size.y;
+
+ float item_height = get_item_height(item.get(), body_size.x, true, true, merge_with_previous, i);
+ pos += item_height + spacing_y;
+ ++num_visible_items;
+ last_visible_item = i;
+
+ int next_body_item_index = get_next_visible_item(i);
+
+ prev_body_item = items[i].get();
+
+ i = next_body_item_index;
+ if(i == -1)
+ break;
}
- return nullptr;
+ return pos - start_pos;
}
static sf::Vector2f to_vec2f(const sf::Vector2i &vec) {
@@ -1049,17 +1154,6 @@ namespace QuickMedia {
float text_offset_x = padding_x;
if(draw_thumbnails && item_thumbnail && !merge_with_previous) {
- double elapsed_time_thumbnail = 0.0;
- if(item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE)
- elapsed_time_thumbnail = item_thumbnail->texture_applied_time.getElapsedTime().asSeconds(); //thumbnail_fade_duration_sec
-
- bool only_show_thumbnail = false;
- double thumbnail_fade_progress = elapsed_time_thumbnail / thumbnail_fade_duration_sec;
- if(thumbnail_fade_progress > 1.0) {
- thumbnail_fade_progress = 1.0;
- only_show_thumbnail = true;
- }
-
// TODO: Verify if this is safe. The thumbnail is being modified in another thread
if(item_thumbnail->loading_state == LoadingState::APPLIED_TO_TEXTURE && item_thumbnail->texture.getNativeHandle() != 0) {
image.setTexture(item_thumbnail->texture, true);
@@ -1068,7 +1162,6 @@ namespace QuickMedia {
sf::Vector2f content_size = to_vec2f(get_item_thumbnail_size(item));
auto new_image_size = clamp_to_size(image_size_f, content_size);
auto image_scale = get_ratio(image_size_f, new_image_size);
- image.setColor(sf::Color(255, 255, 255, thumbnail_fade_progress * 255));
image.setScale(image_scale);
image.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y));
if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) {
@@ -1080,11 +1173,10 @@ namespace QuickMedia {
text_offset_x += image_padding_x + new_image_size.x;
// We want the next image fallback to have the same size as the successful image rendering, because its likely the image fallback will have the same size (for example thumbnails on youtube)
//image_fallback.setSize(sf::Vector2f(width_ratio * image_size.x, height_ratio * image_size.y));
- } else if(!item->thumbnail_url.empty() && !only_show_thumbnail) {
+ } else if(!item->thumbnail_url.empty()) {
sf::Vector2f content_size = to_vec2f(get_item_thumbnail_size(item));
- sf::Uint8 fallback_fade_alpha = (1.0 - thumbnail_fade_progress) * 255;
- sf::Color fallback_color(52, 58, 70, fallback_fade_alpha);
+ sf::Color fallback_color(52, 58, 70);
if(thumbnail_mask_shader && item->thumbnail_mask_type == ThumbnailMaskType::CIRCLE) {
// TODO: Use the mask shader instead, but a vertex shader is also needed for that to pass the vertex coordinates since
// shapes dont have texture coordinates.
@@ -1105,7 +1197,6 @@ namespace QuickMedia {
loading_icon.setPosition(item_pos + sf::Vector2f(image_padding_x, padding_y) + (content_size * 0.5f));
loading_icon.setScale(get_ratio(loading_icon_size, new_loading_icon_size));
loading_icon.setRotation(elapsed_time_sec * 400.0);
- loading_icon.setColor(sf::Color(255, 255, 255, fallback_fade_alpha));
window.draw(loading_icon);
text_offset_x += image_padding_x + content_size.x;
}
@@ -1223,6 +1314,9 @@ namespace QuickMedia {
}
float Body::get_item_height(BodyItem *item, float width, bool load_texture, bool include_embedded_item, bool merge_with_previous, int item_index) {
+ if(load_texture)
+ item->last_drawn_time = elapsed_time_sec;
+
float image_height = 0.0f;
float text_offset_x = padding_x;
if(draw_thumbnails && !item->thumbnail_url.empty() && !merge_with_previous) {
@@ -1313,10 +1407,6 @@ namespace QuickMedia {
item_height = std::max(item_height, image_height);
item_height += (padding_y * 2.0f);
- if(attach_side == AttachSide::TOP && item_index != -1 && item_index < selected_item && item->calculated_height >= 0.0f)
- page_scroll += (item_height - item->calculated_height);
- item->calculated_height = item_height;
-
return item_height;
}
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index ddeacab..3df2973 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -3291,8 +3291,11 @@ namespace QuickMedia {
}
comment_navigation_stack.push(thread_body->get_selected_item());
comment_page_scroll_stack.push(thread_body->get_page_scroll());
- thread_body->clamp_selection();
- thread_body->set_page_scroll(0.0f);
+ //thread_body->clamp_selection();
+ //thread_body->set_page_scroll(0.0f);
+ int prev_sel = thread_body->get_selected_item();
+ thread_body->select_last_item();
+ thread_body->set_selected_item(prev_sel, false);
} else if(event.key.code == sf::Keyboard::BackSpace && !comment_navigation_stack.empty()) {
size_t previous_selected = comment_navigation_stack.top();
float previous_page_scroll = comment_page_scroll_stack.top();
@@ -4864,10 +4867,9 @@ namespace QuickMedia {
move_room = true;
};
- bool fetching_prev_failed = false;
- std::function<void()> on_top_reached = [this, &previous_messages_future, &ui_tabs, &MESSAGES_TAB_INDEX, &gradient_inc, current_room, &fetching_prev_failed] {
+ std::function<void()> on_top_reached = [this, &previous_messages_future, &ui_tabs, &MESSAGES_TAB_INDEX, &gradient_inc, current_room] {
const int selected_tab = ui_tabs.get_selected();
- if(!fetching_prev_failed && !previous_messages_future.valid() && selected_tab == MESSAGES_TAB_INDEX) {
+ if(!previous_messages_future.valid() && selected_tab == MESSAGES_TAB_INDEX) {
gradient_inc = 0;
previous_messages_future = AsyncTask<Messages>([this, current_room]() {
Messages messages;
@@ -5321,7 +5323,6 @@ namespace QuickMedia {
all_messages.insert(all_messages.end(), new_messages.begin(), new_messages.end());
if(new_messages.empty()) {
fetched_enough_messages = true;
- fetching_prev_failed = true;
}
filter_sent_messages(new_messages);
filter_existing_messages(new_messages);