aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Body.cpp192
-rw-r--r--src/BodyItem.cpp83
-rw-r--r--src/QuickMedia.cpp291
-rw-r--r--src/Storage.cpp3
-rw-r--r--src/plugins/FileManager.cpp2
-rw-r--r--src/plugins/Fourchan.cpp2
-rw-r--r--src/plugins/HotExamples.cpp2
-rw-r--r--src/plugins/MangaGeneric.cpp2
-rw-r--r--src/plugins/Mangadex.cpp4
-rw-r--r--src/plugins/Manganelo.cpp2
-rw-r--r--src/plugins/Matrix.cpp166
-rw-r--r--src/plugins/NyaaSi.cpp14
-rw-r--r--src/plugins/Soundcloud.cpp6
13 files changed, 440 insertions, 329 deletions
diff --git a/src/Body.cpp b/src/Body.cpp
index 0804399..6e01266 100644
--- a/src/Body.cpp
+++ b/src/Body.cpp
@@ -92,79 +92,6 @@ namespace QuickMedia {
return sf::Vector2f(vec.x, vec.y);
}
- BodyItem::BodyItem(std::string _title) :
- visible(true),
- dirty(false),
- dirty_description(false),
- dirty_author(false),
- dirty_timestamp(false),
- thumbnail_is_local(false),
- userdata(nullptr),
- timestamp(0),
- title_color(get_current_theme().text_color),
- author_color(get_current_theme().text_color),
- description_color(get_current_theme().text_color)
- {
- if(!_title.empty())
- set_title(std::move(_title));
- }
-
- BodyItem& BodyItem::operator=(const BodyItem &other) {
- url = other.url;
- thumbnail_url = other.thumbnail_url;
- visible = other.visible;
- dirty = !other.title.empty();
- dirty_description = !other.description.empty();
- dirty_author = !other.author.empty();
- dirty_timestamp = other.timestamp != 0;
- thumbnail_is_local = other.thumbnail_is_local;
- title_text.reset();
- description_text.reset();
- author_text.reset();
- timestamp_text.reset();
- replies_to = other.replies_to;
- replies = other.replies;
- post_number = other.post_number;
- userdata = other.userdata;
- loaded_height = 0.0f;
- loaded_image_size = sf::Vector2f(0.0f, 0.0f);
- loaded_content_height = 0.0f;
- embedded_item_status = other.embedded_item_status;
- if(other.embedded_item) {
- embedded_item.reset(new BodyItem(""));
- *embedded_item = *other.embedded_item;
- } else {
- embedded_item.reset();
- }
- thumbnail_mask_type = other.thumbnail_mask_type;
- thumbnail_size = other.thumbnail_size;
- reactions.clear();
- for(auto &reaction : other.reactions) {
- Reaction reaction_copy;
- reaction_copy.text = std::make_unique<Text>(*reaction.text);
- reaction_copy.userdata = reaction.userdata;
- reactions.push_back(std::move(reaction_copy));
- }
- title = other.title;
- description = other.description;
- author = other.author;
- timestamp = other.timestamp;
- title_color = other.title_color;
- author_color = other.author_color;
- description_color = other.description_color;
- extra = other.extra;
- keep_alive_frames = other.keep_alive_frames;
- return *this;
- }
-
- void BodyItem::add_reaction(std::string text, void *userdata) {
- sf::String str = sf::String::fromUtf8(text.begin(), text.end());
- Reaction reaction;
- reaction.text = std::make_unique<Text>(std::move(str), false, std::floor(14 * get_ui_scale()), 0.0f);
- reaction.userdata = userdata;
- reactions.push_back(std::move(reaction));
- }
-
Body::Body(BodyTheme body_theme, sf::Texture &loading_icon_texture, sf::Shader *rounded_rectangle_shader, sf::Shader *rounded_rectangle_mask_shader) :
draw_thumbnails(true),
body_item_render_callback(nullptr),
@@ -329,6 +256,13 @@ namespace QuickMedia {
clamp_selection();
}
+ void Body::set_items(BodyItems items) {
+ for(auto &item : items) {
+ filter_search_fuzzy_item(current_filter, item.get());
+ }
+ this->items = std::move(items);
+ }
+
void Body::clear_items() {
items.clear();
selected_item = 0;
@@ -336,18 +270,53 @@ namespace QuickMedia {
page_scroll = 0.0f;
}
+ void Body::prepend_item(std::shared_ptr<BodyItem> body_item) {
+ apply_search_filter_for_item(body_item.get());
+ items.insert(items.begin(), std::move(body_item));
+ }
+
void Body::prepend_items_reverse(BodyItems new_items) {
+ for(auto &item : new_items) {
+ filter_search_fuzzy_item(current_filter, item.get());
+ }
items.insert(items.begin(), std::make_move_iterator(new_items.rbegin()), std::make_move_iterator(new_items.rend()));
- items_set_dirty();
+ }
+
+ void Body::append_item(std::shared_ptr<BodyItem> body_item) {
+ apply_search_filter_for_item(body_item.get());
+ items.push_back(std::move(body_item));
}
void Body::append_items(BodyItems new_items) {
+ for(auto &item : new_items) {
+ filter_search_fuzzy_item(current_filter, item.get());
+ }
items.insert(items.end(), std::make_move_iterator(new_items.begin()), std::make_move_iterator(new_items.end()));
- items_set_dirty();
+ }
+
+ void Body::insert_item(std::shared_ptr<BodyItem> body_item, int index) {
+ apply_search_filter_for_item(body_item.get());
+ items.insert(items.begin() + index, std::move(body_item));
+ }
+
+ void Body::move_items_to(Body *other_body) {
+ other_body->set_items(std::move(items));
+ }
+
+ void Body::move_item(size_t src_index, size_t dst_index) {
+ assert(src_index < items.size());
+ assert(dst_index < items.size());
+ auto item_to_move = std::move(items[src_index]);
+ items.erase(items.begin() + src_index);
+ if(dst_index <= src_index)
+ items.insert(items.begin() + dst_index, std::move(item_to_move));
+ else
+ items.insert(items.begin() + dst_index - 1, std::move(item_to_move));
}
// TODO: Binary search and use hint to start search from start or end (for example when adding "previous" items or "next" items)
size_t Body::insert_item_by_timestamp(std::shared_ptr<BodyItem> body_item) {
+ apply_search_filter_for_item(body_item.get());
for(size_t i = 0; i < items.size(); ++i) {
if(body_item->get_timestamp() < items[i]->get_timestamp()) {
items.insert(items.begin() + i, std::move(body_item));
@@ -369,7 +338,6 @@ namespace QuickMedia {
}
clamp_selection();
- items_set_dirty(); // TODO: Apply this now, otherwise the below code wont work
if(!selected_body_item)
return;
@@ -382,6 +350,66 @@ namespace QuickMedia {
}
}
+ void Body::for_each_item(std::function<void(std::shared_ptr<BodyItem>&)> callback) {
+ for(std::shared_ptr<BodyItem> &body_item : items) {
+ callback(body_item);
+ }
+ }
+
+ std::shared_ptr<BodyItem> Body::find_item(std::function<bool(std::shared_ptr<BodyItem>&)> callback) {
+ for(std::shared_ptr<BodyItem> &body_item : items) {
+ if(callback(body_item))
+ return body_item;
+ }
+ return nullptr;
+ }
+
+ int Body::find_item_index(std::function<bool(std::shared_ptr<BodyItem>&)> callback) {
+ for(int i = 0; i != (int)items.size(); ++i) {
+ std::shared_ptr<BodyItem> &body_item = items[i];
+ if(callback(body_item))
+ return i;
+ }
+ return -1;
+ }
+
+ bool Body::erase_item(std::function<bool(std::shared_ptr<BodyItem>&)> callback) {
+ for(auto it = items.begin(), end = items.end(); it != end; ++it) {
+ if(callback(*it)) {
+ items.erase(it);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ std::shared_ptr<BodyItem> Body::get_item_by_index(size_t index) {
+ assert(index < items.size());
+ return items[index];
+ }
+
+ BodyItemList Body::get_items() {
+ return BodyItemList(&items);
+ }
+
+ BodyItems Body::get_items_copy() {
+ return items;
+ }
+
+ void Body::copy_range(size_t start_index, size_t end_index, BodyItems &target) {
+ assert(end_index == (size_t)-1 || end_index >= start_index);
+ assert(start_index < items.size() && (end_index == (size_t)-1 || end_index < items.size()));
+ target.insert(target.end(), items.begin() + start_index, end_index == (size_t)-1 ? items.end() : (items.begin() + end_index));
+ }
+
+ size_t Body::get_num_items() const {
+ return items.size();
+ }
+
+ void Body::reverse_items() {
+ std::reverse(items.begin(), items.end());
+ }
+
void Body::clear_cache() {
clear_text_cache();
malloc_trim(0);
@@ -554,12 +582,6 @@ namespace QuickMedia {
// TODO: Use a render target for the whole body so all images can be put into one.
// TODO: Load thumbnails with more than one thread.
void Body::draw(sf::RenderWindow &window, sf::Vector2f pos, sf::Vector2f size, const Json::Value &content_progress) {
- if(items_dirty != DirtyState::FALSE) {
- if(using_filter || items_dirty == DirtyState::FORCE_TRUE)
- filter_search_fuzzy(current_filter);
- items_dirty = DirtyState::FALSE;
- }
-
const bool rendering_card_view = card_view && card_view_enabled;
body_size_changed = std::abs(size.x - body_size.x) > 0.1f || std::abs(size.y - body_size.y) > 0.1f;
@@ -1599,7 +1621,6 @@ namespace QuickMedia {
// TODO: Support utf-8 case insensitive find
static bool string_find_fuzzy_case_insensitive(const std::string &str, const std::string &substr) {
- if(str.empty()) return false;
if(substr.empty()) return true;
size_t str_index = 0;
@@ -1623,7 +1644,6 @@ namespace QuickMedia {
void Body::filter_search_fuzzy(const std::string &text) {
current_filter = text;
- items_dirty = DirtyState::FALSE;
if(text.empty()) {
for(auto &item : items) {
@@ -1670,10 +1690,6 @@ namespace QuickMedia {
page_scroll = scroll;
}
- void Body::items_set_dirty(bool force) {
- items_dirty = force ? DirtyState::FORCE_TRUE : DirtyState::TRUE;
- }
-
void Body::apply_search_filter_for_item(BodyItem *body_item) {
filter_search_fuzzy_item(current_filter, body_item);
}
diff --git a/src/BodyItem.cpp b/src/BodyItem.cpp
new file mode 100644
index 0000000..bf6e45d
--- /dev/null
+++ b/src/BodyItem.cpp
@@ -0,0 +1,83 @@
+#include "../include/BodyItem.hpp"
+#include "../include/Theme.hpp"
+#include "../include/Utils.hpp"
+#include <cmath>
+
+namespace QuickMedia {
+ BodyItem::BodyItem(std::string _title) :
+ visible(true),
+ dirty(false),
+ dirty_description(false),
+ dirty_author(false),
+ dirty_timestamp(false),
+ thumbnail_is_local(false),
+ userdata(nullptr),
+ timestamp(0),
+ title_color(get_current_theme().text_color),
+ author_color(get_current_theme().text_color),
+ description_color(get_current_theme().text_color)
+ {
+ if(!_title.empty())
+ set_title(std::move(_title));
+ }
+
+ BodyItem& BodyItem::operator=(const BodyItem &other) {
+ url = other.url;
+ thumbnail_url = other.thumbnail_url;
+ visible = other.visible;
+ dirty = !other.title.empty();
+ dirty_description = !other.description.empty();
+ dirty_author = !other.author.empty();
+ dirty_timestamp = other.timestamp != 0;
+ thumbnail_is_local = other.thumbnail_is_local;
+ title_text.reset();
+ description_text.reset();
+ author_text.reset();
+ timestamp_text.reset();
+ replies_to = other.replies_to;
+ replies = other.replies;
+ post_number = other.post_number;
+ userdata = other.userdata;
+ loaded_height = 0.0f;
+ loaded_image_size = sf::Vector2f(0.0f, 0.0f);
+ loaded_content_height = 0.0f;
+ embedded_item_status = other.embedded_item_status;
+ if(other.embedded_item) {
+ embedded_item.reset(new BodyItem(""));
+ *embedded_item = *other.embedded_item;
+ } else {
+ embedded_item.reset();
+ }
+ thumbnail_mask_type = other.thumbnail_mask_type;
+ thumbnail_size = other.thumbnail_size;
+ reactions.clear();
+ for(auto &reaction : other.reactions) {
+ Reaction reaction_copy;
+ reaction_copy.text = std::make_unique<Text>(*reaction.text);
+ reaction_copy.userdata = reaction.userdata;
+ reactions.push_back(std::move(reaction_copy));
+ }
+ title = other.title;
+ description = other.description;
+ author = other.author;
+ timestamp = other.timestamp;
+ title_color = other.title_color;
+ author_color = other.author_color;
+ description_color = other.description_color;
+ extra = other.extra;
+ keep_alive_frames = other.keep_alive_frames;
+ return *this;
+ }
+
+ void BodyItem::add_reaction(std::string text, void *userdata) {
+ sf::String str = sf::String::fromUtf8(text.begin(), text.end());
+ Reaction reaction;
+ reaction.text = std::make_unique<Text>(std::move(str), false, std::floor(14 * get_ui_scale()), 0.0f);
+ reaction.userdata = userdata;
+ reactions.push_back(std::move(reaction));
+ }
+
+ void BodyItem::draw_list(Body *body, sf::RenderTarget &render_target) {
+
+ }
+} \ No newline at end of file
diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp
index a4dd182..2db5537 100644
--- a/src/QuickMedia.cpp
+++ b/src/QuickMedia.cpp
@@ -310,7 +310,7 @@ namespace QuickMedia {
bool submit_is_async() override { return false; }
- void add_option(BodyItems &items, std::string title, std::string description, OptionsPageHandler handler) {
+ void add_option(Body *body, std::string title, std::string description, OptionsPageHandler handler) {
assert(handler);
auto body_item = BodyItem::create(std::move(title));
if(!description.empty()) {
@@ -319,7 +319,7 @@ namespace QuickMedia {
}
body_item->url = std::to_string(handlers.size());
handlers.push_back(std::move(handler));
- items.push_back(std::move(body_item));
+ body->append_item(std::move(body_item));
}
private:
std::string title;
@@ -1084,22 +1084,24 @@ namespace QuickMedia {
if(strcmp(plugin_name, "launcher") == 0) {
auto pipe_body = create_body(true);
- pipe_body->items.push_back(create_launcher_body_item("4chan", "4chan", resources_root + "icons/4chan_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("Hot Examples", "hotexamples", ""));
- pipe_body->items.push_back(create_launcher_body_item("Manga (all)", "manga", ""));
- pipe_body->items.push_back(create_launcher_body_item("Mangadex", "mangadex", resources_root + "icons/mangadex_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("Mangakatana", "mangakatana", resources_root + "icons/mangakatana_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("Manganelo", "manganelo", resources_root + "icons/manganelo_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("Manganelos", "manganelos", resources_root + "icons/manganelos_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("Mangatown", "mangatown", resources_root + "icons/mangatown_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("Onimanga", "onimanga", ""));
- pipe_body->items.push_back(create_launcher_body_item("Readm", "readm", resources_root + "icons/readm_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("Matrix", "matrix", resources_root + "icons/matrix_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("Nyaa.si", "nyaa.si", resources_root + "icons/nyaa_si_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("SauceNAO", "saucenao", ""));
- pipe_body->items.push_back(create_launcher_body_item("Soundcloud", "soundcloud", resources_root + "icons/soundcloud_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("YouTube", "youtube", resources_root + "icons/yt_launcher.png"));
- pipe_body->items.push_back(create_launcher_body_item("YouTube (audio only)", "youtube-audio", resources_root + "icons/yt_launcher.png"));
+ pipe_body->set_items({
+ create_launcher_body_item("4chan", "4chan", resources_root + "icons/4chan_launcher.png"),
+ create_launcher_body_item("Hot Examples", "hotexamples", ""),
+ create_launcher_body_item("Manga (all)", "manga", ""),
+ create_launcher_body_item("Mangadex", "mangadex", resources_root + "icons/mangadex_launcher.png"),
+ create_launcher_body_item("Mangakatana", "mangakatana", resources_root + "icons/mangakatana_launcher.png"),
+ create_launcher_body_item("Manganelo", "manganelo", resources_root + "icons/manganelo_launcher.png"),
+ create_launcher_body_item("Manganelos", "manganelos", resources_root + "icons/manganelos_launcher.png"),
+ create_launcher_body_item("Mangatown", "mangatown", resources_root + "icons/mangatown_launcher.png"),
+ create_launcher_body_item("Onimanga", "onimanga", ""),
+ create_launcher_body_item("Readm", "readm", resources_root + "icons/readm_launcher.png"),
+ create_launcher_body_item("Matrix", "matrix", resources_root + "icons/matrix_launcher.png"),
+ create_launcher_body_item("Nyaa.si", "nyaa.si", resources_root + "icons/nyaa_si_launcher.png"),
+ create_launcher_body_item("SauceNAO", "saucenao", ""),
+ create_launcher_body_item("Soundcloud", "soundcloud", resources_root + "icons/soundcloud_launcher.png"),
+ create_launcher_body_item("YouTube", "youtube", resources_root + "icons/yt_launcher.png"),
+ create_launcher_body_item("YouTube (audio only)", "youtube-audio", resources_root + "icons/yt_launcher.png"),
+ });
tabs.push_back(Tab{std::move(pipe_body), std::make_unique<PipePage>(this, "Select plugin to launch"), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "manganelo") == 0) {
tabs.push_back(Tab{create_body(false, true), std::make_unique<ManganeloSearchPage>(this), create_search_bar("Search...", 400)});
@@ -1176,31 +1178,42 @@ namespace QuickMedia {
tabs.push_back(Tab{create_body(), std::make_unique<MangaCombinedSearchPage>(this, std::move(pages)), create_search_bar("Search...", 400)});
} else if(strcmp(plugin_name, "nyaa.si") == 0) {
auto categories_nyaa_si_body = create_body();
- get_nyaa_si_categories(categories_nyaa_si_body->items);
+ BodyItems body_items;
+ get_nyaa_si_categories(body_items);
+ categories_nyaa_si_body->set_items(std::move(body_items));
tabs.push_back(Tab{std::move(categories_nyaa_si_body), std::make_unique<NyaaSiCategoryPage>(this, false), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
auto categories_sukebei_body = create_body();
- get_sukebei_categories(categories_sukebei_body->items);
+ get_sukebei_categories(body_items);
+ categories_sukebei_body->set_items(body_items);
tabs.push_back(Tab{std::move(categories_sukebei_body), std::make_unique<NyaaSiCategoryPage>(this, true), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "4chan") == 0) {
auto boards_page = std::make_unique<FourchanBoardsPage>(this, resources_root);
auto boards_body = create_body();
- boards_page->get_boards(boards_body->items);
+ BodyItems body_items;
+ boards_page->get_boards(body_items);
+ boards_body->set_items(std::move(body_items));
tabs.push_back(Tab{std::move(boards_body), std::move(boards_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "hotexamples") == 0) {
auto body = create_body();
- hot_examples_front_page_fill(body->items);
+ BodyItems body_items;
+ hot_examples_front_page_fill(body_items);
+ body->set_items(std::move(body_items));
tabs.push_back(Tab{std::move(body), std::make_unique<HotExamplesLanguageSelectPage>(this), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "file-manager") == 0) {
auto file_manager_page = std::make_unique<FileManagerPage>(this, fm_mime_type, file_selection_handler);
if(!file_manager_page->set_current_directory(file_manager_start_dir))
fprintf(stderr, "Warning: Invalid directory provided with --dir\n");
auto file_manager_body = create_body();
- file_manager_page->get_files_in_directory(file_manager_body->items);
+ BodyItems body_items;
+ file_manager_page->get_files_in_directory(body_items);
+ file_manager_body->set_items(std::move(body_items));
tabs.push_back(Tab{std::move(file_manager_body), std::move(file_manager_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "stdin") == 0) {
auto pipe_body = create_body();
- PipePage::load_body_items_from_stdin(pipe_body->items);
+ BodyItems body_items;
+ PipePage::load_body_items_from_stdin(body_items);
+ pipe_body->set_items(std::move(body_items));
tabs.push_back(Tab{std::move(pipe_body), std::make_unique<PipePage>(this), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
} else if(strcmp(plugin_name, "youtube") == 0) {
if(youtube_url.empty()) {
@@ -1217,8 +1230,7 @@ namespace QuickMedia {
} else {
current_page = PageType::VIDEO_CONTENT;
auto youtube_video_page = std::make_unique<YoutubeVideoPage>(this, youtube_url);
- BodyItems body_items;
- video_content_page(nullptr, youtube_video_page.get(), "", false, nullptr, body_items, 0);
+ video_content_page(nullptr, youtube_video_page.get(), "", false, nullptr, 0);
}
} else if(strcmp(plugin_name, "pornhub") == 0) {
check_youtube_dl_installed(plugin_name);
@@ -1580,15 +1592,15 @@ namespace QuickMedia {
std::string image_url = body_item->url;
if(is_url_video(body_item->url))
image_url = body_item->thumbnail_url;
- body->items.push_back(InfoPage::add_reverse_image_search(image_url));
+ body->append_item(InfoPage::add_reverse_image_search(image_url));
}
std::vector<std::string> urls = ranges_get_strings(text, extract_urls(text));
for(const std::string &url : urls) {
- body->items.push_back(InfoPage::add_url(url));
+ body->append_item(InfoPage::add_url(url));
}
- if(body->items.empty())
+ if(body->get_num_items() == 0)
return false;
std::vector<Tab> info_tabs;
@@ -1841,7 +1853,7 @@ namespace QuickMedia {
page_stack.push(current_page);
current_page = PageType::VIDEO_CONTENT;
int selected_index = tabs[selected_tab].body->get_selected_item();
- video_content_page(tabs[selected_tab].page.get(), static_cast<VideoPage*>(new_tabs[0].page.get()), "", false, tabs[selected_tab].body.get(), tabs[selected_tab].body->items, selected_index, &tab_associated_data[selected_tab].fetched_page, tab_associated_data[selected_tab].update_search_text);
+ video_content_page(tabs[selected_tab].page.get(), static_cast<VideoPage*>(new_tabs[0].page.get()), "", false, tabs[selected_tab].body.get(), selected_index, &tab_associated_data[selected_tab].fetched_page, tab_associated_data[selected_tab].update_search_text);
} else if(new_tabs.size() == 1 && new_tabs[0].page->get_type() == PageTypez::CHAT) {
MatrixChatPage *tmp_matrix_chat_page = static_cast<MatrixChatPage*>(new_tabs[0].page.get());
MatrixRoomsPage *rooms_page = tmp_matrix_chat_page->rooms_page;
@@ -2111,7 +2123,7 @@ namespace QuickMedia {
continue;
if(associated_data.fetching_next_page_running && associated_data.next_page_future.ready()) {
- const bool body_was_empty = tabs[i].body->items.empty();
+ const bool body_was_empty = tabs[i].body->get_num_items() == 0;
BodyItems new_body_items = associated_data.next_page_future.get();
fprintf(stderr, "Finished fetching page %d, num new items: %zu\n", associated_data.fetched_page + 1, new_body_items.size());
int prev_selected_item = tabs[i].body->get_selected_item();
@@ -2163,18 +2175,18 @@ namespace QuickMedia {
if(associated_data.fetch_status == FetchStatus::LOADING && associated_data.fetch_type == FetchType::SEARCH && associated_data.fetch_future.ready()) {
if(!associated_data.search_text_updated) {
FetchResult fetch_result = associated_data.fetch_future.get();
- tabs[i].body->items = std::move(fetch_result.body_items);
+ tabs[i].body->set_items(std::move(fetch_result.body_items));
if(tabs[i].body->attach_side == AttachSide::TOP) {
tabs[i].body->select_first_item();
} else if(tabs[i].body->attach_side == AttachSide::BOTTOM) {
- std::reverse(tabs[i].body->items.begin(), tabs[i].body->items.end());
+ tabs[i].body->reverse_items();
tabs[i].body->select_last_item();
}
associated_data.fetched_page = 0;
associated_data.fetching_next_page_failed = false;
if(fetch_result.result != PluginResult::OK)
associated_data.search_result_text.setString("Search failed!");
- else if(tabs[i].body->items.empty())
+ else if(tabs[i].body->get_num_items() == 0)
associated_data.search_result_text.setString("No results found");
else
associated_data.search_result_text.setString("");
@@ -2188,19 +2200,19 @@ namespace QuickMedia {
if(associated_data.fetch_status == FetchStatus::LOADING && associated_data.fetch_type == FetchType::LAZY && associated_data.fetch_future.ready()) {
associated_data.lazy_fetch_finished = true;
FetchResult fetch_result = associated_data.fetch_future.get();
- tabs[i].body->items = std::move(fetch_result.body_items);
+ tabs[i].body->set_items(std::move(fetch_result.body_items));
if(tabs[i].search_bar && tabs[i].page->search_is_filter()) tabs[i].body->filter_search_fuzzy(tabs[i].search_bar->get_text());
if(tabs[i].body->attach_side == AttachSide::TOP) {
tabs[i].body->select_first_item();
}
if(tabs[i].body->attach_side == AttachSide::BOTTOM) {
- std::reverse(tabs[i].body->items.begin(), tabs[i].body->items.end());
+ tabs[i].body->reverse_items();
tabs[i].body->select_last_item();
}
LazyFetchPage *lazy_fetch_page = static_cast<LazyFetchPage*>(tabs[i].page.get());
if(fetch_result.result != PluginResult::OK)
associated_data.search_result_text.setString("Failed to fetch page!");
- else if(tabs[i].body->items.empty() && !lazy_fetch_page->lazy_fetch_is_loader())
+ else if(tabs[i].body->get_num_items() == 0 && !lazy_fetch_page->lazy_fetch_is_loader())
associated_data.search_result_text.setString("No results found");
else
associated_data.search_result_text.setString("");
@@ -2233,7 +2245,7 @@ namespace QuickMedia {
AsyncImageLoader::get_instance().update();
window.display();
- if(!tabs[selected_tab].body->items.empty()) {
+ if(tabs[selected_tab].body->get_num_items() > 0) {
if(tabs[selected_tab].body->attach_side == AttachSide::TOP && !tabs[selected_tab].body->is_bottom_cut_off())
on_reached_end();
else if(tabs[selected_tab].body->attach_side == AttachSide::BOTTOM && !tabs[selected_tab].body->is_top_cut_off())
@@ -2435,10 +2447,10 @@ namespace QuickMedia {
auto body = create_body();
auto options_page = std::make_unique<OptionsPage>(this, "Select download option");
- options_page->add_option(body->items, "Download video and audio", "", [&audio_only](){
+ options_page->add_option(body.get(), "Download video and audio", "", [&audio_only](){
audio_only = false;
});
- options_page->add_option(body->items, "Download only audio", "", [&audio_only](){
+ options_page->add_option(body.get(), "Download only audio", "", [&audio_only](){
audio_only = true;
});
@@ -2534,7 +2546,7 @@ namespace QuickMedia {
#define CLEANMASK(mask) ((mask) & (ShiftMask|ControlMask|Mod1Mask|Mod4Mask|Mod5Mask))
- void Program::video_content_page(Page *parent_page, VideoPage *video_page, std::string video_title, bool download_if_streaming_fails, Body *parent_body, BodyItems &next_play_items, int play_index, int *parent_body_page, const std::string &parent_page_search) {
+ void Program::video_content_page(Page *parent_page, VideoPage *video_page, std::string video_title, bool download_if_streaming_fails, Body *parent_body, int play_index, int *parent_body_page, const std::string &parent_page_search) {
PageType previous_page = pop_page_stack();
bool video_loaded = false;
@@ -2551,8 +2563,8 @@ namespace QuickMedia {
BodyItems related_videos;
bool move_in_parent = false;
- if(video_page->autoplay_next_item() && play_index + 1 >= 0 && play_index + 1 < (int)next_play_items.size()) {
- related_videos.insert(related_videos.end(), next_play_items.begin() + play_index + 1, next_play_items.end());
+ if(parent_body && video_page->autoplay_next_item() && play_index + 1 >= 0 && play_index + 1 < (int)parent_body->get_num_items()) {
+ parent_body->copy_range(play_index + 1, (size_t)-1, related_videos);
move_in_parent = true;
}
@@ -2951,7 +2963,7 @@ namespace QuickMedia {
}
if(related_videos_page) {
auto related_videos_body = create_body(false, true);
- related_videos_body->items = related_videos;
+ related_videos_body->set_items(related_videos);
tabs.push_back(Tab{std::move(related_videos_body), std::move(related_videos_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
}
if(channels_page) {
@@ -3068,8 +3080,8 @@ namespace QuickMedia {
fprintf(stderr, "Finished fetching page %d, num new items: %zu\n", fetch_page, new_body_items.size());
size_t num_new_messages = new_body_items.size();
if(num_new_messages > 0) {
- next_play_items.insert(next_play_items.end(), new_body_items.begin(), new_body_items.end());
- if(parent_body) parent_body->items_set_dirty();
+ if(parent_body)
+ parent_body->append_items(new_body_items);
(*parent_body_page)++;
related_videos = std::move(new_body_items);
find_next_video();
@@ -3487,7 +3499,7 @@ namespace QuickMedia {
if(image_index > 0) {
--image_index;
goto end_of_images_page;
- } else if(image_index == 0 && chapters_body->get_selected_item() < (int)chapters_body->items.size() - 1) {
+ } else if(image_index == 0 && chapters_body->get_selected_item() < (int)chapters_body->get_num_items() - 1) {
page_navigation = -1;
goto end_of_images_page;
}
@@ -3891,7 +3903,7 @@ namespace QuickMedia {
BodyItems next_items;
int prev_selected = thread_body->get_selected_item();
// TODO: Use real title
- video_content_page(thread_page, thread_page, "", true, thread_body, thread_body->items, thread_body->get_selected_item());
+ video_content_page(thread_page, thread_page, "", true, thread_body, thread_body->get_selected_item());
if(thread_body->get_selected_item() != prev_selected) {
comment_navigation_stack.clear();
comment_page_scroll_stack.clear();
@@ -3936,7 +3948,9 @@ namespace QuickMedia {
auto file_manager_page = std::make_unique<FileManagerPage>(this, (FileManagerMimeType)(FILE_MANAGER_MIME_TYPE_IMAGE|FILE_MANAGER_MIME_TYPE_VIDEO));
file_manager_page->set_current_directory(fm_dir.string());
auto file_manager_body = create_body();
- file_manager_page->get_files_in_directory(file_manager_body->items);
+ BodyItems body_items;
+ file_manager_page->get_files_in_directory(body_items);
+ file_manager_body->set_items(std::move(body_items));
std::vector<Tab> file_manager_tabs;
file_manager_tabs.push_back(Tab{std::move(file_manager_body), std::move(file_manager_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
@@ -3983,15 +3997,15 @@ namespace QuickMedia {
BodyItem *selected_item = thread_body->get_selected();
if(event.key.code == sf::Keyboard::Enter && selected_item && (comment_navigation_stack.empty() || thread_body->get_selected_item() != comment_navigation_stack.back()) && (!selected_item->replies_to.empty() || !selected_item->replies.empty())) {
- for(auto &body_item : thread_body->items) {
+ thread_body->for_each_item([](std::shared_ptr<BodyItem> &body_item) {
body_item->visible = false;
- }
+ });
selected_item->visible = true;
for(size_t reply_to_index : selected_item->replies_to) {
- thread_body->items[reply_to_index]->visible = true;
+ thread_body->get_item_by_index(reply_to_index)->visible = true;
}
for(size_t reply_index : selected_item->replies) {
- thread_body->items[reply_index]->visible = true;
+ thread_body->get_item_by_index(reply_index)->visible = true;
}
comment_navigation_stack.push_back(thread_body->get_selected_item());
comment_page_scroll_stack.push_back(thread_body->get_page_scroll());
@@ -4003,23 +4017,23 @@ namespace QuickMedia {
comment_navigation_stack.pop_back();
comment_page_scroll_stack.pop_back();
if(comment_navigation_stack.empty()) {
- for(auto &body_item : thread_body->items) {
- body_item->visible = true;
- }
+ thread_body->for_each_item([](std::shared_ptr<BodyItem> &body_item) {
+ body_item->visible = false;
+ });
thread_body->set_selected_item(previous_selected);
thread_body->clamp_selection();
} else {
- for(auto &body_item : thread_body->items) {
+ thread_body->for_each_item([](std::shared_ptr<BodyItem> &body_item) {
body_item->visible = false;
- }
+ });
thread_body->set_selected_item(previous_selected);
- selected_item = thread_body->items[comment_navigation_stack.back()].get();
+ selected_item = thread_body->get_item_by_index(comment_navigation_stack.back()).get();
selected_item->visible = true;
for(size_t reply_to_index : selected_item->replies_to) {
- thread_body->items[reply_to_index]->visible = true;
+ thread_body->get_item_by_index(reply_to_index)->visible = true;
}
for(size_t reply_index : selected_item->replies) {
- thread_body->items[reply_index]->visible = true;
+ thread_body->get_item_by_index(reply_index)->visible = true;
}
thread_body->clamp_selection();
}
@@ -4463,6 +4477,7 @@ namespace QuickMedia {
static const sf::Vector2i CHAT_MESSAGE_THUMBNAIL_MAX_SIZE(600, 337);
+ // TODO: Optimize
static std::shared_ptr<BodyItem> find_body_item_by_event_id(const std::shared_ptr<BodyItem> *body_items, size_t num_body_items, const std::string &event_id, size_t *index_result = nullptr) {
if(event_id.empty())
return nullptr;
@@ -4480,7 +4495,7 @@ namespace QuickMedia {
}
// Returns true if cached and loaded
- static bool load_cached_related_embedded_item(BodyItem *body_item, Message *message, UserInfo *me, const std::string &my_display_name, const std::string &my_user_id, const BodyItems &message_body_items) {
+ static bool load_cached_related_embedded_item(BodyItem *body_item, Message *message, UserInfo *me, const std::string &my_display_name, const std::string &my_user_id, const BodyItemList &message_body_items) {
// Check if we already have the referenced message as a body item, so we dont create a new one.
// TODO: Optimize from linear search to hash map
auto related_body_item = find_body_item_by_event_id(message_body_items.data(), message_body_items.size(), message->related_event_id);
@@ -4499,7 +4514,7 @@ namespace QuickMedia {
return true;
}
- static bool load_cached_related_embedded_item(BodyItem *body_item, Message *message, const std::shared_ptr<UserInfo> &me, RoomData *current_room, const BodyItems &message_body_items) {
+ static bool load_cached_related_embedded_item(BodyItem *body_item, Message *message, const std::shared_ptr<UserInfo> &me, RoomData *current_room, const BodyItemList &message_body_items) {
return load_cached_related_embedded_item(body_item, message, me.get(), current_room->get_user_display_name(me), me->user_id, message_body_items);
}
@@ -4545,7 +4560,7 @@ namespace QuickMedia {
return result_items;
}
- static void messages_load_cached_related_embedded_item(BodyItems &new_body_items, const BodyItems &all_body_items, const std::shared_ptr<UserInfo> &me, RoomData *current_room) {
+ static void messages_load_cached_related_embedded_item(BodyItems &new_body_items, const BodyItemList &all_body_items, const std::shared_ptr<UserInfo> &me, RoomData *current_room) {
std::string my_display_name = current_room->get_user_display_name(me);
for(auto &body_item : new_body_items) {
Message *message = static_cast<Message*>(body_item->userdata);
@@ -4806,7 +4821,7 @@ namespace QuickMedia {
auto me = matrix->get_me(current_room);
auto my_display_name = current_room->get_user_display_name(me);
- auto &body_items = tabs[MESSAGES_TAB_INDEX].body->items;
+ auto body_items = tabs[MESSAGES_TAB_INDEX].body->get_items();
for(auto &message : messages) {
// TODO: Make redacted/edited events as (redacted)/(edited) in the body
if(message->related_event_type == RelatedEventType::REDACTION || message->related_event_type == RelatedEventType::EDIT) {
@@ -4840,7 +4855,7 @@ namespace QuickMedia {
if(messages.empty())
return;
- auto &body_items = tabs[MESSAGES_TAB_INDEX].body->items;
+ auto body_items = tabs[MESSAGES_TAB_INDEX].body->get_items();
// TODO: Check in |messages| instead
for(auto it = unresolved_reactions.begin(); it != unresolved_reactions.end();) {
@@ -4882,20 +4897,19 @@ namespace QuickMedia {
};
auto pinned_body_items_contains_event = [&tabs, PINNED_TAB_INDEX](const std::string &event_id) {
- for(auto &body_item : tabs[PINNED_TAB_INDEX].body->items) {
- if(static_cast<PinnedEventData*>(body_item->userdata)->event_id == event_id)
- return true;
- }
- return false;
+ const int found_item_index = tabs[PINNED_TAB_INDEX].body->find_item_index([&event_id](std::shared_ptr<BodyItem> &body_item) {
+ return static_cast<PinnedEventData*>(body_item->userdata)->event_id == event_id;
+ });
+ return found_item_index != -1;
};
auto process_pinned_events = [&tabs, &ui_tabs, &pinned_body_items_contains_event, PINNED_TAB_INDEX](const std::optional<std::vector<std::string>> &pinned_events) {
if(!pinned_events)
return;
- bool empty_before = tabs[PINNED_TAB_INDEX].body->items.empty();
+ bool empty_before = tabs[PINNED_TAB_INDEX].body->get_num_items() == 0;
int selected_before = tabs[PINNED_TAB_INDEX].body->get_selected_item();
- auto prev_pinned_body_items = tabs[PINNED_TAB_INDEX].body->items;
+ auto prev_pinned_body_items = tabs[PINNED_TAB_INDEX].body->get_items_copy();
tabs[PINNED_TAB_INDEX].body->clear_items();
// TODO: Add message to rooms messages when there are new pinned events
@@ -4910,7 +4924,7 @@ namespace QuickMedia {
event_data->status = FetchStatus::NONE;
event_data->message = nullptr;
body->userdata = event_data;
- tabs[PINNED_TAB_INDEX].body->items.push_back(std::move(body));
+ tabs[PINNED_TAB_INDEX].body->append_item(std::move(body));
}
for(auto &prev_body_item : prev_pinned_body_items) {
@@ -4923,7 +4937,7 @@ namespace QuickMedia {
else
tabs[PINNED_TAB_INDEX].body->set_selected_item(selected_before);
- ui_tabs.set_text(PINNED_TAB_INDEX, "Pinned messages (" + std::to_string(tabs[PINNED_TAB_INDEX].body->items.size()) + ")");
+ ui_tabs.set_text(PINNED_TAB_INDEX, "Pinned messages (" + std::to_string(tabs[PINNED_TAB_INDEX].body->get_num_items()) + ")");
};
Body url_selection_body(BODY_THEME_MINIMAL, loading_icon, &rounded_rectangle_shader, &rounded_rectangle_mask_shader);
@@ -4946,7 +4960,7 @@ namespace QuickMedia {
}
auto me = matrix->get_me(current_room);
auto new_body_items = messages_to_body_items(current_room, all_messages, current_room->get_user_display_name(me), me->user_id);
- messages_load_cached_related_embedded_item(new_body_items, tabs[MESSAGES_TAB_INDEX].body->items, me, current_room);
+ messages_load_cached_related_embedded_item(new_body_items, tabs[MESSAGES_TAB_INDEX].body->get_items(), me, current_room);
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(std::move(new_body_items));
modify_related_messages_in_current_room(all_messages);
process_reactions(all_messages);
@@ -4999,7 +5013,7 @@ namespace QuickMedia {
auto message_set_replaced_by = [&tabs, &pending_sent_replies, MESSAGES_TAB_INDEX](std::shared_ptr<Message> message) {
if(message->related_event_type == RelatedEventType::EDIT) {
- auto body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size(), message->related_event_id);
+ auto body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->get_items().data(), tabs[MESSAGES_TAB_INDEX].body->get_items().size(), message->related_event_id);
if(body_item) {
Message *reply_to_message = static_cast<Message*>(body_item->userdata);
if(!reply_to_message) {
@@ -5203,7 +5217,7 @@ namespace QuickMedia {
message->type = MessageType::TEXT;
message->timestamp = time(NULL) * 1000;
- int num_items = tabs[MESSAGES_TAB_INDEX].body->items.size();
+ int num_items = tabs[MESSAGES_TAB_INDEX].body->get_num_items();
bool scroll_to_end = num_items == 0;
if(tabs[MESSAGES_TAB_INDEX].body->is_selected_item_last_visible_item() && selected_tab == MESSAGES_TAB_INDEX)
scroll_to_end = true;
@@ -5220,7 +5234,7 @@ namespace QuickMedia {
message->related_event_type = RelatedEventType::REACTION;
message->related_event_id = static_cast<Message*>(related_to_message)->event_id;
auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
- load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->items);
+ load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
Messages messages;
messages.push_back(message);
@@ -5236,7 +5250,7 @@ namespace QuickMedia {
} else {
auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
body_item->set_description_color(get_current_theme().provisional_message_color);
- load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->items);
+ load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
post_task_queue.push([this, &current_room, text, msgtype, body_item, message]() {
ProvisionalMessage provisional_message;
@@ -5261,7 +5275,7 @@ namespace QuickMedia {
message->related_event_id = static_cast<Message*>(related_to_message)->event_id;
auto body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
body_item->set_description_color(get_current_theme().provisional_message_color);
- load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->items);
+ load_cached_related_embedded_item(body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({body_item});
post_task_queue.push([this, &current_room, text, related_to_message, body_item, message, transaction_id]() {
ProvisionalMessage provisional_message;
@@ -5282,15 +5296,15 @@ namespace QuickMedia {
message->related_event_type = RelatedEventType::EDIT;
message->related_event_id = static_cast<Message*>(related_to_message)->event_id;
size_t body_item_index = 0;
- auto body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size(), message->related_event_id, &body_item_index);
+ auto body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->get_items().data(), tabs[MESSAGES_TAB_INDEX].body->get_items().size(), message->related_event_id, &body_item_index);
if(body_item) {
- auto body_item_shared_ptr = tabs[MESSAGES_TAB_INDEX].body->items[body_item_index];
+ auto body_item_shared_ptr = tabs[MESSAGES_TAB_INDEX].body->get_item_by_index(body_item_index);
body_item_shared_ptr->set_description(text);
body_item_shared_ptr->set_description_color(get_current_theme().provisional_message_color);
auto edit_body_item = message_to_body_item(current_room, message.get(), current_room->get_user_avatar_url(me), me->user_id);
edit_body_item->visible = false;
- load_cached_related_embedded_item(edit_body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->items);
+ load_cached_related_embedded_item(edit_body_item.get(), message.get(), me, current_room, tabs[MESSAGES_TAB_INDEX].body->get_items());
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps({edit_body_item});
//unreferenced_events.push_back(message);
@@ -5349,7 +5363,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.get(), 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->get_items()))
return;
std::string message_event_id = event_data->message->related_event_id;
@@ -5369,7 +5383,7 @@ namespace QuickMedia {
// Fetch embed message
// Check if we already have the referenced message as a body item in the messages list, so we dont create a new one.
// TODO: Optimize from linear search to hash map
- auto related_body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size(), event_data->event_id);
+ auto related_body_item = find_body_item_by_event_id(tabs[MESSAGES_TAB_INDEX].body->get_items().data(), tabs[MESSAGES_TAB_INDEX].body->get_items().size(), event_data->event_id);
if(related_body_item) {
*body_item = *related_body_item;
body_item->reactions.clear();
@@ -5407,7 +5421,7 @@ namespace QuickMedia {
return;
}
- if(load_cached_related_embedded_item(body_item.get(), 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->get_items()))
return;
std::string message_event_id = message->related_event_id;
@@ -5431,7 +5445,7 @@ namespace QuickMedia {
Message *prev_message = static_cast<Message*>(prev_item->userdata);
if(is_system_message_type(prev_message->type) && is_system_message_type(message->type))
return true;
- else if(is_system_message_type(message->type))
+ else if(is_system_message_type(prev_message->type) || is_system_message_type(message->type))
return false;
if(is_visual_media_message_type(prev_message->type) && !prev_item->thumbnail_url.empty())
@@ -5455,7 +5469,7 @@ namespace QuickMedia {
auto fetch_more_previous_messages_if_needed = [this, &tabs, &current_room, &fetched_enough_messages, &previous_messages_future, MESSAGES_TAB_INDEX]() {
if(!fetched_enough_messages && !previous_messages_future.valid()) {
- if(tabs[MESSAGES_TAB_INDEX].body->items.size() < 30) {
+ if(tabs[MESSAGES_TAB_INDEX].body->get_num_items() < 30) {
previous_messages_future = AsyncTask<Messages>([this, &current_room]() {
Messages messages;
if(matrix->get_previous_room_messages(current_room, messages) != PluginResult::OK)
@@ -5495,7 +5509,7 @@ namespace QuickMedia {
current_page = PageType::VIDEO_CONTENT;
auto youtube_video_page = std::make_unique<YoutubeVideoPage>(this, url);
// TODO: Use real title
- video_content_page(matrix_chat_page, youtube_video_page.get(), "", false, nullptr, tabs[MESSAGES_TAB_INDEX].body->items, tabs[MESSAGES_TAB_INDEX].body->get_selected_item());
+ video_content_page(matrix_chat_page, youtube_video_page.get(), "", false, tabs[MESSAGES_TAB_INDEX].body.get(), tabs[MESSAGES_TAB_INDEX].body->get_selected_item());
redraw = true;
avatar_applied = false;
} else {
@@ -5531,7 +5545,7 @@ namespace QuickMedia {
return;
const int selected_tab = ui_tabs.get_selected();
- int num_items = tabs[MESSAGES_TAB_INDEX].body->items.size();
+ int num_items = tabs[MESSAGES_TAB_INDEX].body->get_num_items();
bool scroll_to_end = num_items == 0;
if(selected_tab == MESSAGES_TAB_INDEX && (tabs[MESSAGES_TAB_INDEX].body->is_selected_item_last_visible_item() || !tabs[MESSAGES_TAB_INDEX].body->get_selected()))
scroll_to_end = true;
@@ -5543,7 +5557,7 @@ namespace QuickMedia {
}
auto new_body_items = messages_to_body_items(current_room, messages, current_room->get_user_display_name(me), me->user_id);
- messages_load_cached_related_embedded_item(new_body_items, tabs[MESSAGES_TAB_INDEX].body->items, me, current_room);
+ messages_load_cached_related_embedded_item(new_body_items, tabs[MESSAGES_TAB_INDEX].body->get_items(), me, current_room);
tabs[MESSAGES_TAB_INDEX].body->insert_items_by_timestamps(std::move(new_body_items));
if(scroll_to_end)
tabs[MESSAGES_TAB_INDEX].body->select_last_item();
@@ -5572,8 +5586,7 @@ namespace QuickMedia {
bool prev_no_video = no_video;
no_video = is_audio;
video_page->set_url(selected->url);
- BodyItems next_items;
- video_content_page(matrix_chat_page, video_page.get(), selected_item_message->body, message_type == MessageType::VIDEO || message_type == MessageType::AUDIO, nullptr, next_items, 0);
+ video_content_page(matrix_chat_page, video_page.get(), selected_item_message->body, message_type == MessageType::VIDEO || message_type == MessageType::AUDIO, nullptr, 0);
no_video = prev_no_video;
redraw = true;
avatar_applied = false;
@@ -5598,7 +5611,7 @@ namespace QuickMedia {
url_selection_body.clear_items();
for(const std::string &url : urls) {
auto body_item = BodyItem::create(url);
- url_selection_body.items.push_back(std::move(body_item));
+ url_selection_body.append_item(std::move(body_item));
}
return true;
}
@@ -5630,50 +5643,46 @@ namespace QuickMedia {
auto update_pinned_messages_author = [&tabs, &current_room, PINNED_TAB_INDEX](const std::shared_ptr<UserInfo> &user) {
fprintf(stderr, "updated pinned messages author for user: %s\n", user->user_id.c_str());
- for(auto &pinned_body_item : tabs[PINNED_TAB_INDEX].body->items) {
+ tabs[PINNED_TAB_INDEX].body->for_each_item([&current_room, &user](std::shared_ptr<BodyItem> &pinned_body_item) {
Message *message = static_cast<PinnedEventData*>(pinned_body_item->userdata)->message;
// Its fine if we dont set it now. When the message is fetches, it will have updated user info since its fetched later
if(!message || message->user != user)
- continue;
-
+ return;
user_update_display_info(pinned_body_item.get(), current_room, message);
- }
+ });
};
auto update_messages_author = [&tabs, &current_room, MESSAGES_TAB_INDEX](const std::shared_ptr<UserInfo> &user) {
fprintf(stderr, "updated messages author for user: %s\n", user->user_id.c_str());
- for(auto &message_body_items : tabs[MESSAGES_TAB_INDEX].body->items) {
+ tabs[MESSAGES_TAB_INDEX].body->for_each_item([&current_room, &user](std::shared_ptr<BodyItem> &message_body_items) {
Message *message = static_cast<Message*>(message_body_items->userdata);
if(!message || message->user != user)
- continue;
-
+ return;
user_update_display_info(message_body_items.get(), current_room, message);
- }
+ });
};
// TODO: Optimize
auto update_pinned_messages_authors = [&tabs, &current_room, PINNED_TAB_INDEX]() {
fprintf(stderr, "updated pinned messages author for all users in room: %s\n", current_room->id.c_str());
- for(auto &pinned_body_item : tabs[PINNED_TAB_INDEX].body->items) {
+ tabs[PINNED_TAB_INDEX].body->for_each_item([&current_room](std::shared_ptr<BodyItem> &pinned_body_item) {
Message *message = static_cast<PinnedEventData*>(pinned_body_item->userdata)->message;
// Its fine if we dont set it now. When the message is fetches, it will have updated user info since its fetched later
if(!message)
- continue;
-
+ return;
user_update_display_info(pinned_body_item.get(), current_room, message);
- }
+ });
};
// TODO: Optimize
auto update_messages_authors = [&tabs, &current_room, MESSAGES_TAB_INDEX]() {
fprintf(stderr, "updated messages author for all users in room: %s\n", current_room->id.c_str());
- for(auto &message_body_items : tabs[MESSAGES_TAB_INDEX].body->items) {
+ tabs[MESSAGES_TAB_INDEX].body->for_each_item([&current_room](std::shared_ptr<BodyItem> &message_body_items) {
Message *message = static_cast<Message*>(message_body_items->userdata);
if(!message)
- continue;
-
+ return;
user_update_display_info(message_body_items.get(), current_room, message);
- }
+ });
};
auto cleanup_tasks = [&set_read_marker_future, &fetch_message_future, &fetch_users_future, &typing_state_queue, &typing_state_thread, &post_task_queue, &provisional_message_queue, &fetched_messages_set, &sent_messages, &pending_sent_replies, &post_thread, &tabs, MESSAGES_TAB_INDEX, PINNED_TAB_INDEX, USERS_TAB_INDEX]() {
@@ -5699,9 +5708,10 @@ namespace QuickMedia {
if(!tabs.empty()) {
tabs[MESSAGES_TAB_INDEX].body->clear_items();
- for(auto &body_item : tabs[PINNED_TAB_INDEX].body->items) {
- delete (PinnedEventData*)body_item->userdata;
- }
+ tabs[PINNED_TAB_INDEX].body->for_each_item([](std::shared_ptr<BodyItem> &pinned_body_item) {
+ delete (PinnedEventData*)pinned_body_item->userdata;
+ pinned_body_item->userdata = nullptr;
+ });
tabs[PINNED_TAB_INDEX].body->clear_items();
tabs[USERS_TAB_INDEX].body->clear_items();
}
@@ -5824,6 +5834,8 @@ namespace QuickMedia {
goto chat_page_end;
} else if(event.key.code == sf::Keyboard::I && event.key.control) {
BodyItem *selected_item = tabs[selected_tab].body->get_selected();
+ if(selected_item && selected_item->url.empty())
+ selected_item = selected_item->embedded_item.get();
if(selected_item && !selected_item->url.empty() && !selected_item->thumbnail_url.empty()) {
Message *selected_item_message = nullptr;
if(selected_tab == MESSAGES_TAB_INDEX) {
@@ -6051,7 +6063,9 @@ namespace QuickMedia {
auto file_manager_page = std::make_unique<FileManagerPage>(this);
file_manager_page->set_current_directory(fm_dir.string());
auto file_manager_body = create_body();
- file_manager_page->get_files_in_directory(file_manager_body->items);
+ BodyItems body_items;
+ file_manager_page->get_files_in_directory(body_items);
+ file_manager_body->set_items(std::move(body_items));
std::vector<Tab> file_manager_tabs;
file_manager_tabs.push_back(Tab{std::move(file_manager_body), std::move(file_manager_page), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
@@ -6226,7 +6240,7 @@ namespace QuickMedia {
modify_related_messages_in_current_room(new_messages);
process_reactions(new_messages);
// TODO: Do not loop all items, only loop the new items
- resolve_unreferenced_events_with_body_items(tabs[MESSAGES_TAB_INDEX].body->items.data(), tabs[MESSAGES_TAB_INDEX].body->items.size());
+ resolve_unreferenced_events_with_body_items(tabs[MESSAGES_TAB_INDEX].body->get_items().data(), tabs[MESSAGES_TAB_INDEX].body->get_items().size());
}
if(num_new_messages > 0 && current_room->initial_prev_messages_fetch) {
current_room->initial_prev_messages_fetch = false;
@@ -6398,7 +6412,7 @@ namespace QuickMedia {
if(selected_tab == MESSAGES_TAB_INDEX && current_room && current_room->body_item && !current_room->last_message_read && matrix->is_initial_sync_finished()) {
if(!tabs[selected_tab].body->is_bottom_cut_off() && is_window_focused && chat_state != ChatState::URL_SELECTION && !setting_read_marker && read_marker_timer.getElapsedTime().asMilliseconds() >= read_marker_timeout_ms) {
- auto &body_items = tabs[selected_tab].body->items;
+ auto body_items = tabs[selected_tab].body->get_items();
int last_timeline_message = (int)body_items.size() - 1;
for(int i = last_timeline_message - 1; i >= 0; --i) {
BodyItem *item = body_items[i].get();
@@ -6574,22 +6588,24 @@ namespace QuickMedia {
auto invites_body = create_body();
auto matrix_invites_page = std::make_unique<MatrixInvitesPage>(this, matrix, invites_body.get());
+ BodyItems room_dir_body_items;
+ add_body_item_unique_title(room_dir_body_items, matrix->get_homeserver_domain());
+ add_body_item_unique_title(room_dir_body_items, "midov.pl");
+ add_body_item_unique_title(room_dir_body_items, "matrix.org");
+ add_body_item_unique_title(room_dir_body_items, "kde.org");
+ add_body_item_unique_title(room_dir_body_items, "librem.one");
+ add_body_item_unique_title(room_dir_body_items, "maunium.net");
+ add_body_item_unique_title(room_dir_body_items, "halogen.city");
+ add_body_item_unique_title(room_dir_body_items, "gnome.org");
+ add_body_item_unique_title(room_dir_body_items, "shivering-isles.com");
+ add_body_item_unique_title(room_dir_body_items, "nerdsin.space");
+ add_body_item_unique_title(room_dir_body_items, "glowers.club");
+ add_body_item_unique_title(room_dir_body_items, "privacytools.io");
+ add_body_item_unique_title(room_dir_body_items, "linuxdelta.com");
+ add_body_item_unique_title(room_dir_body_items, "tchncs.de");
+ add_body_item_unique_title(room_dir_body_items, "jupiterbroadcasting.com");
auto room_directory_body = create_body();
- add_body_item_unique_title(room_directory_body->items, matrix->get_homeserver_domain());
- add_body_item_unique_title(room_directory_body->items, "midov.pl");
- add_body_item_unique_title(room_directory_body->items, "matrix.org");
- add_body_item_unique_title(room_directory_body->items, "kde.org");
- add_body_item_unique_title(room_directory_body->items, "librem.one");
- add_body_item_unique_title(room_directory_body->items, "maunium.net");
- add_body_item_unique_title(room_directory_body->items, "halogen.city");
- add_body_item_unique_title(room_directory_body->items, "gnome.org");
- add_body_item_unique_title(room_directory_body->items, "shivering-isles.com");
- add_body_item_unique_title(room_directory_body->items, "nerdsin.space");
- add_body_item_unique_title(room_directory_body->items, "glowers.club");
- add_body_item_unique_title(room_directory_body->items, "privacytools.io");
- add_body_item_unique_title(room_directory_body->items, "linuxdelta.com");
- add_body_item_unique_title(room_directory_body->items, "tchncs.de");
- add_body_item_unique_title(room_directory_body->items, "jupiterbroadcasting.com");
+ room_directory_body->set_items(std::move(room_dir_body_items));
auto matrix_room_directory_page = std::make_unique<MatrixRoomDirectoryPage>(this, matrix);
MatrixQuickMedia matrix_handler(this, matrix, matrix_rooms_page.get(), matrix_rooms_tag_page.get(), matrix_invites_page.get(), matrix_notifications_page.get());
@@ -6767,6 +6783,7 @@ namespace QuickMedia {
return;
}
+ string_replace_all(filename, '/', '_');
std::string output_filepath = file_save_page(filename);
if(!window.isOpen() || output_filepath.empty()) {
exit_code = 1;
@@ -6959,7 +6976,9 @@ namespace QuickMedia {
auto file_manager_page = std::make_unique<FileManagerPage>(this);
file_manager_page->set_current_directory(file_manager_start_dir);
auto file_manager_body = create_body();
- file_manager_page->get_files_in_directory(file_manager_body->items);
+ BodyItems body_items;
+ file_manager_page->get_files_in_directory(body_items);
+ file_manager_body->set_items(std::move(body_items));
auto search_bar = create_search_bar("Search...", SEARCH_DELAY_FILTER);
Tabs ui_tabs(&rounded_rectangle_shader);
@@ -6985,7 +7004,7 @@ namespace QuickMedia {
if(task_result == TaskResult::TRUE) {
if(!new_tabs.empty()) {
- file_manager_body->items = std::move(new_tabs[0].body->items);
+ new_tabs[0].body->move_items_to(file_manager_body.get());
file_manager_body->select_first_item();
search_bar->clear();
}
@@ -7038,10 +7057,10 @@ namespace QuickMedia {
auto body = create_body();
auto options_page = std::make_unique<OptionsPage>(this, "Are you sure you want to overwrite " + filename_full_path.data + "?");
- options_page->add_option(body->items, "No", "", [&overwrite](){
+ options_page->add_option(body.get(), "No", "", [&overwrite](){
overwrite = false;
});
- options_page->add_option(body->items, "Yes", "", [&overwrite](){
+ options_page->add_option(body.get(), "Yes", "", [&overwrite](){
overwrite = true;
});
diff --git a/src/Storage.cpp b/src/Storage.cpp
index 50d1ffd..9a1c492 100644
--- a/src/Storage.cpp
+++ b/src/Storage.cpp
@@ -309,7 +309,8 @@ namespace QuickMedia {
char *env = getenv("PATH");
std::unordered_set<std::string> paths;
string_split(env, ':', [&paths](const char *str, size_t size) {
- paths.insert(std::string(str, size));
+ if(size > 0)
+ paths.insert(std::string(str, size));
return true;
});
diff --git a/src/plugins/FileManager.cpp b/src/plugins/FileManager.cpp
index f78265b..295b962 100644
--- a/src/plugins/FileManager.cpp
+++ b/src/plugins/FileManager.cpp
@@ -52,7 +52,7 @@ namespace QuickMedia {
set_last_accessed_dir(current_dir);
auto body = create_body();
- body->items = std::move(result_items);
+ body->set_items(std::move(result_items));
result_tabs.push_back(Tab{std::move(body), nullptr, nullptr});
return PluginResult::OK;
}
diff --git a/src/plugins/Fourchan.cpp b/src/plugins/Fourchan.cpp
index c1d7d6a..f7c9910 100644
--- a/src/plugins/Fourchan.cpp
+++ b/src/plugins/Fourchan.cpp
@@ -365,7 +365,7 @@ namespace QuickMedia {
}
auto body = create_body(false);
- body->items = std::move(result_items);
+ body->set_items(std::move(result_items));
result_tabs.push_back(Tab{std::move(body), std::make_unique<FourchanThreadPage>(program, board_id, url), nullptr});
return PluginResult::OK;
}
diff --git a/src/plugins/HotExamples.cpp b/src/plugins/HotExamples.cpp
index 02f1217..29e0110 100644
--- a/src/plugins/HotExamples.cpp
+++ b/src/plugins/HotExamples.cpp
@@ -132,7 +132,7 @@ namespace QuickMedia {
quickmedia_html_search_deinit(&html_search);
auto body = create_body();
- body->items = std::move(result_items);
+ body->set_items(std::move(result_items));
result_tabs.push_back({ std::move(body), std::make_unique<HotExamplesCodeExamplesPage>(program, title + " code examples"), create_search_bar("Search...", SEARCH_DELAY_FILTER) });
return PluginResult::OK;
}
diff --git a/src/plugins/MangaGeneric.cpp b/src/plugins/MangaGeneric.cpp
index 4668970..90da0c2 100644
--- a/src/plugins/MangaGeneric.cpp
+++ b/src/plugins/MangaGeneric.cpp
@@ -368,7 +368,7 @@ namespace QuickMedia {
return PluginResult::ERR;
auto body = create_body();
- body->items = std::move(chapters_items);
+ body->set_items(std::move(chapters_items));
result_tabs.push_back(Tab{std::move(body), std::make_unique<MangaGenericChaptersPage>(program, title, url, manga_id_extractor, service_name, website_url, &list_page_query, fail_on_http_error), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
for(auto &it : creators) {
diff --git a/src/plugins/Mangadex.cpp b/src/plugins/Mangadex.cpp
index 477608e..98683c1 100644
--- a/src/plugins/Mangadex.cpp
+++ b/src/plugins/Mangadex.cpp
@@ -307,7 +307,9 @@ namespace QuickMedia {
PluginResult MangadexSearchPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) {
chapter_image_urls.clear();
auto body = create_body();
- get_chapters_for_manga(this, url, 0, body->items, chapter_image_urls);
+ BodyItems body_items;
+ get_chapters_for_manga(this, url, 0, body_items, chapter_image_urls);
+ body->set_items(std::move(body_items));
result_tabs.push_back(Tab{std::move(body), std::make_unique<MangadexChaptersPage>(program, this, title, url), create_search_bar("Search...", SEARCH_DELAY_FILTER)});
return PluginResult::OK;
}
diff --git a/src/plugins/Manganelo.cpp b/src/plugins/Manganelo.cpp
index e0517dd..d3d7bfa 100644
--- a/src/plugins/Manganelo.cpp
+++ b/src/plugins/Manganelo.cpp
@@ -93,7 +93,7 @@ namespace QuickMedia {
return PluginResult::ERR;
auto chapters_body = page->create_body();
- chapters_body->items = std::move(chapters_items);
+ chapters_body->set_items(std::move(chapters_items));
result_tabs.push_back(Tab{std::move(chapters_body), std::make_unique<ManganeloChaptersPage>(page->program, title, url), page->create_search_bar("Search...", SEARCH_DELAY_FILTER)});
// TODO: Fix. Doesn't work because manganelo changes creator url format
diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp
index 18a76eb..f072a27 100644
--- a/src/plugins/Matrix.cpp
+++ b/src/plugins/Matrix.cpp
@@ -506,26 +506,26 @@ namespace QuickMedia {
});
}
- static void insert_room_body_item_by_timestamp(BodyItems &body_items, std::shared_ptr<BodyItem> new_body_item) {
+ static void insert_room_body_item_by_timestamp(Body *body, std::shared_ptr<BodyItem> new_body_item) {
RoomData *new_room = static_cast<RoomData*>(new_body_item->userdata);
- for(auto it = body_items.begin(), end = body_items.end(); it != end; ++it) {
- RoomData *room = static_cast<RoomData*>((*it)->userdata);
- if(new_room->last_message_timestamp >= room->last_message_timestamp) {
- body_items.insert(it, std::move(new_body_item));
- return;
- }
- }
- body_items.push_back(std::move(new_body_item));
+ const int insert_index = body->find_item_index([new_room](std::shared_ptr<BodyItem> &body_item) {
+ RoomData *room = static_cast<RoomData*>(body_item->userdata);
+ return new_room->last_message_timestamp >= room->last_message_timestamp;
+ });
+
+ if(insert_index == -1)
+ body->append_item(std::move(new_body_item));
+ else
+ body->insert_item(std::move(new_body_item), insert_index);
}
+ // TODO: Optimize
void body_set_selected_item_by_url(Body *body, const std::string &url) {
- for(size_t i = 0; i < body->items.size(); ++i) {
- if(body->items[i]->url == url) {
- body->select_first_item();
- body->set_selected_item(i, false);
- return;
- }
- }
+ const int found_item_index = body->find_item_index([&url](std::shared_ptr<BodyItem> &body_item) {
+ return body_item->url == url;
+ });
+ if(found_item_index != -1)
+ body->set_selected_item(found_item_index, false);
}
void MatrixQuickMedia::clear_data() {
@@ -658,12 +658,8 @@ namespace QuickMedia {
return PluginResult::OK;
}
- void MatrixRoomsPage::on_navigate_to_page(Body *body) {
- body->items_set_dirty(true);
- }
-
void MatrixRoomsPage::add_body_item(std::shared_ptr<BodyItem> body_item) {
- insert_room_body_item_by_timestamp(body->items, body_item);
+ insert_room_body_item_by_timestamp(body, body_item);
}
void MatrixRoomsPage::move_room_to_top(RoomData *room) {
@@ -678,28 +674,25 @@ namespace QuickMedia {
if(room_body_index == selected_item)
return;
- for(size_t i = 0; i < body->items.size(); ++i) {
- RoomData *room_i = static_cast<RoomData*>(body->items[i]->userdata);
+ for(size_t i = 0; i < body->get_num_items(); ++i) {
+ RoomData *room_i = static_cast<RoomData*>(body->get_item_by_index(i)->userdata);
if((int)i == room_body_index)
return;
if((int)i != selected_item && room_i && room->last_message_timestamp >= room_i->last_message_timestamp) {
- auto body_item_to_insert = body->items[room_body_index];
- body->items.erase(body->items.begin() + room_body_index);
- if(room_body_index >= (int)i)
- body->items.insert(body->items.begin() + i, std::move(body_item_to_insert));
- else
- body->items.insert(body->items.begin() + (i - 1), std::move(body_item_to_insert));
- if((int)i < selected_item && room_body_index > selected_item && body->items.size() > 1 && i != body->items.size() - 1) {
+ body->move_item(room_body_index, i);
+ if((int)i < selected_item && room_body_index > selected_item && body->get_num_items() > 1 && i != body->get_num_items() - 1)
body->select_next_item();
- }
+
return;
}
}
}
void MatrixRoomsPage::remove_body_item_by_room_id(const std::string &room_id) {
- remove_body_item_by_url(body->items, room_id);
+ body->erase_item([&room_id](std::shared_ptr<BodyItem> &body_item) {
+ return body_item->url == room_id;
+ });
if(current_chat_page && current_chat_page->room_id == room_id) {
program->set_go_to_previous_page();
body->select_first_item();
@@ -731,9 +724,10 @@ namespace QuickMedia {
auto body = create_body(true);
Body *body_ptr = body.get();
TagData &tag_data = tag_body_items_by_name[url];
- body->items = tag_data.room_body_items;
+ BodyItems room_body_items = tag_data.room_body_items;
+ sort_room_body_items(room_body_items);
+ body->set_items(std::move(room_body_items));
//BodyItem *selected_item = body->get_selected();
- sort_room_body_items(body->items);
//body_set_selected_item(body.get(), selected_item);
auto search_bar = create_search_bar("Search...", SEARCH_DELAY_FILTER);
auto rooms_page = std::make_unique<MatrixRoomsPage>(program, body_ptr, tag_data.tag_item->get_title(), this, search_bar.get());
@@ -742,10 +736,6 @@ namespace QuickMedia {
return PluginResult::OK;
}
- void MatrixRoomTagsPage::on_navigate_to_page(Body *body) {
- body->items_set_dirty(true);
- }
-
void MatrixRoomTagsPage::add_room_body_item_to_tag(std::shared_ptr<BodyItem> body_item, const std::string &tag) {
TagData *tag_data;
auto tag_body_it = tag_body_items_by_name.find(tag);
@@ -759,7 +749,7 @@ namespace QuickMedia {
tag_body_items_by_name.insert(std::make_pair(tag, TagData{tag_body_item, {}}));
// TODO: Sort by tag priority
body->apply_search_filter_for_item(tag_body_item.get());
- body->items.push_back(tag_body_item);
+ body->append_item(tag_body_item);
tag_data = &tag_body_items_by_name[tag];
tag_data->tag_item = tag_body_item;
}
@@ -789,9 +779,10 @@ namespace QuickMedia {
tag_body_it->second.room_body_items.erase(room_body_item_it);
if(tag_body_it->second.room_body_items.empty()) {
- auto room_body_item_it = std::find(body->items.begin(), body->items.end(), tag_body_it->second.tag_item);
- if(room_body_item_it != body->items.end())
- body->items.erase(room_body_item_it);
+ const auto &tag_item = tag_body_it->second.tag_item;
+ body->erase_item([&tag_item](std::shared_ptr<BodyItem> &body_item) {
+ return body_item == tag_item;
+ });
tag_body_items_by_name.erase(tag_body_it);
}
}
@@ -831,8 +822,8 @@ namespace QuickMedia {
PluginResult MatrixInvitesPage::submit(const std::string &title, const std::string &url, std::vector<Tab> &result_tabs) {
auto body = create_body();
- body->items.push_back(BodyItem::create("Accept"));
- body->items.push_back(BodyItem::create("Decline"));
+ body->append_item(BodyItem::create("Accept"));
+ body->append_item(BodyItem::create("Decline"));
result_tabs.push_back(Tab{std::move(body), std::make_unique<MatrixInviteDetailsPage>(program, matrix, this, url, "Invite to " + title), nullptr});
return PluginResult::OK;
}
@@ -864,16 +855,19 @@ namespace QuickMedia {
// TODO: Insert in reverse order (to show the latest invite at the top?)
body->apply_search_filter_for_item(body_item.get());
body->insert_item_by_timestamp(std::move(body_item));
- if(body->items.size() != prev_invite_count) {
- prev_invite_count = body->items.size();
- title = "Invites (" + std::to_string(body->items.size()) + ")";
+ if(body->get_num_items() != prev_invite_count) {
+ prev_invite_count = body->get_num_items();
+ title = "Invites (" + std::to_string(body->get_num_items()) + ")";
}
}
void MatrixInvitesPage::remove_body_item_by_room_id(const std::string &room_id) {
- if(remove_body_item_by_url(body->items, room_id)) {
- prev_invite_count = body->items.size();
- title = "Invites (" + std::to_string(body->items.size()) + ")";
+ const bool item_removed = body->erase_item([&room_id](std::shared_ptr<BodyItem> &body_item) {
+ return body_item->url == room_id;
+ });
+ if(item_removed) {
+ prev_invite_count = body->get_num_items();
+ title = "Invites (" + std::to_string(body->get_num_items()) + ")";
}
}
@@ -908,8 +902,7 @@ namespace QuickMedia {
body_item->thumbnail_mask_type = ThumbnailMaskType::CIRCLE;
body_item->thumbnail_size = sf::Vector2i(32, 32);
- users_body->apply_search_filter_for_item(body_item.get());
- users_body->items.push_back(std::move(body_item));
+ users_body->append_item(std::move(body_item));
}
void MatrixChatPage::add_user(MatrixEventUserInfo user_info) {
@@ -924,12 +917,9 @@ namespace QuickMedia {
return;
// TODO: Optimize
- for(auto it = users_body->items.begin(), end = users_body->items.end(); it != end; ++it) {
- if((*it)->url == user_info.user_id) {
- users_body->items.erase(it);
- return;
- }
- }
+ users_body->erase_item([&user_info](std::shared_ptr<BodyItem> &it) {
+ return it->url == user_info.user_id;
+ });
}
void MatrixChatPage::set_user_info(MatrixEventUserInfo user_info) {
@@ -937,32 +927,25 @@ namespace QuickMedia {
return;
// TODO: Optimize
- for(auto it = users_body->items.begin(), end = users_body->items.end(); it != end; ++it) {
- if((*it)->url == user_info.user_id) {
- if(user_info.avatar_url)
- (*it)->thumbnail_url = user_info.avatar_url.value();
-
- if(user_info.display_name) {
- std::string display_name;
- if(user_info.display_name.value().empty())
- display_name = user_info.user_id;
- else
- display_name = user_info.display_name.value();
-
- (*it)->set_author(extract_first_line_remove_newline_elipses(display_name, AUTHOR_MAX_LENGTH));
-
- //auto user_body_item = *it;
- //users_body->items.erase(it);
-
- // TODO: extract_first_line_remove_newline_elipses(room->get_user_display_name(message->user), AUTHOR_MAX_LENGTH),
- // But that should be done in Text because we need author to be 100% the same as in the input to reorder users
- users_body->apply_search_filter_for_item(it->get());
- //size_t insert_index = get_body_item_sorted_insert_position_by_author(users_body->items, user_body_item->get_author(), 0);
- //users_body->items.insert(users_body->items.begin() + insert_index, std::move(user_body_item));
- }
+ auto user_body_item = users_body->find_item([&user_info](std::shared_ptr<BodyItem> &it) {
+ return it->url == user_info.user_id;
+ });
- return;
- }
+ if(!user_body_item)
+ return;
+
+ if(user_info.avatar_url)
+ user_body_item->thumbnail_url = user_info.avatar_url.value();
+
+ if(user_info.display_name) {
+ const std::string *display_name;
+ if(user_info.display_name.value().empty())
+ display_name = &user_info.user_id;
+ else
+ display_name = &user_info.display_name.value();
+
+ user_body_item->set_author(extract_first_line_remove_newline_elipses(*display_name, AUTHOR_MAX_LENGTH));
+ users_body->apply_search_filter_for_item(user_body_item.get());
}
}
@@ -978,7 +961,7 @@ namespace QuickMedia {
}
size_t MatrixChatPage::get_num_users_in_current_room() const {
- return users_body ? users_body->items.size() : 0;
+ return users_body ? users_body->get_num_items() : 0;
}
void MatrixChatPage::set_room_as_read(RoomData *room) {
@@ -1095,19 +1078,20 @@ namespace QuickMedia {
//int prev_selected_item = notifications_body->get_selected_item();
//notifications_body->items.push_back(notification_to_body_item(notifications_body, notification));
//notifications_body->set_selected_item(prev_selected_item - 1);
- notifications_body->items.insert(notifications_body->items.begin(), notification_to_body_item(notifications_body, notification));
+ notifications_body->prepend_item(notification_to_body_item(notifications_body, notification));
notifications_body->select_next_item();
}
+ // TODO: Only loop unread items
void MatrixNotificationsPage::set_room_as_read(RoomData *room) {
- for(auto &body_item : notifications_body->items) {
+ notifications_body->for_each_item([room](std::shared_ptr<BodyItem> &body_item) {
NotificationsExtraData *extra_data = static_cast<NotificationsExtraData*>(body_item->extra.get());
if(!extra_data->read && extra_data->room == room) {
extra_data->read = true;
body_item->set_author_color(get_current_theme().text_color);
body_item->set_description_color(get_current_theme().text_color);
}
- }
+ });
}
SearchResult MatrixInviteUserPage::search(const std::string &str, BodyItems &result_items) {
@@ -3036,8 +3020,12 @@ namespace QuickMedia {
bool is_inside_code_block = false;
bool is_first_line = true;
string_split(body, '\n', [this, room, &formatted_body, &is_inside_code_block, &is_first_line](const char *str, size_t size){
- if(!is_first_line)
- formatted_body += "<br/>";
+ if(!is_first_line) {
+ if(is_inside_code_block)
+ formatted_body += '\n';
+ else
+ formatted_body += "<br/>";
+ }
std::string line_str(str, size);
html_escape_sequences(line_str);
diff --git a/src/plugins/NyaaSi.cpp b/src/plugins/NyaaSi.cpp
index ccf027d..8e55e62 100644
--- a/src/plugins/NyaaSi.cpp
+++ b/src/plugins/NyaaSi.cpp
@@ -134,12 +134,12 @@ namespace QuickMedia {
return body_item;
}
- static void sort_page_create_body_items(BodyItems &body_items, NyaaSiSortType sort_type) {
+ static void sort_page_create_body_items(Body *body, NyaaSiSortType sort_type) {
for(size_t i = 0; i < sort_type_names.size(); ++i) {
std::string prefix = " ";
if((NyaaSiSortType)i == sort_type)
prefix = "* ";
- body_items.push_back(create_sort_body_item(prefix + sort_type_names[i], (NyaaSiSortType)i));
+ body->append_item(create_sort_body_item(prefix + sort_type_names[i], (NyaaSiSortType)i));
}
}
@@ -294,12 +294,12 @@ namespace QuickMedia {
auto search_page = std::make_unique<NyaaSiSearchPage>(program, strip(title), url, std::move(domain));
NyaaSiSearchPage *search_page_p = search_page.get();
auto body = create_body();
- body->items = std::move(result_items);
+ body->set_items(std::move(result_items));
result_tabs.push_back(Tab{std::move(body), std::move(search_page), create_search_bar("Search...", 500)});
auto sort_order_page_body = create_body();
Body *sort_order_page_body_p = sort_order_page_body.get();
- sort_page_create_body_items(sort_order_page_body->items, NyaaSiSortType::UPLOAD_DATE_DESC);
+ sort_page_create_body_items(sort_order_page_body_p, NyaaSiSortType::UPLOAD_DATE_DESC);
result_tabs.push_back(Tab{std::move(sort_order_page_body), std::make_unique<NyaaSiSortOrderPage>(program, sort_order_page_body_p, search_page_p), nullptr});
return PluginResult::OK;
}
@@ -486,7 +486,7 @@ namespace QuickMedia {
return PluginResult::ERR;
auto body = create_body();
- body->items = std::move(result_items);
+ body->set_items(std::move(result_items));
result_tabs.push_back(Tab{std::move(body), std::make_unique<NyaaSiTorrentPage>(program), nullptr});
return PluginResult::OK;
}
@@ -499,8 +499,8 @@ namespace QuickMedia {
PluginResult NyaaSiSortOrderPage::submit(const std::string&, const std::string&, std::vector<Tab>&) {
const NyaaSiSortType sort_type = (NyaaSiSortType)(size_t)submit_body_item->userdata;
- body->items.clear();
- sort_page_create_body_items(body->items, sort_type);
+ body->clear_items();
+ sort_page_create_body_items(body, sort_type);
search_page->set_sort_type(sort_type);
search_page->needs_refresh = true;
return PluginResult::OK;
diff --git a/src/plugins/Soundcloud.cpp b/src/plugins/Soundcloud.cpp
index 7079e46..f20cf7d 100644
--- a/src/plugins/Soundcloud.cpp
+++ b/src/plugins/Soundcloud.cpp
@@ -247,7 +247,7 @@ namespace QuickMedia {
if(url == "track") {
SoundcloudPlaylist *playlist = static_cast<SoundcloudPlaylist*>(submit_body_item->extra.get());
auto body = create_body(false, true);
- body->items = playlist->tracks;
+ body->set_items(playlist->tracks);
result_tabs.push_back(Tab{std::move(body), std::make_unique<SoundcloudPlaylistPage>(program, playlist, title), nullptr});
} else if(url.find("/stream/users/") != std::string::npos) {
std::string query_url = url + "?client_id=" + client_id + "&limit=20&offset=0&linked_partitioning=1&app_version=1616689516&app_locale=en";
@@ -258,7 +258,9 @@ namespace QuickMedia {
auto body = create_body(false, true);
std::string next_href;
- PluginResult pr = parse_user_page(json_root, body->items, next_href);
+ BodyItems body_items;
+ PluginResult pr = parse_user_page(json_root, body_items, next_href);
+ body->set_items(std::move(body_items));
if(pr != PluginResult::OK) return pr;
result_tabs.push_back(Tab{std::move(body), std::make_unique<SoundcloudUserPage>(program, title, url, std::move(next_href)), nullptr});