Added socials and update notification to android

This commit is contained in:
Yousef Khadadeh 2026-05-17 17:32:05 +03:00
parent 50bc7723d6
commit 51b086c654
11 changed files with 206 additions and 82 deletions

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM9.71002 19.6674C8.74743 17.6259 8.15732 15.3742 8.02731 13H4.06189C4.458 16.1765 6.71639 18.7747 9.71002 19.6674ZM10.0307 13C10.1811 15.4388 10.8778 17.7297 12 19.752C13.1222 17.7297 13.8189 15.4388 13.9693 13H10.0307ZM19.9381 13H15.9727C15.8427 15.3742 15.2526 17.6259 14.29 19.6674C17.2836 18.7747 19.542 16.1765 19.9381 13ZM4.06189 11H8.02731C8.15732 8.62577 8.74743 6.37407 9.71002 4.33256C6.71639 5.22533 4.458 7.8235 4.06189 11ZM10.0307 11H13.9693C13.8189 8.56122 13.1222 6.27025 12 4.24799C10.8778 6.27025 10.1811 8.56122 10.0307 11ZM14.29 4.33256C15.2526 6.37407 15.8427 8.62577 15.9727 11H19.9381C19.542 7.8235 17.2836 5.22533 14.29 4.33256Z"></path></svg>

After

Width:  |  Height:  |  Size: 868 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M5.00488 9.00281C5.55717 9.00281 6.00488 9.45052 6.00488 10.0028C7.63965 10.0028 9.14352 10.5632 10.3349 11.5023L12.5049 11.5028C13.8375 11.5028 15.0348 12.0821 15.8588 13.0025L19.0049 13.0028C20.9972 13.0028 22.7173 14.1681 23.521 15.8542C21.1562 18.9748 17.3268 21.0028 13.0049 21.0028C10.2142 21.0028 7.85466 20.3996 5.944 19.3449C5.80557 19.7284 5.43727 20.0028 5.00488 20.0028H2.00488C1.4526 20.0028 1.00488 19.5551 1.00488 19.0028V10.0028C1.00488 9.45052 1.4526 9.00281 2.00488 9.00281H5.00488ZM6.00589 12.0028L6.00488 17.0248L6.05024 17.0573C7.84406 18.3177 10.183 19.0028 13.0049 19.0028C16.0089 19.0028 18.8035 17.8472 20.84 15.8734L20.9729 15.7398L20.8537 15.6394C20.3897 15.2764 19.8205 15.0512 19.2099 15.0097L19.0049 15.0028L16.8934 15.0028C16.9664 15.3244 17.0049 15.6591 17.0049 16.0028V17.0028H8.00488V15.0028L14.7949 15.0018L14.7605 14.9233C14.38 14.1297 13.593 13.5681 12.6693 13.5081L12.5049 13.5028L9.57547 13.5027C8.66823 12.5773 7.40412 12.0031 6.00589 12.0028ZM4.00488 11.0028H3.00488V18.0028H4.00488V11.0028ZM18.0049 5.00281C19.6617 5.00281 21.0049 6.34595 21.0049 8.00281C21.0049 9.65966 19.6617 11.0028 18.0049 11.0028C16.348 11.0028 15.0049 9.65966 15.0049 8.00281C15.0049 6.34595 16.348 5.00281 18.0049 5.00281ZM18.0049 7.00281C17.4526 7.00281 17.0049 7.45052 17.0049 8.00281C17.0049 8.55509 17.4526 9.00281 18.0049 9.00281C18.5572 9.00281 19.0049 8.55509 19.0049 8.00281C19.0049 7.45052 18.5572 7.00281 18.0049 7.00281ZM11.0049 2.00281C12.6617 2.00281 14.0049 3.34595 14.0049 5.00281C14.0049 6.65966 12.6617 8.00281 11.0049 8.00281C9.34803 8.00281 8.00488 6.65966 8.00488 5.00281C8.00488 3.34595 9.34803 2.00281 11.0049 2.00281ZM11.0049 4.00281C10.4526 4.00281 10.0049 4.45052 10.0049 5.00281C10.0049 5.55509 10.4526 6.00281 11.0049 6.00281C11.5572 6.00281 12.0049 5.55509 12.0049 5.00281C12.0049 4.45052 11.5572 4.00281 11.0049 4.00281Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><path d="M12 22C6.47715 22 2 17.5228 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 17.5228 17.5228 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM11 15H13V17H11V15ZM13 13.3551V14H11V12.5C11 11.9477 11.4477 11.5 12 11.5C12.8284 11.5 13.5 10.8284 13.5 10C13.5 9.17157 12.8284 8.5 12 8.5C11.2723 8.5 10.6656 9.01823 10.5288 9.70577L8.56731 9.31346C8.88637 7.70919 10.302 6.5 12 6.5C13.933 6.5 15.5 8.067 15.5 10C15.5 11.5855 14.4457 12.9248 13 13.3551Z"></path></svg>

After

Width:  |  Height:  |  Size: 634 B

View file

@ -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";

View file

@ -52,6 +52,8 @@
#include <Helpers/Logger.hpp>
#define UPDATE_NOTIFICATION_URL "https://infinipaint.com/updateNotificationVersion.txt"
MainProgram::MainProgram():
input(*this),
fonts(std::make_shared<FontData>()),
@ -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<VersionNumber> newVersion = version_str_to_version_numbers(updateCheckerData.versionFile->str);
std::optional<VersionNumber> 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) {

View file

@ -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<FileDownloader::DownloadData> versionFile;
} updateCheckerData;
private:
std::unordered_set<World*> tabsToClose;
void close_set_to_close_tabs();

View file

@ -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<LayoutElement>("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<LayoutElement>("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<ScrollArea>("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<int>(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<ScrollArea>("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<LayoutElement>("file list disable fill", [&] (LayoutElement* l, const Clay_ElementId& lId) {
CLAY(lId, {
.layout = {

View file

@ -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<void()>& 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;

View file

@ -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({

View file

@ -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 <EmscriptenHelpers/emscripten_browser_file.h>
#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<VersionNumber> newVersion = version_str_to_version_numbers(updateCheckerData.versionFile->str);
std::optional<VersionNumber> 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;

View file

@ -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<FileDownloader::DownloadData> versionFile;
} updateCheckerData;
#endif
int selectedLicense = -1;