diff options
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | TODO | 4 | ||||
m--------- | depends/html-parser | 0 | ||||
m--------- | depends/html-search | 0 | ||||
m--------- | depends/jsoncpp | 0 | ||||
m--------- | depends/mglpp | 0 | ||||
m--------- | depends/rapidjson | 0 | ||||
-rw-r--r-- | include/ImageViewer.hpp | 2 | ||||
-rw-r--r-- | include/QuickMedia.hpp | 1 | ||||
-rw-r--r-- | include/Storage.hpp | 1 | ||||
-rwxr-xr-x | install.sh | 36 | ||||
-rw-r--r-- | meson.build | 138 | ||||
-rw-r--r-- | meson_options.txt | 3 | ||||
-rwxr-xr-x | meson_post_install.sh | 6 | ||||
-rw-r--r-- | plugins/Matrix.hpp | 11 | ||||
-rw-r--r-- | project.conf | 2 | ||||
-rw-r--r-- | src/AsyncImageLoader.cpp | 1 | ||||
-rw-r--r-- | src/FileAnalyzer.cpp | 2 | ||||
-rw-r--r-- | src/ImageViewer.cpp | 25 | ||||
-rw-r--r-- | src/QuickMedia.cpp | 21 | ||||
-rw-r--r-- | src/Storage.cpp | 15 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/plugins/Matrix.cpp | 42 | ||||
-rw-r--r-- | uninstall.sh | 10 | ||||
m--------- | video_player/jsoncpp | 0 |
25 files changed, 268 insertions, 60 deletions
@@ -24,9 +24,8 @@ EXAMPLES: tabbed -c -k quickmedia launcher -e ``` ## Installation -If you are running arch linux then you can install QuickMedia from aur: [https://aur.archlinux.org/packages/quickmedia-git/](https://aur.archlinux.org/packages/quickmedia-git/), otherwise you will need to first install [sibs](https://git.dec05eba.com/sibs/) and then run `./install.sh` as root.\ +If you are running arch linux then you can install QuickMedia from aur: [https://aur.archlinux.org/packages/quickmedia-git/](https://aur.archlinux.org/packages/quickmedia-git/), otherwise you will need to run `./install.sh` as root.\ `tar` and curl needs to be installed to run the `install.sh` script.\ -Installing `lld` (the LLVM linker) can improve compile times.\ There is also an unofficial ebuild for gentoo users. On gentoo you can install QuickMedia by running these commands: ```bash eselect repository add overlay-from-plan9 git https://git.plan9.rocks/cat/overlay-from-plan9 @@ -34,6 +33,7 @@ emerge --sync overlay-from-plan9 emerge -av quickmedia ``` ## Dependencies +Meson needs to be installed to run the build script. ### Libraries `libglvnd (LibGL.so)`, `libx11`, `libxrandr`, `libmpv` ### Executables @@ -105,6 +105,7 @@ Type text and then wait and QuickMedia will automatically search.\ `Home`: Go to the first page.\ `End`: Go to the last page.\ `F`: Toggle between scaling the image to the window size or only down scaling if the image is too large.\ +`B`: Show/hide the bottom progress bar.\ `I`: Switch to scroll view. ### Manga scroll view controls `Arrow up`/`K`: Move up.\ @@ -113,6 +114,7 @@ Type text and then wait and QuickMedia will automatically search.\ `Home`: Go to the first page.\ `End`: Go to the last page.\ `F`: Toggle between scaling the image to the window size or only down scaling if the image is too large.\ +`B`: Show/hide the bottom progress bar.\ `I`: Switch to page view. ### Manga chapters controls `Ctrl+T`: Start tracking the manga after the selected chapter ([AutoMedia](https://git.dec05eba.com/AutoMedia/) needs to be installed). @@ -297,4 +297,6 @@ v0.m3u8 doesn't work for some lbry videos (such as https://odysee.com/@MoneroMag Use DPMSInfoNotify. Use stb_image_resize2.h Youtube audio only download if audio stream not available, also for youtube-dl fallback. -Make history (local-manga and others) use relative path to the downloads directory for thumbnails. Otherwise the thumbnails wont show when moving the download directory.
\ No newline at end of file +Make history (local-manga and others) use relative path to the downloads directory for thumbnails. Otherwise the thumbnails wont show when moving the download directory. +Keep the rooms that we were kicked/banned from so we can still read them and re-read the reason for why we were kicked/banned. Or add a list of historical rooms with leave reason. +Fix youtube broken (always falls back to low quality yt-dlp).
\ No newline at end of file diff --git a/depends/html-parser b/depends/html-parser -Subproject ec0e71c259d5aa8be7b8456509b5617d27742b6 +Subproject 3cf44ec7fba308a4b33b0486545b33e334bed74 diff --git a/depends/html-search b/depends/html-search -Subproject 68989816f43ceda8655c2dbdc0d581971e645fc +Subproject a77706c37d3b6df3049f658dd220b813fe1834b diff --git a/depends/jsoncpp b/depends/jsoncpp -Subproject f23fb32fd9d9c3d01fa67afa0d75f7ff227647e +Subproject 98e28b38ffbae24c0e69e620bf18f8a0c5c6f20 diff --git a/depends/mglpp b/depends/mglpp -Subproject 1a2a6ad8ef354f62bdf9adcfef73af1e5d03695 +Subproject 9634e4fef56016f59d45b0cb530087ab36f0171 diff --git a/depends/rapidjson b/depends/rapidjson -Subproject a42f7cc32be7c1d2100d30098e15ff2661c4a61 +Subproject 49b4e2dc7892f27b56a5a9f058c2c9969609324 diff --git a/include/ImageViewer.hpp b/include/ImageViewer.hpp index b587b82..b3b18dc 100644 --- a/include/ImageViewer.hpp +++ b/include/ImageViewer.hpp @@ -104,5 +104,7 @@ namespace QuickMedia { mgl::vec2d prev_size_first_page; mgl::vec2d prev_size_last_page; + + bool show_progress_bar = true; }; }
\ No newline at end of file diff --git a/include/QuickMedia.hpp b/include/QuickMedia.hpp index a6de75c..038cf19 100644 --- a/include/QuickMedia.hpp +++ b/include/QuickMedia.hpp @@ -245,5 +245,6 @@ namespace QuickMedia { std::mutex login_inputs_mutex; const char *yt_dl_name = nullptr; bool yt_dl_name_checked = false; + bool show_manga_bottom_bar = true; }; } diff --git a/include/Storage.hpp b/include/Storage.hpp index 60c15f6..86c34d2 100644 --- a/include/Storage.hpp +++ b/include/Storage.hpp @@ -34,6 +34,7 @@ namespace QuickMedia { bool file_get_last_modified_time_seconds(const char *path, time_t *result); int file_overwrite(const Path &path, const std::string &data); int file_overwrite_atomic(const Path &path, const std::string &data); + bool file_append(const Path &path, const std::string &data); // The callback is called with 0 as the argument (last_modified_seconds) void for_files_in_dir(const Path &path, FileIteratorCallback callback); void for_files_in_dir_sort_last_modified(const Path &path, FileIteratorCallback callback, FileSortDirection sort_dir = FileSortDirection::ASC); @@ -5,35 +5,9 @@ cd "$script_dir" [ $(id -u) -ne 0 ] && echo "You need root privileges to run the install script" && exit 1 -curl -sfL 'https://dec05eba.com/files/twemoji.tar.gz' -o /tmp/twemoji.tar.gz -mkdir -p /usr/share/quickmedia/emoji -tar xf /tmp/twemoji.tar.gz --directory=/usr/share/quickmedia/emoji -rm -f /tmp/twemoji.tar.gz +rm -rf build +meson setup build +meson configure --prefix=/usr --buildtype=release -Dstrip=true build +ninja -C build install -sibs build --release video_player -sibs build --release - -install -Dm755 "video_player/sibs-build/$(sibs platform)/release/quickmedia-video-player" "/usr/bin/quickmedia-video-player" -install -Dm755 "sibs-build/$(sibs platform)/release/quickmedia" "/usr/bin/quickmedia" -ln -sf "/usr/bin/quickmedia" "/usr/bin/qm" -install -Dm644 boards.json "/usr/share/quickmedia/boards.json" - -install -Dm644 example-config.json "/usr/share/quickmedia/example-config.json" -install -Dm644 README.md "/usr/share/quickmedia/README.md" - -install -Dm644 mpv/fonts/Material-Design-Iconic-Font.ttf "/usr/share/quickmedia/mpv/fonts/Material-Design-Iconic-Font.ttf" -install -Dm644 mpv/scripts/mordenx.lua "/usr/share/quickmedia/mpv/scripts/mordenx.lua" -install -Dm644 mpv/scripts/ytdl_hook.lua "/usr/share/quickmedia/mpv/scripts/ytdl_hook.lua" -install -Dm644 mpv/input.conf "/usr/share/quickmedia/mpv/input.conf" -install -Dm644 mpv/mpv.conf "/usr/share/quickmedia/mpv/mpv.conf" - -for file in images/* icons/* shaders/* themes/*; do - install -Dm644 "$file" "/usr/share/quickmedia/$file" -done - -for file in launcher/*; do - filename=$(basename "$file") - install -Dm644 "$file" "/usr/share/applications/$filename" -done - -echo "Successfully installed QuickMedia" +echo "Successfully installed quickmedia"
\ No newline at end of file diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..a675ac8 --- /dev/null +++ b/meson.build @@ -0,0 +1,138 @@ +project('quickmedia', ['c', 'cpp'], version : '1.0.0', default_options : ['warning_level=2', 'cpp_std=c++17'], subproject_dir : 'depends') + +if get_option('buildtype') == 'debug' + add_project_arguments('-g3', language : ['c', 'cpp']) +elif get_option('buildtype') == 'release' + add_project_arguments('-DNDEBUG', language : ['c', 'cpp']) +endif + +src = [ + 'external/hash-library/sha256.cpp', + 'generated/Tlds.cpp', + 'generated/Emoji.cpp', + 'src/plugins/utils/aes.c', + 'src/plugins/Fourchan.cpp', + 'src/plugins/Mangadex.cpp', + 'src/plugins/ImageBoard.cpp', + 'src/plugins/MangaCombined.cpp', + 'src/plugins/Manga.cpp', + 'src/plugins/Lbry.cpp', + 'src/plugins/NyaaSi.cpp', + 'src/plugins/HotExamples.cpp', + 'src/plugins/FileManager.cpp', + 'src/plugins/MediaGeneric.cpp', + 'src/plugins/Matrix.cpp', + 'src/plugins/Plugin.cpp', + 'src/plugins/MangaGeneric.cpp', + 'src/plugins/Pipe.cpp', + 'src/plugins/Manganelo.cpp', + 'src/plugins/LocalManga.cpp', + 'src/plugins/Page.cpp', + 'src/plugins/Peertube.cpp', + 'src/plugins/LocalAnime.cpp', + 'src/plugins/AniList.cpp', + 'src/plugins/DramaCool.cpp', + 'src/plugins/utils/UniqueProcess.cpp', + 'src/plugins/utils/WatchProgress.cpp', + 'src/plugins/utils/EpisodeNameParser.cpp', + 'src/plugins/Info.cpp', + 'src/plugins/Youtube.cpp', + 'src/plugins/Saucenao.cpp', + 'src/plugins/Soundcloud.cpp', + 'src/Theme.cpp', + 'src/Storage.cpp', + 'src/Text.cpp', + 'src/Config.cpp', + 'src/DownloadUtils.cpp', + 'src/Json.cpp', + 'src/gui/Button.cpp', + 'src/SearchBar.cpp', + 'src/RoundedRectangle.cpp', + 'src/Entry.cpp', + 'src/Notification.cpp', + 'src/AsyncImageLoader.cpp', + 'src/ImageViewer.cpp', + 'src/Body.cpp', + 'src/Program.cpp', + 'src/main.cpp', + 'src/ImageUtils.cpp', + 'src/NetUtils.cpp', + 'src/BodyItem.cpp', + 'src/Downloader.cpp', + 'src/ResourceLoader.cpp', + 'src/VideoPlayer.cpp', + 'src/Tabs.cpp', + 'src/FileAnalyzer.cpp', + 'src/QuickMedia.cpp', + 'src/M3U8.cpp', + 'src/Utils.cpp', + 'src/StringUtils.cpp', +] + +mglpp_proj = subproject('mglpp') +mglpp_dep = mglpp_proj.get_variable('mglpp_dep') + +jsoncpp_proj = subproject('jsoncpp') +jsoncpp_dep = jsoncpp_proj.get_variable('jsoncpp_dep') + +rapidjson_proj = subproject('rapidjson') +rapidjson_dep = rapidjson_proj.get_variable('rapidjson_dep') + +html_parser_proj = subproject('html-parser') +html_parser_dep = html_parser_proj.get_variable('html_parser_dep') + +html_search_proj = subproject('html-search') +html_search_dep = html_search_proj.get_variable('html_search_dep') + +prefix = get_option('prefix') +datadir = get_option('datadir') +qm_resources_path = join_paths(prefix, datadir, 'quickmedia') + +if get_option('native_arch') == true + add_project_arguments('-march=native', language: ['c', 'cpp']) +endif + +executable( + meson.project_name(), + src, + install : true, + dependencies : [ + mglpp_dep, + jsoncpp_dep, + rapidjson_dep, + html_parser_dep, + html_search_dep, + dependency('threads'), + ], +) + +executable( + 'quickmedia-video-player', + [ + 'video_player/src/main.cpp' + ], + install : true, + dependencies : [ + jsoncpp_dep, + dependency('mpv'), + ], +) + +install_subdir('mpv', install_dir : qm_resources_path) +install_subdir('images', install_dir : qm_resources_path) +install_subdir('icons', install_dir : qm_resources_path) +install_subdir('shaders', install_dir : qm_resources_path) +install_subdir('themes', install_dir : qm_resources_path) + +install_data('launcher/QuickMedia.desktop', install_dir : join_paths(prefix, datadir, 'applications')) +install_data(files('boards.json'), install_dir : qm_resources_path) +install_data(files('example-config.json'), install_dir : qm_resources_path) +install_data(files('README.md'), install_dir : qm_resources_path) + +if get_option('install_symlink') == true + install_symlink('qm', install_dir : join_paths(prefix, 'bin'), pointing_to: join_paths(prefix, 'bin', meson.project_name())) +endif + +if get_option('install_emoji') == true + meson.add_install_script('meson_post_install.sh') +endif diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 0000000..0232def --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,3 @@ +option('native_arch', type : 'boolean', value : true, description : 'Build specifically for your own cpu for best performance') +option('install_symlink', type : 'boolean', value : true, description : 'Install a symlink for qm to quickmedia') +option('install_emoji', type : 'boolean', value : true, description : 'Download and install emoji') diff --git a/meson_post_install.sh b/meson_post_install.sh new file mode 100755 index 0000000..1c87f9f --- /dev/null +++ b/meson_post_install.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +curl -sfL 'https://dec05eba.com/files/twemoji.tar.gz' -o /tmp/twemoji.tar.gz +mkdir -p "${MESON_INSTALL_DESTDIR_PREFIX}/share/quickmedia/emoji" +tar xf /tmp/twemoji.tar.gz --directory="${MESON_INSTALL_DESTDIR_PREFIX}/share/quickmedia/emoji" +rm -f /tmp/twemoji.tar.gz
\ No newline at end of file diff --git a/plugins/Matrix.hpp b/plugins/Matrix.hpp index a3ce633..23b0a8a 100644 --- a/plugins/Matrix.hpp +++ b/plugins/Matrix.hpp @@ -320,7 +320,7 @@ namespace QuickMedia { virtual ~MatrixDelegate() = default; virtual void join_room(RoomData *room) = 0; - virtual void leave_room(RoomData *room, LeaveType leave_type, const std::string &reason) = 0; + virtual void leave_room(RoomData *room, const std::string &event_id, LeaveType leave_type, const std::string &reason) = 0; // Note: calling |room| methods inside this function is not allowed virtual void room_add_tag(RoomData *room, const std::string &tag) = 0; @@ -356,7 +356,7 @@ namespace QuickMedia { MatrixQuickMedia(Program *program, Matrix *matrix, MatrixRoomsPage *rooms_page, MatrixRoomTagsPage *room_tags_page, MatrixInvitesPage *invites_page, MatrixNotificationsPage *notifications_page); void join_room(RoomData *room) override; - void leave_room(RoomData *room, LeaveType leave_type, const std::string &reason) override; + void leave_room(RoomData *room, const std::string &event_id, LeaveType leave_type, const std::string &reason) override; void room_add_tag(RoomData *room, const std::string &tag) override; void room_remove_tag(RoomData *room, const std::string &tag) override; void room_add_new_messages(RoomData *room, const Messages &messages, bool is_initial_sync, MessageDirection message_dir) override; @@ -759,6 +759,11 @@ namespace QuickMedia { MatrixDelegate* get_delegate(); + bool is_another_instance_running() const { return matrix_instance_already_running; } + + void mark_other_notification_as_read(const std::string &event_id); + bool is_other_notification_read(const std::string &event_id) const; + // Calls the |MatrixDelegate| pending events. // Should be called from the main (ui) thread void update(); @@ -783,6 +788,7 @@ namespace QuickMedia { void add_new_invites(); void parse_custom_emoji(const rapidjson::Value &custom_emoji_json); void load_custom_emoji_from_cache(); + void load_other_notifications(); PluginResult get_previous_room_messages(RoomData *room_data, bool latest_messages, size_t &num_new_messages, bool *reached_end = nullptr); void events_add_user_info(const rapidjson::Value &events_json, RoomData *room_data, int64_t timestamp); std::shared_ptr<UserInfo> parse_user_info(const rapidjson::Value &json, const std::string &user_id, RoomData *room_data, int64_t timestamp); @@ -850,6 +856,7 @@ namespace QuickMedia { std::unordered_map<std::string, CustomEmoji> custom_emoji_by_key; std::unordered_set<std::string> silenced_invites; std::unordered_map<std::string, int64_t> qm_read_markers_by_room_cache; + std::unordered_set<std::string> other_notifications_read; MessageQueue<std::shared_ptr<MatrixChatBodyDecryptJob>> decrypt_task; std::thread decrypt_thread; diff --git a/project.conf b/project.conf index b737123..5f01694 100644 --- a/project.conf +++ b/project.conf @@ -7,7 +7,7 @@ platforms = ["posix"] [config] # This needs to be commented out for now because rapidjson depends on undefined behavior according to gcc... #error_on_warning = "true" -ignore_dirs = ["video_player"] +ignore_dirs = ["video_player", "build"] [lang.cpp] version = "c++17" diff --git a/src/AsyncImageLoader.cpp b/src/AsyncImageLoader.cpp index 14cfe6a..a6706f5 100644 --- a/src/AsyncImageLoader.cpp +++ b/src/AsyncImageLoader.cpp @@ -27,6 +27,7 @@ namespace QuickMedia { bool ffmpeg_convert_image_format(const Path &thumbnail_path, const Path &destination_path) { + // TODO: Dont output as jpg, ffmpeg jpg is very slow const char *args[] = { "ffmpeg", "-y", "-v", "quiet", "-i", thumbnail_path.data.c_str(), "--", destination_path.data.c_str(), nullptr}; return exec_program(args, nullptr, nullptr) == 0; } diff --git a/src/FileAnalyzer.cpp b/src/FileAnalyzer.cpp index 4deb8c3..1d24c5f 100644 --- a/src/FileAnalyzer.cpp +++ b/src/FileAnalyzer.cpp @@ -157,6 +157,7 @@ namespace QuickMedia { char size_arg_str[512]; snprintf(size_arg_str, sizeof(size_arg_str), "scale=%d:%d:force_original_aspect_ratio=decrease", width, height); + // TODO: Dont output as jpg, ffmpeg jpg is very slow const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-ss", seconds_str, "-i", file.get_filepath().c_str(), "-frames:v", "1", "-vf", size_arg_str, "--", destination_path_tmp.data.c_str(), nullptr }; if(exec_program(program_args, nullptr, nullptr, allowed_exit_status, 2) != 0) { fprintf(stderr, "Failed to execute ffmpeg, maybe its not installed?\n"); @@ -168,6 +169,7 @@ namespace QuickMedia { if(fallback_first_frame && get_file_type(destination_path_tmp) == FileType::FILE_NOT_FOUND) return video_get_frame(file, destination_path, width, height, 0, false); } else { + // TODO: Dont output as jpg, ffmpeg jpg is very slow const char *program_args[] = { "ffmpeg", "-y", "-v", "quiet", "-ss", seconds_str, "-i", file.get_filepath().c_str(), "-frames:v", "1", "--", destination_path_tmp.data.c_str(), nullptr }; if(exec_program(program_args, nullptr, nullptr, allowed_exit_status, 2) != 0) { fprintf(stderr, "Failed to execute ffmpeg, maybe its not installed?\n"); diff --git a/src/ImageViewer.cpp b/src/ImageViewer.cpp index fb9912c..454f34b 100644 --- a/src/ImageViewer.cpp +++ b/src/ImageViewer.cpp @@ -296,6 +296,9 @@ namespace QuickMedia { if(event.key.code == mgl::Keyboard::F) *fit_image_to_window = !*fit_image_to_window; + + if(event.key.code == mgl::Keyboard::B) + show_progress_bar = !show_progress_bar; } else if(event.type == mgl::Event::KeyReleased) { if(is_key_scroll_up(event.key)) up_pressed = false; @@ -426,16 +429,18 @@ namespace QuickMedia { const float font_height = page_text_character_size + 8.0f; const float background_height = font_height + 6.0f; - mgl::Rectangle page_text_background(mgl::vec2f(window_size.x, background_height)); - mgl::Color text_background_color = get_theme().shade_color; - text_background_color.a = 225; - page_text_background.set_color(text_background_color); - page_text_background.set_position(mgl::vec2f(0.0f, window_size.y - background_height)); - window->draw(page_text_background); - - auto page_text_bounds = page_text.get_bounds(); - page_text.set_position(mgl::vec2f(floor(window_size.x * 0.5f - page_text_bounds.size.x * 0.5f), floor(window_size.y - background_height * 0.5f - font_height * 0.55f))); - window->draw(page_text); + if(show_progress_bar) { + mgl::Rectangle page_text_background(mgl::vec2f(window_size.x, background_height)); + mgl::Color text_background_color = get_theme().shade_color; + text_background_color.a = 225; + page_text_background.set_color(text_background_color); + page_text_background.set_position(mgl::vec2f(0.0f, window_size.y - background_height)); + window->draw(page_text_background); + + auto page_text_bounds = page_text.get_bounds(); + page_text.set_position(mgl::vec2f(floor(window_size.x * 0.5f - page_text_bounds.size.x * 0.5f), floor(window_size.y - background_height * 0.5f - font_height * 0.55f))); + window->draw(page_text); + } // Free pages that are not visible on the screen int i = 0; diff --git a/src/QuickMedia.cpp b/src/QuickMedia.cpp index f3e21da..0671349 100644 --- a/src/QuickMedia.cpp +++ b/src/QuickMedia.cpp @@ -953,7 +953,7 @@ namespace QuickMedia { string_split(urls_str, ',', [&arrays](const char *str, size_t size) { std::string url(str, size); url = strip(url); - if(!url.empty() && (arrays.empty() || arrays.back() != url)) + if(url.find(".com") != std::string::npos && (arrays.empty() || arrays.back() != url)) arrays.push_back(std::move(url)); return true; }); @@ -4490,6 +4490,9 @@ namespace QuickMedia { } else if(event.key.code == mgl::Keyboard::F) { fit_image_to_window = !fit_image_to_window; redraw = true; + } else if(event.key.code == mgl::Keyboard::B) { + show_manga_bottom_bar = !show_manga_bottom_bar; + redraw = true; } } } @@ -4514,7 +4517,7 @@ namespace QuickMedia { } const float font_height = chapter_text_character_size + 8.0f; - const float bottom_panel_height = font_height + 6.0f; + const float bottom_panel_height = show_manga_bottom_bar ? font_height + 6.0f : 0.0f; mgl::vec2f content_size; content_size.x = window_size.x; @@ -4553,13 +4556,15 @@ namespace QuickMedia { window.draw(image); } - chapter_text_background.set_size(mgl::vec2f(window_size.x, bottom_panel_height)); - chapter_text_background.set_position(mgl::vec2f(0.0f, std::floor(window_size.y - bottom_panel_height))); - window.draw(chapter_text_background); + if(show_manga_bottom_bar) { + chapter_text_background.set_size(mgl::vec2f(window_size.x, bottom_panel_height)); + chapter_text_background.set_position(mgl::vec2f(0.0f, std::floor(window_size.y - bottom_panel_height))); + window.draw(chapter_text_background); - auto text_bounds = chapter_text.get_bounds(); - chapter_text.set_position(vec2f_floor(window_size.x * 0.5f - text_bounds.size.x * 0.5f, window_size.y - bottom_panel_height * 0.5f - font_height * 0.55f)); - window.draw(chapter_text); + auto text_bounds = chapter_text.get_bounds(); + chapter_text.set_position(vec2f_floor(window_size.x * 0.5f - text_bounds.size.x * 0.5f, window_size.y - bottom_panel_height * 0.5f - font_height * 0.55f)); + window.draw(chapter_text); + } window.display(); } else { diff --git a/src/Storage.cpp b/src/Storage.cpp index 7bb3be6..5c12911 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -244,6 +244,21 @@ namespace QuickMedia { return rename_atomic(tmp_path.data.c_str(), path.data.c_str()); } + bool file_append(const Path &path, const std::string &data) { + FILE *file = fopen_eintr(path.data.c_str(), "ab"); + if(!file) { + perror(path.data.c_str()); + return false; + } + + if(fwrite_eintr(data.data(), data.size(), file) != data.size()) { + fclose(file); + return false; + } + + return fclose(file) == 0; + } + void for_files_in_dir(const Path &path, FileIteratorCallback callback) { try { for(auto &p : std::filesystem::directory_iterator(path.data)) { diff --git a/src/main.cpp b/src/main.cpp index ef0568b..b09cf14 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,8 +1,10 @@ #include "../include/QuickMedia.hpp" #include <locale.h> +#include <malloc.h> int main(int argc, char **argv) { setlocale(LC_ALL, "C"); // Sigh... stupid C + // mallopt(M_MMAP_THRESHOLD, 65536); QuickMedia::Program program; return program.run(argc, argv); } diff --git a/src/plugins/Matrix.cpp b/src/plugins/Matrix.cpp index 1b43b2d..7080bf9 100644 --- a/src/plugins/Matrix.cpp +++ b/src/plugins/Matrix.cpp @@ -629,12 +629,15 @@ namespace QuickMedia { rooms_page->add_body_item(body_item); } - void MatrixQuickMedia::leave_room(RoomData *room, LeaveType leave_type, const std::string &reason) { + void MatrixQuickMedia::leave_room(RoomData *room, const std::string &event_id, LeaveType leave_type, const std::string &reason) { room_body_item_by_room.erase(room); rooms_page->remove_body_item_by_room_id(room->id); room_tags_page->remove_body_item_by_room_id(room->id); - if(leave_type != LeaveType::LEAVE) + if(leave_type != LeaveType::LEAVE && (event_id.empty() || !matrix->is_other_notification_read(event_id))) { show_notification("QuickMedia", reason); + if(!event_id.empty()) + matrix->mark_other_notification_as_read(event_id); + } } void MatrixQuickMedia::room_add_tag(RoomData *room, const std::string &tag) { @@ -1674,6 +1677,7 @@ namespace QuickMedia { load_silenced_invites(); load_custom_emoji_from_cache(); + load_other_notifications(); sync_thread = std::thread([this, matrix_cache_dir]() { FILE *sync_cache_file; @@ -1858,8 +1862,8 @@ namespace QuickMedia { fwrite(json_data.data(), 1, json_data.size(), sync_cache_file); file_overwrite(get_cache_dir().join("matrix").join(update_cache_file_name), "1"); // To make sure the cache format is up to date - malloc_trim(0); } + malloc_trim(0); fclose(sync_cache_file); } } @@ -2208,6 +2212,18 @@ namespace QuickMedia { parse_custom_emoji(json_root); } + void Matrix::load_other_notifications() { + std::string result; + if(file_get_content(get_storage_dir().join("matrix").join("other_notifications_read"), result) != 0) + return; + + other_notifications_read.clear(); + string_split_view(result, '\n', [this](const char *str, size_t line) { + other_notifications_read.insert(std::string(str, line)); + return true; + }); + } + PluginResult Matrix::parse_sync_account_data(const rapidjson::Value &account_data_json) { if(!account_data_json.IsObject()) return PluginResult::OK; @@ -3884,6 +3900,10 @@ namespace QuickMedia { if(!type_json.IsString() || strcmp(type_json.GetString(), "m.room.member") != 0) continue; + const rapidjson::Value &event_id_json = GetMember(event_json, "event_id"); + if(!event_id_json.IsString()) + continue; + const rapidjson::Value &sender_json = GetMember(event_json, "sender"); if(!sender_json.IsString()) continue; @@ -3924,7 +3944,10 @@ namespace QuickMedia { if(!reason_str.empty()) desc += ", reason: " + reason_str; - ui_thread_tasks.push([this, room, leave_type, desc{std::move(desc)}]{ delegate->leave_room(room, leave_type, desc); }); + std::string event_id_str = event_id_json.GetString(); + ui_thread_tasks.push([this, room, event_id_str{std::move(event_id_str)}, leave_type, desc{std::move(desc)}]{ + delegate->leave_room(room, event_id_str, leave_type, desc); + }); remove_room(room_id_str); break; } @@ -4213,6 +4236,15 @@ namespace QuickMedia { return delegate; } + void Matrix::mark_other_notification_as_read(const std::string &event_id) { + other_notifications_read.insert(event_id); + file_append(get_storage_dir().join("matrix").join("other_notifications_read"), event_id + "\n"); + } + + bool Matrix::is_other_notification_read(const std::string &event_id) const { + return other_notifications_read.find(event_id) != other_notifications_read.end(); + } + PluginResult Matrix::post_message(RoomData *room, const std::string &body, std::string &event_id_response, const std::optional<UploadInfo> &file_info, const std::optional<UploadInfo> &thumbnail_info, const std::string &msgtype, const std::string &custom_transaction_id) { std::string transaction_id = custom_transaction_id; if(transaction_id.empty()) @@ -5629,7 +5661,7 @@ namespace QuickMedia { if(download_result == DownloadResult::OK) { RoomData *room = get_room_by_id(room_id); if(room) { - ui_thread_tasks.push([this, room]{ delegate->leave_room(room, LeaveType::LEAVE, ""); }); + ui_thread_tasks.push([this, room]{ delegate->leave_room(room, "", LeaveType::LEAVE, ""); }); remove_room(room_id); } } diff --git a/uninstall.sh b/uninstall.sh new file mode 100644 index 0000000..a1acbbf --- /dev/null +++ b/uninstall.sh @@ -0,0 +1,10 @@ +#!/bin/sh -e + +script_dir=$(dirname "$0") +cd "$script_dir" + +[ $(id -u) -ne 0 ] && echo "You need root privileges to run the uninstall script" && exit 1 + +ninja -C build uninstall + +echo "Successfully uninstalled quickmedia"
\ No newline at end of file diff --git a/video_player/jsoncpp b/video_player/jsoncpp -Subproject f23fb32fd9d9c3d01fa67afa0d75f7ff227647e +Subproject 98e28b38ffbae24c0e69e620bf18f8a0c5c6f20 |