From 51b086c654f36bca7d644336ec356e37474c0c42 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Sun, 17 May 2026 17:32:05 +0300 Subject: [PATCH] Added socials and update notification to android --- assets/data/icons/RemixIcon/global-line.svg | 1 + .../data/icons/RemixIcon/hand-coin-line.svg | 1 + assets/data/icons/RemixIcon/question-line.svg | 1 + src/GlobalConfig.hpp | 3 +- src/MainProgram.cpp | 51 +++++++ src/MainProgram.hpp | 10 ++ src/Screens/FileSelectScreen.cpp | 135 +++++++++++++++++- src/Screens/FileSelectScreen.hpp | 7 +- src/Screens/PhoneDrawingProgramScreen.cpp | 2 +- src/Toolbar.cpp | 68 +-------- src/Toolbar.hpp | 9 -- 11 files changed, 206 insertions(+), 82 deletions(-) create mode 100644 assets/data/icons/RemixIcon/global-line.svg create mode 100644 assets/data/icons/RemixIcon/hand-coin-line.svg create mode 100644 assets/data/icons/RemixIcon/question-line.svg diff --git a/assets/data/icons/RemixIcon/global-line.svg b/assets/data/icons/RemixIcon/global-line.svg new file mode 100644 index 0000000..c1d81d7 --- /dev/null +++ b/assets/data/icons/RemixIcon/global-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/data/icons/RemixIcon/hand-coin-line.svg b/assets/data/icons/RemixIcon/hand-coin-line.svg new file mode 100644 index 0000000..94a3e4c --- /dev/null +++ b/assets/data/icons/RemixIcon/hand-coin-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/data/icons/RemixIcon/question-line.svg b/assets/data/icons/RemixIcon/question-line.svg new file mode 100644 index 0000000..5409158 --- /dev/null +++ b/assets/data/icons/RemixIcon/question-line.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/GlobalConfig.hpp b/src/GlobalConfig.hpp index b7713de..dd366b0 100644 --- a/src/GlobalConfig.hpp +++ b/src/GlobalConfig.hpp @@ -85,8 +85,7 @@ class GlobalConfig { void load_palettes(); void load_licenses(); - bool showPerformance = false; - bool checkForUpdates = false; + bool checkForUpdates = true; bool useNativeFilePicker = true; std::string themeCurrentlyLoaded = "Default"; diff --git a/src/MainProgram.cpp b/src/MainProgram.cpp index 656936e..d5f40c0 100755 --- a/src/MainProgram.cpp +++ b/src/MainProgram.cpp @@ -52,6 +52,8 @@ #include +#define UPDATE_NOTIFICATION_URL "https://infinipaint.com/updateNotificationVersion.txt" + MainProgram::MainProgram(): input(*this), fonts(std::make_shared()), @@ -108,12 +110,61 @@ void MainProgram::update() { deltaTime.update_time_point(); input.update(); g.update(); + update_notification_check(); screen->update(); background_update(); NetThreadManager::get().synchronous_update(); post_callback(); } +void MainProgram::update_notification_check() { +#ifndef __EMSCRIPTEN__ + if(!updateCheckerData.updateCheckDone) { + if(conf.checkForUpdates) { + if(!updateCheckerData.versionFile) + updateCheckerData.versionFile = FileDownloader::download_data_from_url(UPDATE_NOTIFICATION_URL); + else { + switch(updateCheckerData.versionFile->status) { + case FileDownloader::DownloadData::Status::IN_PROGRESS: + break; + case FileDownloader::DownloadData::Status::SUCCESS: { + updateCheckerData.updateCheckDone = true; + std::optional newVersion = version_str_to_version_numbers(updateCheckerData.versionFile->str); + std::optional currentVersion = VersionConstants::CURRENT_VERSION_NUMBER; + if(newVersion.has_value() && currentVersion.has_value()) { + VersionNumber& newV = newVersion.value(); + VersionNumber& currentV = currentVersion.value(); + updateCheckerData.newVersionStr = version_numbers_to_version_str(newV); + Logger::get().log(Logger::LogType::INFO, "Latest online version is v" + updateCheckerData.newVersionStr); + if(newV > currentV) { + updateCheckerData.showGui = true; + Logger::get().log(Logger::LogType::PHONE_USERINFO, "New version v" + updateCheckerData.newVersionStr + " available"); + g.gui.set_to_layout(); + } + else if(newV == currentV) + Logger::get().log(Logger::LogType::INFO, "Current version is up to date"); + else + Logger::get().log(Logger::LogType::INFO, "Local version has larger version number than the latest online one"); + } + else + Logger::get().log(Logger::LogType::INFO, "Update notification file couldn't be converted to version numbers"); + updateCheckerData.versionFile = nullptr; + break; + } + case FileDownloader::DownloadData::Status::FAILURE: + Logger::get().log(Logger::LogType::INFO, "Failed to check for updates"); + updateCheckerData.updateCheckDone = true; + updateCheckerData.versionFile = nullptr; + break; + } + } + } + else + updateCheckerData.updateCheckDone = true; + } +#endif +} + void MainProgram::background_update() { bool isAnyWorldConnected = false; for(auto& w : worlds) { diff --git a/src/MainProgram.hpp b/src/MainProgram.hpp index 5a447a8..e7d6fe6 100644 --- a/src/MainProgram.hpp +++ b/src/MainProgram.hpp @@ -63,6 +63,7 @@ struct UserLogMessage { class MainProgram { public: static constexpr size_t LOG_SIZE = 30; + static constexpr const char* UPDATE_DOWNLOAD_URL = "https://infinipaint.com/download.html"; InputManager input; @@ -191,6 +192,15 @@ class MainProgram { void switch_to_tab(size_t wIndex); ~MainProgram(); + + void update_notification_check(); + struct UpdateCheckerData { + bool showGui = false; + bool updateCheckDone = false; + std::string newVersionStr; + std::shared_ptr versionFile; + } updateCheckerData; + private: std::unordered_set tabsToClose; void close_set_to_close_tabs(); diff --git a/src/Screens/FileSelectScreen.cpp b/src/Screens/FileSelectScreen.cpp index 277e1e4..1f19a7e 100644 --- a/src/Screens/FileSelectScreen.cpp +++ b/src/Screens/FileSelectScreen.cpp @@ -151,7 +151,7 @@ void FileSelectScreen::global_log() { auto& gui = main.g.gui; auto& io = gui.io; - float notificationSize = std::min(300.0f, gui.io.safeWindowRect.width() - 20.0f); + float notificationSize = std::min(240.0f, gui.io.safeWindowRect.width() - 20.0f); gui.set_z_index(gui.get_z_index() + 100, [&] { gui.new_id("Global log popup list file select screen", [&] { @@ -298,13 +298,33 @@ void FileSelectScreen::main_display() { case SelectedMenu::SETTINGS: settings_view(); break; + case SelectedMenu::ABOUT: + about_view(); + break; } global_log(); } window_gap_side_bar(gui, WindowFillSideBarConfig::Direction::RIGHT); } - window_gap_side_bar(gui, WindowFillSideBarConfig::Direction::BOTTOM); - edit_action_bar(); + switch(selectedMenu) { + case SelectedMenu::FILES: + window_gap_side_bar(gui, WindowFillSideBarConfig::Direction::BOTTOM); + edit_action_bar(); + break; + case SelectedMenu::TRASH: + window_gap_side_bar(gui, WindowFillSideBarConfig::Direction::BOTTOM); + edit_action_bar(); + break; + case SelectedMenu::CONNECT: + window_gap_side_bar(gui, WindowFillSideBarConfig::Direction::BOTTOM); + break; + case SelectedMenu::SETTINGS: + window_gap_side_bar(gui, WindowFillSideBarConfig::Direction::BOTTOM); + break; + case SelectedMenu::ABOUT: + about_bottom_bar(); + break; + } menu_black_box(); } } @@ -441,6 +461,69 @@ void FileSelectScreen::delete_selected_files_in_trash() { } } +void FileSelectScreen::about_bottom_bar() { + auto& gui = main.g.gui; + gui.element("about bottom bar fill", [&](LayoutElement*, const Clay_ElementId& lId) { + CLAY(lId, {}) { + window_fill_side_bar(gui, { + .dir = WindowFillSideBarConfig::Direction::BOTTOM, + .backgroundColor = gui.io.theme->backColor1 + }, [&] { + gui.element("about bottom bar", [&](LayoutElement*, const Clay_ElementId& lId) { + CLAY(lId, { + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(40)}, + .layoutDirection = CLAY_LEFT_TO_RIGHT + } + }) { + gui.element("about scroll area", ScrollArea::Options{ + .scrollHorizontal = true, + .clipHorizontal = true, + .scrollbarX = ScrollArea::ScrollbarType::NORMAL, + .innerContent = [&] (auto&) { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}, + .layoutDirection = CLAY_LEFT_TO_RIGHT + }, + }) { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0)} + } + }) { + text_button(gui, "infinipaintnoticebutton", "InfiniPaint", { + .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, + .isSelected = selectedLicense == -1, + .onClick = [&] { selectedLicense = -1; } + }); + } + for(int i = 0; i < static_cast(main.conf.thirdPartyLicenses.size()); i++) { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIT(0) }, + .padding = CLAY_PADDING_ALL(1) + } + }) { + gui.new_id(i, [&] { + text_button(gui, "noticebutton", main.conf.thirdPartyLicenses[i].first, { + .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, + .isSelected = selectedLicense == i, + .onClick = [&, i] { selectedLicense = i; } + }); + }); + } + } + } + } + }); + } + }); + }); + } + }); +} + void FileSelectScreen::edit_action_bar() { auto& gui = main.g.gui; if(actionBarOpenAnim->get_val()) { @@ -578,6 +661,9 @@ void FileSelectScreen::title_bar() { case SelectedMenu::SETTINGS: mutable_text_label(gui, "main screen header text settings", "Settings"); break; + case SelectedMenu::ABOUT: + mutable_text_label(gui, "main screen header about", "About"); + break; } CLAY_AUTO_ID({ .layout = { @@ -785,6 +871,17 @@ void FileSelectScreen::main_menu() { mainMenuOpenAnim->animation_trigger_reverse(); if(mainViewScrollArea) mainViewScrollArea->reset_scroll(); }); + icon_text_transparent_option_selected_button("About", "data/icons/RemixIcon/question-line.svg", "About", selectedMenu == SelectedMenu::ABOUT, [&] { + selectedMenu = SelectedMenu::ABOUT; + mainMenuOpenAnim->animation_trigger_reverse(); + if(mainViewScrollArea) mainViewScrollArea->reset_scroll(); + }); + icon_text_transparent_option_selected_button("Website", "data/icons/RemixIcon/global-line.svg", "Website", false, [&] { + SDL_OpenURL("https://infinipaint.com/"); + }); + icon_text_transparent_option_selected_button("Donate", "data/icons/RemixIcon/hand-coin-line.svg", "Donate", false, [&] { + SDL_OpenURL("https://infinipaint.com/donate.html"); + }); } } }); @@ -1015,19 +1112,43 @@ void FileSelectScreen::settings_view() { slider_scalar_field(gui, "tablet brush minimum size", "Brush relative minimum size", &main.conf.tabletOptions.brushMinimumSize, 0.0f, 1.0f, {.decimalPrecision = 3}); slider_scalar_field(gui, "tablet brush pressure smoothing factor", "Brush pressure smoothing factor", &main.conf.tabletOptions.brushPressureSmoothingFactor, 0.0f, 1.0f, {.decimalPrecision = 3}); checkbox_boolean_field(gui, "pen pressure width", "Pen pressure affects brush size", &main.conf.tabletOptions.pressureAffectsBrushWidth); -#ifndef __ANDROID__ - checkbox_boolean_field(gui, "use mobile UI", "Use mobile UI (requires restart)", &main.conf.mobileUI); -#endif + #ifndef __ANDROID__ + checkbox_boolean_field(gui, "use mobile UI", "Use mobile UI (requires restart)", &main.conf.mobileUI); + #endif + #ifndef __EMSCRIPTEN__ + checkbox_boolean_field(gui, "update notifications enable", "Check for updates on startup", &main.conf.checkForUpdates); + #endif } } } }); } +void FileSelectScreen::about_view() { + auto& gui = main.g.gui; + auto& io = gui.io; + + mainViewScrollArea = gui.element("about scroll area", ScrollArea::Options{ + .scrollVertical = true, + .clipVertical = true, + .scrollbarY = ScrollArea::ScrollbarType::NORMAL, + .innerContent = [&] (auto&) { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}, + .layoutDirection = CLAY_LEFT_TO_RIGHT + }, + }) { + text_label_size(gui, (selectedLicense == -1) ? main.conf.ownLicenseText : main.conf.thirdPartyLicenses[selectedLicense].second, 0.8f); + } + } + }); +} + void FileSelectScreen::menu_black_box() { auto& gui = main.g.gui; if(!mainMenuOpenAnim->is_at_start()) { - gui.set_z_index(gui.get_z_index() + 1, [&] { + gui.set_z_index(gui.get_z_index() + 2000, [&] { gui.element("file list disable fill", [&] (LayoutElement* l, const Clay_ElementId& lId) { CLAY(lId, { .layout = { diff --git a/src/Screens/FileSelectScreen.hpp b/src/Screens/FileSelectScreen.hpp index 589b5d1..a2f5812 100644 --- a/src/Screens/FileSelectScreen.hpp +++ b/src/Screens/FileSelectScreen.hpp @@ -93,10 +93,12 @@ class FileSelectScreen : public Screen { void file_view(); void connect_view(); void settings_view(); + void about_view(); void create_file_button(); void file_view_edit(); void menu_black_box(); void edit_action_bar(); + void about_bottom_bar(); void edit_title_bar(); void title_bar(); void text_transparent_option_button(const char* id, const char* text, const std::function& onClick); @@ -123,9 +125,12 @@ class FileSelectScreen : public Screen { FILES, TRASH, CONNECT, - SETTINGS + SETTINGS, + ABOUT } selectedMenu = SelectedMenu::FILES; + int selectedLicense = -1; + void start_edit_mode(); size_t numberOfSelectedEntries; bool editMode = false; diff --git a/src/Screens/PhoneDrawingProgramScreen.cpp b/src/Screens/PhoneDrawingProgramScreen.cpp index 12a9b04..7210a18 100644 --- a/src/Screens/PhoneDrawingProgramScreen.cpp +++ b/src/Screens/PhoneDrawingProgramScreen.cpp @@ -366,7 +366,7 @@ void PhoneDrawingProgramScreen::global_log() { auto& gui = main.g.gui; auto& io = gui.io; - float notificationSize = std::min(300.0f, gui.io.safeWindowRect.width() - 20.0f); + float notificationSize = std::min(240.0f, gui.io.safeWindowRect.width() - 20.0f); gui.new_id("Global log popup list phone drawing screen", [&] { CLAY_AUTO_ID({ diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 4a2e1ff..8be3382 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -73,9 +73,6 @@ #include "Screens/DesktopDrawingProgramScreen.hpp" -#define UPDATE_DOWNLOAD_URL "https://infinipaint.com/download.html" -#define UPDATE_NOTIFICATION_URL "https://infinipaint.com/updateNotificationVersion.txt" - #ifdef __EMSCRIPTEN__ #include #endif @@ -199,10 +196,6 @@ void Toolbar::layout_run() { auto& gui = main.g.gui; auto& io = gui.io; -#ifndef __EMSCRIPTEN__ - update_notification_check(); -#endif - if(drawGui) { CLAY_AUTO_ID({ .layout = { @@ -220,10 +213,8 @@ void Toolbar::layout_run() { close_popup_gui(); if(main.conf.viewWebVersionWelcome) web_version_welcome(); -#ifndef __EMSCRIPTEN__ - else if(updateCheckerData.showGui) + else if(main.updateCheckerData.showGui) update_notification_gui(); -#endif else if(filePicker.isOpen) file_picker_gui(); else if(optionsMenuOpen) @@ -671,82 +662,35 @@ void Toolbar::center_message(const char* id, const std::string& m) { }); } -#ifndef __EMSCRIPTEN__ -void Toolbar::update_notification_check() { - if(!updateCheckerData.updateCheckDone) { - if(main.conf.checkForUpdates) { - if(!updateCheckerData.versionFile) - updateCheckerData.versionFile = FileDownloader::download_data_from_url(UPDATE_NOTIFICATION_URL); - else { - switch(updateCheckerData.versionFile->status) { - case FileDownloader::DownloadData::Status::IN_PROGRESS: - break; - case FileDownloader::DownloadData::Status::SUCCESS: { - updateCheckerData.updateCheckDone = true; - std::optional newVersion = version_str_to_version_numbers(updateCheckerData.versionFile->str); - std::optional currentVersion = VersionConstants::CURRENT_VERSION_NUMBER; - if(newVersion.has_value() && currentVersion.has_value()) { - VersionNumber& newV = newVersion.value(); - VersionNumber& currentV = currentVersion.value(); - updateCheckerData.newVersionStr = version_numbers_to_version_str(newV); - Logger::get().log(Logger::LogType::INFO, "Latest online version is v" + updateCheckerData.newVersionStr); - if(newV > currentV) { - updateCheckerData.showGui = true; - main.g.gui.set_to_layout(); - } - else if(newV == currentV) - Logger::get().log(Logger::LogType::INFO, "Current version is up to date"); - else - Logger::get().log(Logger::LogType::INFO, "Local version has larger version number than the latest online one"); - } - else - Logger::get().log(Logger::LogType::INFO, "Update notification file couldn't be converted to version numbers"); - updateCheckerData.versionFile = nullptr; - break; - } - case FileDownloader::DownloadData::Status::FAILURE: - Logger::get().log(Logger::LogType::INFO, "Failed to check for updates"); - updateCheckerData.updateCheckDone = true; - updateCheckerData.versionFile = nullptr; - break; - } - } - } - else - updateCheckerData.updateCheckDone = true; - } -} - void Toolbar::update_notification_gui() { auto& gui = main.g.gui; center_obstructing_window_gui("Update notifications GUI", CLAY_SIZING_FIXED(700), CLAY_SIZING_FIT(0), [&] { gui.new_id("update notification gui", [&] { - text_label_centered(gui, "Update v" + updateCheckerData.newVersionStr + " available!"); + text_label_centered(gui, "Update v" + main.updateCheckerData.newVersionStr + " available!"); text_button(gui, "download", "Open download page in web browser", { .wide = true, .onClick = [&]{ - SDL_OpenURL(UPDATE_DOWNLOAD_URL); - updateCheckerData.showGui = false; + SDL_OpenURL(MainProgram::UPDATE_DOWNLOAD_URL); + main.updateCheckerData.showGui = false; } }); text_button(gui, "ignore forever", "Ignore and don't notify again (can be changed in settings)", { .wide = true, .onClick = [&]{ main.conf.checkForUpdates = false; - updateCheckerData.showGui = false; + main.updateCheckerData.showGui = false; } }); text_button(gui, "ignore for now", "Ignore for now", { .wide = true, .onClick = [&]{ - updateCheckerData.showGui = false; + main.updateCheckerData.showGui = false; } }); }); }); } -#endif void Toolbar::grid_menu(Element* gridMenuButton) { auto& gui = main.g.gui; diff --git a/src/Toolbar.hpp b/src/Toolbar.hpp index bd855fb..9e1de72 100644 --- a/src/Toolbar.hpp +++ b/src/Toolbar.hpp @@ -131,16 +131,7 @@ class Toolbar { bool closeAppWhenDone = false; } closePopupData; - #ifndef __EMSCRIPTEN__ void update_notification_gui(); - void update_notification_check(); - struct UpdateCheckerData { - bool showGui = false; - bool updateCheckDone = false; - std::string newVersionStr; - std::shared_ptr versionFile; - } updateCheckerData; - #endif int selectedLicense = -1;