From 2641e4922be84a5ad65070022f49c6f274005a56 Mon Sep 17 00:00:00 2001 From: StackZ <47382115+SuperSaiyajinStackZ@users.noreply.github.com> Date: Fri, 19 Jun 2020 04:54:05 +0200 Subject: [PATCH] UniStore v2! (#36) * Do not build here. * WIP: UniStoreV2! This implementation is ugly and a big cleanup is needed. * [UniStoreV2]: Add `Lang::get(...)`. * Add back UniStore autobooting. * UniStoreV2: Add List Layout. * Some more UniStore work. Also constify vector's. * Some more spritesheet checks. * oops.. forgot to do `Config::fading`. * Display UniStore version on the Store list bar. * version now needs to be `0` or `1` or not included. versions with 2, 3, 4 and up shows an error now. * You can now also scroll to the next page with D-Pad Left/D-Pad Right! * Last fix before merge? --- assets/gfx/sprites.t3s | 1 + assets/gfx/sprites/noIcon.png | Bin 0 -> 532 bytes azure-pipelines.yml | 2 +- include/screens/credits.hpp | 4 +- include/screens/ftpScreen.hpp | 4 +- include/screens/mainMenu.hpp | 2 +- include/screens/scriptBrowse.hpp | 6 +- include/screens/scriptCreator.hpp | 8 +- include/screens/scriptlist.hpp | 8 +- include/screens/settings.hpp | 6 +- include/screens/unistore.hpp | 35 +- .../screens/{exiting.hpp => unistore_v1.hpp} | 43 +- include/screens/unistore_v2.hpp | 104 +++ include/utils/scriptHelper.hpp | 1 + romfs/lang/en/app.json | 14 +- source/download/download.cpp | 2 +- source/gui/gfx.cpp | 8 +- source/init.cpp | 6 +- source/screens/exiting.cpp | 37 - source/screens/mainMenu.cpp | 9 +- source/screens/unistore.cpp | 835 +++--------------- source/screens/unistore_v1.cpp | 540 +++++++++++ source/screens/unistore_v2.cpp | 721 +++++++++++++++ 23 files changed, 1598 insertions(+), 798 deletions(-) create mode 100644 assets/gfx/sprites/noIcon.png rename include/screens/{exiting.hpp => unistore_v1.hpp} (56%) create mode 100644 include/screens/unistore_v2.hpp delete mode 100644 source/screens/exiting.cpp create mode 100644 source/screens/unistore_v1.cpp create mode 100644 source/screens/unistore_v2.cpp diff --git a/assets/gfx/sprites.t3s b/assets/gfx/sprites.t3s index b1706ab..2dd7c53 100644 --- a/assets/gfx/sprites.t3s +++ b/assets/gfx/sprites.t3s @@ -7,6 +7,7 @@ sprites/button.png sprites/delete.png sprites/download_all.png sprites/dropdown.png +sprites/noIcon.png sprites/top_screen_bot.png sprites/top_screen_top.png sprites/search.png diff --git a/assets/gfx/sprites/noIcon.png b/assets/gfx/sprites/noIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..44c43ddc84fa4f1de71ff9ad3f914a25a3ee97b9 GIT binary patch literal 532 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@H^c5T=q*lv*N}Lwq0A2 z#WN?0vjaZMCw8`%Ed@APAJ#|S`HC>+s&&yJMX&=yO_j3rS_hv z!wms4fr`_#rM#!-6^H2Yo|_(CdWrXe>4ftkIvlPGr7nE&`u#$So4f70%$3-V)&;jV zMXr{1+>xNa+*ySqmT&KIJC~pfoNt%=bSzO2F5)_Qs%x)!O8XLlq~7X#x{0Rh9d|fe z7I}n3UVL>&N_snIY!c5OajP>gXXhlXw{*H~@M6-euV=1**k`q7chGa~i2~Na-iKfB z&Xk{RrM;ph%}BjQ=#cJWMtzfiKhBBHU*f4BP;X!1!69lq_uk3Rk6zt*puWlUgOi`) z-mIQys&z`y%(_eDRgM`t{qyJBC} arrowPos = { + const std::vector arrowPos = { {0, 215, 25, 25}, // Back Arrow. - {295, 215, 25, 25}, // Next Page. + {295, 215, 25, 25} // Next Page. }; }; diff --git a/include/screens/ftpScreen.hpp b/include/screens/ftpScreen.hpp index 7a4f1fe..68ccc89 100644 --- a/include/screens/ftpScreen.hpp +++ b/include/screens/ftpScreen.hpp @@ -36,7 +36,7 @@ public: private: int ftpEnabled = 1; - std::vector arrowPos = { - {0, 215, 25, 25}, // Back Arrow. + const std::vector arrowPos = { + {0, 215, 25, 25} // Back Arrow. }; }; \ No newline at end of file diff --git a/include/screens/mainMenu.hpp b/include/screens/mainMenu.hpp index bd8b6d6..46b38ec 100644 --- a/include/screens/mainMenu.hpp +++ b/include/screens/mainMenu.hpp @@ -39,7 +39,7 @@ public: private: int Selection = 0; - std::vector mainButtons = { + const std::vector mainButtons = { {0, 60, 149, 52}, // UniStore. {162, 60, 149, 52}, // Scripts. {0, 130, 149, 52}, // Settings. diff --git a/include/screens/scriptBrowse.hpp b/include/screens/scriptBrowse.hpp index ce72521..21524b9 100644 --- a/include/screens/scriptBrowse.hpp +++ b/include/screens/scriptBrowse.hpp @@ -64,7 +64,7 @@ private: void downloadAll(); // Button | Icon struct. - std::vector arrowPos = { + const std::vector arrowPos = { {295, 0, 25, 25}, // Arrow Up. {295, 215, 25, 25}, // Arrow Down. {0, 215, 25, 25}, // Back Arrow. @@ -72,12 +72,12 @@ private: }; // DropDownMenu. - std::vector dropPos = { + const std::vector dropPos = { {5, 30, 25, 25}, // Download All. {5, 70, 25, 25}, // Refresh. {5, 110, 25, 25} // ViewMode. }; - std::vector dropPos2 = { + const std::vector dropPos2 = { {0, 28, 140, 30}, // Download All. {0, 68, 140, 30}, // Refresh. {0, 108, 140, 30} // ViewMode. diff --git a/include/screens/scriptCreator.hpp b/include/screens/scriptCreator.hpp index ee228f9..d9995d4 100644 --- a/include/screens/scriptCreator.hpp +++ b/include/screens/scriptCreator.hpp @@ -83,19 +83,19 @@ private: std::string jsonFileName; // Main Pos. - std::vector mainButtons = { + const std::vector mainButtons = { {90, 40, 140, 35}, // New Script. - {90, 100, 140, 35}, // Existing Script. + {90, 100, 140, 35} // Existing Script. }; // Creator Button Pos. - std::vector creatorButtons = { + const std::vector creatorButtons = { {10, 40, 140, 35}, {170, 40, 140, 35}, {10, 100, 140, 35}, {170, 100, 140, 35}, {10, 160, 140, 35}, - {170, 160, 140, 35}, + {170, 160, 140, 35} }; }; diff --git a/include/screens/scriptlist.hpp b/include/screens/scriptlist.hpp index d7e8dd1..eb70d8f 100644 --- a/include/screens/scriptlist.hpp +++ b/include/screens/scriptlist.hpp @@ -88,13 +88,13 @@ private: // Button | Icon structs. - std::vector arrowPos = { + const std::vector arrowPos = { {295, 0, 25, 25}, // Arrow Up. {295, 215, 25, 25}, // Arrow Down. {0, 215, 25, 25}, // Back Arrow. {5, 0, 25, 25} // Dropdown Menu. }; - std::vector subPos = { + const std::vector subPos = { {0, 60, 149, 52}, // Script list. {162, 60, 149, 52}, // Get Scripts. {0, 130, 149, 52}, // Script Creator. @@ -102,11 +102,11 @@ private: }; // DropDownMenu. - std::vector dropPos = { + const std::vector dropPos = { {5, 30, 25, 25}, // Delete. {5, 70, 25, 25} // ViewMode. }; - std::vector dropPos2 = { + const std::vector dropPos2 = { {0, 28, 140, 30}, // Delete. {0, 68, 140, 30} // ViewMode. }; diff --git a/include/screens/settings.hpp b/include/screens/settings.hpp index a6a8dd3..1b93677 100644 --- a/include/screens/settings.hpp +++ b/include/screens/settings.hpp @@ -58,20 +58,20 @@ private: void colorChanging(u32 hDown, u32 hHeld, touchPosition touch); void MiscSettingsLogic(u32 hDown, u32 hHeld, touchPosition touch); - std::vector mainButtons = { + const std::vector mainButtons = { {80, 30, 149, 52}, // Language. {80, 90, 149, 52}, // Colors. {80, 150, 149, 52} // Credits. }; - std::vector mainButtons2 = { + const std::vector mainButtons2 = { {0, 60, 149, 52}, // Change Music File. {162, 60, 149, 52}, // Change bar style. {0, 130, 149, 52}, // Change Key Delay. {162, 130, 149, 52} // Toggle animation. }; - std::vector arrowPos = { + const std::vector arrowPos = { {0, 0, 25, 25}, // Previous Arrow. {295, 0, 25, 25}, // Next Arrow. {0, 215, 25, 25}, // Back Arrow. diff --git a/include/screens/unistore.hpp b/include/screens/unistore.hpp index a2c6305..440dc06 100644 --- a/include/screens/unistore.hpp +++ b/include/screens/unistore.hpp @@ -38,37 +38,34 @@ class UniStore : public Screen { public: void Draw(void) const override; void Logic(u32 hDown, u32 hHeld, touchPosition touch) override; - UniStore(); + UniStore(bool doAutoboot, std::string file); private: + bool doAutoboot = false; + std::string autobootFile = ""; void refreshList(); nlohmann::json openStoreFile(); void loadStoreDesc(void); - void loadStoreSheet(int pos); + StoreInfo parseStoreInfo(std::string fileName); + void autobootLogic(); void DrawSubMenu(void) const; void DrawStoreList(void) const; - void DrawStore(void) const; void DrawSearch(void) const; void DrawFullURLScreen(void) const; void DrawGitHubScreen(void) const; - void DrawGlossary(void) const; void SubMenuLogic(u32 hDown, u32 hHeld, touchPosition touch); void StoreSelectionLogic(u32 hDown, u32 hHeld, touchPosition touch); - void StoreLogic(u32 hDown, u32 hHeld, touchPosition touch); void SearchLogic(u32 hDown, u32 hHeld, touchPosition touch); void FullURLLogic(u32 hDown, u32 hHeld, touchPosition touch); void GitHubLogic(u32 hDown, u32 hHeld, touchPosition touch); - - Result execute(); void descript(); void updateStore(int selectedStore); void deleteStore(int selectedStore); bool handleIfDisplayText(); int mode = 0; - int lastMode = 1; - mutable bool displayInformations = true; + bool displayInformations = true; // Stuff for the GitHub Store Search function and Full URL. std::string OwnerAndRepo = ""; @@ -88,46 +85,46 @@ private: // Other stuff. std::vector storeInfo; // Store Selection. - std::vector appStoreList; // Actual store. ;P std::vector descLines; std::string storeDesc = ""; - nlohmann::json appStoreJson; + nlohmann::json JSON; std::string currentStoreFile; // Icon | Button Structs. - std::vector arrowPos = { + const std::vector arrowPos = { {295, 0, 25, 25}, // Arrow Up. {295, 215, 25, 25}, // Arrow Down. {0, 215, 25, 25}, // Back Arrow. - {5, 0, 25, 25}, // Dropdown Menu. + {5, 0, 25, 25} // Dropdown Menu. }; - std::vector URLBtn = { + const std::vector URLBtn = { {0, 60, 149, 52}, // FULL URL. {162, 60, 149, 52}, // GitHub. {0, 130, 149, 52}, // TinyDB. - {162, 130, 149, 52} // QR Code? + {162, 130, 149, 52} // Universal-DB. }; - std::vector GitHubPos = { + const std::vector GitHubPos = { {30, 50, 260, 30}, // Owner & Repo. {30, 130, 260, 30}, // Filename. {135, 180, 50, 30} // OK. }; - std::vector subPos = { + const std::vector subPos = { {80, 30, 149, 52}, // StoreList. {80, 90, 149, 52}, // storeSearch. {80, 150, 149, 52} // storePathChange. }; // DropDownMenu. - std::vector dropPos = { + const std::vector dropPos = { {5, 30, 25, 25}, // Delete. {5, 70, 25, 25}, // Update. {5, 110, 25, 25} // ViewMode. }; - std::vector dropPos2 = { + + const std::vector dropPos2 = { {0, 28, 140, 30}, // Delete. {0, 68, 140, 30}, // Update. {0, 108, 140, 30} // ViewMode. diff --git a/include/screens/exiting.hpp b/include/screens/unistore_v1.hpp similarity index 56% rename from include/screens/exiting.hpp rename to include/screens/unistore_v1.hpp index b2345d0..0bb5317 100644 --- a/include/screens/exiting.hpp +++ b/include/screens/unistore_v1.hpp @@ -24,15 +24,52 @@ * reasonable ways as different from the original version. */ -#ifndef EXITING_HPP -#define EXITING_HPP +#ifndef UNIVERSAL_STORE_V1_HPP +#define UNIVERSAL_STORE_V1_HPP #include "common.hpp" +#include "json.hpp" +#include "structs.hpp" +#include -class Exiting : public Screen { +#include + +class UniStoreV1 : public Screen { public: void Draw(void) const override; void Logic(u32 hDown, u32 hHeld, touchPosition touch) override; + UniStoreV1(nlohmann::json &JSON, const std::string sheetPath, bool displayInf); + ~UniStoreV1(); +private: + // Selections. + mutable int Selection = 0; + bool sheetHasLoaded = false; + int screenPos = 0; + mutable int screenPosList = 0; + bool dropDownMenu = false; + int dropSelection = 0; + int keyRepeatDelay = 0; + nlohmann::json storeJson; + C2D_SpriteSheet sheet; + std::vector objects; + mutable bool displayInformations = true; + void drawBlend(int key, int x, int y) const; + void parseObjects(); + Result execute(); + + // Icon | Button Structs. + const std::vector arrowPos = { + {295, 0, 25, 25}, // Arrow Up. + {295, 215, 25, 25}, // Arrow Down. + {0, 215, 25, 25}, // Back Arrow. + {5, 0, 25, 25} // Dropdown Menu. + }; + // DropDownMenu. + const std::vector dropPos = { + {5, 30, 140, 30}, // Delete. + {5, 70, 140, 30}, // Update. + {5, 110, 140, 30} // ViewMode. + }; }; #endif \ No newline at end of file diff --git a/include/screens/unistore_v2.hpp b/include/screens/unistore_v2.hpp new file mode 100644 index 0000000..9dc537e --- /dev/null +++ b/include/screens/unistore_v2.hpp @@ -0,0 +1,104 @@ +/* +* This file is part of Universal-Updater +* Copyright (C) 2019-2020 DeadPhoenix8091, Epicpkmn11, Flame, RocketRobz, StackZ, TotallyNotGuy +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#ifndef UNIVERSAL_STORE_V2_HPP +#define UNIVERSAL_STORE_V2_HPP + +#include "common.hpp" +#include "json.hpp" +#include "structs.hpp" +#include + +#include + +class UniStoreV2 : public Screen { +public: + void Draw(void) const override; + void Logic(u32 hDown, u32 hHeld, touchPosition touch) override; + UniStoreV2(nlohmann::json &JSON, const std::string sheetPath); + ~UniStoreV2(); +private: + bool darkMode = true, sheetLoaded = false, canDisplay = false, hasLoaded = false, isDropDown = false; + int selectedBox = 0, lastViewMode = 0, dropSelection = 0, iconAmount = 0, selectedBoxList = 0, selection = -1, storePage = 0, downloadPage = 0, storePageList = 0, mode = 0, subSelection = 0; + nlohmann::json storeJson; + C2D_SpriteSheet sheet; + std::vector objects; + + // Base stuff. + void DrawBaseTop(void) const; + void DrawBaseBottom(void) const; + void drawBox(float xPos, float yPos, float width, float height, bool selected) const; + void DrawGrid(void) const; + void DrawDescription(int selection) const; + u32 returnTextColor() const; + void parseObjects(int selection); + Result runFunctions(std::string entry); + void DrawList(void) const; + void displaySelectedEntry(int selection) const; + void DropLogic(u32 hDown, u32 hHeld, touchPosition touch); + void DropDownMenu(void) const; + + const std::vector StoreBoxesGrid = { + {20, 30, 100, 50}, + {150, 30, 100, 50}, + {280, 30, 100, 50}, + + {20, 95, 100, 50}, + {150, 95, 100, 50}, + {280, 95, 100, 50}, + + {20, 160, 100, 50}, + {150, 160, 100, 50}, + {280, 160, 100, 50} + }; + + const std::vector StoreBoxesList = { + {20, 30, 360, 50}, + {20, 95, 360, 50}, + {20, 160, 360, 50} + }; + + const std::vector downloadBoxes = { + {10, 40, 300, 25}, + {10, 75, 300, 25}, + {10, 110, 300, 25}, + {10, 145, 300, 25}, + {10, 180, 300, 25} + }; + + const std::vector iconPos = { + {5, 0, 25, 25} // Dropdown Menu. + }; + + const std::vector dropPos = { + {5, 30, 140, 25}, // Theme. + {5, 70, 140, 25} // Style. + }; + + u32 barColorLight, barColorDark, bgColorLight, bgColorDark, textColorLight, textColorDark, boxColorLight, boxColorDark, outlineColorLight, outlineColorDark; +}; + +#endif \ No newline at end of file diff --git a/include/utils/scriptHelper.hpp b/include/utils/scriptHelper.hpp index 04639d8..ebeee43 100644 --- a/include/utils/scriptHelper.hpp +++ b/include/utils/scriptHelper.hpp @@ -45,6 +45,7 @@ struct StoreInfo { std::string file; std::string storeSheet; std::string sheetURL; + int version; }; enum ScriptState { diff --git a/romfs/lang/en/app.json b/romfs/lang/en/app.json index be25f79..11985d6 100644 --- a/romfs/lang/en/app.json +++ b/romfs/lang/en/app.json @@ -56,7 +56,7 @@ "CREDITS": "Credits", "DEVELOPED_BY": "Developed by: Universal-Team.", - "MAIN_DEV": "Main Developer: SuperSaiyajinStackie", + "MAIN_DEV": "Main Developer: StackZ", "CURRENT_VERSION": "Current version: ", "MANY_THANKS": "Many Thanks to:", "TRANSLATORS": "All our Translators", @@ -178,7 +178,15 @@ "ENABLED": "Enabled!", "DISABLED": "Disabled!", "DOWNLOAD_SPEED": "Download Speed: ", - "BYTES_PER_SECOND": " bytes per second", + "KB_PER_SECOND": " KB per second", "PROGRESS_BAR_ENABLE": "Would you like to enable the progressbar?", - "PROGRESS_BAR_DISABLE": "Would you like to disable the progressbar?" + "PROGRESS_BAR_DISABLE": "Would you like to disable the progressbar?", + "CATEGORY": "Category: ", + "SYSTEM": "System: ", + "LAST_UPDATED": "Last updated: ", + "CHANGE_THEME": "Change Theme", + "CHANGE_STYLE": "Change Style", + "NO_DOWNLOADS_AVAILABLE": "No downloads available.", + "UNISTORE_VERSION": "UniStore version: ", + "UNISTORE_NOT_SUPPORTED": "This UniStore version is not supported!" } diff --git a/source/download/download.cpp b/source/download/download.cpp index 22795b7..44bebf2 100644 --- a/source/download/download.cpp +++ b/source/download/download.cpp @@ -861,7 +861,7 @@ void displayProgressBar() { formatBytes(downloadNow).c_str(), formatBytes(downloadTotal).c_str(), ((float)downloadNow/(float)downloadTotal) * 100.0f, - Lang::get("DOWNLOAD_SPEED").c_str(), (downloadSpeed), Lang::get("BYTES_PER_SECOND").c_str()); + Lang::get("DOWNLOAD_SPEED").c_str(), (downloadSpeed / 1000), Lang::get("KB_PER_SECOND").c_str()); // Extracting. } else if (progressBarType == 1) { snprintf(str, sizeof(str), "%s / %s (%.2f%%)", diff --git a/source/gui/gfx.cpp b/source/gui/gfx.cpp index fcdfde8..06432dc 100644 --- a/source/gui/gfx.cpp +++ b/source/gui/gfx.cpp @@ -77,13 +77,11 @@ void GFX::DrawBottom(void) { extern C2D_SpriteSheet sprites; -void GFX::DrawSprite(int img, int x, int y, float ScaleX, float ScaleY) -{ +void GFX::DrawSprite(int img, int x, int y, float ScaleX, float ScaleY) { Gui::DrawSprite(sprites, img, x, y, ScaleX, ScaleY); } -void GFX::DrawSpriteBlend(int img, int x, int y, float ScaleX, float ScaleY) -{ +void GFX::DrawSpriteBlend(int img, int x, int y, float ScaleX, float ScaleY) { C2D_ImageTint tint; if (isScriptSelected) { C2D_SetImageTint(&tint, C2D_TopLeft, TextColor, 0.5); @@ -96,6 +94,7 @@ void GFX::DrawSpriteBlend(int img, int x, int y, float ScaleX, float ScaleY) C2D_SetImageTint(&tint, C2D_BotLeft, Config::TxtColor, 0.5); C2D_SetImageTint(&tint, C2D_BotRight, Config::TxtColor, 0.5); } + C2D_DrawImageAt(C2D_SpriteSheetGetImage(sprites, img), x, y, 0.5f, &tint, ScaleX, ScaleY); } @@ -119,6 +118,7 @@ void GFX::DrawArrow(int x, int y, float rotation, int arrowSprite) { } else { C2D_SpriteFromSheet(&sprite, sprites, sprites_side_arrow_idx); } + C2D_SpriteRotateDegrees(&sprite, rotation); C2D_SpriteSetPos(&sprite, x, y); C2D_SpriteSetDepth(&sprite, 0.5); diff --git a/source/init.cpp b/source/init.cpp index 4c77156..2c92ac2 100644 --- a/source/init.cpp +++ b/source/init.cpp @@ -119,7 +119,7 @@ Result Init::Initialize() { if (Config::autoboot == 1) { if (access(Config::AutobootFile.c_str(), F_OK) == 0) { - Gui::setScreen(std::make_unique(), false, true); + Gui::setScreen(std::make_unique(true, Config::AutobootFile), false, true); } else { AutobootWhat = 0; Config::autoboot = 0; @@ -179,8 +179,6 @@ Result Init::MainLoop() { return 0; } -extern void freeSheet(); - Result Init::Exit() { if (songIsFound == true) { stopMusic(); @@ -190,8 +188,6 @@ Result Init::Exit() { ndspExit(); } - // Free UniStore spritesheet, just in case. - freeSheet(); // Only save config, if *any* changes are made. (To reduce SD Writes.) if (changesMade) { Config::save(); diff --git a/source/screens/exiting.cpp b/source/screens/exiting.cpp deleted file mode 100644 index b3868bb..0000000 --- a/source/screens/exiting.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* -* This file is part of Universal-Updater -* Copyright (C) 2019-2020 DeadPhoenix8091, Epicpkmn11, Flame, RocketRobz, StackZ, TotallyNotGuy -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Additional Terms 7.b and 7.c of GPLv3 apply to this file: -* * Requiring preservation of specified reasonable legal notices or -* author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -* * Prohibiting misrepresentation of the origin of that material, -* or requiring that modified versions of such material be marked in -* reasonable ways as different from the original version. -*/ - -#include "common.hpp" -#include "exiting.hpp" - -void Exiting::Draw(void) const { - GFX::DrawTop(); - Gui::Draw_Rect(0, 0, 400, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, 255)); // Fade in/out effect - Gui::ScreenDraw(Bottom); - Gui::Draw_Rect(0, 0, 320, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, 255)); // Fade in/out effect -} - -void Exiting::Logic(u32 hDown, u32 hHeld, touchPosition touch) { } \ No newline at end of file diff --git a/source/screens/mainMenu.cpp b/source/screens/mainMenu.cpp index 695ca0f..c6f61fa 100644 --- a/source/screens/mainMenu.cpp +++ b/source/screens/mainMenu.cpp @@ -25,7 +25,6 @@ */ #include "config.hpp" -#include "exiting.hpp" #include "ftpScreen.hpp" #include "mainMenu.hpp" #include "scriptHelper.hpp" @@ -68,9 +67,9 @@ void MainMenu::Draw(void) const { void MainMenu::Logic(u32 hDown, u32 hHeld, touchPosition touch) { if ((hDown & KEY_START) || (hDown & KEY_TOUCH && touching(touch, mainButtons[4]))) { - exiting = true; - Gui::setScreen(std::make_unique(), Config::fading, true); + fadeout = true; fadecolor = 0; + exiting = true; } // Navigation. @@ -87,7 +86,7 @@ void MainMenu::Logic(u32 hDown, u32 hHeld, touchPosition touch) { if (hDown & KEY_A) { switch(Selection) { case 0: - Gui::setScreen(std::make_unique(), Config::fading, true); + Gui::setScreen(std::make_unique(false, "NOT_USED"), Config::fading, true); break; case 1: Gui::setScreen(std::make_unique(), Config::fading, true); @@ -103,7 +102,7 @@ void MainMenu::Logic(u32 hDown, u32 hHeld, touchPosition touch) { if (hDown & KEY_TOUCH) { if (touching(touch, mainButtons[0])) { - Gui::setScreen(std::make_unique(), Config::fading, true); + Gui::setScreen(std::make_unique(false, "NOT_USED"), Config::fading, true); } else if (touching(touch, mainButtons[1])) { Gui::setScreen(std::make_unique(), Config::fading, true); } else if (touching(touch, mainButtons[2])) { diff --git a/source/screens/unistore.cpp b/source/screens/unistore.cpp index 595c392..74a6ad8 100644 --- a/source/screens/unistore.cpp +++ b/source/screens/unistore.cpp @@ -27,38 +27,76 @@ #include "download.hpp" #include "fileBrowse.hpp" #include "formatting.hpp" -#include "json.hpp" #include "keyboard.hpp" #include "mainMenu.hpp" #include "unistore.hpp" +#include "unistore_v1.hpp" +#include "unistore_v2.hpp" -#include -#include #include +extern void notImplemented(void); extern bool touching(touchPosition touch, Structs::ButtonPos button); -extern u32 getColor(std::string colorString); -extern bool isScriptSelected; - -extern u32 barColor; -extern u32 bgTopColor; -extern u32 bgBottomColor; -extern u32 TextColor; -extern u32 progressBar; -extern u32 selected; -extern u32 unselected; -extern int AutobootWhat; -bool changeBackState = false; extern bool changesMade; -C2D_SpriteSheet appStoreSheet; +bool specialHandling = false; +bool didAutoboot = false; + +UniStore::UniStore(bool doAutoboot, std::string file) { + this->doAutoboot = doAutoboot; + this->autobootFile = file; +} + +// Autoboot stuff. +void UniStore::autobootLogic() { + if (this->doAutoboot) { + if (!didAutoboot) { + specialHandling = true; // Special back handling. + if (ScriptHelper::checkIfValid(this->autobootFile, 1) == true) { + storeInfo.push_back(parseStoreInfo(this->autobootFile)); + + // Update if WiFi found and wanted. + if (checkWifiStatus()) { + if (Msg::promptMsg(Lang::get("WOULD_YOU_LIKE_UPDATE"))) { + if (storeInfo[0].url != "" && storeInfo[0].url != "MISSING: storeInfo.url" && + storeInfo[0].file != "" && storeInfo[0].file != "MISSING: storeInfo.file") { + ScriptHelper::downloadFile(storeInfo[0].url, storeInfo[0].file, Lang::get("UPDATING")); + } + + if (storeInfo[0].sheetURL != "" && storeInfo[0].sheetURL != "MISSING: storeInfo.sheetURL" && + storeInfo[0].storeSheet != "" && storeInfo[0].storeSheet != "MISSING: storeInfo.sheet") { + ScriptHelper::downloadFile(storeInfo[0].sheetURL, storeInfo[0].storeSheet, Lang::get("UPDATING")); + } + } + } + + currentStoreFile = this->autobootFile; + Msg::DisplayMsg(Lang::get("PREPARE_STORE")); + JSON = openStoreFile(); + displayInformations = handleIfDisplayText(); + const std::string sheetURL = storeInfo[0].storeSheet; + if (storeInfo[0].version == 0) { + Gui::setScreen(std::make_unique(JSON, sheetURL, displayInformations), Config::fading, true); + } else if (storeInfo[0].version == 1) { + Gui::setScreen(std::make_unique(JSON, sheetURL), Config::fading, true); + } else { + Msg::DisplayWarnMsg(Lang::get("UNISTORE_NOT_SUPPORTED")); + } + } else { + specialHandling = true; // Special back handling. + // Display Warn or so? + } + } + } +} // Parse informations like URL, Title, Author, Description. -StoreInfo parseStoreInfo(std::string fileName) { +StoreInfo UniStore::parseStoreInfo(std::string fileName) { FILE* file = fopen(fileName.c_str(), "rt"); - if(!file) { + if (!file) { printf("File not found\n"); return {"", ""}; } + nlohmann::json json = nlohmann::json::parse(file, nullptr, false); fclose(file); @@ -70,169 +108,37 @@ StoreInfo parseStoreInfo(std::string fileName) { info.file = ScriptHelper::getString(json, "storeInfo", "file"); info.storeSheet = ScriptHelper::getString(json, "storeInfo", "sheet"); info.sheetURL = ScriptHelper::getString(json, "storeInfo", "sheetURL"); + info.version = ScriptHelper::getNum(json, "storeInfo", "version"); return info; } +// Return a parsed UniStore file. nlohmann::json UniStore::openStoreFile() { FILE* file = fopen(currentStoreFile.c_str(), "rt"); nlohmann::json jsonFile; - if(file) jsonFile = nlohmann::json::parse(file, nullptr, false); + if (file) jsonFile = nlohmann::json::parse(file, nullptr, false); fclose(file); return jsonFile; } -// Parse the Objects. -std::vector parseStoreObjects(std::string storeName) { - FILE* file = fopen(storeName.c_str(), "rt"); - if(!file) { - printf("File not found\n"); - return {{""}}; - } - nlohmann::json json = nlohmann::json::parse(file, nullptr, false); - fclose(file); - - std::vector objs; - for(auto it = json.begin();it != json.end(); it++) { - if(it.key() != "storeInfo") { - objs.push_back(it.key()); - } - } - return objs; -} - -bool sheetHasLoaded = false; -// Sheet / Icon stuff. -void UniStore::loadStoreSheet(int pos) { - if (sheetHasLoaded == false) { - appStoreSheet = C2D_SpriteSheetLoad(storeInfo[pos].storeSheet.c_str()); - sheetHasLoaded = true; - } -} - -void loadStoreAutobootSheet(const std::string &sheet) { - if (sheetHasLoaded == false) { - appStoreSheet = C2D_SpriteSheetLoad(sheet.c_str()); - sheetHasLoaded = true; - } -} - -void freeSheet() { - if (sheetHasLoaded == true) { - C2D_SpriteSheetFree(appStoreSheet); - sheetHasLoaded = false; - } -} - -void drawBlend(int key, int x, int y) { - C2D_ImageTint tint; - C2D_SetImageTint(&tint, C2D_TopLeft, C2D_Color32(0, 0, 0, 180), 0.5); - C2D_SetImageTint(&tint, C2D_TopRight, C2D_Color32(0, 0, 0, 180), 0.5); - C2D_SetImageTint(&tint, C2D_BotLeft, C2D_Color32(0, 0, 0, 180), 0.5); - C2D_SetImageTint(&tint, C2D_BotRight, C2D_Color32(0, 0, 0, 180), 0.5); - C2D_DrawImageAt(C2D_SpriteSheetGetImage(appStoreSheet, key), x, y, 0.5f, &tint); -} - -void drawNormal(int key, int x, int y) { - C2D_DrawImageAt(C2D_SpriteSheetGetImage(appStoreSheet, key), x, y, 0.5f, NULL); -} - +// Do the description, if found. void UniStore::descript() { if (storeInfo[Selection].description != "" || storeInfo[Selection].description != "MISSING: storeInfo.description") { storeDesc = storeInfo[Selection].description; } else storeDesc = ""; } +// Load the store description. void UniStore::loadStoreDesc(void) { descLines.clear(); while(storeDesc.find('\n') != storeDesc.npos) { descLines.push_back(storeDesc.substr(0, storeDesc.find('\n'))); storeDesc = storeDesc.substr(storeDesc.find('\n')+1); } + descLines.push_back(storeDesc.substr(0, storeDesc.find('\n'))); } -// Store colors. -void loadStoreColors(nlohmann::json &json) { - u32 colorTemp; - colorTemp = getColor(ScriptHelper::getString(json, "storeInfo", "barColor")); - barColor = colorTemp == 0 ? Config::Color1 : colorTemp; - - colorTemp = getColor(ScriptHelper::getString(json, "storeInfo", "bgTopColor")); - bgTopColor = colorTemp == 0 ? Config::Color2 : colorTemp; - - colorTemp = getColor(ScriptHelper::getString(json, "storeInfo", "bgBottomColor")); - bgBottomColor = colorTemp == 0 ? Config::Color3 : colorTemp; - - colorTemp = getColor(ScriptHelper::getString(json, "storeInfo", "textColor")); - TextColor = colorTemp == 0 ? Config::TxtColor : colorTemp; - - colorTemp = getColor(ScriptHelper::getString(json, "storeInfo", "selectedColor")); - selected = colorTemp == 0 ? Config::SelectedColor : colorTemp; - - colorTemp = getColor(ScriptHelper::getString(json, "storeInfo", "unselectedColor")); - unselected = colorTemp == 0 ? Config::UnselectedColor : colorTemp; - - colorTemp = getColor(ScriptHelper::getString(json, "storeInfo", "progressbarColor")); - progressBar = colorTemp == 0 ? Config::progressbarColor : colorTemp; -} - -UniStore::UniStore() { - // Autobooting UniStore. ;) - if (AutobootWhat == 1) { - // If store isn't found, go to MainMenu. - if (access(Config::AutobootFile.c_str(), F_OK) != 0) { - AutobootWhat = 0; - changeBackState = true; - Gui::setScreen(std::make_unique(), Config::fading, true); - } - - StoreInfo SI; - // If WiFi enabled & File exist, update store. - if (ScriptHelper::checkIfValid(Config::AutobootFile, 1) == true) { - SI = parseStoreInfo(Config::AutobootFile); - if (checkWifiStatus()) { - if (Msg::promptMsg(Lang::get("WOULD_YOU_LIKE_UPDATE"))) { - if(SI.url != "" && SI.url != "MISSING: storeInfo.url" && SI.file != "" && SI.file != "MISSING: storeInfo.file") { - ScriptHelper::downloadFile(SI.url, SI.file, Lang::get("UPDATING")); - } - if(SI.sheetURL != "" && SI.sheetURL != "MISSING: storeInfo.sheetURL" && SI.storeSheet != "" && SI.storeSheet != "MISSING: storeInfo.sheet") { - ScriptHelper::downloadFile(SI.sheetURL, SI.storeSheet, Lang::get("UPDATING")); - } - } - } - } else { - AutobootWhat = 0; - changeBackState = true; - Gui::setScreen(std::make_unique(), Config::fading, true); - } - - if (ScriptHelper::checkIfValid(Config::AutobootFile, 1) == true) { - currentStoreFile = Config::AutobootFile; - Msg::DisplayMsg(Lang::get("PREPARE_STORE")); - if (SI.storeSheet != "" || SI.storeSheet != "MISSING: storeInfo.sheet") { - if(access(SI.storeSheet.c_str(), F_OK) != -1 ) { - loadStoreAutobootSheet(SI.storeSheet); - } - } - appStoreJson = openStoreFile(); - appStoreList = parseStoreObjects(currentStoreFile); - loadStoreColors(appStoreJson); - Selection = 0; - displayInformations = handleIfDisplayText(); - isScriptSelected = true; - mode = 2; - AutobootWhat = 0; - changeBackState = true; - } else { - AutobootWhat = 0; - changeBackState = true; - Gui::setScreen(std::make_unique(), Config::fading, true); - } - } -} - -extern void notImplemented(void); - void UniStore::DrawSubMenu(void) const { GFX::DrawTop(); if (Config::UseBars == true) { @@ -263,14 +169,18 @@ void UniStore::DrawStoreList(void) const { GFX::DrawTop(); if (Config::UseBars == true) { Gui::DrawStringCentered(0, 0, 0.7f, Config::TxtColor, storeInfo[Selection].title, 400); + Gui::DrawString(5, 220, 0.6f, Config::TxtColor, Lang::get("UNISTORE_VERSION") + std::to_string(storeInfo[Selection].version + 1), 400); Gui::DrawString(397-Gui::GetStringWidth(0.6f, storeAmount), 239-Gui::GetStringHeight(0.6f, storeAmount), 0.6f, Config::TxtColor, storeAmount); } else { Gui::DrawStringCentered(0, 2, 0.7f, Config::TxtColor, storeInfo[Selection].title, 400); + Gui::DrawString(5, 218, 0.6f, Config::TxtColor, Lang::get("UNISTORE_VERSION") + std::to_string(storeInfo[Selection].version + 1), 400); Gui::DrawString(397-Gui::GetStringWidth(0.6f, storeAmount), 237-Gui::GetStringHeight(0.6f, storeAmount), 0.6f, Config::TxtColor, storeAmount); } - for(uint i=0;i 0) Gui::Draw_Rect(0, 0, 400, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); // Fade in/out effect GFX::DrawBottom(); GFX::DrawArrow(295, -1); @@ -283,11 +193,12 @@ void UniStore::DrawStoreList(void) const { Gui::Draw_Rect(0, 40+(i*57), 320, 45, Config::UnselectedColor); line1 = storeInfo[screenPos + i].title; line2 = storeInfo[screenPos + i].author; - if(screenPos + i == Selection) { + if (screenPos + i == Selection) { if (!dropDownMenu) { Gui::drawAnimatedSelector(0, 40+(i*57), 320, 45, .060, TRANSPARENT, Config::SelectedColor); } } + Gui::DrawStringCentered(0, 38+(i*57), 0.7f, Config::TxtColor, line1, 320); Gui::DrawStringCentered(0, 62+(i*57), 0.7f, Config::TxtColor, line2, 320); } @@ -295,11 +206,12 @@ void UniStore::DrawStoreList(void) const { for(int i=0;i 0) Gui::Draw_Rect(0, 0, 320, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); // Fade in/out effect -} -void UniStore::DrawStore(void) const { - std::string entryAmount = std::to_string(Selection+1) + " | " + std::to_string((int)appStoreJson.at("storeContent").size()); - std::string info; - GFX::DrawTop(); - // Top Background. - if (appStoreJson.at("storeInfo").contains("iconIndexTop") && sheetHasLoaded == true) { - drawNormal(appStoreJson["storeInfo"]["iconIndexTop"], 0, 0); - } - - // Icon. - if (appStoreJson.at("storeContent").at(Selection).at("info").contains("iconIndex") && sheetHasLoaded == true) { - if (appStoreJson.at("storeContent").at(Selection).at("info").contains("posX") && appStoreJson.at("storeContent").at(Selection).at("info").contains("posY")) { - drawNormal(appStoreJson["storeContent"][Selection]["info"]["iconIndex"], appStoreJson["storeContent"][Selection]["info"]["posX"], appStoreJson["storeContent"][Selection]["info"]["posY"]); - } else { - drawNormal(appStoreJson["storeContent"][Selection]["info"]["iconIndex"], 175, 155); - } - } - - if (displayInformations != false) { - if (Config::UseBars == true) { - Gui::DrawStringCentered(0, 0, 0.7f, TextColor, std::string(appStoreJson["storeInfo"]["title"]), 400); - Gui::DrawString(397-Gui::GetStringWidth(0.6f, entryAmount), 239-Gui::GetStringHeight(0.6f, entryAmount), 0.6f, TextColor, entryAmount); - } else { - Gui::DrawStringCentered(0, 2, 0.7f, TextColor, std::string(appStoreJson["storeInfo"]["title"]), 400); - Gui::DrawString(397-Gui::GetStringWidth(0.6f, entryAmount), 237-Gui::GetStringHeight(0.6f, entryAmount), 0.6f, TextColor, entryAmount); - } - - Gui::DrawStringCentered(0, 32, 0.6f, TextColor, Lang::get("TITLE") + std::string(appStoreJson["storeContent"][Selection]["info"]["title"]), 400); - Gui::DrawStringCentered(0, 57, 0.6f, TextColor, Lang::get("AUTHOR") + std::string(appStoreJson["storeContent"][Selection]["info"]["author"]), 400); - Gui::DrawStringCentered(0, 82, 0.6f, TextColor, Lang::get("DESC") + std::string(appStoreJson["storeContent"][Selection]["info"]["description"]), 400); - - if (appStoreJson["storeContent"][Selection]["info"]["version"] != "") { - Gui::DrawStringCentered(0, 107, 0.6f, TextColor, Lang::get("VERSION") + std::string(appStoreJson["storeContent"][Selection]["info"]["version"]), 400); - } else { - Gui::DrawStringCentered(0, 107, 0.6f, TextColor, Lang::get("VERSION") + Lang::get("UNKNOWN"), 400); - } - - if (appStoreJson["storeContent"][Selection]["info"]["fileSize"] != 0) { - Gui::DrawStringCentered(0, 132, 0.6f, TextColor, Lang::get("FILE_SIZE") + formatBytes(int64_t(appStoreJson["storeContent"][Selection]["info"]["fileSize"])), 400); - } else { - Gui::DrawStringCentered(0, 132, 0.6f, TextColor, Lang::get("FILE_SIZE") + Lang::get("UNKNOWN"), 400); - } - } - - if (fadealpha > 0) Gui::Draw_Rect(0, 0, 400, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); // Fade in/out effect - GFX::DrawBottom(); - // Bottom Background. - if (appStoreJson.at("storeInfo").contains("iconIndexBottom") && sheetHasLoaded == true) { - drawNormal(appStoreJson["storeInfo"]["iconIndexBottom"], 0, 0); - } - - GFX::DrawArrow(295, -1); - GFX::DrawArrow(315, 240, 180.0); - GFX::DrawArrow(0, 218, 0, 1); - GFX::DrawSpriteBlend(sprites_dropdown_idx, arrowPos[3].x, arrowPos[3].y); - - if (Config::viewMode == 0) { - for(int i=0;i 0) Gui::Draw_Rect(0, 0, 320, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); // Fade in/out effect } @@ -443,29 +247,27 @@ void UniStore::Draw(void) const { } else if (mode == 1) { DrawStoreList(); } else if (mode == 2) { - DrawStore(); - } else if (mode == 3) { DrawSearch(); - } else if (mode == 4) { + } else if (mode == 3) { DrawFullURLScreen(); - } else if (mode == 5) { + } else if (mode == 4) { DrawGitHubScreen(); - } else if (mode == 6) { - DrawGlossary(); } } void UniStore::updateStore(int selectedStore) { if (checkWifiStatus()) { if (Msg::promptMsg(Lang::get("WOULD_YOU_LIKE_UPDATE"))) { - if(storeInfo[selectedStore].url != "" && storeInfo[selectedStore].url != "MISSING: storeInfo.url" && + if (storeInfo[selectedStore].url != "" && storeInfo[selectedStore].url != "MISSING: storeInfo.url" && storeInfo[selectedStore].file != "" && storeInfo[selectedStore].file != "MISSING: storeInfo.file") { ScriptHelper::downloadFile(storeInfo[selectedStore].url, storeInfo[selectedStore].file, Lang::get("UPDATING")); } - if(storeInfo[selectedStore].sheetURL != "" && storeInfo[selectedStore].sheetURL != "MISSING: storeInfo.sheetURL" && + + if (storeInfo[selectedStore].sheetURL != "" && storeInfo[selectedStore].sheetURL != "MISSING: storeInfo.sheetURL" && storeInfo[selectedStore].storeSheet != "" && storeInfo[selectedStore].storeSheet != "MISSING: storeInfo.sheet") { ScriptHelper::downloadFile(storeInfo[selectedStore].sheetURL, storeInfo[selectedStore].storeSheet, Lang::get("UPDATING")); } + // Refresh the list. Msg::DisplayMsg(Lang::get("REFRESHING_LIST")); dirContents.clear(); @@ -478,8 +280,6 @@ void UniStore::updateStore(int selectedStore) { loadStoreDesc(); } } - } else { - notConnectedMsg(); } } @@ -505,8 +305,8 @@ void UniStore::refreshList() { } void UniStore::SubMenuLogic(u32 hDown, u32 hHeld, touchPosition touch) { if ((hDown & KEY_B) || (hDown & KEY_TOUCH && touching(touch, arrowPos[2]))) { - if (changeBackState) { - Gui::setScreen(std::make_unique(), Config::fading, true); + if (specialHandling) { + Gui::setScreen(std::make_unique(), true, true); } else { Gui::screenBack(Config::fading); return; @@ -543,7 +343,7 @@ void UniStore::SubMenuLogic(u32 hDown, u32 hHeld, touchPosition touch) { case 1: if (checkWifiStatus()) { Selection = 0; - mode = 3; + mode = 2; } else { notConnectedMsg(); } @@ -579,7 +379,7 @@ void UniStore::SubMenuLogic(u32 hDown, u32 hHeld, touchPosition touch) { } else if (touching(touch, subPos[1])) { if (checkWifiStatus() == true) { Selection = 0; - mode = 3; + mode = 2; } else { notConnectedMsg(); } @@ -609,6 +409,7 @@ void UniStore::deleteStore(int selectedStore) { descript(); loadStoreDesc(); } + if (dirContents.size() == 0) { dirContents.clear(); storeInfo.clear(); @@ -619,8 +420,8 @@ void UniStore::deleteStore(int selectedStore) { bool UniStore::handleIfDisplayText() { - if (appStoreJson.at("storeInfo").contains("displayInformation")) { - if (appStoreJson["storeInfo"]["displayInformation"] != true) { + if (JSON.at("storeInfo").contains("displayInformation")) { + if (JSON["storeInfo"]["displayInformation"] != true) { return false; } else { return true; @@ -785,19 +586,17 @@ void UniStore::StoreSelectionLogic(u32 hDown, u32 hHeld, touchPosition touch) { updateStore(Selection); currentStoreFile = dirContents[Selection].name; Msg::DisplayMsg(Lang::get("PREPARE_STORE")); - if (storeInfo[Selection].storeSheet != "" || storeInfo[Selection].storeSheet != "MISSING: storeInfo.sheet") { - if(access(storeInfo[Selection].storeSheet.c_str(), F_OK) != -1 ) { - loadStoreSheet(Selection); - } - } - appStoreJson = openStoreFile(); - appStoreList = parseStoreObjects(currentStoreFile); - loadStoreColors(appStoreJson); - Selection = 0; + JSON = openStoreFile(); displayInformations = handleIfDisplayText(); - isScriptSelected = true; - Selection = 0; - mode = 2; + const std::string sheetURL = storeInfo[Selection].storeSheet; + + if (storeInfo[Selection].version == 0) { + Gui::setScreen(std::make_unique(JSON, sheetURL, displayInformations), Config::fading, true); + } else if (storeInfo[Selection].version == 1) { + Gui::setScreen(std::make_unique(JSON, sheetURL), Config::fading, true); + } else { + Msg::DisplayWarnMsg(Lang::get("UNISTORE_NOT_SUPPORTED")); + } } } } @@ -824,40 +623,37 @@ void UniStore::StoreSelectionLogic(u32 hDown, u32 hHeld, touchPosition touch) { updateStore(screenPos + i); currentStoreFile = dirContents[screenPos + i].name; Msg::DisplayMsg(Lang::get("PREPARE_STORE")); - if (storeInfo[screenPos + i].storeSheet != "" || storeInfo[screenPos + i].storeSheet != "MISSING: storeInfo.sheet") { - if(access(storeInfo[screenPos + i].storeSheet.c_str(), F_OK) != -1 ) { - loadStoreSheet(screenPos + i); - } - } - appStoreJson = openStoreFile(); - appStoreList = parseStoreObjects(currentStoreFile); - loadStoreColors(appStoreJson); - Selection = 0; + JSON = openStoreFile(); displayInformations = handleIfDisplayText(); - isScriptSelected = true; - mode = 2; + const std::string sheetURL = storeInfo[screenPos + i].storeSheet; + if (storeInfo[screenPos + i].version == 0) { + Gui::setScreen(std::make_unique(JSON, sheetURL, displayInformations), Config::fading, true); + } else if (storeInfo[screenPos + i].version == 1) { + Gui::setScreen(std::make_unique(JSON, sheetURL), Config::fading, true); + } else { + Msg::DisplayWarnMsg(Lang::get("UNISTORE_NOT_SUPPORTED")); + } } } } } else if (Config::viewMode == 1) { for(int i=0;i (i+1)*27 && touch.py < (i+2)*27) { + if (touch.py > (i+1)*27 && touch.py < (i+2)*27) { if (ScriptHelper::checkIfValid(dirContents[screenPosList + i].name, 1) == true) { updateStore(screenPosList + i); currentStoreFile = dirContents[screenPosList + i].name; Msg::DisplayMsg(Lang::get("PREPARE_STORE")); - if (storeInfo[screenPosList + i].storeSheet != "" || storeInfo[screenPosList + i].storeSheet != "MISSING: storeInfo.sheet") { - if(access(storeInfo[screenPosList + i].storeSheet.c_str(), F_OK) != -1 ) { - loadStoreSheet(screenPosList + i); - } - } - appStoreJson = openStoreFile(); - appStoreList = parseStoreObjects(currentStoreFile); - loadStoreColors(appStoreJson); - Selection = 0; + + JSON = openStoreFile(); displayInformations = handleIfDisplayText(); - isScriptSelected = true; - mode = 2; + const std::string sheetURL = storeInfo[screenPosList + i].storeSheet; + if (storeInfo[screenPosList + i].version == 0) { + Gui::setScreen(std::make_unique(JSON, sheetURL, displayInformations), Config::fading, true); + } else if (storeInfo[screenPosList + i].version == 1) { + Gui::setScreen(std::make_unique(JSON, sheetURL), Config::fading, true); + } else { + Msg::DisplayWarnMsg(Lang::get("UNISTORE_NOT_SUPPORTED")); + } } } } @@ -887,186 +683,20 @@ void UniStore::StoreSelectionLogic(u32 hDown, u32 hHeld, touchPosition touch) { } } -void UniStore::StoreLogic(u32 hDown, u32 hHeld, touchPosition touch) { - if (keyRepeatDelay) keyRepeatDelay--; - - //DropDown Logic. - if (dropDownMenu) { - if ((hDown & KEY_SELECT) || (hDown & KEY_TOUCH && touching(touch, arrowPos[3]))) { - dropDownMenu = false; - } - if (hDown & KEY_DOWN) { - if (dropSelection < 1) dropSelection++; - } - if (hDown & KEY_UP) { - if (dropSelection > 0) dropSelection--; - } - if (hDown & KEY_A) { - if (Config::viewMode == 0) { - Config::viewMode = 1; - } else { - Config::viewMode = 0; - } - dropDownMenu = false; - } - - if (hDown & KEY_TOUCH) { - if (touching(touch, dropPos2[0])) { - if (Config::viewMode == 0) { - Config::viewMode = 1; - } else { - Config::viewMode = 0; - } - dropDownMenu = false; - } - } - } else { - if ((hDown & KEY_SELECT) || (hDown & KEY_TOUCH && touching(touch, arrowPos[3]))) { - dropSelection = 0; - dropDownMenu = true; - } - - if ((hDown & KEY_B) || (hDown & KEY_TOUCH && touching(touch, arrowPos[2]))) { - Selection = 0; - refreshList(); - mode = 1; - appStoreList.clear(); - isScriptSelected = false; - freeSheet(); - } - - // Go one entry up. - if ((hHeld & KEY_UP && !keyRepeatDelay) || (hDown & KEY_TOUCH && touching(touch, arrowPos[0]))) { - if (Selection > 0) { - Selection--; - } else { - Selection = (int)appStoreJson.at("storeContent").size()-1; - } - - keyRepeatDelay = Config::keyDelay; - } - - // Go one entry down. - if ((hHeld & KEY_DOWN && !keyRepeatDelay) || (hDown & KEY_TOUCH && touching(touch, arrowPos[1]))) { - if (Selection < (int)appStoreJson.at("storeContent").size()-1) { - Selection++; - } else { - Selection = 0; - } - - keyRepeatDelay = Config::keyDelay; - } - - if ((hHeld & KEY_RIGHT && !keyRepeatDelay)) { - if (Config::viewMode == 0) { - if (Selection < (int)appStoreJson.at("storeContent").size()-1-3) { - Selection += 3; - } else { - Selection = (int)appStoreJson.at("storeContent").size()-1; - } - } else { - if (Selection < (int)appStoreJson.at("storeContent").size()-1-6) { - Selection += 7; - } else { - Selection = (int)appStoreJson.at("storeContent").size()-1; - } - } - - keyRepeatDelay = Config::keyDelay; - } - - if ((hHeld & KEY_LEFT && !keyRepeatDelay)) { - if (Config::viewMode == 0) { - if (Selection > 2) { - Selection -= 3; - } else { - Selection = 0; - } - } else { - if (Selection > 6) { - Selection -= 7; - } else { - Selection = 0; - } - } - - keyRepeatDelay = Config::keyDelay; - } - - // Execute touched Entry. - if (hDown & KEY_TOUCH) { - if (Config::viewMode == 0) { - for(int i=0;i 40+(i*57) && touch.py < 40+(i*57)+45) { - Selection = screenPos + i; - std::string info = appStoreJson["storeContent"][Selection]["info"]["title"]; - if (Msg::promptMsg(Lang::get("EXECUTE_STORE") + "\n\n" + info)) { - execute(); - } - } - } - } else if (Config::viewMode == 1) { - for(int i=0;i (i+1)*27 && touch.py < (i+2)*27) { - Selection = screenPosList + i; - std::string info = appStoreJson["storeContent"][Selection]["info"]["title"]; - if (Msg::promptMsg(Lang::get("EXECUTE_STORE") + "\n\n" + info)) { - execute(); - } - } - } - } - } - // Execute that Entry. - if (hDown & KEY_A) { - std::string info = appStoreJson["storeContent"][Selection]["info"]["title"]; - if (Msg::promptMsg(Lang::get("EXECUTE_STORE") + "\n\n" + info)) { - execute(); - } - } - - if (Config::viewMode == 0) { - if(Selection < screenPos) { - screenPos = Selection; - } else if (Selection > screenPos + ENTRIES_PER_SCREEN - 1) { - screenPos = Selection - ENTRIES_PER_SCREEN + 1; - } - } else if (Config::viewMode == 1) { - if(Selection < screenPosList) { - screenPosList = Selection; - } else if (Selection > screenPosList + ENTRIES_PER_LIST - 1) { - screenPosList = Selection - ENTRIES_PER_LIST + 1; - } - } - } -} - void UniStore::Logic(u32 hDown, u32 hHeld, touchPosition touch) { + this->autobootLogic(); + if (mode == 0) { SubMenuLogic(hDown, hHeld, touch); } else if (mode == 1) { StoreSelectionLogic(hDown, hHeld, touch); } else if (mode == 2) { - StoreLogic(hDown, hHeld, touch); - } else if (mode == 3) { SearchLogic(hDown, hHeld, touch); - } else if (mode == 4) { + } else if (mode == 3) { FullURLLogic(hDown, hHeld, touch); - } else if (mode == 5) { + } else if (mode == 4) { GitHubLogic(hDown, hHeld, touch); } - - if (hDown & KEY_L || hDown & KEY_R) { - if (mode == 6) { - mode = lastMode; - } else if (mode == 1) { - lastMode = 1; - mode = 6; - } else if (mode == 2) { - lastMode = 2; - mode = 6; - } - } } void UniStore::DrawSearch(void) const { @@ -1084,7 +714,7 @@ void UniStore::DrawSearch(void) const { GFX::DrawButton(URLBtn[0].x, URLBtn[0].y,Lang::get("FULL_URL")); GFX::DrawButton(URLBtn[1].x, URLBtn[1].y, Lang::get("GITHUB")); GFX::DrawButton(URLBtn[2].x, URLBtn[2].y, "TinyDB"); - GFX::DrawButton(URLBtn[3].x, URLBtn[3].y, "QR Code"); + GFX::DrawButton(URLBtn[3].x, URLBtn[3].y, "Universal DB"); // Selector. Animation::Button(URLBtn[Selection].x, URLBtn[Selection].y, .060); } @@ -1097,39 +727,47 @@ void UniStore::SearchLogic(u32 hDown, u32 hHeld, touchPosition touch) { if (hDown & KEY_RIGHT || hDown & KEY_R) { if (Selection == 0) Selection = 1; + else if (Selection == 2) Selection = 3; } if (hDown & KEY_LEFT || hDown & KEY_L) { if (Selection == 1) Selection = 0; + else if (Selection == 3) Selection = 2; } if (hDown & KEY_DOWN) { if (Selection == 0) Selection = 2; + else if (Selection == 1) Selection = 3; } if (hDown & KEY_UP) { if (Selection == 2) Selection = 0; + else if (Selection == 3) Selection = 1; } if (hDown & KEY_A) { if (Selection == 0) { Selection = 0; - mode = 4; + mode = 3; } else if (Selection == 1) { Selection = 0; - mode = 5; + mode = 4; } else if (Selection == 2) { ScriptHelper::downloadFile("https://tinydb.eiphax.tech/api/tinydb.unistore", Config::StorePath + "TinyDB.unistore", Lang::get("DOWNLOADING") + "TinyDB"); + } else if (Selection == 3) { + ScriptHelper::downloadFile("https://github.com/Universal-Team/db/raw/master/unistore/universal-db.unistore", Config::StorePath + "Universal-DB.unistore", Lang::get("DOWNLOADING") + "Universal DB"); } } if (hDown & KEY_TOUCH && touching(touch, URLBtn[0])) { Selection = 0; - mode = 4; + mode = 3; } else if (hDown & KEY_TOUCH && touching(touch, URLBtn[1])) { Selection = 0; - mode = 5; + mode = 4; } else if (hDown & KEY_TOUCH && touching(touch, URLBtn[2])) { ScriptHelper::downloadFile("https://tinydb.eiphax.tech/api/tinydb.unistore", Config::StorePath + "TinyDB.unistore", Lang::get("DOWNLOADING") + "TinyDB"); + } else if (hDown & KEY_TOUCH & touching(touch, URLBtn[3])) { + ScriptHelper::downloadFile("https://github.com/Universal-Team/db/raw/master/unistore/universal-db.unistore", Config::StorePath + "Universal-DB.unistore", Lang::get("DOWNLOADING") + "Universal DB"); } } @@ -1184,7 +822,7 @@ void UniStore::GitHubLogic(u32 hDown, u32 hHeld, touchPosition touch) { OwnerAndRepo = ""; fileName = ""; Selection = 0; - mode = 3; + mode = 2; } } @@ -1235,211 +873,6 @@ void UniStore::FullURLLogic(u32 hDown, u32 hHeld, touchPosition touch) { FullURL = ""; fileName = ""; Selection = 0; - mode = 3; + mode = 2; } -} - - -void UniStore::DrawGlossary(void) const { - GFX::DrawTop(); - if (Config::UseBars == true) { - Gui::DrawStringCentered(0, 0, 0.7f, Config::TxtColor, Lang::get("GLOSSARY"), 400); - } else { - Gui::DrawStringCentered(0, 2, 0.7f, Config::TxtColor, Lang::get("GLOSSARY"), 400); - } - - if (lastMode == 1) { - Gui::DrawString(15, 35, 0.7f, Config::TxtColor, std::to_string(Selection +1) + " | " + std::to_string(storeInfo.size()), 40); - Gui::DrawString(65, 35, 0.7f, Config::TxtColor, Lang::get("ENTRY"), 300); - } else if (lastMode == 2) { - Gui::DrawString(15, 35, 0.7f, Config::TxtColor, std::to_string(Selection+1) + " | " + std::to_string((int)appStoreJson.at("storeContent").size()), 40); - Gui::DrawString(65, 35, 0.7f, Config::TxtColor, Lang::get("ENTRY"), 300); - } - GFX::DrawBottom(); - - GFX::DrawSpriteBlend(sprites_view_idx, 20, 40); - Gui::DrawString(50, 42, 0.6f, Config::TxtColor, Lang::get("CHANGE_VIEW_MODE"), 260); - GFX::DrawArrow(20, 70); - Gui::DrawString(50, 72, 0.6f, Config::TxtColor, Lang::get("ENTRY_UP"), 260); - GFX::DrawArrow(42, 125, 180.0); - Gui::DrawString(50, 102, 0.6f, Config::TxtColor, Lang::get("ENTRY_DOWN"), 260); - GFX::DrawArrow(20, 130, 0, 1); - Gui::DrawString(50, 132, 0.6f, Config::TxtColor, Lang::get("GO_BACK"), 260); - if (lastMode == 1) { - GFX::DrawSpriteBlend(sprites_update_idx, 20, 160); - Gui::DrawString(50, 162, 0.6f, Config::TxtColor, Lang::get("UPDATE_STORE"), 260); - GFX::DrawSpriteBlend(sprites_delete_idx, 20, 190); - Gui::DrawString(50, 192, 0.6f, Config::TxtColor, Lang::get("DELETE_UNISTORE"), 260); - } -} - -// Execute Entry. -Result UniStore::execute() { - Result ret = NONE; // No Error has been occured now. - for(int i=0;i<(int)appStoreJson.at("storeContent").at(Selection).at("script").size();i++) { - if (ret == NONE) { - std::string type = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("type"); - if(type == "deleteFile") { - bool missing = false; - std::string file, message; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("file"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - if(!missing) ret = ScriptHelper::removeFile(file, message); - else ret = SYNTAX_ERROR; - - } else if(type == "downloadFile") { - bool missing = false; - std::string file, output, message; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("file"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("output")) output = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("output"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - if(!missing) ret = ScriptHelper::downloadFile(file, output, message); - else ret = SYNTAX_ERROR; - - } else if(type == "downloadRelease") { - bool missing = false, includePrereleases = false, showVersions = false; - std::string repo, file, output, message; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("repo")) repo = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("repo"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("file"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("output")) output = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("output"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("includePrereleases") && appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("includePrereleases").is_boolean()) - includePrereleases = appStoreJson.at(Selection).at("script").at(i).at("includePrereleases"); - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("showVersions") && appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("showVersions").is_boolean()) - showVersions = appStoreJson.at(Selection).at("script").at(i).at("showVersions"); - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - if(!missing) ret = ScriptHelper::downloadRelease(repo, file, output, includePrereleases, showVersions, message); - else ret = SYNTAX_ERROR; - - } else if(type == "extractFile") { - bool missing = false; - std::string file, input, output, message; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("file"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("input")) input = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("input"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("output")) output = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("output"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - if(!missing) ScriptHelper::extractFile(file, input, output, message); - else ret = SYNTAX_ERROR; - - } else if(type == "installCia") { - bool missing = false, updateSelf = false; - std::string file, message; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("file"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("updateSelf") && appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("updateSelf").is_boolean()) { - updateSelf = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("updateSelf"); - } - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - if(!missing) ScriptHelper::installFile(file, updateSelf, message); - else ret = SYNTAX_ERROR; - - } else if (type == "mkdir") { - bool missing = false; - std::string directory, message; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("directory")) directory = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("directory"); - else missing = true; - if(!missing) makeDirs(directory.c_str()); - else ret = SYNTAX_ERROR; - - } else if (type == "rmdir") { - bool missing = false; - std::string directory, message, promptmsg; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("directory")) directory = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("directory"); - else missing = true; - promptmsg = Lang::get("DELETE_PROMPT") + "\n" + directory; - if(!missing) { - if(access(directory.c_str(), F_OK) != 0 ) { - ret = DELETE_ERROR; - } else { - if (Msg::promptMsg(promptmsg)) { - removeDirRecursive(directory.c_str()); - } - } - } - else ret = SYNTAX_ERROR; - - } else if (type == "mkfile") { - bool missing = false; - std::string file; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("file"); - else missing = true; - if(!missing) ScriptHelper::createFile(file.c_str()); - else ret = SYNTAX_ERROR; - - } else if (type == "timeMsg") { - bool missing = false; - std::string message; - int seconds; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("seconds") && appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("seconds").is_number()) - seconds = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("seconds"); - else missing = true; - if(!missing) ScriptHelper::displayTimeMsg(message, seconds); - else ret = SYNTAX_ERROR; - - } else if (type == "saveConfig") { - Config::save(); - - } else if (type == "notImplemented") { - notImplemented(); - - } else if (type == "bootTitle") { - std::string TitleID = ""; - std::string message = ""; - bool isNAND = false, missing = false; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("TitleID")) TitleID = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("TitleID"); - else missing = true; - if (appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("NAND") && appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("NAND").is_boolean()) isNAND = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("NAND"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - else missing = true; - if(!missing) ScriptHelper::bootTitle(TitleID, isNAND, message); - else ret = SYNTAX_ERROR; - - } else if (type == "promptMessage") { - std::string Message = ""; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - ret = ScriptHelper::prompt(Message); - - } else if (type == "copy") { - std::string Message = "", source = "", destination = ""; - bool missing = false; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("source")) source = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("source"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("destination")) destination = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("destination"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - if (!missing) ret = ScriptHelper::copyFile(source, destination, Message); - else ret = SYNTAX_ERROR; - - } else if (type == "move") { - std::string Message = "", oldFile = "", newFile = ""; - bool missing = false; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("old")) oldFile = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("old"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("new")) newFile = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("new"); - else missing = true; - if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - if (!missing) ret = ScriptHelper::renameFile(oldFile, newFile, Message); - else ret = SYNTAX_ERROR; - } - } - } - if (ret == NONE) doneMsg(); - else if (ret == FAILED_DOWNLOAD) Msg::DisplayWarnMsg(Lang::get("DOWNLOAD_ERROR")); - else if (ret == SCRIPT_CANCELED) Msg::DisplayWarnMsg(Lang::get("SCRIPT_CANCELED")); - else if (ret == SYNTAX_ERROR) Msg::DisplayWarnMsg(Lang::get("SYNTAX_ERROR")); - else if (ret == COPY_ERROR) Msg::DisplayWarnMsg(Lang::get("COPY_ERROR")); - else if (ret == MOVE_ERROR) Msg::DisplayWarnMsg(Lang::get("MOVE_ERROR")); - else if (ret == DELETE_ERROR) Msg::DisplayWarnMsg(Lang::get("DELETE_ERROR")); - return ret; } \ No newline at end of file diff --git a/source/screens/unistore_v1.cpp b/source/screens/unistore_v1.cpp new file mode 100644 index 0000000..b0c8a90 --- /dev/null +++ b/source/screens/unistore_v1.cpp @@ -0,0 +1,540 @@ +/* +* This file is part of Universal-Updater +* Copyright (C) 2019-2020 DeadPhoenix8091, Epicpkmn11, Flame, RocketRobz, StackZ, TotallyNotGuy +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#include "download.hpp" +#include "formatting.hpp" +#include "json.hpp" +#include "scriptHelper.hpp" +#include "unistore_v1.hpp" +#include + +extern bool touching(touchPosition touch, Structs::ButtonPos button); +extern u32 getColor(std::string colorString); +extern bool isScriptSelected; + +extern u32 barColor; +extern u32 bgTopColor; +extern u32 bgBottomColor; +extern u32 TextColor; +extern u32 progressBar; +extern u32 selected; +extern u32 unselected; +extern bool didAutoboot; + +UniStoreV1::UniStoreV1(nlohmann::json &JSON, const std::string sheetPath, bool displayInf) { + this->storeJson = JSON; + this->displayInformations = displayInf; + + if (access(sheetPath.c_str(), F_OK) != 0) { + this->sheetHasLoaded = false; + } else { + Gui::loadSheet(sheetPath.c_str(), this->sheet); + this->sheetHasLoaded = true; + } + + u32 colorTemp; + colorTemp = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "barColor")); + barColor = colorTemp == 0 ? Config::Color1 : colorTemp; + + colorTemp = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "bgTopColor")); + bgTopColor = colorTemp == 0 ? Config::Color2 : colorTemp; + + colorTemp = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "bgBottomColor")); + bgBottomColor = colorTemp == 0 ? Config::Color3 : colorTemp; + + colorTemp = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "textColor")); + TextColor = colorTemp == 0 ? Config::TxtColor : colorTemp; + + colorTemp = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "selectedColor")); + selected = colorTemp == 0 ? Config::SelectedColor : colorTemp; + + colorTemp = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "unselectedColor")); + unselected = colorTemp == 0 ? Config::UnselectedColor : colorTemp; + + colorTemp = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "progressbarColor")); + progressBar = colorTemp == 0 ? Config::progressbarColor : colorTemp; +} + +void UniStoreV1::drawBlend(int key, int x, int y) const { + C2D_ImageTint tint; + C2D_SetImageTint(&tint, C2D_TopLeft, C2D_Color32(0, 0, 0, 180), 0.5); + C2D_SetImageTint(&tint, C2D_TopRight, C2D_Color32(0, 0, 0, 180), 0.5); + C2D_SetImageTint(&tint, C2D_BotLeft, C2D_Color32(0, 0, 0, 180), 0.5); + C2D_SetImageTint(&tint, C2D_BotRight, C2D_Color32(0, 0, 0, 180), 0.5); + C2D_DrawImageAt(C2D_SpriteSheetGetImage(this->sheet, key), x, y, 0.5f, &tint); +} + +void UniStoreV1::parseObjects() { + this->objects.clear(); + for(auto it = this->storeJson.begin();it != this->storeJson.end(); it++) { + if (it.key() != "storeInfo") { + this->objects.push_back(it.key()); + } + } +} + +UniStoreV1::~UniStoreV1() { + // Only unload if sheet has loaded. + if (this->sheetHasLoaded) { + Gui::unloadSheet(this->sheet); + } +} + +void UniStoreV1::Draw(void) const { + std::string entryAmount = std::to_string(this->Selection+1) + " | " + std::to_string((int)this->storeJson.at("storeContent").size()); + std::string info; + GFX::DrawTop(); + // Top Background. + if (this->storeJson.at("storeInfo").contains("iconIndexTop") && sheetHasLoaded == true) { + Gui::DrawSprite(this->sheet, this->storeJson["storeInfo"]["iconIndexTop"], 0, 0); + } + + // Icon. + if (this->storeJson.at("storeContent").at(Selection).at("info").contains("iconIndex") && sheetHasLoaded == true) { + if (this->storeJson.at("storeContent").at(Selection).at("info").contains("posX") && this->storeJson.at("storeContent").at(Selection).at("info").contains("posY")) { + Gui::DrawSprite(this->sheet, this->storeJson["storeContent"][Selection]["info"]["iconIndex"], this->storeJson["storeContent"][Selection]["info"]["posX"], this->storeJson["storeContent"][Selection]["info"]["posY"]); + } else { + Gui::DrawSprite(this->sheet, this->storeJson["storeContent"][Selection]["info"]["iconIndex"], 175, 155); + } + } + + if (displayInformations != false) { + if (Config::UseBars == true) { + Gui::DrawStringCentered(0, 0, 0.7f, TextColor, std::string(this->storeJson["storeInfo"]["title"]), 400); + Gui::DrawString(397-Gui::GetStringWidth(0.6f, entryAmount), 239-Gui::GetStringHeight(0.6f, entryAmount), 0.6f, TextColor, entryAmount); + } else { + Gui::DrawStringCentered(0, 2, 0.7f, TextColor, std::string(this->storeJson["storeInfo"]["title"]), 400); + Gui::DrawString(397-Gui::GetStringWidth(0.6f, entryAmount), 237-Gui::GetStringHeight(0.6f, entryAmount), 0.6f, TextColor, entryAmount); + } + + Gui::DrawStringCentered(0, 32, 0.6f, TextColor, Lang::get("TITLE") + std::string(this->storeJson["storeContent"][Selection]["info"]["title"]), 400); + Gui::DrawStringCentered(0, 57, 0.6f, TextColor, Lang::get("AUTHOR") + std::string(this->storeJson["storeContent"][Selection]["info"]["author"]), 400); + Gui::DrawStringCentered(0, 82, 0.6f, TextColor, Lang::get("DESC") + std::string(this->storeJson["storeContent"][Selection]["info"]["description"]), 400); + + if (this->storeJson["storeContent"][Selection]["info"]["version"] != "") { + Gui::DrawStringCentered(0, 107, 0.6f, TextColor, Lang::get("VERSION") + std::string(this->storeJson["storeContent"][Selection]["info"]["version"]), 400); + } else { + Gui::DrawStringCentered(0, 107, 0.6f, TextColor, Lang::get("VERSION") + Lang::get("UNKNOWN"), 400); + } + + if (this->storeJson["storeContent"][Selection]["info"]["fileSize"] != 0) { + Gui::DrawStringCentered(0, 132, 0.6f, TextColor, Lang::get("FILE_SIZE") + formatBytes(int64_t(this->storeJson["storeContent"][Selection]["info"]["fileSize"])), 400); + } else { + Gui::DrawStringCentered(0, 132, 0.6f, TextColor, Lang::get("FILE_SIZE") + Lang::get("UNKNOWN"), 400); + } + } + + if (fadealpha > 0) Gui::Draw_Rect(0, 0, 400, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); // Fade in/out effect + GFX::DrawBottom(); + + // Bottom Background. + if (this->storeJson.at("storeInfo").contains("iconIndexBottom") && sheetHasLoaded == true) { + Gui::DrawSprite(this->sheet, this->storeJson["storeInfo"]["iconIndexBottom"], 0, 0); + } + + GFX::DrawArrow(295, -1); + GFX::DrawArrow(315, 240, 180.0); + GFX::DrawArrow(0, 218, 0, 1); + GFX::DrawSpriteBlend(sprites_dropdown_idx, arrowPos[3].x, arrowPos[3].y); + + if (Config::viewMode == 0) { + for(int i = 0; i < ENTRIES_PER_SCREEN && i < (int)this->storeJson.at("storeContent").size(); i++) { + info = this->storeJson["storeContent"][screenPos + i]["info"]["title"]; + if (screenPos + i == Selection) { + if (this->storeJson.at("storeInfo").contains("buttonLarge") && sheetHasLoaded == true) { + Gui::DrawSprite(this->sheet, this->storeJson["storeInfo"]["buttonLarge"], 0, 40+(i*57)); + } else { + if (!dropDownMenu) { + Gui::drawAnimatedSelector(0, 40+(i*57), 320, 45, .060, TRANSPARENT, selected); + } + } + } else { + if (this->storeJson.at("storeInfo").contains("buttonLarge") && sheetHasLoaded == true) { + this->drawBlend(this->storeJson["storeInfo"]["buttonLarge"], 0, 40+(i*57)); + } else { + Gui::Draw_Rect(0, 40+(i*57), 320, 45, unselected); + } + } + Gui::DrawStringCentered(0, 50+(i*57), 0.7f, TextColor, info, 320); + } + } else if (Config::viewMode == 1) { + for(int i = 0; i < ENTRIES_PER_LIST && i < (int)this->storeJson.at("storeContent").size(); i++) { + info = this->storeJson["storeContent"][screenPosList + i]["info"]["title"]; + if(screenPosList + i == Selection) { + if (this->storeJson.at("storeInfo").contains("buttonSmall") && sheetHasLoaded == true) { + Gui::DrawSprite(this->sheet, this->storeJson["storeInfo"]["buttonSmall"], 0, (i+1)*27); + } else { + if (!dropDownMenu) { + Gui::drawAnimatedSelector(0, (i+1)*27, 320, 25, .060, TRANSPARENT, selected); + } + } + } else { + if (this->storeJson.at("storeInfo").contains("buttonSmall") && sheetHasLoaded == true) { + this->drawBlend(this->storeJson["storeInfo"]["buttonSmall"], 0, (i+1)*27); + } else { + Gui::Draw_Rect(0, (i+1)*27, 320, 25, unselected); + } + } + Gui::DrawStringCentered(0, ((i+1)*27)+1, 0.7f, TextColor, info, 320); + } + } + + // DropDown Menu. + if (dropDownMenu) { + // Draw Operation Box. + Gui::Draw_Rect(0, 25, 140, 44, barColor); + Gui::drawAnimatedSelector(dropPos[0].x, dropPos[0].y, dropPos[0].w, dropPos[0].h, .090, TRANSPARENT, Config::SelectedColor); + // Draw Dropdown Icons. + GFX::DrawSpriteBlend(sprites_view_idx, dropPos[0].x, dropPos[0].y); + // Dropdown Text. + Gui::DrawString(dropPos[0].x+30, dropPos[0].y+5, 0.4f, Config::TxtColor, Lang::get("VIEW_DDM"), 100); + } + + if (fadealpha > 0) Gui::Draw_Rect(0, 0, 320, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); // Fade in/out effect +} + +void UniStoreV1::Logic(u32 hDown, u32 hHeld, touchPosition touch) { + if (keyRepeatDelay) keyRepeatDelay--; + + //DropDown Logic. + if (dropDownMenu) { + if ((hDown & KEY_SELECT) || (hDown & KEY_TOUCH && touching(touch, arrowPos[3]))) { + dropDownMenu = false; + } + if (hDown & KEY_DOWN) { + if (dropSelection < 1) dropSelection++; + } + if (hDown & KEY_UP) { + if (dropSelection > 0) dropSelection--; + } + if (hDown & KEY_A) { + if (Config::viewMode == 0) { + Config::viewMode = 1; + } else { + Config::viewMode = 0; + } + dropDownMenu = false; + } + + if (hDown & KEY_TOUCH) { + if (touching(touch, dropPos[0])) { + if (Config::viewMode == 0) { + Config::viewMode = 1; + } else { + Config::viewMode = 0; + } + dropDownMenu = false; + } + } + } else { + if ((hDown & KEY_SELECT) || (hDown & KEY_TOUCH && touching(touch, arrowPos[3]))) { + dropSelection = 0; + dropDownMenu = true; + } + + if ((hDown & KEY_B) || (hDown & KEY_TOUCH && touching(touch, arrowPos[2]))) { + if (!didAutoboot) didAutoboot = true; + Gui::screenBack(Config::fading); + return; + } + + // Go one entry up. + if ((hHeld & KEY_UP && !keyRepeatDelay) || (hDown & KEY_TOUCH && touching(touch, arrowPos[0]))) { + if (Selection > 0) { + Selection--; + } else { + Selection = (int)this->storeJson.at("storeContent").size()-1; + } + + keyRepeatDelay = Config::keyDelay; + } + + // Go one entry down. + if ((hHeld & KEY_DOWN && !keyRepeatDelay) || (hDown & KEY_TOUCH && touching(touch, arrowPos[1]))) { + if (Selection < (int)this->storeJson.at("storeContent").size()-1) { + Selection++; + } else { + Selection = 0; + } + + keyRepeatDelay = Config::keyDelay; + } + + if ((hHeld & KEY_RIGHT && !keyRepeatDelay)) { + if (Config::viewMode == 0) { + if (Selection < (int)this->storeJson.at("storeContent").size()-1-3) { + Selection += 3; + } else { + Selection = (int)this->storeJson.at("storeContent").size()-1; + } + } else { + if (Selection < (int)this->storeJson.at("storeContent").size()-1-6) { + Selection += 7; + } else { + Selection = (int)this->storeJson.at("storeContent").size()-1; + } + } + + keyRepeatDelay = Config::keyDelay; + } + + if ((hHeld & KEY_LEFT && !keyRepeatDelay)) { + if (Config::viewMode == 0) { + if (Selection > 2) { + Selection -= 3; + } else { + Selection = 0; + } + } else { + if (Selection > 6) { + Selection -= 7; + } else { + Selection = 0; + } + } + + keyRepeatDelay = Config::keyDelay; + } + + // Execute touched Entry. + if (hDown & KEY_TOUCH) { + if (Config::viewMode == 0) { + for(int i=0;istoreJson.at("storeContent").size();i++) { + if (touch.py > 40+(i*57) && touch.py < 40+(i*57)+45) { + Selection = screenPos + i; + std::string info = this->storeJson["storeContent"][Selection]["info"]["title"]; + if (Msg::promptMsg(Lang::get("EXECUTE_STORE") + "\n\n" + info)) { + execute(); + } + } + } + } else if (Config::viewMode == 1) { + for(int i=0;istoreJson.at("storeContent").size();i++) { + if (touch.py > (i+1)*27 && touch.py < (i+2)*27) { + Selection = screenPosList + i; + std::string info = this->storeJson["storeContent"][Selection]["info"]["title"]; + if (Msg::promptMsg(Lang::get("EXECUTE_STORE") + "\n\n" + info)) { + execute(); + } + } + } + } + } + // Execute that Entry. + if (hDown & KEY_A) { + std::string info = this->storeJson["storeContent"][Selection]["info"]["title"]; + if (Msg::promptMsg(Lang::get("EXECUTE_STORE") + "\n\n" + info)) { + execute(); + } + } + + if (Config::viewMode == 0) { + if(Selection < screenPos) { + screenPos = Selection; + } else if (Selection > screenPos + ENTRIES_PER_SCREEN - 1) { + screenPos = Selection - ENTRIES_PER_SCREEN + 1; + } + } else if (Config::viewMode == 1) { + if(Selection < screenPosList) { + screenPosList = Selection; + } else if (Selection > screenPosList + ENTRIES_PER_LIST - 1) { + screenPosList = Selection - ENTRIES_PER_LIST + 1; + } + } + } +} + + +// Execute Entry. +Result UniStoreV1::execute() { + Result ret = NONE; // No Error has been occured now. + for(int i=0;i<(int)this->storeJson.at("storeContent").at(Selection).at("script").size();i++) { + if (ret == NONE) { + std::string type = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("type"); + if(type == "deleteFile") { + bool missing = false; + std::string file, message; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if(!missing) ret = ScriptHelper::removeFile(file, message); + else ret = SYNTAX_ERROR; + + } else if(type == "downloadFile") { + bool missing = false; + std::string file, output, message; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("output")) output = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("output"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if(!missing) ret = ScriptHelper::downloadFile(file, output, message); + else ret = SYNTAX_ERROR; + + } else if(type == "downloadRelease") { + bool missing = false, includePrereleases = false, showVersions = false; + std::string repo, file, output, message; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("repo")) repo = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("repo"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("output")) output = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("output"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("includePrereleases") && this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("includePrereleases").is_boolean()) + includePrereleases = this->storeJson.at(Selection).at("script").at(i).at("includePrereleases"); + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("showVersions") && this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("showVersions").is_boolean()) + showVersions = this->storeJson.at(Selection).at("script").at(i).at("showVersions"); + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if(!missing) ret = ScriptHelper::downloadRelease(repo, file, output, includePrereleases, showVersions, message); + else ret = SYNTAX_ERROR; + + } else if(type == "extractFile") { + bool missing = false; + std::string file, input, output, message; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("input")) input = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("input"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("output")) output = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("output"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if(!missing) ScriptHelper::extractFile(file, input, output, message); + else ret = SYNTAX_ERROR; + + } else if(type == "installCia") { + bool missing = false, updateSelf = false; + std::string file, message; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("updateSelf") && this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("updateSelf").is_boolean()) { + updateSelf = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("updateSelf"); + } + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if(!missing) ScriptHelper::installFile(file, updateSelf, message); + else ret = SYNTAX_ERROR; + + } else if (type == "mkdir") { + bool missing = false; + std::string directory, message; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("directory")) directory = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("directory"); + else missing = true; + if(!missing) makeDirs(directory.c_str()); + else ret = SYNTAX_ERROR; + + } else if (type == "rmdir") { + bool missing = false; + std::string directory, message, promptmsg; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("directory")) directory = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("directory"); + else missing = true; + promptmsg = Lang::get("DELETE_PROMPT") + "\n" + directory; + if(!missing) { + if(access(directory.c_str(), F_OK) != 0 ) { + ret = DELETE_ERROR; + } else { + if (Msg::promptMsg(promptmsg)) { + removeDirRecursive(directory.c_str()); + } + } + } + else ret = SYNTAX_ERROR; + + } else if (type == "mkfile") { + bool missing = false; + std::string file; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("file"); + else missing = true; + if(!missing) ScriptHelper::createFile(file.c_str()); + else ret = SYNTAX_ERROR; + + } else if (type == "timeMsg") { + bool missing = false; + std::string message; + int seconds; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("seconds") && this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("seconds").is_number()) + seconds = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("seconds"); + else missing = true; + if(!missing) ScriptHelper::displayTimeMsg(message, seconds); + else ret = SYNTAX_ERROR; + + } else if (type == "saveConfig") { + Config::save(); + + } else if (type == "notImplemented") { + notImplemented(); + + } else if (type == "bootTitle") { + std::string TitleID = ""; + std::string message = ""; + bool isNAND = false, missing = false; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("TitleID")) TitleID = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("TitleID"); + else missing = true; + if (this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("NAND") && this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("NAND").is_boolean()) isNAND = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("NAND"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + else missing = true; + if(!missing) ScriptHelper::bootTitle(TitleID, isNAND, message); + else ret = SYNTAX_ERROR; + + } else if (type == "promptMessage") { + std::string Message = ""; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + ret = ScriptHelper::prompt(Message); + + } else if (type == "copy") { + std::string Message = "", source = "", destination = ""; + bool missing = false; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("source")) source = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("source"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("destination")) destination = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("destination"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if (!missing) ret = ScriptHelper::copyFile(source, destination, Message); + else ret = SYNTAX_ERROR; + + } else if (type == "move") { + std::string Message = "", oldFile = "", newFile = ""; + bool missing = false; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("old")) oldFile = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("old"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("new")) newFile = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("new"); + else missing = true; + if(this->storeJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = this->storeJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if (!missing) ret = ScriptHelper::renameFile(oldFile, newFile, Message); + else ret = SYNTAX_ERROR; + } + } + } + if (ret == NONE) doneMsg(); + else if (ret == FAILED_DOWNLOAD) Msg::DisplayWarnMsg(Lang::get("DOWNLOAD_ERROR")); + else if (ret == SCRIPT_CANCELED) Msg::DisplayWarnMsg(Lang::get("SCRIPT_CANCELED")); + else if (ret == SYNTAX_ERROR) Msg::DisplayWarnMsg(Lang::get("SYNTAX_ERROR")); + else if (ret == COPY_ERROR) Msg::DisplayWarnMsg(Lang::get("COPY_ERROR")); + else if (ret == MOVE_ERROR) Msg::DisplayWarnMsg(Lang::get("MOVE_ERROR")); + else if (ret == DELETE_ERROR) Msg::DisplayWarnMsg(Lang::get("DELETE_ERROR")); + return ret; +} \ No newline at end of file diff --git a/source/screens/unistore_v2.cpp b/source/screens/unistore_v2.cpp new file mode 100644 index 0000000..aa3b876 --- /dev/null +++ b/source/screens/unistore_v2.cpp @@ -0,0 +1,721 @@ +/* +* This file is part of Universal-Updater +* Copyright (C) 2019-2020 DeadPhoenix8091, Epicpkmn11, Flame, RocketRobz, StackZ, TotallyNotGuy +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* Additional Terms 7.b and 7.c of GPLv3 apply to this file: +* * Requiring preservation of specified reasonable legal notices or +* author attributions in that material or in the Appropriate Legal +* Notices displayed by works containing it. +* * Prohibiting misrepresentation of the origin of that material, +* or requiring that modified versions of such material be marked in +* reasonable ways as different from the original version. +*/ + +#include "download.hpp" +#include "json.hpp" +#include "scriptHelper.hpp" +#include "unistore_v2.hpp" + +#include + +extern u32 getColor(std::string colorString); +extern bool touching(touchPosition touch, Structs::ButtonPos button); +#define STORE_ENTRIES 9 +#define STORE_ENTRIES_LIST 3 +#define DOWNLOAD_ENTRIES 5 +extern bool didAutoboot; + +UniStoreV2::UniStoreV2(nlohmann::json &JSON, const std::string sheetPath) { + this->storeJson = JSON; + + if (access(sheetPath.c_str(), F_OK) != 0) { + this->iconAmount = 0; + this->sheetLoaded = false; + } else { + if (C2D_SpriteSheetLoad(sheetPath.c_str()) != nullptr) { + this->sheet = C2D_SpriteSheetLoad(sheetPath.c_str()); + this->iconAmount = (int)C2D_SpriteSheetCount(this->sheet); + this->sheetLoaded = true; + } else { + this->iconAmount = 0; + this->sheetLoaded = false; + } + } + + // Get colors. + this->barColorLight = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "barLight")); + this->barColorDark = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "barDark")); + + this->bgColorLight = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "bgLight")); + this->bgColorDark = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "bgDark")); + + this->textColorLight = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "textLight")); + this->textColorDark = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "textDark")); + + this->boxColorLight = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "boxLight")); + this->boxColorDark = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "boxDark")); + + this->outlineColorLight = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "outlineLight")); + this->outlineColorDark = getColor(ScriptHelper::getString(this->storeJson, "storeInfo", "outlineDark")); +} + +UniStoreV2::~UniStoreV2() { + // Only unload if sheet has loaded. + if (this->sheetLoaded) { + C2D_SpriteSheetFree(this->sheet); + } +} + + +u32 UniStoreV2::returnTextColor() const { + return this->darkMode ? this->textColorDark : this->textColorLight; +} + + +// Base draws. +void UniStoreV2::DrawBaseTop(void) const { + Gui::ScreenDraw(Top); + Gui::Draw_Rect(0, 0, 400, 25, this->darkMode ? this->barColorDark : this->barColorLight); + Gui::Draw_Rect(0, 25, 400, 190, this->darkMode ? this->bgColorDark : this->bgColorLight); + Gui::Draw_Rect(0, 215, 400, 25, this->darkMode ? this->barColorDark : this->barColorLight); + if (Config::UseBars == true) { + GFX::DrawSprite(sprites_top_screen_top_idx, 0, 0); + GFX::DrawSprite(sprites_top_screen_bot_idx, 0, 215); + } +} + +void UniStoreV2::DrawBaseBottom(void) const { + Gui::ScreenDraw(Bottom); + Gui::Draw_Rect(0, 0, 320, 25, this->darkMode ? this->barColorDark : this->barColorLight); + Gui::Draw_Rect(0, 25, 320, 190, this->darkMode ? this->bgColorDark : this->bgColorLight); + Gui::Draw_Rect(0, 215, 320, 25, this->darkMode ? this->barColorDark : this->barColorLight); + if (Config::UseBars == true) { + GFX::DrawSprite(sprites_top_screen_top_idx, 0, 0); + GFX::DrawSprite(sprites_top_screen_bot_idx, 0, 215); + } +} + +// Draw a box. +void UniStoreV2::drawBox(float xPos, float yPos, float width, float height, bool selected) const { + static constexpr int w = 1; + const u32 tempColor = this->darkMode ? this->outlineColorDark : this->outlineColorLight; + const u32 outlineColor = selected ? tempColor : C2D_Color32(0, 0, 0, 255); + C2D_DrawRectSolid(xPos, yPos, 0.5, width, height, this->darkMode ? this->boxColorDark : this->boxColorLight); + + // Grid part. + C2D_DrawRectSolid(xPos, yPos, 0.5, width, w, outlineColor); // top + C2D_DrawRectSolid(xPos, yPos + w, 0.5, w, height - 2 * w, outlineColor); // left + C2D_DrawRectSolid(xPos + width - w, yPos + w, 0.5, w, height - 2 * w, outlineColor); // right + C2D_DrawRectSolid(xPos, yPos + height - w, 0.5, width, w, outlineColor); // bottom +} + +void UniStoreV2::DrawGrid(void) const { + for (int i = 0, i2 = 0 + (this->storePage * STORE_ENTRIES); i2 < STORE_ENTRIES + (this->storePage * STORE_ENTRIES) && i2 < (int)this->storeJson.at("storeContent").size(); i2++, i++) { + if (i == this->selectedBox) { + this->drawBox(this->StoreBoxesGrid[i].x, this->StoreBoxesGrid[i].y, 100, 50, true); + } else { + this->drawBox(this->StoreBoxesGrid[i].x, this->StoreBoxesGrid[i].y, 100, 50, false); + } + + if (this->sheetLoaded) { + if (this->storeJson.at("storeContent").at(i + (this->storePage * STORE_ENTRIES)).at("info").contains("icon_index")) { + if ((int)this->storeJson.at("storeContent").at(i + (this->storePage * STORE_ENTRIES)).at("info").at("icon_index") < this->iconAmount) { + Gui::DrawSprite(this->sheet, this->storeJson.at("storeContent").at(i + (this->storePage * STORE_ENTRIES)).at("info").at("icon_index"), this->StoreBoxesGrid[i].x+26, this->StoreBoxesGrid[i].y+1); + } else { + GFX::DrawSprite(sprites_noIcon_idx, this->StoreBoxesGrid[i].x+26, this->StoreBoxesGrid[i].y+1); + } + } else { + GFX::DrawSprite(sprites_noIcon_idx, this->StoreBoxesGrid[i].x+26, this->StoreBoxesGrid[i].y+1); + } + } else { + GFX::DrawSprite(sprites_noIcon_idx, this->StoreBoxesGrid[i].x+26, this->StoreBoxesGrid[i].y+1); + } + } +} + +void UniStoreV2::DrawList(void) const { + for (int i = 0, i2 = 0 + (this->storePageList * STORE_ENTRIES_LIST); i2 < STORE_ENTRIES_LIST + (this->storePageList * STORE_ENTRIES_LIST) && i2 < (int)this->storeJson.at("storeContent").size(); i2++, i++) { + if (i == this->selectedBoxList) { + this->drawBox(this->StoreBoxesList[i].x, this->StoreBoxesList[i].y, 360, 50, true); + } else { + this->drawBox(this->StoreBoxesList[i].x, this->StoreBoxesList[i].y, 360, 50, false); + } + + if (this->sheetLoaded) { + if (this->storeJson.at("storeContent").at(i + (this->storePageList * STORE_ENTRIES_LIST)).at("info").contains("icon_index")) { + if ((int)this->storeJson.at("storeContent").at(i + (this->storePageList * STORE_ENTRIES_LIST)).at("info").at("icon_index") < this->iconAmount) { + Gui::DrawSprite(this->sheet, this->storeJson.at("storeContent").at(i + (this->storePageList * STORE_ENTRIES_LIST)).at("info").at("icon_index"), this->StoreBoxesList[i].x+1, this->StoreBoxesList[i].y+1); + } else { + GFX::DrawSprite(sprites_noIcon_idx, this->StoreBoxesList[i].x+1, this->StoreBoxesList[i].y+1); + } + } else { + GFX::DrawSprite(sprites_noIcon_idx, this->StoreBoxesList[i].x+1, this->StoreBoxesList[i].y+1); + } + } else { + GFX::DrawSprite(sprites_noIcon_idx, this->StoreBoxesList[i].x+1, this->StoreBoxesList[i].y+1); + } + + // Display Author & App name. + if (this->storeJson.at("storeContent").at(i + (this->storePageList * STORE_ENTRIES_LIST)).at("info").contains("title")) { + Gui::DrawString(this->StoreBoxesList[i].x+55, this->StoreBoxesList[i].y+12, 0.45f, this->returnTextColor(), (std::string)this->storeJson.at("storeContent").at(i + (this->storePageList * STORE_ENTRIES_LIST)).at("info").at("title"), 300); + } else { + Gui::DrawString(this->StoreBoxesList[i].x+55, this->StoreBoxesList[i].y+12, 0.45f, this->returnTextColor(), "?", 300); + } + + if (this->storeJson.at("storeContent").at(i + (this->storePageList * STORE_ENTRIES_LIST)).at("info").contains("author")) { + Gui::DrawString(this->StoreBoxesList[i].x+55, this->StoreBoxesList[i].y+28, 0.45f, this->returnTextColor(), (std::string)this->storeJson.at("storeContent").at(i + (this->storePageList * STORE_ENTRIES_LIST)).at("info").at("author"), 300); + } else { + Gui::DrawString(this->StoreBoxesList[i].x+55, this->StoreBoxesList[i].y+28, 0.45f, this->returnTextColor(), "?", 300); + } + } +} + +// Parse the objects from a script. +void UniStoreV2::parseObjects(int selection) { + this->objects.clear(); + for(auto it = this->storeJson.at("storeContent").at(selection).begin(); it != this->storeJson.at("storeContent").at(selection).end(); it++) { + if (it.key() != "info") { + this->objects.push_back(it.key()); + } + } +} + +void UniStoreV2::DropDownMenu(void) const { + if (this->mode != 2) { + // DropDown Menu. + if (this->isDropDown) { + // Draw Operation Box. + for (int i = 0; i < 2; i++) { + Gui::Draw_Rect(dropPos[i].x, dropPos[i].y, dropPos[i].w, dropPos[i].h, this->darkMode ? this->barColorDark : this->barColorLight); + } + + Gui::drawAnimatedSelector(dropPos[dropSelection].x, dropPos[dropSelection].y, dropPos[dropSelection].w, dropPos[dropSelection].h, .090, this->darkMode ? this->barColorDark : this->barColorLight, TRANSPARENT); + + // Draw Dropdown Icons. + //GFX::DrawSpriteBlend(sprites_theme_idx, this->dropPos[0].x, this->dropPos[0].y); // Theme Icon instead. + //GFX::DrawSpriteBlend(sprites_style_idx, this->dropPos[1].x, this->dropPos[1].y); // Style Icon instead. + + // Dropdown Text. + Gui::DrawString(this->dropPos[0].x+30, this->dropPos[0].y+5, 0.4f, this->returnTextColor(), Lang::get("CHANGE_THEME"), 100); + Gui::DrawString(this->dropPos[1].x+30, this->dropPos[1].y+5, 0.4f, this->returnTextColor(), Lang::get("CHANGE_STYLE"), 100); + } + } +} + +void UniStoreV2::displaySelectedEntry(int selection) const { + this->DrawBaseTop(); + + Gui::DrawStringCentered(0, 218, 0.7f, this->returnTextColor(), std::to_string(this->downloadPage + 1) + " | " + std::to_string(1 + (this->objects.size() / DOWNLOAD_ENTRIES))); + + if (this->storeJson.at("storeContent").at(selection).at("info").contains("title")) { + if (Config::UseBars == true) { + Gui::DrawStringCentered(0, 0, 0.7f, this->returnTextColor(), (std::string)this->storeJson.at("storeContent").at(selection).at("info").at("title"), 400); + } else { + Gui::DrawStringCentered(0, 2, 0.7f, this->returnTextColor(), (std::string)this->storeJson.at("storeContent").at(selection).at("info").at("title"), 400); + } + } else { + if (Config::UseBars == true) { + Gui::DrawStringCentered(0, 0, 0.7f, this->returnTextColor(), "?", 400); + } else { + Gui::DrawStringCentered(0, 2, 0.7f, this->returnTextColor(), "?", 400); + } + } + + if (this->storeJson.at("storeContent").at(selection).at("info").contains("author")) { + Gui::DrawStringCentered(0, 40, 0.6f, this->returnTextColor(), Lang::get("AUTHOR") + (std::string)this->storeJson.at("storeContent").at(selection).at("info").at("author"), 400); + } else { + Gui::DrawStringCentered(0, 40, 0.6f, this->returnTextColor(), Lang::get("AUTHOR") + "?", 400); + } + + if (this->storeJson.at("storeContent").at(selection).at("info").contains("version")) { + Gui::DrawStringCentered(0, 60, 0.6f, this->returnTextColor(), Lang::get("VERSION") + (std::string)this->storeJson.at("storeContent").at(selection).at("info").at("version"), 400); + } else { + Gui::DrawStringCentered(0, 60, 0.6f, this->returnTextColor(), Lang::get("VERSION") + "?", 400); + } + + if (this->storeJson.at("storeContent").at(selection).at("info").contains("category")) { + Gui::DrawStringCentered(0, 80, 0.6f, this->returnTextColor(), Lang::get("CATEGORY") + (std::string)this->storeJson.at("storeContent").at(selection).at("info").at("category"), 400); + } else { + Gui::DrawStringCentered(0, 80, 0.6f, this->returnTextColor(), Lang::get("CATEGORY") + "?", 400); + } + + if (this->storeJson.at("storeContent").at(selection).at("info").contains("console")) { + Gui::DrawStringCentered(0, 100, 0.6f, this->returnTextColor(), Lang::get("SYSTEM") + (std::string)this->storeJson.at("storeContent").at(selection).at("info").at("console"), 400); + } else { + Gui::DrawStringCentered(0, 100, 0.6f, this->returnTextColor(), Lang::get("SYSTEM") + "?", 400); + } + + if (this->storeJson.at("storeContent").at(selection).at("info").contains("last_updated")) { + Gui::DrawStringCentered(0, 120, 0.6f, this->returnTextColor(), Lang::get("LAST_UPDATED") + (std::string)this->storeJson.at("storeContent").at(selection).at("info").at("last_updated"), 400); + } else { + Gui::DrawStringCentered(0, 120, 0.6f, this->returnTextColor(), Lang::get("LAST_UPDATED") + "?", 400); + } + + if (this->storeJson.at("storeContent").at(selection).at("info").contains("description")) { + Gui::DrawStringCentered(0, 140, 0.5f, this->returnTextColor(), Lang::get("DESC") + (std::string)this->storeJson.at("storeContent").at(selection).at("info").at("description"), 400); + } else { + Gui::DrawStringCentered(0, 140, 0.5f, this->returnTextColor(), Lang::get("DESC") + "?", 400); + } + + this->DrawBaseBottom(); + + if (this->objects.size() > 0) { + for (int i = 0, i2 = (this->downloadPage * DOWNLOAD_ENTRIES); i2 < DOWNLOAD_ENTRIES + (this->downloadPage * DOWNLOAD_ENTRIES) && i2 < (int)this->objects.size(); i2++, i++) { + if (i + (this->downloadPage * DOWNLOAD_ENTRIES) == this->subSelection) { + this->drawBox(downloadBoxes[i].x, downloadBoxes[i].y, downloadBoxes[i].w, downloadBoxes[i].h, true); + } else { + this->drawBox(downloadBoxes[i].x, downloadBoxes[i].y, downloadBoxes[i].w, downloadBoxes[i].h, false); + } + + Gui::DrawStringCentered(0, downloadBoxes[i].y+4, 0.5f, this->returnTextColor(), this->objects[i + (this->downloadPage * DOWNLOAD_ENTRIES)], 280); + } + } else { + Gui::DrawStringCentered(0, downloadBoxes[0].y+4, 0.5f, this->returnTextColor(), Lang::get("NO_DOWNLOADS_AVAILABLE"), 280); + } +} + + +void UniStoreV2::Draw(void) const { + if (this->mode == 0) { + this->DrawBaseTop(); + + if (Config::UseBars == true) { + Gui::DrawStringCentered(0, 0, 0.6f, this->returnTextColor(), (std::string)this->storeJson.at("storeInfo").at("title"), 400); + } else { + Gui::DrawStringCentered(0, 2, 0.6f, this->returnTextColor(), (std::string)this->storeJson.at("storeInfo").at("title"), 400); + } + + this->DrawGrid(); + + Gui::DrawStringCentered(0, 218, 0.6f, this->returnTextColor(), std::to_string(this->storePage + 1) + " | " + std::to_string(1 + (this->storeJson.at("storeContent").size() / STORE_ENTRIES))); + + if (fadealpha > 0) Gui::Draw_Rect(0, 0, 400, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); + this->DrawBaseBottom(); + + if (fadealpha > 0) Gui::Draw_Rect(0, 0, 320, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); + } else if (this->mode == 1) { + this->DrawBaseTop(); + + if (Config::UseBars == true) { + Gui::DrawStringCentered(0, 0, 0.6f, this->returnTextColor(), (std::string)this->storeJson.at("storeInfo").at("title"), 400); + } else { + Gui::DrawStringCentered(0, 2, 0.6f, this->returnTextColor(), (std::string)this->storeJson.at("storeInfo").at("title"), 400); + } + + this->DrawList(); + Gui::DrawStringCentered(0, 218, 0.6f, this->returnTextColor(), std::to_string(this->storePageList + 1) + " | " + std::to_string(1 + (this->storeJson.at("storeContent").size() / STORE_ENTRIES_LIST))); + + if (fadealpha > 0) Gui::Draw_Rect(0, 0, 400, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); + this->DrawBaseBottom(); + + if (fadealpha > 0) Gui::Draw_Rect(0, 0, 320, 240, C2D_Color32(fadecolor, fadecolor, fadecolor, fadealpha)); + } else if (this->mode == 2) { + this->displaySelectedEntry(this->selection); + } + + if (this->mode != 2) GFX::DrawSpriteBlend(sprites_dropdown_idx, iconPos[0].x, iconPos[0].y); + this->DropDownMenu(); +} + +void UniStoreV2::DropLogic(u32 hDown, u32 hHeld, touchPosition touch) { + if (this->mode != 2) { + if (hDown & KEY_DOWN) { + if (this->dropSelection < (int)this->dropPos.size()-1) this->dropSelection++; + } + + if (hDown & KEY_UP) { + if (this->dropSelection > 0) this->dropSelection--; + } + + if (hDown & KEY_A) { + switch(this->dropSelection) { + case 0: + if (this->darkMode) this->darkMode = false; + else this->darkMode = true; + break; + case 1: + if (this->mode == 0) this->mode = 1; + else this->mode = 0; + break; + } + this->isDropDown = false; + } + + if ((hDown & KEY_SELECT) || (hDown & KEY_TOUCH && touching(touch, this->iconPos[3]))) { + this->isDropDown = false; + } + + if (hDown & KEY_TOUCH) { + if (touching(touch, this->dropPos[0])) { + if (this->darkMode) this->darkMode = false; + else this->darkMode = true; + this->isDropDown = false; + } else if (touching(touch, this->dropPos[1])) { + if (this->mode == 0) this->mode = 1; + else this->mode = 0; + this->isDropDown = false; + } + } + } +} + +void UniStoreV2::Logic(u32 hDown, u32 hHeld, touchPosition touch) { + if (this->isDropDown) { + this->DropLogic(hDown, hHeld, touch); + } else { + if (this->mode == 0) { + if (hDown & KEY_B) { + if (!didAutoboot) didAutoboot = true; + Gui::screenBack(Config::fading); + return; + } + + if (hDown & KEY_RIGHT) { + // Try to go to next page. + if (this->selectedBox == 2 || this->selectedBox == 5 || this->selectedBox == 8) { + if (STORE_ENTRIES + (this->storePage * STORE_ENTRIES) < (int)this->storeJson.at("storeContent").size()) { + this->selectedBox = 0; + this->storePage++; + } + } else { + if ((this->storePage * STORE_ENTRIES) + this->selectedBox + 1 < (int)this->storeJson.at("storeContent").size()) { + if (this->selectedBox < 8 + (this->storePage * STORE_ENTRIES)) this->selectedBox++; + } + } + } + + if (hDown & KEY_LEFT) { + // Try to go to next page. + if (this->selectedBox == 0 || this->selectedBox == 3 || this->selectedBox == 6) { + if (this->storePage > 0) { + this->selectedBox = 0; + this->storePage--; + } + } else { + if (this->selectedBox > 0) this->selectedBox--; + } + } + + if (hDown & KEY_UP) { + if (this->selectedBox > 2 + (this->storePage * STORE_ENTRIES)) this->selectedBox -= 3; + } + + if (hDown & KEY_DOWN) { + if ((this->storePage * STORE_ENTRIES) + this->selectedBox + 3 < (int)this->storeJson.at("storeContent").size()) { + if (this->selectedBox < 6) this->selectedBox += 3; + } + } + + if (hDown & KEY_R) { + if (STORE_ENTRIES + (this->storePage * STORE_ENTRIES) < (int)this->storeJson.at("storeContent").size()) { + this->selectedBox = 0; + this->storePage++; + } + } + + if (hDown & KEY_L) { + if (this->storePage > 0) { + this->selectedBox = 0; + this->storePage--; + } + } + + + if (hDown & KEY_A) { + if (this->selectedBox + (this->storePage * STORE_ENTRIES) < (int)this->storeJson.at("storeContent").size()) { + this->selection = this->selectedBox + (this->storePage * STORE_ENTRIES); + this->parseObjects(this->selection); + this->canDisplay = true; + this->lastViewMode = this->mode; + this->mode = 2; + } + } + + } else if (this->mode == 1) { + if (hDown & KEY_B) { + if (!didAutoboot) didAutoboot = true; + Gui::screenBack(Config::fading); + return; + } + + if (hDown & KEY_DOWN) { + if ((this->storePageList * STORE_ENTRIES_LIST) + this->selectedBoxList + 1 < (int)this->storeJson.at("storeContent").size()) { + if (this->selectedBoxList < STORE_ENTRIES_LIST-1) this->selectedBoxList++; + } + } + + if (hDown & KEY_UP) { + if (this->selectedBoxList > 0) this->selectedBoxList--; + } + + if (hDown & KEY_RIGHT || hDown & KEY_R) { + if (STORE_ENTRIES_LIST + (this->storePageList * STORE_ENTRIES_LIST) < (int)this->storeJson.at("storeContent").size()) { + this->selectedBoxList = 0; + this->storePageList++; + } + } + + if (hDown & KEY_LEFT || hDown & KEY_L) { + if (this->storePageList > 0) { + this->selectedBoxList = 0; + this->storePageList--; + } + } + + if (hDown & KEY_A) { + if (this->selectedBoxList + (this->storePageList * STORE_ENTRIES_LIST) < (int)this->storeJson.at("storeContent").size()) { + this->selection = this->selectedBoxList + (this->storePageList * STORE_ENTRIES_LIST); + this->parseObjects(this->selection); + this->canDisplay = true; + this->lastViewMode = this->mode; + this->mode = 2; + } + } + + } else if (this->mode == 2) { + if (hDown & KEY_TOUCH) { + if (this->objects.size() > 0) { + for (int i = 0, i2 = 0 + (this->downloadPage * DOWNLOAD_ENTRIES); i2 < DOWNLOAD_ENTRIES + (this->downloadPage * DOWNLOAD_ENTRIES) && i2 < (int)this->objects.size(); i2++, i++) { + if (touching(touch, downloadBoxes[i])) { + if (Msg::promptMsg(Lang::get("EXECUTE_SCRIPT") + "\n" + this->objects[i + (this->downloadPage * DOWNLOAD_ENTRIES)])) runFunctions(this->objects[i + (this->downloadPage * DOWNLOAD_ENTRIES)]); + } + } + } + } + + if (hDown & KEY_A) { + if (this->objects.size() > 0) { + if ((int)this->objects.size() >= this->subSelection) { + if (Msg::promptMsg(Lang::get("EXECUTE_SCRIPT") + "\n" + this->objects[this->subSelection])) runFunctions(this->objects[this->subSelection]); + } + } + } + + if (hDown & KEY_DOWN) { + if (this->subSelection < (int)this->objects.size()-1) { + if (this->subSelection < DOWNLOAD_ENTRIES + (this->downloadPage * DOWNLOAD_ENTRIES)-1) { + this->subSelection++; + } + } + } + + if (hDown & KEY_UP) { + if (this->subSelection > 0) { + if (this->subSelection > this->downloadPage * DOWNLOAD_ENTRIES) { + this->subSelection--; + } + } + } + + + if (hDown & KEY_R || hDown & KEY_RIGHT) { + if (DOWNLOAD_ENTRIES + (this->downloadPage * DOWNLOAD_ENTRIES) < (int)this->objects.size()) { + this->downloadPage++; + this->subSelection = this->downloadPage * DOWNLOAD_ENTRIES; + } + } + + if (hDown & KEY_L || hDown & KEY_LEFT) { + if (this->downloadPage > 0) { + this->downloadPage--; + this->subSelection = this->downloadPage * DOWNLOAD_ENTRIES; + } + } + + if (hDown & KEY_B) { + this->downloadPage = 0; // Reset page to 0. + this->subSelection = 0; + this->mode = this->lastViewMode; + } + } + + if ((hDown & KEY_SELECT) || (hDown & KEY_TOUCH && touching(touch, iconPos[0]))) { + if (this->mode != 2) { + this->dropSelection = 0; + this->isDropDown = true; + } + } + } +} + + +// Execute | run the script. +Result UniStoreV2::runFunctions(std::string entry) { + Result ret = NONE; // No Error as of yet. + for(int i=0;i<(int)this->storeJson.at("storeContent").at(this->selection).at(entry).size();i++) { + if (ret == NONE) { + std::string type = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("type"); + + if (type == "deleteFile") { + bool missing = false; + std::string file, message; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("file")) file = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + if(!missing) ret = ScriptHelper::removeFile(file, message); + else ret = SYNTAX_ERROR; + + } else if(type == "downloadFile") { + bool missing = false; + std::string file, output, message; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("file")) file = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("output")) output = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("output"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + if(!missing) ret = ScriptHelper::downloadFile(file, output, message); + else ret = SYNTAX_ERROR; + + } else if(type == "downloadRelease") { + bool missing = false, includePrereleases = false, showVersions = false; + std::string repo, file, output, message; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("repo")) repo = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("repo"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("file")) file = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("output")) output = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("output"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("includePrereleases") && this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("includePrereleases").is_boolean()) + includePrereleases = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("includePrereleases"); + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("showVersions") && this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("showVersions").is_boolean()) + showVersions = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("showVersions"); + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + if(!missing) ret = ScriptHelper::downloadRelease(repo, file, output, includePrereleases, showVersions, message); + + } else if(type == "extractFile") { + bool missing = false; + std::string file, input, output, message; + if(this->storeJson.at("storeContent").at("storeContent").at(this->selection).at(entry).at(i).contains("file")) file = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("input")) input = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("input"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("output")) output = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("output"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + if(!missing) ScriptHelper::extractFile(file, input, output, message); + else ret = SYNTAX_ERROR; + + } else if(type == "installCia") { + bool missing = false, updateSelf = false; + std::string file, message; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("file")) file = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("file"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("updateSelf") && this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("updateSelf").is_boolean()) { + updateSelf = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("updateSelf"); + } + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + if(!missing) ScriptHelper::installFile(file, updateSelf, message); + else ret = SYNTAX_ERROR; + + } else if (type == "mkdir") { + bool missing = false; + std::string directory, message; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("directory")) directory = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("directory"); + else missing = true; + if(!missing) makeDirs(directory.c_str()); + else ret = SYNTAX_ERROR; + + } else if (type == "rmdir") { + bool missing = false; + std::string directory, message, promptmsg; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("directory")) directory = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("directory"); + else missing = true; + promptmsg = Lang::get("DELETE_PROMPT") + "\n" + directory; + if(!missing) { + if(access(directory.c_str(), F_OK) != 0 ) { + ret = DELETE_ERROR; + } else { + if (Msg::promptMsg(promptmsg)) { + removeDirRecursive(directory.c_str()); + } + } + } + else ret = SYNTAX_ERROR; + + } else if (type == "mkfile") { + bool missing = false; + std::string file; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("file")) file = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("file"); + else missing = true; + if(!missing) ScriptHelper::createFile(file.c_str()); + else ret = SYNTAX_ERROR; + + } else if (type == "timeMsg") { + bool missing = false; + std::string message; + int seconds; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("seconds") && this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("seconds").is_number()) + seconds = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("seconds"); + else missing = true; + if(!missing) ScriptHelper::displayTimeMsg(message, seconds); + else ret = SYNTAX_ERROR; + + } else if (type == "saveConfig") { + Config::save(); + + } else if (type == "bootTitle") { + std::string TitleID = ""; + std::string message = ""; + bool isNAND = false, missing = false; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("TitleID")) TitleID = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("TitleID"); + else missing = true; + if (this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("NAND") && this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("NAND").is_boolean()) isNAND = this->storeJson.at(this->selection).at(entry).at(i).at("NAND"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + else missing = true; + if(!missing) ScriptHelper::bootTitle(TitleID, isNAND, message); + else ret = SYNTAX_ERROR; + + } else if (type == "promptMessage") { + std::string Message = ""; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) Message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + ret = ScriptHelper::prompt(Message); + + } else if (type == "copy") { + std::string Message = "", source = "", destination = ""; + bool missing = false; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("source")) source = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("source"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("destination")) destination = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("destination"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) Message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + if (!missing) ret = ScriptHelper::copyFile(source, destination, Message); + else ret = SYNTAX_ERROR; + + } else if (type == "move") { + std::string Message = "", oldFile = "", newFile = ""; + bool missing = false; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("old")) oldFile = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("old"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("new")) newFile = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("new"); + else missing = true; + if(this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).contains("message")) Message = this->storeJson.at("storeContent").at(this->selection).at(entry).at(i).at("message"); + if (!missing) ret = ScriptHelper::renameFile(oldFile, newFile, Message); + else ret = SYNTAX_ERROR; + } + } + } + if (ret == NONE) doneMsg(); + else if (ret == FAILED_DOWNLOAD) Msg::DisplayWarnMsg(Lang::get("DOWNLOAD_ERROR")); + else if (ret == SCRIPT_CANCELED) Msg::DisplayWarnMsg(Lang::get("SCRIPT_CANCELED")); + else if (ret == SYNTAX_ERROR) Msg::DisplayWarnMsg(Lang::get("SYNTAX_ERROR")); + else if (ret == COPY_ERROR) Msg::DisplayWarnMsg(Lang::get("COPY_ERROR")); + else if (ret == MOVE_ERROR) Msg::DisplayWarnMsg(Lang::get("MOVE_ERROR")); + else if (ret == DELETE_ERROR) Msg::DisplayWarnMsg(Lang::get("DELETE_ERROR")); + return ret; +} \ No newline at end of file