aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordec05eba <dec05eba@protonmail.com>2021-05-17 04:09:47 +0200
committerdec05eba <dec05eba@protonmail.com>2021-05-17 04:09:47 +0200
commit28168bb3a63b7506a79441d6ce5ed312ba6f6e1a (patch)
treec68ca0a70f3cefd4d490abcc754995641d04ddf6 /src
parente37a174979059a97c342c51b741f4f89609830c4 (diff)
Make body movement smooth, async load video related videos to allow cancellation with esc
Diffstat (limited to 'src')
-rw-r--r--src/Body.cpp113
-rw-r--r--src/QuickMedia.cpp21
-rw-r--r--src/main.cpp1
-rw-r--r--src/plugins/Matrix.cpp4
4 files changed, 109 insertions, 30 deletions
diff --git a/src/Body.cpp b/src/Body.cpp
index ffafb90..d7a4456 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -284,6 +284,8 @@ namespace QuickMedia {
page_scroll = 0.0f;
clamp_selection();
clamp_selected_item_to_body_count = 1;
+ //item_background_target_pos_y = body_pos.y;
+ //item_background.set_position(sf::Vector2f(body_pos.x, item_background_target_pos_y));
}
void Body::select_last_item() {
@@ -294,6 +296,8 @@ namespace QuickMedia {
//page_scroll = 0.0f;
clamp_selection();
clamp_selected_item_to_body_count = 1;
+ //item_background_target_pos_y = body_pos.y + body_size.y - item_background.get_size().y;
+ //item_background.set_position(sf::Vector2f(body_pos.x, item_background_target_pos_y));
}
void Body::clear_items() {
@@ -304,6 +308,8 @@ namespace QuickMedia {
prev_selected_item = selected_item;
page_scroll = 0.0f;
clamp_selected_item_to_body_count = 1;
+ //item_background_target_pos_y = body_pos.y;
+ //item_background.set_position(sf::Vector2f(body_pos.x, item_background_target_pos_y));
}
void Body::prepend_items(BodyItems new_items) {
@@ -481,6 +487,9 @@ namespace QuickMedia {
sf::Vector2f scissor_pos = pos;
sf::Vector2f scissor_size = size;
const float start_y = pos.y;
+ float frame_time = frame_timer.restart().asSeconds();
+ if(frame_time > 2.0f)
+ frame_time = 2.0f;
body_pos = pos;
bool body_size_changed = std::abs(size.x - body_size.x) > 0.1f || std::abs(size.y - body_size.y) > 0.1f;
@@ -489,26 +498,33 @@ namespace QuickMedia {
elapsed_time_sec = draw_timer.getElapsedTime().asSeconds();
+ const bool scroll_past_first = first_item_fully_visible && offset_to_top > 0.1f;
+ const bool scroll_past_last = last_item_fully_visible && offset_to_bottom > 0.1f;
+
+ if((attach_side == AttachSide::BOTTOM && scroll_past_first) || (attach_side == AttachSide::TOP && scroll_past_last))
+ body_size_changed = true;
+
bool keep_selected_inside_body = clamp_selected_item_to_body_count > 0 || offset_to_top > 0.1f || offset_to_bottom > 0.1f;
- if(has_scrolled_with_input) {
- clamp_selected_item_to_body_count--;
- if(clamp_selected_item_to_body_count < 0)
- clamp_selected_item_to_body_count = 0;
- }
+ clamp_selected_item_to_body_count--;
+ if(clamp_selected_item_to_body_count < 0)
+ clamp_selected_item_to_body_count = 0;
if(is_touch_enabled()) {
- float frame_time = frame_timer.restart().asSeconds();
- if(frame_time > 2.0f)
- frame_time = 2.0f;
-
const sf::Vector2f mouse_pos_diff(mouse_pos_raw.x - mouse_pos.x, mouse_pos_raw.y - mouse_pos.y);
const float move_speed = 25.0f;
- mouse_pos.x += (mouse_pos_diff.x * frame_time * move_speed);
- mouse_pos.y += (mouse_pos_diff.y * frame_time * move_speed);
+ mouse_pos.x += (mouse_pos_diff.x * std::min(1.0f, frame_time * move_speed));
+ mouse_pos.y += (mouse_pos_diff.y * std::min(1.0f, frame_time * move_speed));
sf::Vector2f mouse_smooth_diff(mouse_pos.x - prev_mouse_pos.x, mouse_pos.y - prev_mouse_pos.y);
prev_mouse_pos = mouse_pos;
+ if(mouse_left_pressed && (scroll_past_first || scroll_past_last)) {
+ mouse_scroll_accel.x = 0.0f;
+ mouse_scroll_accel.y = 0.0f;
+ mouse_pos.x = mouse_pos_raw.x;
+ mouse_pos.y = mouse_pos_raw.y;
+ }
+
if(items_cut_off) {
if(mouse_left_pressed) {
selected_scrolled += mouse_smooth_diff.y;
@@ -531,14 +547,14 @@ namespace QuickMedia {
clamp_selection();
// TODO: Cache this
if(on_top_reached) {
- int first_visible_item = -1;
+ int first_visible_item_n = -1;
for(int i = 0; i <= selected_item; ++i) {
if(items[i]->visible) {
- first_visible_item = i;
+ first_visible_item_n = i;
break;
}
}
- if(first_visible_item == first_fully_visible_item)
+ if(first_visible_item_n == first_fully_visible_item)
on_top_reached();
}
} else if(mouse_scroll_accel.y < -0.1 && last_fully_visible_item != -1) {
@@ -546,14 +562,14 @@ namespace QuickMedia {
clamp_selection();
// TODO: Cache this
if(on_bottom_reached) {
- int last_visible_item = -1;
+ int last_visible_item_n = -1;
for(int i = items.size() - 1; i >= selected_item; --i) {
if(items[i]->visible) {
- last_visible_item = i;
+ last_visible_item_n = i;
break;
}
}
- if(last_visible_item == last_fully_visible_item)
+ if(last_visible_item_n == last_fully_visible_item)
on_bottom_reached();
}
}
@@ -574,10 +590,28 @@ namespace QuickMedia {
}
}
- item_separator.setFillColor(line_separator_color);
+ const double scroll_diff = extra_scroll_target - extra_scroll_current;
+ const double scroll_move_speed = 25.0;
+ extra_scroll_current += (scroll_diff * std::min(1.0, frame_time * scroll_move_speed));
+
+ double scroll_smooth_diff = extra_scroll_current - prev_extra_scroll;
+ prev_extra_scroll = extra_scroll_current;
+
+ selected_scrolled += scroll_smooth_diff;
+
+ bool selected_item_fits_on_screen = selected_item_height <= size.y;
+ if(selected_item_fits_on_screen && render_selected_item_bg && !first_item_fully_visible && !last_item_fully_visible && items_cut_off && (selected_item == first_visible_item || selected_item == last_visible_item || selected_item == first_fully_visible_item || selected_item == last_fully_visible_item)) {
+ page_scroll += scroll_smooth_diff;
+ keep_selected_inside_body = false;
+ }
+
+ //item_separator.setFillColor(line_separator_color);
+ const int prev_num_visible_items = num_visible_items;
num_visible_items = 0;
first_fully_visible_item = -1;
last_fully_visible_item = -1;
+ first_visible_item = -1;
+ last_visible_item = -1;
selected_line_top_visible = true;
selected_line_bottom_visible = true;
@@ -594,7 +628,8 @@ namespace QuickMedia {
offset_to_top = 0.0f;
offset_to_bottom = 0.0f;
mouse_left_clicked = false;
- last_visible_item = -1;
+ //item_background_target_pos_y = body_pos.y;
+ //item_background.set_position(sf::Vector2f(body_pos.x, item_background_target_pos_y));
return;
}
@@ -615,6 +650,7 @@ namespace QuickMedia {
int i = prev_selected_item;
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();
+ double scroll_before = page_scroll;
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());
@@ -628,10 +664,13 @@ namespace QuickMedia {
++i;
}
prev_selected_item = selected_item;
+ if(selected_item_fits_on_screen)
+ extra_scroll_target -= (page_scroll - scroll_before);
} else if(selected_item_diff < 0) {
int num_items_scrolled = 0;
int i = prev_selected_item - 1;
BodyItem *prev_body_item;
+ double scroll_before = page_scroll;
while(num_items_scrolled < selected_int_diff_abs && i >= 0) {
if(items[i]->visible) {
const int prev_body_item_index = get_previous_visible_item(i);
@@ -646,6 +685,8 @@ namespace QuickMedia {
--i;
}
prev_selected_item = selected_item;
+ if(selected_item_fits_on_screen)
+ extra_scroll_target -= (page_scroll - scroll_before);
}
bool merge_with_previous = false;
@@ -669,7 +710,8 @@ namespace QuickMedia {
} else if(attach_side == AttachSide::BOTTOM) {
if(last_item_fully_visible) {
page_scroll += offset_to_bottom;
- } else {
+ } else if(first_item_fully_visible && !last_item_fully_visible && body_size_changed) {
+ page_scroll -= offset_to_top;
//page_scroll = get_offset_to_last_visible_item(size);
}
}
@@ -678,7 +720,7 @@ namespace QuickMedia {
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;
+ selected_item_fits_on_screen = selected_item_height <= size.y;
selected_line_top_visible = pos.y - start_y + page_scroll >= 0.0f;
selected_line_bottom_visible = pos.y - start_y + page_scroll + selected_item_height <= size.y;
@@ -719,6 +761,25 @@ namespace QuickMedia {
sf::Vector2u window_size = window.getSize();
+ if(prev_num_visible_items > 0) {
+ const float item_background_prev_pos_y = item_background.get_position().y;
+ const float item_background_pos_diff = item_background_target_pos_y - item_background_prev_pos_y;
+ const float item_background_move_speed = 50.0f;
+ item_background.set_position(sf::Vector2f(pos.x, item_background_prev_pos_y + (item_background_pos_diff * std::min(1.0f, frame_time * item_background_move_speed))));
+
+ const float item_background_prev_height = item_background.get_size().y;
+ const float item_background_height_diff = item_background_target_height - item_background_prev_height;
+ const float item_background_height_speed = 50.0f;
+ item_background.set_size(sf::Vector2f(size.x, item_background_prev_height + (item_background_height_diff * std::min(1.0f, frame_time * item_background_height_speed))));
+
+ if(render_selected_item_bg) {
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(scissor_pos.x, (int)window_size.y - (int)scissor_pos.y - (int)scissor_size.y, scissor_size.x, scissor_size.y);
+ item_background.draw(window);
+ glDisable(GL_SCISSOR_TEST);
+ }
+ }
+
sf::Vector2f prev_pos = pos;
int i;
for(i = selected_item - 1; i >= 0;) {
@@ -753,6 +814,7 @@ namespace QuickMedia {
draw_item(window, item.get(), prev_pos, size, item_height, i, content_progress, true, merge_with_previous);
glDisable(GL_SCISSOR_TEST);
++num_visible_items;
+ first_visible_item = i;
last_visible_item = i;
if(first_item_fully_visible)
@@ -810,6 +872,8 @@ namespace QuickMedia {
after_pos.y += item_height;
after_pos.y += spacing_y;
++num_visible_items;
+ if(first_visible_item == -1)
+ first_visible_item = i;
last_visible_item = i;
int next_body_item_index = get_next_visible_item(i);
@@ -1125,10 +1189,9 @@ namespace QuickMedia {
//item_separator.setPosition(item_pos + sf::Vector2f(10.0f, std::floor(item_height + spacing_y * 0.5f)));
//window.draw(item_separator);
- if(render_selected_item_bg && item_index == selected_item) {
- item_background.set_position(item_pos);
- item_background.set_size(sf::Vector2f(size.x, item_height));
- item_background.draw(window);
+ if(item_index == selected_item) {
+ item_background_target_pos_y = item_pos.y;
+ item_background_target_height = item_height;
}
float text_offset_x = padding_x;
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index cd4a279..cd1377a 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -561,7 +561,6 @@ namespace QuickMedia {
}
void Program::init(Window parent_window, std::string &program_path) {
- XInitThreads();
disp = XOpenDisplay(NULL);
if (!disp)
throw std::runtime_error("Failed to open display to X11 server");
@@ -2187,8 +2186,15 @@ namespace QuickMedia {
return;
channel_url.clear();
- // TODO: Remove this and use lazy_fetch instead
- related_videos = video_page->get_related_media(video_url, channel_url);
+ TaskResult load_related_media_result = run_task_with_loading_screen([video_page, &related_videos, &video_url, &channel_url]{
+ related_videos = video_page->get_related_media(video_url, channel_url);
+ return true;
+ });
+
+ if(load_related_media_result == TaskResult::CANCEL) {
+ current_page = previous_page;
+ return;
+ }
// TODO: Make this also work for other video plugins
if(strcmp(plugin_name, "youtube") != 0 || resume_video)
@@ -2297,7 +2303,7 @@ namespace QuickMedia {
KeySym pressed_keysym = XKeycodeToKeysym(disp, xev.xkey.keycode, 0);
#pragma GCC diagnostic pop
bool pressing_ctrl = (CLEANMASK(xev.xkey.state) == ControlMask);
- if(pressed_keysym == XK_Escape || pressed_keysym == XK_BackSpace || pressed_keysym == XK_q) {
+ if(pressed_keysym == XK_Escape || pressed_keysym == XK_q || pressed_keysym == XK_BackSpace) {
current_page = previous_page;
break;
} else if(pressed_keysym == XK_f && pressing_ctrl) {
@@ -2402,7 +2408,7 @@ namespace QuickMedia {
if(new_video_url.empty() && parent_page && parent_body_page) {
BodyItems new_body_items;
const int fetch_page = (*parent_body_page) + 1;
- run_task_with_loading_screen([parent_page, parent_page_search, fetch_page, &new_body_items] {
+ TaskResult load_next_page_result = run_task_with_loading_screen([parent_page, parent_page_search, fetch_page, &new_body_items] {
if(parent_page->get_page(parent_page_search, fetch_page, new_body_items) != PluginResult::OK) {
fprintf(stderr, "Failed to get next page (page %d)\n", fetch_page);
return false;
@@ -2418,6 +2424,11 @@ namespace QuickMedia {
related_videos = std::move(new_body_items);
find_next_video();
}
+
+ if(load_next_page_result == TaskResult::CANCEL) {
+ current_page = previous_page;
+ continue;
+ }
}
// If there are no videos to play, then dont play any...
diff --git a/src/main.cpp b/src/main.cpp
index 89d824d..15041d5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2,6 +2,7 @@
#include <unistd.h>
int main(int argc, char **argv) {
+ XInitThreads();
setlocale(LC_ALL, "C"); // Sigh... stupid C
QuickMedia::Program program;
return program.run(argc, argv);
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 8679a54..1d471fc 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -920,12 +920,16 @@ namespace QuickMedia {
PluginResult MatrixInviteDetailsPage::submit(const std::string &title, const std::string&, std::vector<Tab>&) {
if(title == "Accept") {
if(matrix->join_room(room_id) == PluginResult::OK) {
+ // TODO: Wait for room invite list change from the server instead of removing room here.
+ // Then the invite list can be updated when accepting/declining an invite in another client.
invites_page->remove_body_item_by_room_id(room_id);
} else {
show_notification("QuickMedia", "Failed to accept the room invite", Urgency::CRITICAL);
}
} else if(title == "Decline") {
if(matrix->leave_room(room_id) == PluginResult::OK) {
+ // TODO: Wait for room invite list change from the server instead of removing room here.
+ // Then the invite list can be updated when accepting/declining an invite in another client.
invites_page->remove_body_item_by_room_id(room_id);
} else {
show_notification("QuickMedia", "Failed to decline the room invite", Urgency::CRITICAL);