summaryrefslogtreecommitdiffstats
path: root/src/ui.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/ui.hpp')
-rw-r--r--src/ui.hpp81
1 files changed, 53 insertions, 28 deletions
diff --git a/src/ui.hpp b/src/ui.hpp
index 2c87d2a..414fff9 100644
--- a/src/ui.hpp
+++ b/src/ui.hpp
@@ -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')) {