diff options
Diffstat (limited to 'src/ui.hpp')
-rw-r--r-- | src/ui.hpp | 81 |
1 files changed, 53 insertions, 28 deletions
@@ -32,6 +32,8 @@ struct scroll_window_state { // The line at the top of the screen float scroll_top = 0; + // TODO we can probably do away when we use lazy views everywhere + int no_shown_items = 0; // To deal with large items bool large_item_mode = false; @@ -91,7 +93,7 @@ toggle_read(rttt::active_storage<std::string, item_view_state> &&state, rttt::active_storage<std::string, item_view_state> mark_read(rttt::active_storage<std::string, item_view_state> &&state, - const std::string &id) { + const std::string &id) { if (!is_read(state, id)) return toggle_read(std::move(state), id); return std::move(state); @@ -225,7 +227,7 @@ inline bool drawHelpPopup(bool open) { "/r/front, /hn/top) "); ImGui::Text(" s - toggle Messages window "); ImGui::Text(" g - go to top "); - ImGui::Text(" G - go to end "); + ImGui::Text(" G - go to bottom (of the loaded items)"); ImGui::Text(" o/O - open in browser "); ImGui::Text(" j/k down/up - navigate items "); ImGui::Text( @@ -280,10 +282,11 @@ lineariseComments(std::vector<ItemVariant> items, if (result.size() >= head) break; + // FIXME: not loaded comments don't have an id yet, should probably treat them separately? auto maybe_id = try_id_string(item); - assert(maybe_id.has_value()); - - bool is_collapsed = ui::is_collapsed(item_view_states, maybe_id.value()); + bool is_collapsed = false; + if (maybe_id.has_value()) + is_collapsed = ui::is_collapsed(item_view_states, maybe_id.value()); result.push_back({depth, item}); @@ -462,8 +465,7 @@ inline void drawItem(const ItemVariant &item, size_t id, size_t indent, // Draw a scrollable window of items template <typename T> scroll_window_state drawItems( - scroll_window_state &&state, const T &items, - const rttt::list_mode &list_mode, + scroll_window_state &&state, T &items, const rttt::list_mode &list_mode, rttt::active_storage<std::string, ui::item_view_state> &item_view_states) { size_t counter = 0; ImGui::SetScrollY(state.scroll_top); @@ -473,13 +475,19 @@ scroll_window_state drawItems( auto it = items.begin(); auto s_it = it; + bool passed_highlighted_item = false; + // Number of stories to draw below the scrollable area. + // Important because hackernews only loads the "viewable" items, so we need to + // cache some extra for smooth scroling + size_t draw_extra = 10; + for (; it != items.end(); ++it) { - const auto &indent = it->first; - const auto &item = it->second; + const auto &indent = (*it).first; + const auto &item = (*it).second; bool isHighlighted = false; - if (!maybe_hid.has_value() || maybe_hid.value().empty() || - maybe_hid.value() == "0") { + + if (!maybe_hid.has_value()) { // Invalid value, so select the top one if (counter == 0) isHighlighted = true; @@ -521,22 +529,38 @@ scroll_window_state drawItems( state.ui_view_mode, ui::item_view_state()); } - if (isHighlighted && - ImGui::GetCursorPosY() > state.scroll_top + ImGui::GetWindowHeight()) { - // Tried using IsItemVisible, but that does not seem to work with - // scrolling - state.highlighted_item_size = - ImGui::GetCursorPosY() - state.highlighted_item_size; - state.large_item_mode = - (state.highlighted_item_size - state.large_item_offset) > - ImGui::GetWindowHeight(); - if (!state.large_item_mode) { - ImGui::SetScrollHereY(1.0); - state.scroll_top = ImGui::GetScrollY(); + if (isHighlighted) { + passed_highlighted_item = true; + if (ImGui::GetCursorPosY() > + state.scroll_top + ImGui::GetWindowHeight()) { + // Tried using IsItemVisible, but that does not seem to work with + // scrolling + state.highlighted_item_size = + ImGui::GetCursorPosY() - state.highlighted_item_size; + state.large_item_mode = + (state.highlighted_item_size - state.large_item_offset) > + ImGui::GetWindowHeight(); + if (!state.large_item_mode) { + ImGui::SetScrollHereY(1.0); + state.scroll_top = ImGui::GetScrollY(); + } } } + ++counter; + + if (passed_highlighted_item && + ImGui::GetCursorPosY() > state.scroll_top + ImGui::GetWindowHeight()) { + --draw_extra; + // Stop drawing if we have shown the highlighted_item and are outside the + // visible area + if (draw_extra == 0) + break; + } } + + state.no_shown_items = counter; + if (ImGui::IsWindowFocused()) { if (ImGui::IsKeyPressed('J', true) || ImGui::IsKeyPressed('K', true)) { auto maybe_id = try_id_string(state.highlighted_item); @@ -556,9 +580,9 @@ scroll_window_state drawItems( } } if (!state.large_item_mode) { - if (s_it > items.begin()) { + if (s_it != items.begin()) { --s_it; - state.highlighted_item = s_it->second; + state.highlighted_item = (*s_it).second; } } } @@ -574,9 +598,10 @@ scroll_window_state drawItems( } } if (!state.large_item_mode) { - if (items.size() > 0 && s_it < items.end() - 1) { + if (!items.empty() && s_it != items.end()) { ++s_it; - state.highlighted_item = s_it->second; + if (s_it != items.end()) + state.highlighted_item = (*s_it).second; } } } @@ -590,7 +615,7 @@ scroll_window_state drawItems( if (ImGui::IsKeyReleased('G')) { state.large_item_mode = false; state.large_item_offset = 0; - state.highlighted_item = items.back().second; + state.highlighted_item = (*(--it)).second; } if (ImGui::IsKeyReleased('v')) { |