Add queue system with background downloading and much more (#73)

* Do not build here until it is merged.

* WIP: Queue System.

Right now crashes randomly for whatever reason..

* Animate queue spinner more slowly

* Use LightLocks to prevent crashing in the queue

(I hope it's fixed at least)

* Build nightlies in queue-system

* Use version.h for version and specify 7 digits

* Remove unneeded $(CURDIR)

I put that these for testing, but it's not needed

* Multiple Changes, see desc for more.

1.) Theme Implementation.
2.) Show Battery + Time.
3.) Some more work on Queue-System (might still be broke).
4.) Update Copyright to 2021.
5.) Add `%FIRM%` to regex.
6.) Mass Add to Queue.
7.) Search with AND / OR filter.

* Gaaah, not again...

* Remove DoNothing, some LightLock changes, etc

aka
Further improvements to overall system stability and other minor adjustments have been made to enhance the user experience.

* See desc for more.

- Current Queue Entry can now be canceled.

- Fix installed list.

- Display Download Speed.

- BYE BYE Queue LightLock!

* Various adjustments to the queue menu

- Make cancel button slightly smaller
- Right align "Steps: ..." text
- Remove "Current Operation:" text
- Change KB/MB/GB to KiB/MiB/GiB
- Lots of little positioning tweaks
- Fix bug where you could get stuck in the prompt
- Make spinny thing have a ! when action is needed
- Make extracting file increment at the start instead of the end
- Delete dumb VS Code file and gitignore it

* Change to hollow full charge plugged in icon

* Fix the settings positions a bit

* Fix custom font download not having prompt

Also tweak the text positions, I forgot to change them

Co-authored-by: StackZ <47382115+SuperSaiyajinStackZ@users.noreply.github.com>
This commit is contained in:
Pk11
2021-03-13 01:28:23 -06:00
committed by GitHub
parent e52bd33905
commit 60e29ddb90
92 changed files with 2564 additions and 1187 deletions
+1 -1
View File
@@ -2,7 +2,7 @@ name: Build Universal-Updater
on: on:
push: push:
branches-ignore: [translation, full-rewrite, PNG] branches-ignore: [translation]
paths-ignore: paths-ignore:
- 'README.md' - 'README.md'
pull_request: pull_request:
+3 -3
View File
@@ -6,16 +6,16 @@
*.elf *.elf
*.cia *.cia
*.3dsx *.3dsx
*/build *build
*.map *.map
*.lst *.lst
.vscode/ipch .vscode
*.DS_Store *.DS_Store
romfs/gfx/*.t3x romfs/gfx/*.t3x
include/version.hpp
bannertool* bannertool*
makerom* makerom*
*.pfs0 *.pfs0
*.nso *.nso
*.nacp *.nacp
build/sprites.h
-59
View File
@@ -1,59 +0,0 @@
{
"files.associations": {
"*.tcc": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"exception": "cpp",
"fstream": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"limits": "cpp",
"memory": "cpp",
"new": "cpp",
"ostream": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"streambuf": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"array": "cpp",
"atomic": "cpp",
"bit": "cpp",
"cstdint": "cpp",
"deque": "cpp",
"forward_list": "cpp",
"map": "cpp",
"unordered_map": "cpp",
"vector": "cpp",
"algorithm": "cpp",
"functional": "cpp",
"iterator": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"string": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"initializer_list": "cpp",
"bitset": "cpp",
"chrono": "cpp",
"condition_variable": "cpp",
"ratio": "cpp",
"regex": "cpp",
"shared_mutex": "cpp"
}
}
+15 -5
View File
@@ -46,11 +46,22 @@ endif
CURRENT_VERSION := $(shell git describe --abbrev=0 --tags) CURRENT_VERSION := $(shell git describe --abbrev=0 --tags)
# If on a tagged commit, use the tag instead of the commit # If on a tagged commit, use just the tag
ifneq ($(shell echo $(shell git tag -l --points-at HEAD) | head -c 1),) ifneq ($(shell echo $(shell git tag -l --points-at HEAD) | head -c 1),)
GIT_VER := $(shell git tag -l --points-at HEAD) GIT_VER := $(shell git tag -l --points-at HEAD)
else else
GIT_VER := $(shell git describe --abbrev=0 --tags)-$(shell git rev-parse --short HEAD) GIT_VER := $(shell git describe --abbrev=0 --tags)-$(shell git rev-parse --short=7 HEAD)
endif
# Ensure version.hpp exists
ifeq (,$(wildcard include/version.hpp))
$(shell mkdir -p include)
$(shell touch include/version.hpp)
endif
# Print new version if changed
ifeq (,$(findstring $(GIT_VER), $(shell cat include/version.hpp)))
$(shell printf "#ifndef VERSION_HPP\n#define VERSION_HPP\n\n#define VER_NUMBER \"$(GIT_VER)\"\n\n#endif\n" > include/version.hpp)
endif endif
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
@@ -78,8 +89,8 @@ endif
TARGET := Universal-Updater TARGET := Universal-Updater
BUILD := build BUILD := build
UNIVCORE := Universal-Core UNIVCORE := Universal-Core
SOURCES := $(UNIVCORE) source source/download source/gui source/lang source/overlays source/qr source/screens \ SOURCES := $(UNIVCORE) source source/download source/gui source/lang source/menu source/overlays \
source/store source/utils source/qr source/screens source/store source/utils
DATA := data DATA := data
INCLUDES := $(UNIVCORE) include include/download include/gui include/lang include/overlays include/qr include/screens \ INCLUDES := $(UNIVCORE) include include/download include/gui include/lang include/overlays include/qr include/screens \
include/store include/utils include/store include/utils
@@ -99,7 +110,6 @@ RSF_FILE := app/build-cia.rsf
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
CFLAGS := -g -Wall -Wno-psabi -O2 -mword-relocations \ CFLAGS := -g -Wall -Wno-psabi -O2 -mword-relocations \
-DV_STRING=\"$(GIT_VER)\" \
-DC_V=\"$(CURRENT_VERSION)\" \ -DC_V=\"$(CURRENT_VERSION)\" \
-fomit-frame-pointer -ffunction-sections \ -fomit-frame-pointer -ffunction-sections \
$(ARCH) $(ARCH)
+18
View File
@@ -3,15 +3,33 @@
sprites/add.png sprites/add.png
sprites/add_font.png sprites/add_font.png
sprites/arrow.png sprites/arrow.png
sprites/battery/battery_0.png
sprites/battery/battery_1.png
sprites/battery/battery_2.png
sprites/battery/battery_3.png
sprites/battery/battery_4.png
sprites/battery/battery_blink.png
sprites/battery/battery_charge.png
sprites/battery/battery_charge_full.png
sprites/cancel.png
sprites/checked.png sprites/checked.png
sprites/delete.png sprites/delete.png
sprites/download.png sprites/download.png
sprites/info.png sprites/info.png
sprites/installed.png
sprites/keyboard.png sprites/keyboard.png
sprites/list.png sprites/list.png
sprites/noIcon.png sprites/noIcon.png
sprites/notes.png sprites/notes.png
sprites/qr_code.png sprites/qr_code.png
sprites/queue0.png
sprites/queue1.png
sprites/queue2.png
sprites/queue3.png
sprites/queue4.png
sprites/queue5.png
sprites/queue6.png
sprites/queue7.png
sprites/screenshot.png sprites/screenshot.png
sprites/search.png sprites/search.png
sprites/settings.png sprites/settings.png
Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 249 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

+4 -2
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -27,15 +27,17 @@
#ifndef _UNIVERSAL_UPDATER_COMMON_HPP #ifndef _UNIVERSAL_UPDATER_COMMON_HPP
#define _UNIVERSAL_UPDATER_COMMON_HPP #define _UNIVERSAL_UPDATER_COMMON_HPP
#include <3ds.h>
#include "config.hpp" #include "config.hpp"
#include "gfx.hpp" #include "gfx.hpp"
#include "lang.hpp" #include "lang.hpp"
#include "msg.hpp" #include "msg.hpp"
#include "screenCommon.hpp" #include "screenCommon.hpp"
#include <3ds.h>
#include <vector>
#define _STORE_PATH "sdmc:/3ds/Universal-Updater/stores/" #define _STORE_PATH "sdmc:/3ds/Universal-Updater/stores/"
#define _META_PATH "sdmc:/3ds/Universal-Updater/MetaData.json" #define _META_PATH "sdmc:/3ds/Universal-Updater/MetaData.json"
#define _THEME_AMOUNT 1
#define _UNISTORE_VERSION 4 #define _UNISTORE_VERSION 4
inline std::unique_ptr<Config> config; inline std::unique_ptr<Config> config;
+30 -32
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -32,50 +32,48 @@
#include <citro2d.h> #include <citro2d.h>
#include <string> #include <string>
/*
Define all used Colors, for easier changes.
*/
/* Standard Colors. */ /* Standard Colors. */
#define WHITE C2D_Color32(255, 255, 255, 255) #define WHITE C2D_Color32(255, 255, 255, 255)
#define BLACK C2D_Color32(0, 0, 0, 255) #define BLACK C2D_Color32(0, 0, 0, 255)
#define TRANSPARENT C2D_Color32(0, 0, 0, 0) #define TRANSPARENT C2D_Color32(0, 0, 0, 0)
#define DIM_COLOR C2D_Color32(0, 0, 0, 190) #define DIM_COLOR C2D_Color32(0, 0, 0, 190)
/* Bar, Text, BG Colors. */ struct UITheme {
#define TEXT_COLOR WHITE uint32_t BarColor;
#define BAR_COLOR C2D_Color32(50, 73, 98, 255) uint32_t BGColor;
#define BAR_OUTL_COLOR C2D_Color32(25, 30, 53, 255) uint32_t BarOutline;
#define BG_COLOR C2D_Color32(38, 44, 77, 255) uint32_t TextColor;
uint32_t EntryBar;
/* Entry Colors. */ uint32_t EntryOutline;
#define ENTRY_BAR_COLOR BAR_COLOR uint32_t BoxInside;
#define ENTRY_BAR_OUTL_COLOR BAR_OUTL_COLOR uint32_t BoxSelected;
uint32_t BoxUnselected;
/* Entry Box Colors. */ uint32_t ProgressbarOut;
#define BOX_INSIDE_COLOR C2D_Color32(28, 33, 58, 255) uint32_t ProgressbarIn;
#define BOX_SELECTED_COLOR C2D_Color32(108, 130, 155, 255) uint32_t SearchBar;
#define BOX_UNSELECTED_COLOR BLACK uint32_t SearchbarOutline;
uint32_t SideBarSelected;
/* Progressbar Colors. */ uint32_t SideBarUnselected;
#define PROGRESSBAR_OUT_COLOR BOX_INSIDE_COLOR /* NOTE: Also used for the buttons. */
#define PROGRESSBAR_IN_COLOR SIDEBAR_UNSELECTED_COLOR uint32_t MarkSelected;
uint32_t MarkUnselected;
/* Search Menu Colors. */ uint32_t DownListPrev;
#define SEARCH_BAR_COLOR C2D_Color32(51, 75, 102, 255) uint32_t SideBarIconColor;
#define SEARCH_BAR_OUTL_COLOR BAR_OUTL_COLOR };
/* Sidebar Colors. */
#define SIDEBAR_SELECTED_COLOR C2D_Color32(108, 130, 155, 255)
#define SIDEBAR_UNSELECTED_COLOR C2D_Color32(77, 101, 128, 255)
namespace GFX { namespace GFX {
extern std::vector<UITheme> Themes;
extern int SelectedTheme;
void DrawTop(void); void DrawTop(void);
void DrawBottom(); void DrawBottom();
void DrawSprite(int img, int x, int y, float ScaleX = 1, float ScaleY = 1); void DrawSprite(int img, int x, int y, float ScaleX = 1, float ScaleY = 1);
void DrawBox(float xPos, float yPos, float width = 50, float height = 50, bool selected = false, uint32_t clr = BOX_INSIDE_COLOR); void DrawBox(float xPos, float yPos, float width = 50, float height = 50, bool selected = false, uint32_t clr = GFX::Themes[GFX::SelectedTheme].BoxInside);
void DrawCheckbox(float xPos, float yPos, bool selected); void DrawCheckbox(float xPos, float yPos, bool selected);
void DrawToggle(float xPos, float yPos, bool toggled); void DrawToggle(float xPos, float yPos, bool toggled);
void DrawTime();
void DrawBattery();
void HandleBattery();
}; };
#endif #endif
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+4 -6
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -28,15 +28,13 @@
#define _UNIVERSAL_UPDATER_OVERLAY_HPP #define _UNIVERSAL_UPDATER_OVERLAY_HPP
#include "common.hpp" #include "common.hpp"
#include "store.hpp"
#include "storeEntry.hpp"
#include <3ds.h> #include <3ds.h>
namespace Overlays { namespace Overlays {
void SelectStore(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, std::unique_ptr<Meta> &meta); void SelectStore();
void SelectLanguage(const std::unique_ptr<Store> &store); void SelectLanguage();
void ShowCredits(); void ShowCredits();
std::string SelectDir(const std::string &oldDir, const std::string &msg, const std::unique_ptr<Store> &store); std::string SelectDir(const std::string &oldDir, const std::string &msg);
}; };
#endif #endif
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+10 -12
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -37,11 +37,12 @@
0: Entry Info. 0: Entry Info.
1: Download List. 1: Download List.
2: Search + Favorites. 2: Queue.
3: Sorting. 3: Search + Favorites.
4: Settings / Credits(?). 4: Sorting.
5: Screenshot Menu. 5: Settings / Credits(?).
6: Release Notes. 6: Screenshot Menu.
7: Release Notes.
*/ */
class MainScreen : public Screen { class MainScreen : public Screen {
@@ -50,21 +51,18 @@ public:
void Draw(void) const override; void Draw(void) const override;
void Logic(u32 hDown, u32 hHeld, touchPosition touch) override; void Logic(u32 hDown, u32 hHeld, touchPosition touch) override;
private: private:
std::unique_ptr<Store> store = nullptr;
std::unique_ptr<Meta> meta = nullptr;
std::vector<std::unique_ptr<StoreEntry>> entries;
std::vector<std::string> dwnldList, dwnldSizes; std::vector<std::string> dwnldList, dwnldSizes;
bool initialized = false, fetchDown = false, showMarks = false, showSettings = false, bool initialized = false, fetchDown = false, showMarks = false, showSettings = false,
ascending = false, updateFilter = false, screenshotFetch = false, canDisplay = false; ascending = false, updateFilter = false, screenshotFetch = false, canDisplay = false, isAND = true;
int storeMode = 0, marks = 0, markIndex = 0, sPage = 0, lMode = 0, sSelection = 0, int storeMode = 0, marks = 0, markIndex = 0, sPage = 0, lMode = 0, sSelection = 0,
lastMode = 0, smallDelay = 0, sPos = 0, screenshotIndex = 0, sSize = 0, zoom = 0, scrollIndex = 0; lastMode = 0, smallDelay = 0, sPos = 0, screenshotIndex = 0, sSize = 0, zoom = 0, scrollIndex = 0, queueIndex = 0;
SortType sorttype = SortType::LAST_UPDATED; SortType sorttype = SortType::LAST_UPDATED;
/* Title, Author, Category, Console. */ /* Title, Author, Category, Console. */
std::vector<bool> searchIncludes = { false, false, false, false }; std::vector<bool> searchIncludes = { false, false, false, false }, installs = { };
std::string searchResult = "", screenshotName = ""; std::string searchResult = "", screenshotName = "";
C2D_Image Screenshot = { nullptr, nullptr }; C2D_Image Screenshot = { nullptr, nullptr };
+45 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
#include "json.hpp" #include "json.hpp"
#include <string> #include <string>
#include <vector>
enum favoriteMarks { enum favoriteMarks {
STAR = 1 << 0, STAR = 1 << 0,
@@ -46,15 +47,58 @@ public:
std::string GetUpdated(const std::string &unistoreName, const std::string &entry) const; std::string GetUpdated(const std::string &unistoreName, const std::string &entry) const;
int GetMarks(const std::string &unistoreName, const std::string &entry) const; int GetMarks(const std::string &unistoreName, const std::string &entry) const;
bool UpdateAvailable(const std::string &unistoreName, const std::string &entry, const std::string &updated) const; bool UpdateAvailable(const std::string &unistoreName, const std::string &entry, const std::string &updated) const;
std::vector<std::string> GetInstalled(const std::string &unistoreName, const std::string &entry) const;
void SetUpdated(const std::string &unistoreName, const std::string &entry, const std::string &updated) { void SetUpdated(const std::string &unistoreName, const std::string &entry, const std::string &updated) {
if (this->metadataJson.is_discarded()) return;
this->metadataJson[unistoreName][entry]["updated"] = updated; this->metadataJson[unistoreName][entry]["updated"] = updated;
}; };
void SetMarks(const std::string &unistoreName, const std::string &entry, int marks) { void SetMarks(const std::string &unistoreName, const std::string &entry, int marks) {
if (this->metadataJson.is_discarded()) return;
this->metadataJson[unistoreName][entry]["marks"] = marks; this->metadataJson[unistoreName][entry]["marks"] = marks;
}; };
/* TODO: Handle this better. */
void SetInstalled(const std::string &unistoreName, const std::string &entry, const std::string &name) {
if (this->metadataJson.is_discarded()) return;
const std::vector<std::string> installs = this->GetInstalled(unistoreName, entry);
bool write = true;
if (!installs.empty()) {
write = !installs.empty();
for (int i = 0; i < (int)installs.size(); i++) {
if (installs[i] == name) {
write = false;
break;
}
}
}
if (write) this->metadataJson[unistoreName][entry]["installed"] += name;
}
/* Remove installed state from a download list entry. */
void RemoveInstalled(const std::string &unistoreName, const std::string &entry, const std::string &name) {
if (this->metadataJson.is_discarded()) return;
const std::vector<std::string> installs = this->GetInstalled(unistoreName, entry);
int idx = -1;
if (!installs.empty()) {
for (int i = 0; i < (int)installs.size(); i++) {
if (installs[i] == name) {
idx = i;
break;
}
}
}
if (idx != -1) this->metadataJson[unistoreName][entry]["installed"].erase(idx);
}
void ImportMetadata(); void ImportMetadata();
void SaveCall(); void SaveCall();
private: private:
+2 -2
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -44,7 +44,7 @@ public:
std::string GetUniStoreTitle() const; std::string GetUniStoreTitle() const;
std::string GetUniStoreAuthor() const; std::string GetUniStoreAuthor() const;
/* Get Information of the UniStore Entries. */ /* Get Information of the UniStore entries. */
std::string GetTitleEntry(int index) const; std::string GetTitleEntry(int index) const;
std::string GetAuthorEntry(int index) const; std::string GetAuthorEntry(int index) const;
std::string GetDescriptionEntry(int index) const; std::string GetDescriptionEntry(int index) const;
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+33 -20
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@
#ifndef _UNIVERSAL_UPDATER_STORE_UTILS_HPP #ifndef _UNIVERSAL_UPDATER_STORE_UTILS_HPP
#define _UNIVERSAL_UPDATER_STORE_UTILS_HPP #define _UNIVERSAL_UPDATER_STORE_UTILS_HPP
#include "common.hpp" #include "meta.hpp"
#include "store.hpp" #include "store.hpp"
#include "storeEntry.hpp" #include "storeEntry.hpp"
#include <vector> #include <vector>
@@ -39,33 +39,41 @@ enum class SortType : uint8_t {
}; };
namespace StoreUtils { namespace StoreUtils {
extern std::unique_ptr<Meta> meta;
extern std::unique_ptr<Store> store;
extern std::vector<std::unique_ptr<StoreEntry>> entries;
/* Grid. */ /* Grid. */
void DrawGrid(const std::unique_ptr<Store> &store, const std::vector<std::unique_ptr<StoreEntry>> &entries); void DrawGrid();
void GridLogic(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, int &currentMode, int &lastMode, bool &fetch, int &smallDelay); void GridLogic(int &currentMode, int &lastMode, bool &fetch, int &smallDelay);
/* Top List. */ /* Top List. */
void DrawList(const std::unique_ptr<Store> &store, const std::vector<std::unique_ptr<StoreEntry>> &entries); void DrawList();
void ListLogic(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, int &currentMode, int &lastMode, bool &fetch, int &smallDelay); void ListLogic(int &currentMode, int &lastMode, bool &fetch, int &smallDelay);
/* Entry Info. */ /* Entry Info. */
void DrawEntryInfo(const std::unique_ptr<Store> &store, const std::unique_ptr<StoreEntry> &entry); void DrawEntryInfo(const std::unique_ptr<StoreEntry> &entry);
void EntryHandle(bool &showMark, bool &fetch, bool &sFetch, int &mode, const std::unique_ptr<StoreEntry> &entry); void EntryHandle(bool &showMark, bool &fetch, bool &sFetch, int &mode, const std::unique_ptr<StoreEntry> &entry);
/* Side Menu. */ /* Side Menu. */
void DrawSideMenu(int currentMenu); void DrawSideMenu(int currentMenu);
void SideMenuHandle(int &currentMenu, bool &fetch, int &lastMenu); void SideMenuHandle(int &currentMenu, bool &fetch, int &lastMenu);
/* Download Entries. */ /* Download entries. */
void DrawDownList(const std::unique_ptr<Store> &store, const std::vector<std::string> &entries, bool fetch, const std::unique_ptr<StoreEntry> &entry, const std::vector<std::string> &sizes); void DrawDownList(const std::vector<std::string> &entries, bool fetch, const std::unique_ptr<StoreEntry> &entry, const std::vector<std::string> &sizes, const std::vector<bool> &installs);
void DownloadHandle(const std::unique_ptr<Store> &store, const std::unique_ptr<StoreEntry> &entry, const std::vector<std::string> &entries, int &currentMenu, std::unique_ptr<Meta> &meta, const int &lastMode, int &smallDelay); void DownloadHandle(const std::unique_ptr<StoreEntry> &entry, const std::vector<std::string> &entries, int &currentMenu, const int &lastMode, int &smallDelay, std::vector<bool> &installs);
/* Queue System. */
void DrawQueueMenu(const int queueIndex);
void QueueMenuHandle(int &queueIndex, int &storeMode);
/* Search + Favorite Menu. */ /* Search + Favorite Menu. */
void DrawSearchMenu(const std::vector<bool> &searchIncludes, const std::string &searchResult, int marks, bool updateFilter); void DrawSearchMenu(const std::vector<bool> &searchIncludes, const std::string &searchResult, int marks, bool updateFilter, bool isAND);
void SearchHandle(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, std::vector<bool> &searchIncludes, std::unique_ptr<Meta> &meta, std::string &searchResult, int &marks, bool &updateFilter, bool ascending, SortType sorttype); void SearchHandle(std::vector<bool> &searchIncludes, std::string &searchResult, int &marks, bool &updateFilter, bool ascending, SortType sorttype, bool &isAND);
/* Mark Menu. */ /* Mark Menu. */
void DisplayMarkBox(int marks); void DisplayMarkBox(int marks);
void MarkHandle(std::unique_ptr<StoreEntry> &entry, const std::unique_ptr<Store> &store, bool &showMark, std::unique_ptr<Meta> &meta); void MarkHandle(std::unique_ptr<StoreEntry> &entry, bool &showMark);
/* Credits. */ /* Credits. */
void DrawCredits(); void DrawCredits();
@@ -76,14 +84,14 @@ namespace StoreUtils {
/* Settings. */ /* Settings. */
void DrawSettings(int page, int selection, int sPos); void DrawSettings(int page, int selection, int sPos);
void SettingsHandle(int &page, bool &dspSettings, int &storeMode, int &selection, std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, std::unique_ptr<Meta> &meta, int &sPos); void SettingsHandle(int &page, bool &dspSettings, int &storeMode, int &selection, int &sPos);
/* Sorting. */ /* Sorting. */
void DrawSorting(bool asc, SortType st); void DrawSorting(bool asc, SortType st);
void SortHandle(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, bool &asc, SortType &st); void SortHandle(bool &asc, SortType &st);
/* Release Notes. */ /* Release Notes. */
void DrawReleaseNotes(const int &scrollIndex, const std::unique_ptr<StoreEntry> &entry, const std::unique_ptr<Store> &store); void DrawReleaseNotes(const int &scrollIndex, const std::unique_ptr<StoreEntry> &entry);
void ReleaseNotesLogic(int &scrollIndex, int &storeMode); void ReleaseNotesLogic(int &scrollIndex, int &storeMode);
bool compareTitleDescending(const std::unique_ptr<StoreEntry> &a, const std::unique_ptr<StoreEntry> &b); bool compareTitleDescending(const std::unique_ptr<StoreEntry> &a, const std::unique_ptr<StoreEntry> &b);
@@ -95,13 +103,18 @@ namespace StoreUtils {
bool compareUpdateDescending(const std::unique_ptr<StoreEntry> &a, const std::unique_ptr<StoreEntry> &b); bool compareUpdateDescending(const std::unique_ptr<StoreEntry> &a, const std::unique_ptr<StoreEntry> &b);
bool compareUpdateAscending(const std::unique_ptr<StoreEntry> &a, const std::unique_ptr<StoreEntry> &b); bool compareUpdateAscending(const std::unique_ptr<StoreEntry> &a, const std::unique_ptr<StoreEntry> &b);
void SortEntries(bool Ascending, SortType sorttype, std::vector<std::unique_ptr<StoreEntry>> &entries); void SortEntries(bool Ascending, SortType sorttype);
void search(std::vector<std::unique_ptr<StoreEntry>> &entries, const std::string &query, bool title, bool author, bool category, bool console, int selectedMarks, bool updateAvl); void search(const std::string &query, bool title, bool author, bool category, bool console, int selectedMarks, bool updateAvl, bool isAND);
void FilterUpdateAvailable(std::vector<std::unique_ptr<StoreEntry>> &entries); void FilterUpdateAvailable();
void ResetAll(const std::unique_ptr<Store> &store, const std::unique_ptr<Meta> &meta, std::vector<std::unique_ptr<StoreEntry>> &entries); void ResetAll();
void RefreshUpdateAVL();
void AddToQueue(int index, const std::string &entry, const std::string &entryName, const std::string &lUpdated);
void AddAllToQueue();
}; };
#endif #endif
+10 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -38,8 +38,17 @@ enum class ProgressBar {
}; };
namespace Animation { namespace Animation {
extern int DisplayY, DisplayDelay;
extern bool MoveUp, DoDelay;
void DrawProgressBar(u64 currentProgress, u64 totalProgress); void DrawProgressBar(u64 currentProgress, u64 totalProgress);
void displayProgressBar(); void displayProgressBar();
void DrawQueue(int x, int y);
void QueueAnimHandle();
void QueueEntryDone();
void HandleQueueEntryDone();
}; };
#endif #endif
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+16 -3
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -64,6 +64,9 @@ public:
std::string archPath() const { return this->v_archivePath; }; std::string archPath() const { return this->v_archivePath; };
void archPath(const std::string &v) { this->v_archivePath = v; if (!this->changesMade) this->changesMade = true; }; void archPath(const std::string &v) { this->v_archivePath = v; if (!this->changesMade) this->changesMade = true; };
std::string firmPath() const { return this->v_firmPath; };
void firmPath(const std::string &v) { this->v_firmPath = v; if (!this->changesMade) this->changesMade = true; };
/* Fetching old metadata. */ /* Fetching old metadata. */
bool metadata() const { return this->v_metadata; }; bool metadata() const { return this->v_metadata; };
void metadata(bool v) { this->v_metadata = v; if (!this->changesMade) this->changesMade = true; }; void metadata(bool v) { this->v_metadata = v; if (!this->changesMade) this->changesMade = true; };
@@ -87,6 +90,14 @@ public:
/* If displaying changelog. */ /* If displaying changelog. */
bool changelog() const { return this->v_changelog; }; bool changelog() const { return this->v_changelog; };
void changelog(bool v) { this->v_changelog = v; if (!this->changesMade) this->changesMade = true; }; void changelog(bool v) { this->v_changelog = v; if (!this->changesMade) this->changesMade = true; };
/* The active Theme. */
int theme() const { return this->v_theme; };
void theme(int v) { this->v_theme = v; if (!this->changesMade) this->changesMade = true; };
/* If showing prompt if action failed / succeeded. */
bool prompt() const { return this->v_prompt; };
void prompt(bool v) { this->v_prompt = v; if (!this->changesMade) this->changesMade = true; };
private: private:
/* Mainly helper. */ /* Mainly helper. */
bool getBool(const std::string &key); bool getBool(const std::string &key);
@@ -99,12 +110,14 @@ private:
nlohmann::json json; nlohmann::json json;
bool changesMade = false; bool changesMade = false;
int v_theme = 0;
std::string v_language = "en", v_lastStore = "universal-db.unistore", std::string v_language = "en", v_lastStore = "universal-db.unistore",
v_3dsxPath = "sdmc:/3ds", v_ndsPath = "sdmc:", v_archivePath = "sdmc:", v_3dsxPath = "sdmc:/3ds", v_ndsPath = "sdmc:", v_archivePath = "sdmc:",
v_shortcutPath = "sdmc:/3ds/Universal-Updater/shortcuts"; v_shortcutPath = "sdmc:/3ds/Universal-Updater/shortcuts", v_firmPath = "sdmc:/luma/payloads";
bool v_list = false, v_autoUpdate = true, v_metadata = true, v_updateCheck = true, bool v_list = false, v_autoUpdate = true, v_metadata = true, v_updateCheck = true,
v_showBg = false, v_customFont = false, v_changelog = true; v_showBg = false, v_customFont = false, v_changelog = true, v_prompt = true;
}; };
#endif #endif
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+82
View File
@@ -0,0 +1,82 @@
/*
* This file is part of Universal-Updater
* Copyright (C) 2019-2021 Universal-Team
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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_UPDATER_QUEUE_SYSTEM_HPP
#define _UNIVERSAL_UPDATER_QUEUE_SYSTEM_HPP
#include "json.hpp"
#include <citro2d.h>
#include <deque>
#include <memory>
/* Extend this, if more statuses are neccessary. */
enum class QueueStatus {
None,
Copying,
Deleting,
Downloading,
Extracting,
Installing,
Moving,
Request, // For User needed Requests.
Failed,
Done
};
enum RequestType {
PROMPT_RET = -3,
NO_REQUEST = -1,
RMDIR_REQUEST = 1, // remove dir prompt request.
PROMPT_REQUEST = 2, // skip prompt request.
PROMPT_ERROR = 3 // Error message prompt. Unused right now.
};
class Queue {
public:
Queue(nlohmann::json object, const C2D_Image &img, const std::string &name, const std::string &uName, const std::string &eName, const std::string &lUpdated) :
obj(object), icn(img), name(name), unistoreName(uName), entryName(eName), lastUpdated(lUpdated) { };
QueueStatus status = QueueStatus::None;
nlohmann::json obj;
C2D_Image icn;
int total, current;
std::string name = "", unistoreName = "", entryName = "", lastUpdated = "";
};
/* Of course also a namespace to that part, so we can do that in a Thread. */
namespace QueueSystem {
extern int RequestNeeded, RequestAnswer;
extern std::string RequestMsg, EndMsg;
extern int LastElement;
extern bool Wait, Popup, CancelCallback;
void QueueHandle(); // Handles the Queue.
void AddToQueue(nlohmann::json obj, const C2D_Image &icn, const std::string &name, const std::string &uName, const std::string &eName, const std::string &lUpdated); // Adds to Queue.
void ClearQueue(); // Clears the Queue.
void Resume();
};
#endif
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+9 -9
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -44,15 +44,15 @@ enum ScriptState {
namespace ScriptUtils { namespace ScriptUtils {
bool matchPattern(const std::string &pattern, const std::string &tested); bool matchPattern(const std::string &pattern, const std::string &tested);
Result removeFile(const std::string &file, const std::string &message); Result removeFile(const std::string &file, const std::string &message, bool isARG = false);
void bootTitle(const std::string &TitleID, bool isNAND, const std::string &message); void bootTitle(const std::string &TitleID, bool isNAND, const std::string &message, bool isARG = false);
Result prompt(const std::string &message); Result prompt(const std::string &message);
Result copyFile(const std::string &source, const std::string &destination, const std::string &message); Result copyFile(const std::string &source, const std::string &destination, const std::string &message, bool isARG = false);
Result renameFile(const std::string &oldName, const std::string &newName, const std::string &message); Result renameFile(const std::string &oldName, const std::string &newName, const std::string &message, bool isARG = false);
Result downloadRelease(const std::string &repo, const std::string &file, const std::string &output, bool includePrereleases, const std::string &message); Result downloadRelease(const std::string &repo, const std::string &file, const std::string &output, bool includePrereleases, const std::string &message, bool isARG = false);
Result downloadFile(const std::string &file, const std::string &output, const std::string &message); Result downloadFile(const std::string &file, const std::string &output, const std::string &message, bool isARG = false);
void installFile(const std::string &file, bool updatingSelf, const std::string &message); void installFile(const std::string &file, bool updatingSelf, const std::string &message, bool isARG = false);
void extractFile(const std::string &file, const std::string &input, const std::string &output, const std::string &message); void extractFile(const std::string &file, const std::string &input, const std::string &output, const std::string &message, bool isARG = false);
Result runFunctions(nlohmann::json storeJson, int selection, const std::string &entry); Result runFunctions(nlohmann::json storeJson, int selection, const std::string &entry);
}; };
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+2 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -37,6 +37,7 @@ namespace StringUtils {
std::string formatBytes(int bytes); std::string formatBytes(int bytes);
std::string GetMarkString(int marks); std::string GetMarkString(int marks);
std::vector<std::string> GetMarks(int marks); std::vector<std::string> GetMarks(int marks);
std::string format(const std::string &fmt_str, ...);
}; };
#endif #endif
+26
View File
@@ -1,4 +1,9 @@
{ {
"ACTION_CANCELED": "%s canceled!",
"ACTION_FAILED": "%s failed!",
"ACTION_REQUIRED": "Action required!",
"ACTION_SUCCEEDED": "%s succeeded!",
"ACTIVE_THEME": "Active Theme",
"ASCENDING": "Ascending", "ASCENDING": "Ascending",
"ARGUMENT_INVALID": "Argument invalid.\nPlease check the xml file for proper arguments.", "ARGUMENT_INVALID": "Argument invalid.\nPlease check the xml file for proper arguments.",
"AUTHOR": "Author", "AUTHOR": "Author",
@@ -13,6 +18,7 @@
"CATEGORY": "Category", "CATEGORY": "Category",
"CHANGE_3DSX_PATH": "Change 3DSX path", "CHANGE_3DSX_PATH": "Change 3DSX path",
"CHANGE_ARCHIVE_PATH": "Change archive path", "CHANGE_ARCHIVE_PATH": "Change archive path",
"CHANGE_FIRM_PATH": "Change firm path",
"CHANGE_NDS_PATH": "Change NDS path", "CHANGE_NDS_PATH": "Change NDS path",
"CHANGE_SHORTCUT_PATH": "Change shortcut path", "CHANGE_SHORTCUT_PATH": "Change shortcut path",
"CHECK_UNISTORE_UPDATES": "Checking for UniStore updates...", "CHECK_UNISTORE_UPDATES": "Checking for UniStore updates...",
@@ -21,6 +27,7 @@
"CONNECT_WIFI": "Please Connect to WiFi.", "CONNECT_WIFI": "Please Connect to WiFi.",
"CONSOLE": "Console", "CONSOLE": "Console",
"CONTRIBUTOR_TRANSLATORS": "- All Translators & Contributors", "CONTRIBUTOR_TRANSLATORS": "- All Translators & Contributors",
"COPYING": "Copying... %s / %s (%.2f%%)",
"COPY_ERROR": "Copy Error!", "COPY_ERROR": "Copy Error!",
"CREATE_SHORTCUT": "Would you like to create a shortcut?", "CREATE_SHORTCUT": "Would you like to create a shortcut?",
"CREDITS": "Credits", "CREDITS": "Credits",
@@ -31,6 +38,7 @@
"DELETE_ERROR": "Delete Error!", "DELETE_ERROR": "Delete Error!",
"DELETE_PROMPT": "Are you sure you want to delete this Directory?", "DELETE_PROMPT": "Are you sure you want to delete this Directory?",
"DELETE_UNNEEDED_FILE": "Deleting unneeded file...", "DELETE_UNNEEDED_FILE": "Deleting unneeded file...",
"DELETING": "Deleting...",
"DESCENDING": "Descending", "DESCENDING": "Descending",
"DIRECTION": "Direction", "DIRECTION": "Direction",
"DIRECTORY_SETTINGS": "Directory Settings", "DIRECTORY_SETTINGS": "Directory Settings",
@@ -40,6 +48,8 @@
"DONE": "Done!", "DONE": "Done!",
"DOWNLOAD_ERROR": "Download Error!", "DOWNLOAD_ERROR": "Download Error!",
"DOWNLOAD_FAILED": "Download Failed!", "DOWNLOAD_FAILED": "Download Failed!",
"DOWNLOAD_SPEED": "Speed: %lld KiB/s",
"DOWNLOADING": "Downloading... %s / %s (%.2f%%)",
"DOWNLOADING_COMPATIBLE_FONT": "Downloading compatible font...", "DOWNLOADING_COMPATIBLE_FONT": "Downloading compatible font...",
"DOWNLOADING_SPRITE_SHEET": "Downloading Spritesheet...", "DOWNLOADING_SPRITE_SHEET": "Downloading Spritesheet...",
"DOWNLOADING_SPRITE_SHEET2": "Downloading Spritesheet %i of %i...", "DOWNLOADING_SPRITE_SHEET2": "Downloading Spritesheet %i of %i...",
@@ -56,8 +66,11 @@
"ENTRIES": "Entries", "ENTRIES": "Entries",
"EXECUTE_ENTRY": "Would you like to execute this entry?", "EXECUTE_ENTRY": "Would you like to execute this entry?",
"EXIT_APP": "Exit Universal-Updater", "EXIT_APP": "Exit Universal-Updater",
"EXTRACTING": "Extracting... %s / %s (%.2f%%)",
"FEATURE_SIDE_EFFECTS": "This Feature may have side effects while the Queue is running.\nAre you sure you want to continue?",
"FETCHING_METADATA": "Fetching old metadata...", "FETCHING_METADATA": "Fetching old metadata...",
"FETCHING_RECOMMENDED_UNISTORES": "Fetching recommended UniStores...", "FETCHING_RECOMMENDED_UNISTORES": "Fetching recommended UniStores...",
"FILES": "File: %d / %d",
"FILE_EXTRACTED": "file extracted.", "FILE_EXTRACTED": "file extracted.",
"FILE_SLASH": "Seems like a '/' is included, which is not supported.\nPlease change 'file' to filename only.", "FILE_SLASH": "Seems like a '/' is included, which is not supported.\nPlease change 'file' to filename only.",
"FILES_EXTRACTED": "files extracted.", "FILES_EXTRACTED": "files extracted.",
@@ -67,6 +80,7 @@
"GUI_SETTINGS": "GUI Settings", "GUI_SETTINGS": "GUI Settings",
"GUI_SETTINGS_BTN": "GUI settings...", "GUI_SETTINGS_BTN": "GUI settings...",
"INCLUDE_IN_RESULTS": "Include in results:", "INCLUDE_IN_RESULTS": "Include in results:",
"INSTALLING": "Installing... %s / %s (%.2f%%)",
"INSTALL_UNIVERSAL_UPDATER": "Installing Universal-Updater...", "INSTALL_UNIVERSAL_UPDATER": "Installing Universal-Updater...",
"INVALID_UNISTORE": "Invalid UniStore", "INVALID_UNISTORE": "Invalid UniStore",
"KEY_CONTINUE": "Press any key to continue.", "KEY_CONTINUE": "Press any key to continue.",
@@ -83,6 +97,16 @@
"NO_LICENSE": "No License", "NO_LICENSE": "No License",
"NO_SCREENSHOTS_AVAILABLE": "No Screenshots available", "NO_SCREENSHOTS_AVAILABLE": "No Screenshots available",
"NOT_IMPLEMENTED": "Not Implemented Yet", "NOT_IMPLEMENTED": "Not Implemented Yet",
"OP_COPYING": "Copying",
"OP_DELETING": "Deleting",
"OP_DOWNLOADING": "Downloading",
"OP_EXTRACTING": "Extracting",
"OP_INSTALLING": "Installing",
"OP_MOVING": "Moving",
"OP_WAITING": "Waiting",
"QUEUE": "Queue",
"QUEUE_POSITION": "Queue position",
"QUEUE_PROGRESS": "Step: %d / %d",
"RECOMMENDED_UNISTORES": "Recommended UniStores", "RECOMMENDED_UNISTORES": "Recommended UniStores",
"REVISION": "Revision", "REVISION": "Revision",
"SCREENSHOT": "Screenshot %d / %d", "SCREENSHOT": "Screenshot %d / %d",
@@ -93,6 +117,7 @@
"SELECT_LANG": "Choose the language", "SELECT_LANG": "Choose the language",
"SELECT_UNISTORE": "Select UniStore", "SELECT_UNISTORE": "Select UniStore",
"SELECT_UNISTORE_2": "Select a UniStore", "SELECT_UNISTORE_2": "Select a UniStore",
"SELECTION_QUEUE": "Add Selection to Queue",
"SETTINGS": "Settings", "SETTINGS": "Settings",
"SHEET_SLASH": "Seems like a '/' is included, which is not supported.\nPlease change 'sheet' to filename only.", "SHEET_SLASH": "Seems like a '/' is included, which is not supported.\nPlease change 'sheet' to filename only.",
"SHORTCUT_CREATED": "Shortcut created!", "SHORTCUT_CREATED": "Shortcut created!",
@@ -102,6 +127,7 @@
"START_SELECT": "Press START to select the current folder", "START_SELECT": "Press START to select the current folder",
"STORE_INFO": "Store Info", "STORE_INFO": "Store Info",
"SYNTAX_ERROR": "Syntax Error!", "SYNTAX_ERROR": "Syntax Error!",
"THEME_DEFAULT": "Default",
"TITLE": "Title", "TITLE": "Title",
"TOP_STYLE": "Top Style", "TOP_STYLE": "Top Style",
"UNISTORE_BG": "Use UniStore BG", "UNISTORE_BG": "Use UniStore BG",
+109 -16
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -26,23 +26,49 @@
#include "common.hpp" #include "common.hpp"
#include "gfx.hpp" #include "gfx.hpp"
#include "stringutils.hpp"
#include <ctime>
/* int GFX::SelectedTheme = 0;
Draw the base top screen.
*/ /* All available Themes here inside that vector. */
std::vector<UITheme> GFX::Themes = {
/* Default Theme. */
{
C2D_Color32(50, 73, 98, 255), // Bar.
C2D_Color32(38, 44, 77, 255), // BG.
C2D_Color32(25, 30, 53, 255), // Bar Outline.
WHITE, // Text.
C2D_Color32(50, 73, 98, 255), // Entry bar.
C2D_Color32(25, 30, 53, 255), // Entry Outline.
C2D_Color32(28, 33, 58, 255), // Box Inside.
C2D_Color32(108, 130, 155, 255), // Box Outside.
BLACK, // Box Unselected.
C2D_Color32(28, 33, 58, 255), // Progressbar Out.
C2D_Color32(77, 101, 128, 255), // Progressbar In.
C2D_Color32(51, 75, 102, 255), // Searchbar.
C2D_Color32(25, 30, 53, 255), // Searchbar Outline.
C2D_Color32(108, 130, 155, 255), // Sidebar Selected.
C2D_Color32(77, 101, 128, 255), // Sidebar Unselected.
C2D_Color32(77, 101, 128, 255), // Mark Selected.
C2D_Color32(28, 33, 58, 255), // Mark Unselected.
C2D_Color32(28, 33, 58, 255), // Downlist Preview (Top).
C2D_Color32(173, 204, 239, 255) // SideBar Icon Color.
}
};
/* Draw the base top screen. */
void GFX::DrawTop(void) { void GFX::DrawTop(void) {
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 0, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 26, 400, 214, BG_COLOR); Gui::Draw_Rect(0, 26, 400, 214, GFX::Themes[GFX::SelectedTheme].BGColor);
Gui::Draw_Rect(0, 25, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
} }
/* /* Draw the base bottom screen. */
Draw the base bottom screen.
*/
void GFX::DrawBottom() { void GFX::DrawBottom() {
Gui::ScreenDraw(Bottom); Gui::ScreenDraw(Bottom);
Gui::Draw_Rect(0, 0, 320, 240, BG_COLOR); Gui::Draw_Rect(0, 0, 320, 240, GFX::Themes[GFX::SelectedTheme].BGColor);
} }
/* /*
@@ -56,15 +82,15 @@ void GFX::DrawBottom() {
uint32_t clr: (Optional) The color of the inside of the box. uint32_t clr: (Optional) The color of the inside of the box.
*/ */
void GFX::DrawBox(float xPos, float yPos, float width, float height, bool selected, uint32_t clr) { void GFX::DrawBox(float xPos, float yPos, float width, float height, bool selected, uint32_t clr) {
Gui::Draw_Rect(xPos, yPos, width, height, BOX_INSIDE_COLOR); // Draw middle BG. Gui::Draw_Rect(xPos, yPos, width, height, GFX::Themes[GFX::SelectedTheme].BoxInside); // Draw middle BG.
if (selected) { if (selected) {
static constexpr int depth = 2; static constexpr int depth = 2;
Gui::Draw_Rect(xPos - depth, yPos - depth, width + depth * 2, depth, BOX_SELECTED_COLOR); // Top. Gui::Draw_Rect(xPos - depth, yPos - depth, width + depth * 2, depth, GFX::Themes[GFX::SelectedTheme].BoxSelected); // Top.
Gui::Draw_Rect(xPos - depth, yPos - depth, depth, height + depth * 2, BOX_SELECTED_COLOR); // Left. Gui::Draw_Rect(xPos - depth, yPos - depth, depth, height + depth * 2, GFX::Themes[GFX::SelectedTheme].BoxSelected); // Left.
Gui::Draw_Rect(xPos + width, yPos - depth, depth, height + depth * 2, BOX_SELECTED_COLOR); // Right. Gui::Draw_Rect(xPos + width, yPos - depth, depth, height + depth * 2, GFX::Themes[GFX::SelectedTheme].BoxSelected); // Right.
Gui::Draw_Rect(xPos - depth, yPos + height, width + depth * 2, depth, BOX_SELECTED_COLOR); // Bottom. Gui::Draw_Rect(xPos - depth, yPos + height, width + depth * 2, depth, GFX::Themes[GFX::SelectedTheme].BoxSelected); // Bottom.
} }
} }
@@ -103,4 +129,71 @@ void GFX::DrawCheckbox(float xPos, float yPos, bool selected) {
*/ */
void GFX::DrawToggle(float xPos, float yPos, bool toggled) { void GFX::DrawToggle(float xPos, float yPos, bool toggled) {
GFX::DrawSprite((toggled ? sprites_toggle_on_idx : sprites_toggle_off_idx), xPos, yPos); GFX::DrawSprite((toggled ? sprites_toggle_on_idx : sprites_toggle_off_idx), xPos, yPos);
}
void GFX::DrawTime() {
time_t unixTime = time(nullptr);
struct tm *timeStruct = gmtime((const time_t *)&unixTime);
const std::string str = StringUtils::format("%02i:%02i", timeStruct->tm_hour, timeStruct->tm_min); // <Hour>:<Minute>.
Gui::DrawString(11, 5, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 0, 0, font);
}
static int blinkDelay = 40;
static bool blinkState = true, batteryLow = false;
void GFX::DrawBattery() {
u8 chargeState = false, level = 0;
PTMU_GetBatteryChargeState(&chargeState); // Get Charge state.
PTMU_GetBatteryLevel(&level); // Get Battery Level.
if (chargeState) {
GFX::DrawSprite((level < 5 ? sprites_battery_charge_idx : sprites_battery_charge_full_idx), 366, 1);
if (batteryLow) batteryLow = false; // Cause we're charging.
} else {
switch(level) {
case 0: // Blinky.
GFX::DrawSprite((blinkState ? sprites_battery_blink_idx : sprites_battery_0_idx), 366, 1);
if (!batteryLow) batteryLow = true;
break;
case 1: // Red.
GFX::DrawSprite(sprites_battery_0_idx, 366, 1);
if (batteryLow) batteryLow = false; // Cause we're not low.
break;
case 2: // One.
GFX::DrawSprite(sprites_battery_1_idx, 366, 1);
if (batteryLow) batteryLow = false; // Cause we're not low.
break;
case 3: // Two.
GFX::DrawSprite(sprites_battery_2_idx, 366, 1);
if (batteryLow) batteryLow = false; // Cause we're not low.
break;
case 4: // Three.
GFX::DrawSprite(sprites_battery_3_idx, 366, 1);
if (batteryLow) batteryLow = false; // Cause we're not low.
break;
case 5: // Full.
GFX::DrawSprite(sprites_battery_4_idx, 366, 1);
if (batteryLow) batteryLow = false; // Cause we're not low.
break;
}
}
}
void GFX::HandleBattery() {
if (batteryLow) {
if (blinkDelay > 0) {
blinkDelay--;
if (blinkDelay == 0) {
blinkState = !blinkState;
blinkDelay = 40;
}
}
}
} }
+11 -11
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -39,7 +39,7 @@ void Msg::DisplayMsg(const std::string &Text) {
C2D_TargetClear(Bottom, TRANSPARENT); C2D_TargetClear(Bottom, TRANSPARENT);
GFX::DrawTop(); GFX::DrawTop();
Gui::DrawStringCentered(0, (240 - Gui::GetStringHeight(0.6f, Text)) / 2, 0.6f, TEXT_COLOR, Text, 395, 0, font); Gui::DrawStringCentered(0, (240 - Gui::GetStringHeight(0.6f, Text)) / 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Text, 395, 0, font);
GFX::DrawBottom(); GFX::DrawBottom();
C3D_FrameEnd(0); C3D_FrameEnd(0);
} }
@@ -56,7 +56,7 @@ void Msg::DisplayWarnMsg(const std::string &Text) {
C2D_TargetClear(Bottom, TRANSPARENT); C2D_TargetClear(Bottom, TRANSPARENT);
GFX::DrawTop(); GFX::DrawTop();
Gui::DrawStringCentered(0, 1, 0.6f, TEXT_COLOR, Text, 390, 0, font); Gui::DrawStringCentered(0, 1, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Text, 390, 0, font);
GFX::DrawBottom(); GFX::DrawBottom();
C3D_FrameEnd(0); C3D_FrameEnd(0);
@@ -78,11 +78,11 @@ bool Msg::promptMsg(const std::string &promptMsg) {
C2D_TargetClear(Bottom, TRANSPARENT); C2D_TargetClear(Bottom, TRANSPARENT);
GFX::DrawTop(); GFX::DrawTop();
Gui::Draw_Rect(0, 215, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 215, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 214, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 214, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, (240 - Gui::GetStringHeight(0.6f, promptMsg)) / 2, 0.6f, TEXT_COLOR, promptMsg, 395, 0, font); Gui::DrawStringCentered(0, (240 - Gui::GetStringHeight(0.6f, promptMsg)) / 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, promptMsg, 395, 0, font);
Gui::DrawStringCentered(0, 218, 0.6f, TEXT_COLOR, Lang::get("CONFIRM_OR_CANCEL"), 390, 0, font); Gui::DrawStringCentered(0, 218, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CONFIRM_OR_CANCEL"), 390, 0, font);
GFX::DrawBottom(); GFX::DrawBottom();
C3D_FrameEnd(0); C3D_FrameEnd(0);
@@ -110,10 +110,10 @@ void Msg::waitMsg(const std::string &msg) {
C2D_TargetClear(Bottom, TRANSPARENT); C2D_TargetClear(Bottom, TRANSPARENT);
GFX::DrawTop(); GFX::DrawTop();
Gui::DrawStringCentered(0, (240 - Gui::GetStringHeight(0.6f, msg)) / 2, 0.6f, TEXT_COLOR, msg, 395, 0, font); Gui::DrawStringCentered(0, (240 - Gui::GetStringHeight(0.6f, msg)) / 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, msg, 395, 0, font);
Gui::Draw_Rect(0, 215, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 215, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 214, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 214, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 218, 0.6f, TEXT_COLOR, Lang::get("KEY_CONTINUE"), 390, 0, font); Gui::DrawStringCentered(0, 218, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("KEY_CONTINUE"), 390, 0, font);
GFX::DrawBottom(); GFX::DrawBottom();
C3D_FrameEnd(0); C3D_FrameEnd(0);
+9 -3
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -28,6 +28,7 @@
#include "download.hpp" #include "download.hpp"
#include "init.hpp" #include "init.hpp"
#include "mainScreen.hpp" #include "mainScreen.hpp"
#include "queueSystem.hpp"
#include "sound.hpp" #include "sound.hpp"
#include <dirent.h> #include <dirent.h>
@@ -120,6 +121,7 @@ Result Init::Initialize() {
Gui::init(); Gui::init();
cfguInit(); cfguInit();
ptmuInit();
amInit(); amInit();
acInit(); acInit();
@@ -136,6 +138,8 @@ Result Init::Initialize() {
mkdir("sdmc:/3ds/Universal-Updater/shortcuts", 0777); mkdir("sdmc:/3ds/Universal-Updater/shortcuts", 0777);
config = std::make_unique<Config>(); config = std::make_unique<Config>();
GFX::SelectedTheme = config->theme();
if (GFX::SelectedTheme > (_THEME_AMOUNT - 1)) GFX::SelectedTheme = 0; // In case it is above the max themes.
Lang::load(config->language()); Lang::load(config->language());
Gui::loadSheet("romfs:/gfx/sprites.t3x", sprites); Gui::loadSheet("romfs:/gfx/sprites.t3x", sprites);
@@ -150,6 +154,7 @@ Result Init::Initialize() {
Gui::setScreen(std::make_unique<MainScreen>(), false, false); Gui::setScreen(std::make_unique<MainScreen>(), false, false);
InitMusic(); InitMusic();
return 0; return 0;
} }
@@ -173,11 +178,11 @@ Result Init::MainLoop() {
C3D_FrameBegin(C3D_FRAME_SYNCDRAW); C3D_FrameBegin(C3D_FRAME_SYNCDRAW);
C2D_TargetClear(Top, C2D_Color32(0, 0, 0, 0)); C2D_TargetClear(Top, C2D_Color32(0, 0, 0, 0));
C2D_TargetClear(Bottom, C2D_Color32(0, 0, 0, 0)); C2D_TargetClear(Bottom, C2D_Color32(0, 0, 0, 0));
Gui::DrawScreen(false); Gui::DrawScreen(false);
if (!exiting) Gui::ScreenLogic(hDown, hHeld, touch, true, false);
C3D_FrameEnd(0); C3D_FrameEnd(0);
if (!exiting) Gui::ScreenLogic(hDown, hHeld, touch, true, false);
if (exiting) { if (exiting) {
if (hDown & KEY_START) fullExit = true; // Make it optionally faster. if (hDown & KEY_START) fullExit = true; // Make it optionally faster.
@@ -204,6 +209,7 @@ Result Init::Exit() {
gfxExit(); gfxExit();
cfguExit(); cfguExit();
config->save(); config->save();
ptmuExit();
acExit(); acExit();
amExit(); amExit();
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+5 -7
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -33,9 +33,7 @@
#define ARG_AMOUNT 4 // In case for more args, change this. It must be ARG amount + 1, because of 3DSX Path. #define ARG_AMOUNT 4 // In case for more args, change this. It must be ARG amount + 1, because of 3DSX Path.
std::string _3dsxPath = ""; std::string _3dsxPath = "";
/* /* ARG Init. */
ARG Init.
*/
static void InitForARG() { static void InitForARG() {
gfxInitDefault(); gfxInitDefault();
romfsInit(); romfsInit();
@@ -51,14 +49,14 @@ static void InitForARG() {
mkdir("sdmc:/3ds/Universal-Updater/shortcuts", 0777); mkdir("sdmc:/3ds/Universal-Updater/shortcuts", 0777);
config = std::make_unique<Config>(); config = std::make_unique<Config>();
GFX::SelectedTheme = config->theme();
if (GFX::SelectedTheme > (_THEME_AMOUNT - 1)) GFX::SelectedTheme = 0; // In case it is above the max themes.
Lang::load(config->language()); Lang::load(config->language());
Init::LoadFont(); Init::LoadFont();
osSetSpeedupEnable(true); // Enable speed-up for New 3DS users. osSetSpeedupEnable(true); // Enable speed-up for New 3DS users.
} }
/* /* ARG Exit. */
ARG Exit.
*/
static Result ExitForARG() { static Result ExitForARG() {
Gui::exit(); Gui::exit();
Init::UnloadFont(); Init::UnloadFont();
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,7 +24,10 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "animation.hpp"
#include "common.hpp"
#include "keyboard.hpp" #include "keyboard.hpp"
#include "queueSystem.hpp"
#include "scriptUtils.hpp" #include "scriptUtils.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include "structs.hpp" #include "structs.hpp"
@@ -35,15 +38,25 @@ extern std::string _3dsxPath;
extern bool is3DSX; extern bool is3DSX;
extern bool touching(touchPosition touch, Structs::ButtonPos button); extern bool touching(touchPosition touch, Structs::ButtonPos button);
static const std::vector<Structs::ButtonPos> downloadBoxes = { static const std::vector<Structs::ButtonPos> downloadBoxes = {
{ 54, 32, 262, 22 }, { 46, 32, 241, 22 },
{ 54, 62, 262, 22 }, { 46, 62, 241, 22 },
{ 54, 92, 262, 22 }, { 46, 92, 241, 22 },
{ 54, 122, 262, 22 }, { 46, 122, 241, 22 },
{ 54, 152, 262, 22 }, { 46, 152, 241, 22 },
{ 54, 182, 262, 22 }, { 46, 182, 241, 22 },
{ 54, 212, 262, 22 }, { 46, 212, 241, 22 },
{ 50, 216, 24, 24 } { 42, 216, 24, 24 }
};
static const std::vector<Structs::ButtonPos> installedPos = {
{ 288, 32, 24, 24 },
{ 288, 62, 24, 24 },
{ 288, 92, 24, 24 },
{ 288, 122, 24, 24 },
{ 288, 152, 24, 24 },
{ 288, 182, 24, 24 },
{ 288, 212, 24, 24 },
}; };
/* /*
@@ -87,51 +100,56 @@ static bool CreateShortcut(const std::string &entryName, int index, const std::s
/* /*
Draw the Download Entries part. Draw the Download entries part.
const std::unique_ptr<Store> &store: Const Reference to the Store class.
const std::vector<std::string> &entries: Const Reference to the download list as a vector of strings. const std::vector<std::string> &entries: Const Reference to the download list as a vector of strings.
bool fetch: if fetching or not. bool fetch: if fetching or not.
const std::unique_ptr<StoreEntry> &entry: Const Reference to the StoreEntry. const std::unique_ptr<StoreEntry> &entry: Const Reference to the StoreEntry.
const std::vector<std::string> &sizes: Const Reference to the download sizes as a vector of strings. const std::vector<std::string> &sizes: Const Reference to the download sizes as a vector of strings.
*/ */
void StoreUtils::DrawDownList(const std::unique_ptr<Store> &store, const std::vector<std::string> &entries, bool fetch, const std::unique_ptr<StoreEntry> &entry, const std::vector<std::string> &sizes) { void StoreUtils::DrawDownList(const std::vector<std::string> &entries, bool fetch, const std::unique_ptr<StoreEntry> &entry, const std::vector<std::string> &sizes, const std::vector<bool> &installs) {
/* For the Top Screen. */ /* For the Top Screen. */
if (store && store->GetValid() && !fetch && entry) { if (StoreUtils::store && StoreUtils::store->GetValid() && !fetch && entry) {
if (entries.size() > 0) { if (entries.size() > 0) {
Gui::Draw_Rect(0, 174, 400, 66, BOX_INSIDE_COLOR); Gui::Draw_Rect(0, 174, 400, 66, GFX::Themes[GFX::SelectedTheme].DownListPrev);
const C2D_Image tempImg = entry->GetIcon(); const C2D_Image tempImg = entry->GetIcon();
const uint8_t offsetW = (48 - tempImg.subtex->width) / 2; // Center W. const uint8_t offsetW = (48 - tempImg.subtex->width) / 2; // Center W.
const uint8_t offsetH = (48 - tempImg.subtex->height) / 2; // Center H. const uint8_t offsetH = (48 - tempImg.subtex->height) / 2; // Center H.
C2D_DrawImageAt(tempImg, 9 + offsetW, 174 + 9 + offsetH, 0.5); C2D_DrawImageAt(tempImg, 9 + offsetW, 174 + 9 + offsetH, 0.5);
Gui::DrawString(70, 174 + 15, 0.45f, TEXT_COLOR, entries[store->GetDownloadIndex()], 310, 0, font); Gui::DrawString(70, 174 + 15, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, entries[StoreUtils::store->GetDownloadIndex()], 310, 0, font);
if (!sizes.empty()) { if (!sizes.empty()) {
if (sizes[store->GetDownloadIndex()] != "") { if (sizes[StoreUtils::store->GetDownloadIndex()] != "") {
Gui::DrawString(70, 174 + 30, 0.45f, TEXT_COLOR, Lang::get("SIZE") + ": " + sizes[store->GetDownloadIndex()], 310, 0, font); Gui::DrawString(70, 174 + 30, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SIZE") + ": " + sizes[StoreUtils::store->GetDownloadIndex()], 310, 0, font);
} }
} }
} }
} }
GFX::DrawBottom(); GFX::DrawTime();
Gui::Draw_Rect(48, 0, 272, 25, ENTRY_BAR_COLOR); GFX::DrawBattery();
Gui::Draw_Rect(48, 25, 272, 1, ENTRY_BAR_OUTL_COLOR); Animation::QueueEntryDone();
Gui::DrawStringCentered(25, 2, 0.6, TEXT_COLOR, Lang::get("AVAILABLE_DOWNLOADS"), 265, 0, font);
if (store && store->GetValid() && !fetch && entry) { GFX::DrawBottom();
Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
Gui::DrawStringCentered(17, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("AVAILABLE_DOWNLOADS"), 273, 0, font);
if (StoreUtils::store && StoreUtils::store->GetValid() && !fetch && entry) {
if (entries.size() > 0) { if (entries.size() > 0) {
for (int i = 0; i < DOWNLOAD_ENTRIES && i < (int)entries.size(); i++) { for (int i = 0; i < DOWNLOAD_ENTRIES && i < (int)entries.size(); i++) {
if (store->GetDownloadIndex() == i + store->GetDownloadSIndex()) GFX::DrawBox(downloadBoxes[i].x, downloadBoxes[i].y, downloadBoxes[i].w, downloadBoxes[i].h, false); if (StoreUtils::store->GetDownloadIndex() == i + StoreUtils::store->GetDownloadSIndex()) Gui::Draw_Rect(downloadBoxes[i].x, downloadBoxes[i].y, downloadBoxes[i].w, downloadBoxes[i].h, GFX::Themes[GFX::SelectedTheme].MarkSelected);
Gui::DrawStringCentered(54 - 160 + (262 / 2), downloadBoxes[i].y + 4, 0.45f, TEXT_COLOR, entries[(i + store->GetDownloadSIndex())], 260, 0, font); Gui::DrawStringCentered(46 - 160 + (241 / 2), downloadBoxes[i].y + 4, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, entries[(i + StoreUtils::store->GetDownloadSIndex())], 235, 0, font);
if (installs[(i + StoreUtils::store->GetDownloadSIndex())]) GFX::DrawSprite(sprites_installed_idx, installedPos[i].x, installedPos[i].y);
} }
if (is3DSX) GFX::DrawSprite(sprites_shortcut_idx, downloadBoxes[6].x, downloadBoxes[6].y); if (is3DSX) GFX::DrawSprite(sprites_shortcut_idx, downloadBoxes[6].x, downloadBoxes[6].y);
} else { // If no downloads available.. } else { // If no downloads available..
Gui::DrawStringCentered(54 - 160 + (262 / 2), downloadBoxes[0].y + 4, 0.5f, TEXT_COLOR, Lang::get("NO_DOWNLOADS_AVAILABLE"), 255, 0, font); Gui::DrawStringCentered(46 - 160 + (241 / 2), downloadBoxes[0].y + 4, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("NO_DOWNLOADS_AVAILABLE"), 235, 0, font);
} }
} }
} }
@@ -144,26 +162,25 @@ void StoreUtils::DrawDownList(const std::unique_ptr<Store> &store, const std::ve
- Execute an Entry of the download list. - Execute an Entry of the download list.
- Return back to EntryInfo through `B`. - Return back to EntryInfo through `B`.
const std::unique_ptr<Store> &store: Const Reference to the Store class, since we do not modify anything in it.
const std::unique_ptr<StoreEntry> &entry: Const Reference to the current StoreEntry, since we do not modify anything in it. const std::unique_ptr<StoreEntry> &entry: Const Reference to the current StoreEntry, since we do not modify anything in it.
const std::vector<std::string> &entries: Const Reference to the download list, since we do not modify anything in it. const std::vector<std::string> &entries: Const Reference to the download list, since we do not modify anything in it.
int &currentMenu: Reference to the StoreMode / Menu, so we can switch back to EntryInfo with `B`. int &currentMenu: Reference to the StoreMode / Menu, so we can switch back to EntryInfo with `B`.
std::unique_ptr<Meta> &meta: Reference to the Meta, to apply the updates stuff.
const int &lastMode: Const Reference to the last mode. const int &lastMode: Const Reference to the last mode.
int &smallDelay: Reference to the small delay. This helps to not directly press A. int &smallDelay: Reference to the small delay. This helps to not directly press A.
std::vector<bool> &installs: Reference to the installed states.
*/ */
void StoreUtils::DownloadHandle(const std::unique_ptr<Store> &store, const std::unique_ptr<StoreEntry> &entry, const std::vector<std::string> &entries, int &currentMenu, std::unique_ptr<Meta> &meta, const int &lastMode, int &smallDelay) { void StoreUtils::DownloadHandle(const std::unique_ptr<StoreEntry> &entry, const std::vector<std::string> &entries, int &currentMenu, const int &lastMode, int &smallDelay, std::vector<bool> &installs) {
if (store && entry) { // Ensure, store & entry is not a nullptr. if (StoreUtils::store && entry) { // Ensure, store & entry is not a nullptr.
if (smallDelay > 0) { if (smallDelay > 0) {
smallDelay--; smallDelay--;
} }
if ((hDown & KEY_Y) || (hDown & KEY_START) || (hDown & KEY_TOUCH && touching(touch, downloadBoxes[6]))) { if ((hDown & KEY_Y) || (hDown & KEY_START) || (hDown & KEY_TOUCH && touching(touch, downloadBoxes[6]))) {
if (is3DSX) { // Only allow if 3DSX. if (is3DSX) { // Only allow if 3DSX.
if (entries.size() <= 0) return; // Smaller than 0 -> No No. if (StoreUtils::entries.size() <= 0) return; // Smaller than 0 -> No No.
if (Msg::promptMsg(Lang::get("CREATE_SHORTCUT"))) { if (Msg::promptMsg(Lang::get("CREATE_SHORTCUT"))) {
if (CreateShortcut(entry->GetTitle(), store->GetDownloadIndex(), store->GetFileName(), entry->GetAuthor())) { if (CreateShortcut(entry->GetTitle(), StoreUtils::store->GetDownloadIndex(), StoreUtils::store->GetFileName(), entry->GetAuthor())) {
Msg::waitMsg(Lang::get("SHORTCUT_CREATED")); Msg::waitMsg(Lang::get("SHORTCUT_CREATED"));
} }
} }
@@ -173,43 +190,62 @@ void StoreUtils::DownloadHandle(const std::unique_ptr<Store> &store, const std::
if (hRepeat & KEY_DOWN) { if (hRepeat & KEY_DOWN) {
if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid. if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid.
if (store->GetDownloadIndex() < (int)entries.size() - 1) store->SetDownloadIndex(store->GetDownloadIndex() + 1); if (StoreUtils::store->GetDownloadIndex() < (int)entries.size() - 1) StoreUtils::store->SetDownloadIndex(StoreUtils::store->GetDownloadIndex() + 1);
else store->SetDownloadIndex(0); else StoreUtils::store->SetDownloadIndex(0);
} }
if (hRepeat & KEY_UP) { if (hRepeat & KEY_UP) {
if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid. if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid.
if (store->GetDownloadIndex() > 0) store->SetDownloadIndex(store->GetDownloadIndex() - 1); if (StoreUtils::store->GetDownloadIndex() > 0) StoreUtils::store->SetDownloadIndex(StoreUtils::store->GetDownloadIndex() - 1);
else store->SetDownloadIndex(entries.size() - 1); else StoreUtils::store->SetDownloadIndex(entries.size() - 1);
} }
if (hRepeat & KEY_RIGHT) { if (hRepeat & KEY_RIGHT) {
if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid. if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid.
if (store->GetDownloadIndex() + DOWNLOAD_ENTRIES < (int)entries.size()-1) store->SetDownloadIndex(store->GetDownloadIndex() + DOWNLOAD_ENTRIES); if (StoreUtils::store->GetDownloadIndex() + DOWNLOAD_ENTRIES < (int)entries.size()-1) StoreUtils::store->SetDownloadIndex(StoreUtils::store->GetDownloadIndex() + DOWNLOAD_ENTRIES);
else store->SetDownloadIndex(entries.size()-1); else StoreUtils::store->SetDownloadIndex(entries.size()-1);
} }
if (hRepeat & KEY_LEFT) { if (hRepeat & KEY_LEFT) {
if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid. if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid.
if (store->GetDownloadIndex() - DOWNLOAD_ENTRIES > 0) store->SetDownloadIndex(store->GetDownloadIndex() - DOWNLOAD_ENTRIES); if (StoreUtils::store->GetDownloadIndex() - DOWNLOAD_ENTRIES > 0) StoreUtils::store->SetDownloadIndex(StoreUtils::store->GetDownloadIndex() - DOWNLOAD_ENTRIES);
else store->SetDownloadIndex(0); else StoreUtils::store->SetDownloadIndex(0);
} }
if (smallDelay == 0 && hDown & KEY_TOUCH) { if (smallDelay == 0 && hDown & KEY_TOUCH) {
if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid. if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid.
bool didTouch = false;
for (int i = 0; i < DOWNLOAD_ENTRIES; i++) { for (int i = 0; i < DOWNLOAD_ENTRIES; i++) {
if (touching(touch, downloadBoxes[i])) { if (touching(touch, downloadBoxes[i])) {
if (i + store->GetDownloadSIndex() < (int)entries.size()) { if (i + StoreUtils::store->GetDownloadSIndex() < (int)entries.size()) {
if (Msg::promptMsg(Lang::get("EXECUTE_ENTRY") + "\n\n" + entries[i + store->GetDownloadSIndex()])) { if (Msg::promptMsg(Lang::get("EXECUTE_ENTRY") + "\n\n" + entries[i + StoreUtils::store->GetDownloadSIndex()])) {
ScriptUtils::runFunctions(store->GetJson(), entry->GetEntryIndex(), entries[i + store->GetDownloadSIndex()]); StoreUtils::AddToQueue(entry->GetEntryIndex(), entries[i + StoreUtils::store->GetDownloadSIndex()], entry->GetTitle(), entry->GetLastUpdated());
if (meta) meta->SetUpdated(store->GetUniStoreTitle(), entry->GetTitle(), entry->GetLastUpdated());
entry->SetUpdateAvl(false);
} }
didTouch = true;
break;
}
}
}
if (!didTouch) {
for (int i = 0; i < DOWNLOAD_ENTRIES; i++) {
if (touching(touch, installedPos[i])) {
if (i + StoreUtils::store->GetDownloadSIndex() < (int)entries.size()) {
if (installs[i + StoreUtils::store->GetDownloadSIndex()]) {
StoreUtils::meta->RemoveInstalled(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle(), entries[i + StoreUtils::store->GetDownloadSIndex()]);
installs[i + StoreUtils::store->GetDownloadSIndex()] = false;
}
}
didTouch = true;
break;
} }
} }
} }
@@ -218,17 +254,24 @@ void StoreUtils::DownloadHandle(const std::unique_ptr<Store> &store, const std::
if (smallDelay == 0 && hDown & KEY_A) { if (smallDelay == 0 && hDown & KEY_A) {
if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid. if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid.
if (Msg::promptMsg(Lang::get("EXECUTE_ENTRY") + "\n\n" + entries[store->GetDownloadIndex()])) { if (Msg::promptMsg(Lang::get("EXECUTE_ENTRY") + "\n\n" + entries[StoreUtils::store->GetDownloadIndex()])) {
ScriptUtils::runFunctions(store->GetJson(), entry->GetEntryIndex(), entries[store->GetDownloadIndex()]); StoreUtils::AddToQueue(entry->GetEntryIndex(), entries[StoreUtils::store->GetDownloadIndex()], entry->GetTitle(), entry->GetLastUpdated());
if (meta) meta->SetUpdated(store->GetUniStoreTitle(), entry->GetTitle(), entry->GetLastUpdated()); }
entry->SetUpdateAvl(false); }
if (hDown & KEY_X) {
if (entries.size() <= 0) return; // Smaller *than* 0 -> Invalid.
if (installs[StoreUtils::store->GetDownloadIndex()]) {
StoreUtils::meta->RemoveInstalled(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle(), entries[StoreUtils::store->GetDownloadIndex()]);
installs[StoreUtils::store->GetDownloadIndex()] = false;
} }
} }
if (hDown & KEY_B) currentMenu = lastMode; // Go back to EntryInfo. if (hDown & KEY_B) currentMenu = lastMode; // Go back to EntryInfo.
/* Scroll Handle. */ /* Scroll Handle. */
if (store->GetDownloadIndex() < store->GetDownloadSIndex()) store->SetDownloadSIndex(store->GetDownloadIndex()); if (StoreUtils::store->GetDownloadIndex() < StoreUtils::store->GetDownloadSIndex()) StoreUtils::store->SetDownloadSIndex(StoreUtils::store->GetDownloadIndex());
else if (store->GetDownloadIndex() > store->GetDownloadSIndex() + DOWNLOAD_ENTRIES - 1) store->SetDownloadSIndex(store->GetDownloadIndex() - DOWNLOAD_ENTRIES + 1); else if (StoreUtils::store->GetDownloadIndex() > StoreUtils::store->GetDownloadSIndex() + DOWNLOAD_ENTRIES - 1) StoreUtils::store->SetDownloadSIndex(StoreUtils::store->GetDownloadIndex() - DOWNLOAD_ENTRIES + 1);
} }
} }
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,40 +24,41 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "common.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include "structs.hpp" #include "structs.hpp"
extern bool touching(touchPosition touch, Structs::ButtonPos button); extern bool touching(touchPosition touch, Structs::ButtonPos button);
static const Structs::ButtonPos btn = { 53, 215, 24, 24 }; static const Structs::ButtonPos btn = { 45, 215, 24, 24 };
static const Structs::ButtonPos sshot = { 83, 215, 24, 24 }; static const Structs::ButtonPos sshot = { 75, 215, 24, 24 };
static const Structs::ButtonPos notes = { 113, 215, 24, 24 }; static const Structs::ButtonPos notes = { 105, 215, 24, 24 };
extern bool checkWifiStatus(); extern bool checkWifiStatus();
extern bool QueueRuns;
/* /*
Draw the Entry Info part. Draw the Entry Info part.
const std::unique_ptr<Store> &store: Const Reference to the Store class.
const std::unique_ptr<StoreEntry> &entry: Const Reference to the current StoreEntry. const std::unique_ptr<StoreEntry> &entry: Const Reference to the current StoreEntry.
*/ */
void StoreUtils::DrawEntryInfo(const std::unique_ptr<Store> &store, const std::unique_ptr<StoreEntry> &entry) { void StoreUtils::DrawEntryInfo(const std::unique_ptr<StoreEntry> &entry) {
if (store && entry) { // Ensure, store & entry is not a nullptr. if (StoreUtils::store && entry) { // Ensure, store & entry is not a nullptr.
Gui::Draw_Rect(48, 0, 272, 36, ENTRY_BAR_COLOR); Gui::Draw_Rect(40, 0, 280, 36, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(48, 36, 272, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(40, 36, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
Gui::DrawStringCentered(25, 0, 0.6, TEXT_COLOR, entry->GetTitle(), 265, 0, font); Gui::DrawStringCentered(17, 0, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, entry->GetTitle(), 273, 0, font);
Gui::DrawStringCentered(25, 20, 0.4, TEXT_COLOR, entry->GetAuthor(), 265, 0, font); Gui::DrawStringCentered(17, 20, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, entry->GetAuthor(), 273, 0, font);
Gui::DrawStringCentered(25, 50, 0.4, TEXT_COLOR, entry->GetDescription(), 240, 0, font, C2D_WordWrap); Gui::DrawStringCentered(17, 50, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, entry->GetDescription(), 248, 0, font, C2D_WordWrap);
Gui::DrawString(61, 130, 0.45, TEXT_COLOR, Lang::get("VERSION") + ": " + entry->GetVersion(), 240, 0, font); Gui::DrawString(53, 130, 0.45, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("VERSION") + ": " + entry->GetVersion(), 248, 0, font);
Gui::DrawString(61, 145, 0.45, TEXT_COLOR, Lang::get("CATEGORY") + ": " + entry->GetCategory(), 240, 0, font); Gui::DrawString(53, 145, 0.45, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CATEGORY") + ": " + entry->GetCategory(), 248, 0, font);
Gui::DrawString(61, 160, 0.45, TEXT_COLOR, Lang::get("CONSOLE") + ": " + entry->GetConsole(), 240, 0, font); Gui::DrawString(53, 160, 0.45, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CONSOLE") + ": " + entry->GetConsole(), 248, 0, font);
Gui::DrawString(61, 175, 0.45, TEXT_COLOR, Lang::get("LAST_UPDATED") + ": " + entry->GetLastUpdated(), 240, 0, font); Gui::DrawString(53, 175, 0.45, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("LAST_UPDATED") + ": " + entry->GetLastUpdated(), 248, 0, font);
Gui::DrawString(61, 190, 0.45, TEXT_COLOR, Lang::get("LICENSE") + ": " + entry->GetLicense(), 240, 0, font); Gui::DrawString(53, 190, 0.45, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("LICENSE") + ": " + entry->GetLicense(), 248, 0, font);
GFX::DrawBox(btn.x, btn.y, btn.w, btn.h, false); GFX::DrawBox(btn.x, btn.y, btn.w, btn.h, false);
if (!entry->GetScreenshots().empty()) GFX::DrawSprite(sprites_screenshot_idx, sshot.x, sshot.y); if (!entry->GetScreenshots().empty()) GFX::DrawSprite(sprites_screenshot_idx, sshot.x, sshot.y);
if (entry->GetReleaseNotes() != "") GFX::DrawSprite(sprites_notes_idx, notes.x, notes.y); if (entry->GetReleaseNotes() != "") GFX::DrawSprite(sprites_notes_idx, notes.x, notes.y);
Gui::DrawString(btn.x + 5, btn.y + 2, 0.6f, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(btn.x + 5, btn.y + 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
} }
} }
@@ -71,8 +72,8 @@ void StoreUtils::DrawEntryInfo(const std::unique_ptr<Store> &store, const std::u
bool &showMark: Reference to showMark.. to show the mark menu. bool &showMark: Reference to showMark.. to show the mark menu.
bool &fetch: Reference to fetch, so we know, if we need to fetch, when accessing download list. bool &fetch: Reference to fetch, so we know, if we need to fetch, when accessing download list.
bool &sFetch: Reference to the screenshot fetch. bool &sFetch: Reference to the screenshot fetch.
int &mode: Reference to the Store mode. int &mode: Reference to the store mode.
const std::unique_ptr<StoreEntry> &entry: The Store Entry. const std::unique_ptr<StoreEntry> &entry: The store Entry.
*/ */
void StoreUtils::EntryHandle(bool &showMark, bool &fetch, bool &sFetch, int &mode, const std::unique_ptr<StoreEntry> &entry) { void StoreUtils::EntryHandle(bool &showMark, bool &fetch, bool &sFetch, int &mode, const std::unique_ptr<StoreEntry> &entry) {
if (entry) { if (entry) {
@@ -81,14 +82,21 @@ void StoreUtils::EntryHandle(bool &showMark, bool &fetch, bool &sFetch, int &mod
if ((hDown & KEY_Y) || (hDown & KEY_TOUCH && touching(touch, sshot))) { if ((hDown & KEY_Y) || (hDown & KEY_TOUCH && touching(touch, sshot))) {
if (!entry->GetScreenshots().empty()) { if (!entry->GetScreenshots().empty()) {
if (checkWifiStatus()) { if (checkWifiStatus()) {
sFetch = true; if (QueueRuns) {
mode = 5; if (!Msg::promptMsg(Lang::get("FEATURE_SIDE_EFFECTS"))) return;
sFetch = true;
mode = 6;
} else {
sFetch = true;
mode = 6;
}
} }
} }
} }
if ((hDown & KEY_X) || (hDown & KEY_TOUCH && touching(touch, notes))) { if ((hDown & KEY_X) || (hDown & KEY_TOUCH && touching(touch, notes))) {
if (entry->GetReleaseNotes() != "") mode = 6; if (entry->GetReleaseNotes() != "") mode = 7;
} }
} }
} }
+172
View File
@@ -0,0 +1,172 @@
/*
* This file is part of Universal-Updater
* Copyright (C) 2019-2021 Universal-Team
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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 "storeUtils.hpp"
#include "structs.hpp"
static const std::vector<Structs::ButtonPos> GridBoxes = {
{ 25, 45, 50, 50 },
{ 100, 45, 50, 50 },
{ 175, 45, 50, 50 },
{ 250, 45, 50, 50 },
{ 325, 45, 50, 50 },
{ 25, 105, 50, 50 },
{ 100, 105, 50, 50 },
{ 175, 105, 50, 50 },
{ 250, 105, 50, 50 },
{ 325, 105, 50, 50 },
{ 25, 165, 50, 50 },
{ 100, 165, 50, 50 },
{ 175, 165, 50, 50 },
{ 250, 165, 50, 50 },
{ 325, 165, 50, 50 }
};
/* Draw the Top Grid. */
void StoreUtils::DrawGrid() {
if (StoreUtils::store) { // Ensure, store is not a nullptr.
if (config->usebg() && StoreUtils::store->customBG()) {
C2D_DrawImageAt(StoreUtils::store->GetStoreImg(), 0, 26, 0.5f, nullptr);
} else {
Gui::Draw_Rect(0, 26, 400, 214, GFX::Themes[GFX::SelectedTheme].BGColor);
}
for (int i = 0, i2 = 0 + (StoreUtils::store->GetScreenIndx() * 5); i2 < 15 + (StoreUtils::store->GetScreenIndx() * 5) && i2 < (int)StoreUtils::entries.size(); i2++, i++) {
/* Boxes. */
if (i == StoreUtils::store->GetBox()) GFX::DrawBox(GridBoxes[i].x, GridBoxes[i].y, 50, 50, true);
/* Ensure, entries is larger than the index. */
if ((int)StoreUtils::entries.size() > i2) {
if (StoreUtils::entries[i2]) { // Ensure, the Entry is not nullptr.
const C2D_Image tempImg = StoreUtils::entries[i2]->GetIcon();
const uint8_t offsetW = (48 - tempImg.subtex->width) / 2; // Center W.
const uint8_t offsetH = (48 - tempImg.subtex->height) / 2; // Center H.
C2D_DrawImageAt(tempImg, GridBoxes[i].x + 1 + offsetW, GridBoxes[i].y + 1 + offsetH, 0.5);
/* Update Available mark. */
if (StoreUtils::entries[i2]->GetUpdateAvl()) GFX::DrawSprite(sprites_update_app_idx, GridBoxes[i].x + 32, GridBoxes[i].y + 32);
}
}
}
}
}
/*
Top Grid Logic Handle.
Here you can..
- Scroll through the Grid with the D-Pad.
const int &currentMode: Reference to the current Mode.
int &lastMode: Reference to the last mode.
bool &fetch: Reference to fetch.
int &smallDelay: Reference to the small delay.
*/
void StoreUtils::GridLogic(int &currentMode, int &lastMode, bool &fetch, int &smallDelay) {
if (StoreUtils::store) { // Ensure, store is not a nullptr.
if (hRepeat & KEY_DOWN) {
if (StoreUtils::store->GetBox() > 9) {
if (StoreUtils::store->GetEntry() + 5 < (int)StoreUtils::entries.size() - 1) {
StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() + 5);
if (StoreUtils::entries.size() > 15) StoreUtils::store->SetScreenIndx((StoreUtils::store->GetEntry() / 5) - 2);
} else {
if (StoreUtils::store->GetEntry() < (int)StoreUtils::entries.size() - 1) {
StoreUtils::store->SetEntry(StoreUtils::entries.size() - 1);
StoreUtils::store->SetBox(10 + (StoreUtils::store->GetEntry() % 5));
if (StoreUtils::entries.size() > 15) StoreUtils::store->SetScreenIndx((StoreUtils::store->GetEntry() / 5) - 2);
}
}
} else {
if (StoreUtils::store->GetEntry() + 5 < (int)StoreUtils::entries.size()) {
StoreUtils::store->SetBox(StoreUtils::store->GetBox() + 5);
StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() + 5);
}
}
}
if (hRepeat & KEY_RIGHT) {
if (StoreUtils::store->GetEntry() < (int)StoreUtils::entries.size() - 1) {
if (StoreUtils::store->GetBox() < 14) {
StoreUtils::store->SetBox(StoreUtils::store->GetBox() + 1);
StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() + 1);
} else {
StoreUtils::store->SetBox(10);
StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() + 1);
StoreUtils::store->SetScreenIndx((StoreUtils::store->GetEntry() / 5) - 2);
}
}
}
if (hRepeat & KEY_LEFT) {
if (StoreUtils::store->GetEntry() > 0) {
if (StoreUtils::store->GetBox() > 0) {
StoreUtils::store->SetBox(StoreUtils::store->GetBox() - 1);
StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() - 1);
} else {
StoreUtils::store->SetBox(4);
StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() - 1);
StoreUtils::store->SetScreenIndx((StoreUtils::store->GetEntry() / 5));
}
}
}
if (hRepeat & KEY_UP) {
if (StoreUtils::store->GetBox() < 5) {
if (StoreUtils::store->GetEntry() > 4) {
StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() - 5);
StoreUtils::store->SetScreenIndx((StoreUtils::store->GetEntry() / 5));
}
} else {
StoreUtils::store->SetBox(StoreUtils::store->GetBox() - 5);
StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() - 5);
}
}
if (hDown & KEY_A) {
fetch = true;
smallDelay = 5;
lastMode = currentMode;
currentMode = 1;
}
}
}
+119
View File
@@ -0,0 +1,119 @@
/*
* This file is part of Universal-Updater
* Copyright (C) 2019-2021 Universal-Team
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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 "storeUtils.hpp"
#include "structs.hpp"
static const std::vector<Structs::ButtonPos> StoreBoxesList = {
{ 20, 45, 360, 50 },
{ 20, 105, 360, 50 },
{ 20, 165, 360, 50 }
};
/* Draw the top List. */
void StoreUtils::DrawList() {
if (StoreUtils::store) { // Ensure, store is not a nullptr.
if (config->usebg() && StoreUtils::store->customBG()) {
C2D_DrawImageAt(StoreUtils::store->GetStoreImg(), 0, 26, 0.5f, nullptr);
} else {
Gui::Draw_Rect(0, 26, 400, 214, GFX::Themes[GFX::SelectedTheme].BGColor);
}
if (StoreUtils::entries.size() > 0) {
for (int i = 0; i < 3 && i < (int)StoreUtils::entries.size(); i++) {
if (i + StoreUtils::store->GetScreenIndx() == StoreUtils::store->GetEntry()) {
GFX::DrawBox(StoreBoxesList[i].x, StoreBoxesList[i].y, StoreBoxesList[i].w, StoreBoxesList[i].h, false);
}
/* Ensure, entries is larger than the index. */
if ((int)StoreUtils::entries.size() > i + StoreUtils::store->GetScreenIndx()) {
if (StoreUtils::entries[i + StoreUtils::store->GetScreenIndx()]) { // Ensure, the Entry is not nullptr.
const C2D_Image tempImg = StoreUtils::entries[i + StoreUtils::store->GetScreenIndx()]->GetIcon();
const uint8_t offsetW = (48 - tempImg.subtex->width) / 2; // Center W.
const uint8_t offsetH = (48 - tempImg.subtex->height) / 2; // Center H.
C2D_DrawImageAt(tempImg, StoreBoxesList[i].x + 1 + offsetW, StoreBoxesList[i].y + 1 + offsetH, 0.5);
}
if (StoreUtils::entries[i + StoreUtils::store->GetScreenIndx()]->GetUpdateAvl()) GFX::DrawSprite(sprites_update_app_idx, StoreBoxesList[i].x + 32, StoreBoxesList[i].y + 32);
Gui::DrawStringCentered(29, StoreBoxesList[i].y + 5, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, StoreUtils::entries[i + StoreUtils::store->GetScreenIndx()]->GetTitle(), 300, 0, font);
Gui::DrawStringCentered(29, StoreBoxesList[i].y + 24, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, StoreUtils::entries[i + StoreUtils::store->GetScreenIndx()]->GetAuthor(), 300, 0, font);
}
}
}
}
}
/*
Top List Logic Handle.
Here you can..
- Scroll through the Grid with the D-Pad Up / Down and skip 3 entries with Left / Right.
int &currentMode: Const Reference to the current Mode.
int &lastMode: Reference to the last mode.
bool &fetch: Reference to fetch.
int &smallDelay: Reference to the small delay.
*/
void StoreUtils::ListLogic(int &currentMode, int &lastMode, bool &fetch, int &smallDelay) {
if (StoreUtils::store) { // Ensure, store is not a nullptr.
if (hRepeat & KEY_DOWN) {
if (StoreUtils::store->GetEntry() < (int)StoreUtils::entries.size() - 1) StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() + 1);
else StoreUtils::store->SetEntry(0);
}
if (hRepeat & KEY_RIGHT) {
if (StoreUtils::store->GetEntry() < (int)StoreUtils::entries.size() - 3) StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() + 3);
else StoreUtils::store->SetEntry(StoreUtils::entries.size() - 1);
}
if (hRepeat & KEY_LEFT) {
if (StoreUtils::store->GetEntry() - 2 > 0) StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() - 3);
else StoreUtils::store->SetEntry(0);
}
if (hRepeat & KEY_UP) {
if (StoreUtils::store->GetEntry() > 0) StoreUtils::store->SetEntry(StoreUtils::store->GetEntry() - 1);
else StoreUtils::store->SetEntry(StoreUtils::entries.size() - 1);
}
if (hDown & KEY_A) {
fetch = true;
smallDelay = 5;
lastMode = currentMode;
currentMode = 1;
}
/* Scroll Logic. */
if (StoreUtils::store->GetEntry() < StoreUtils::store->GetScreenIndx()) StoreUtils::store->SetScreenIndx(StoreUtils::store->GetEntry());
else if (StoreUtils::store->GetEntry() > StoreUtils::store->GetScreenIndx() + 3 - 1) StoreUtils::store->SetScreenIndx(StoreUtils::store->GetEntry() - 3 + 1);
}
}
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "common.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include "structs.hpp" #include "structs.hpp"
@@ -35,7 +36,7 @@ static const std::vector<Structs::ButtonPos> markBox = {
{ 196, 94, 52, 52 }, { 196, 94, 52, 52 },
{ 258, 94, 52, 52 }, { 258, 94, 52, 52 },
{ 53, 215, 24, 24 } { 45, 215, 24, 24 }
}; };
/* /*
@@ -47,28 +48,28 @@ void StoreUtils::DisplayMarkBox(int marks) {
Gui::Draw_Rect(0, 0, 320, 240, DIM_COLOR); // Darken. Gui::Draw_Rect(0, 0, 320, 240, DIM_COLOR); // Darken.
Gui::Draw_Rect(markBox[0].x, markBox[0].y, markBox[0].w, markBox[0].h, (marks & favoriteMarks::STAR ? Gui::Draw_Rect(markBox[0].x, markBox[0].y, markBox[0].w, markBox[0].h, (marks & favoriteMarks::STAR ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::Draw_Rect(markBox[1].x, markBox[1].y, markBox[1].w, markBox[1].h, (marks & favoriteMarks::HEART ? Gui::Draw_Rect(markBox[1].x, markBox[1].y, markBox[1].w, markBox[1].h, (marks & favoriteMarks::HEART ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::Draw_Rect(markBox[2].x, markBox[2].y, markBox[2].w, markBox[2].h, (marks & favoriteMarks::DIAMOND ? Gui::Draw_Rect(markBox[2].x, markBox[2].y, markBox[2].w, markBox[2].h, (marks & favoriteMarks::DIAMOND ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::Draw_Rect(markBox[3].x, markBox[3].y, markBox[3].w, markBox[3].h, (marks & favoriteMarks::CLUBS ? Gui::Draw_Rect(markBox[3].x, markBox[3].y, markBox[3].w, markBox[3].h, (marks & favoriteMarks::CLUBS ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::Draw_Rect(markBox[4].x, markBox[4].y, markBox[4].w, markBox[4].h, (marks & favoriteMarks::SPADE ? Gui::Draw_Rect(markBox[4].x, markBox[4].y, markBox[4].w, markBox[4].h, (marks & favoriteMarks::SPADE ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::DrawString(markBox[0].x + 15, markBox[0].y + 11, 0.9, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(markBox[0].x + 15, markBox[0].y + 11, 0.9, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
Gui::DrawString(markBox[1].x + 15, markBox[1].y + 11, 0.9, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(markBox[1].x + 15, markBox[1].y + 11, 0.9, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
Gui::DrawString(markBox[2].x + 15, markBox[2].y + 11, 0.9, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(markBox[2].x + 15, markBox[2].y + 11, 0.9, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
Gui::DrawString(markBox[3].x + 15, markBox[3].y + 11, 0.9, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(markBox[3].x + 15, markBox[3].y + 11, 0.9, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
Gui::DrawString(markBox[4].x + 15, markBox[4].y + 11, 0.9, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(markBox[4].x + 15, markBox[4].y + 11, 0.9, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
GFX::DrawBox(markBox[5].x, markBox[5].y, markBox[5].w, markBox[5].h, false); GFX::DrawBox(markBox[5].x, markBox[5].y, markBox[5].w, markBox[5].h, false);
Gui::DrawString(markBox[5].x + 5, markBox[5].y + 2, 0.6f, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(markBox[5].x + 5, markBox[5].y + 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
} }
/* /*
@@ -79,47 +80,45 @@ void StoreUtils::DisplayMarkBox(int marks) {
- Return to EntryInfo with `B`. - Return to EntryInfo with `B`.
std::unique_ptr<StoreEntry> &entry: Reference to the current StoreEntry. std::unique_ptr<StoreEntry> &entry: Reference to the current StoreEntry.
const std::unique_ptr<Store> &store: Const Reference to the Store, since we do not modify anything there.
bool &showMark: Reference to showMark, so we know, if we should stay here or not. bool &showMark: Reference to showMark, so we know, if we should stay here or not.
std::unique_ptr<Meta> &meta: Reference to the Meta class.
*/ */
void StoreUtils::MarkHandle(std::unique_ptr<StoreEntry> &entry, const std::unique_ptr<Store> &store, bool &showMark, std::unique_ptr<Meta> &meta) { void StoreUtils::MarkHandle(std::unique_ptr<StoreEntry> &entry, bool &showMark) {
hidScanInput(); hidScanInput();
touchPosition t; touchPosition t;
hidTouchRead(&t); hidTouchRead(&t);
if (meta && entry && store) { if (StoreUtils::meta && entry && StoreUtils::store) {
if (hidKeysDown() & KEY_TOUCH) { if (hidKeysDown() & KEY_TOUCH) {
/* Star. */ /* Star. */
if (touching(t, markBox[0])) { if (touching(t, markBox[0])) {
meta->SetMarks(store->GetUniStoreTitle(), entry->GetTitle(), StoreUtils::meta->SetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle(),
meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::STAR); StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::STAR);
entry->SetMark(meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle())); entry->SetMark(StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()));
/* Heart. */ /* Heart. */
} else if (touching(t, markBox[1])) { } else if (touching(t, markBox[1])) {
meta->SetMarks(store->GetUniStoreTitle(), entry->GetTitle(), StoreUtils::meta->SetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle(),
meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::HEART); StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::HEART);
entry->SetMark(meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle())); entry->SetMark(StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()));
/* Diamond. */ /* Diamond. */
} else if (touching(t, markBox[2])) { } else if (touching(t, markBox[2])) {
meta->SetMarks(store->GetUniStoreTitle(), entry->GetTitle(), StoreUtils::meta->SetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle(),
meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::DIAMOND); StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::DIAMOND);
entry->SetMark(meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle())); entry->SetMark(StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()));
/* Clubs. */ /* Clubs. */
} else if (touching(t, markBox[3])) { } else if (touching(t, markBox[3])) {
meta->SetMarks(store->GetUniStoreTitle(), entry->GetTitle(), StoreUtils::meta->SetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle(),
meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::CLUBS); StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::CLUBS);
entry->SetMark(meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle())); entry->SetMark(StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()));
/* Spade. */ /* Spade. */
} else if (touching(t, markBox[4])) { } else if (touching(t, markBox[4])) {
meta->SetMarks(store->GetUniStoreTitle(), entry->GetTitle(), StoreUtils::meta->SetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle(),
meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::SPADE); StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()) ^ favoriteMarks::SPADE);
entry->SetMark(meta->GetMarks(store->GetUniStoreTitle(), entry->GetTitle())); entry->SetMark(StoreUtils::meta->GetMarks(StoreUtils::store->GetUniStoreTitle(), entry->GetTitle()));
} }
} }
} }
+311
View File
@@ -0,0 +1,311 @@
/*
* This file is part of Universal-Updater
* Copyright (C) 2019-2021 Universal-Team
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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 "queueSystem.hpp"
#include "scriptUtils.hpp"
#include "storeUtils.hpp"
#include "structs.hpp"
#include <curl/curl.h>
#include <math.h> // for std::min.
extern u32 extractSize, writeOffset;
extern u32 installSize, installOffset;
extern u32 copyOffset, copySize;
extern int filesExtracted, extractFilesCount;
extern curl_off_t downloadTotal;
extern curl_off_t downloadNow;
extern curl_off_t downloadSpeed;
extern CURL *CurlHandle;
bool ShowQueueProgress = true; // Queue Mode View.
int queueMenuIdx = 0; // Queue Menu Index.
#define QUEUE_ENTRIES 2 // 2 entries per screen or so.
extern bool touching(touchPosition touch, Structs::ButtonPos button);
static const std::vector<Structs::ButtonPos> QueueBoxes = {
{ 47, 36, 266, 90 },
{ 47, 139, 266, 90 },
{ 292, 37, 20, 20 }, // Cancel current Queue.
{ 292, 140, 20, 20 } // Remove next Queue.
};
extern std::deque<std::unique_ptr<Queue>> queueEntries;
void DrawStatus(QueueStatus s) {
if (!ShowQueueProgress) {
if (!queueEntries.empty()) {
Gui::DrawString(QueueBoxes[0].x + 10, QueueBoxes[0].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, queueEntries[0]->name, 230, 0, font);
char prog[256];
snprintf(prog, sizeof(prog), Lang::get("QUEUE_PROGRESS").c_str(), queueEntries[0]->current, queueEntries[0]->total);
Gui::DrawString(QueueBoxes[0].x + 241, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, prog, 80, 0, font, C2D_AlignRight);
Gui::Draw_Rect(QueueBoxes[0].x + 60, QueueBoxes[0].y + 30, 182, 30, GFX::Themes[GFX::SelectedTheme].ProgressbarOut);
Gui::Draw_Rect(QueueBoxes[0].x + 60 + 1, QueueBoxes[0].y + 30 + 1, (int)(((float)queueEntries[0]->current / (float)queueEntries[0]->total) * 180.0f), 28, GFX::Themes[GFX::SelectedTheme].ProgressbarIn);
switch(s) {
case QueueStatus::Done:
case QueueStatus::Failed:
case QueueStatus::None:
break;
case QueueStatus::Copying:
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("OP_COPYING"), 120, 0, font);
break;
case QueueStatus::Deleting:
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("OP_DELETING"), 120, 0, font);
break;
case QueueStatus::Downloading:
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("OP_DOWNLOADING"), 120, 0, font);
break;
case QueueStatus::Extracting:
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("OP_EXTRACTING"), 120, 0, font);
break;
case QueueStatus::Installing:
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("OP_INSTALLING"), 120, 0, font);
break;
case QueueStatus::Moving:
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("OP_MOVING"), 120, 0, font);
break;
case QueueStatus::Request:
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("OP_WAITING"), 120, 0, font);
break;
}
}
return;
}
char str[256], str2[256];
/* Progress. */
if (!queueEntries.empty()) {
char prog[256];
snprintf(prog, sizeof(prog), Lang::get("QUEUE_PROGRESS").c_str(), queueEntries[0]->current, queueEntries[0]->total);
Gui::DrawString((QueueBoxes[0].x + 241), QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, prog, 80, 0, font, C2D_AlignRight);
}
/* String Handle. */
switch(s) {
case QueueStatus::Done:
case QueueStatus::Failed:
case QueueStatus::None:
case QueueStatus::Moving:
break;
case QueueStatus::Copying:
snprintf(str, sizeof(str), Lang::get("COPYING").c_str(),
StringUtils::formatBytes(copyOffset).c_str(),
StringUtils::formatBytes(copySize).c_str(),
((float)copyOffset/(float)copySize) * 100.0f);
break;
case QueueStatus::Deleting:
snprintf(str, sizeof(str), Lang::get("DELETING").c_str());
break;
case QueueStatus::Downloading:
if (CurlHandle) curl_easy_getinfo(CurlHandle, CURLINFO_SPEED_DOWNLOAD_T, &downloadSpeed);
else downloadSpeed = 0;
if (downloadTotal < 1.0f) downloadTotal = 1.0f;
if (downloadTotal < downloadNow) downloadTotal = downloadNow;
snprintf(str, sizeof(str), Lang::get("DOWNLOADING").c_str(),
StringUtils::formatBytes(downloadNow).c_str(),
StringUtils::formatBytes(downloadTotal).c_str(),
((float)downloadNow/(float)downloadTotal) * 100.0f);
snprintf(str2, sizeof(str2), Lang::get("DOWNLOAD_SPEED").c_str(),
((downloadSpeed / 1024)));
break;
case QueueStatus::Extracting:
snprintf(str, sizeof(str), Lang::get("EXTRACTING").c_str(),
StringUtils::formatBytes(writeOffset).c_str(),
StringUtils::formatBytes(extractSize).c_str(),
((float)writeOffset/(float)extractSize) * 100.0f);
snprintf(str2, sizeof(str2), Lang::get("FILES").c_str(),
filesExtracted, extractFilesCount);
break;
case QueueStatus::Installing:
snprintf(str, sizeof(str), Lang::get("INSTALLING").c_str(),
StringUtils::formatBytes(installOffset).c_str(),
StringUtils::formatBytes(installSize).c_str(),
((float)installOffset/(float)installSize) * 100.0f);
break;
case QueueStatus::Request:
snprintf(str, sizeof(str), Lang::get("OP_WAITING").c_str());
snprintf(str2, sizeof(str2), Lang::get("ACTION_REQUIRED").c_str());
break;
}
/* Draw Handle. */
switch(s) {
case QueueStatus::Done:
case QueueStatus::Failed:
case QueueStatus::None:
break;
case QueueStatus::Copying:
Gui::DrawString(QueueBoxes[0].x + 10, QueueBoxes[0].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 230, 0, font);
Gui::Draw_Rect(QueueBoxes[0].x + 60, QueueBoxes[0].y + 30, 182, 30, GFX::Themes[GFX::SelectedTheme].ProgressbarOut);
Gui::Draw_Rect(QueueBoxes[0].x + 60 + 1, QueueBoxes[0].y + 30 + 1, (int)(((float)copyOffset / (float)copySize) * 180.0f), 28, GFX::Themes[GFX::SelectedTheme].ProgressbarIn);
break;
case QueueStatus::Deleting:
Gui::DrawString(QueueBoxes[0].x + 10, QueueBoxes[0].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 230, 0, font);
break;
case QueueStatus::Downloading:
Gui::DrawString(QueueBoxes[0].x + 10, QueueBoxes[0].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 230, 0, font);
Gui::Draw_Rect(QueueBoxes[0].x + 60, QueueBoxes[0].y + 30, 182, 30, GFX::Themes[GFX::SelectedTheme].ProgressbarOut);
Gui::Draw_Rect(QueueBoxes[0].x + 60 + 1, QueueBoxes[0].y + 30 + 1, (int)(((float)downloadNow / (float)downloadTotal) * 180.0f), 28, GFX::Themes[GFX::SelectedTheme].ProgressbarIn);
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, str2, 120, 0, font);
break;
case QueueStatus::Extracting:
Gui::DrawString(QueueBoxes[0].x + 10, QueueBoxes[0].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 230, 0, font);
Gui::Draw_Rect(QueueBoxes[0].x + 60, QueueBoxes[0].y + 30, 182, 30, GFX::Themes[GFX::SelectedTheme].ProgressbarOut);
Gui::Draw_Rect(QueueBoxes[0].x + 60 + 1, QueueBoxes[0].y + 30 + 1, (int)(((float)writeOffset / (float)extractSize) * 180.0f), 28, GFX::Themes[GFX::SelectedTheme].ProgressbarIn);
Gui::DrawString(QueueBoxes[0].x + 60, QueueBoxes[0].y + 68, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, str2, 120, 0, font);
break;
case QueueStatus::Installing:
Gui::DrawString(QueueBoxes[0].x + 10, QueueBoxes[0].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 230, 0, font);
Gui::Draw_Rect(QueueBoxes[0].x + 60, QueueBoxes[0].y + 30, 182, 30, GFX::Themes[GFX::SelectedTheme].ProgressbarOut);
Gui::Draw_Rect(QueueBoxes[0].x + 60 + 1, QueueBoxes[0].y + 30 + 1, (int)(((float)installOffset / (float)installSize) * 180.0f), 28, GFX::Themes[GFX::SelectedTheme].ProgressbarIn);
break;
case QueueStatus::Moving:
Gui::DrawString(QueueBoxes[0].x + 10, QueueBoxes[0].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("OP_MOVING"), 230, 0, font);
break;
case QueueStatus::Request:
Gui::DrawString(QueueBoxes[0].x + 10, QueueBoxes[0].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 230, 0, font);
Gui::Draw_Rect(QueueBoxes[0].x + 60, QueueBoxes[0].y + 30, 182, 30, GFX::Themes[GFX::SelectedTheme].ProgressbarOut);
Gui::DrawStringCentered(QueueBoxes[0].x + 151 - 160, QueueBoxes[0].y + 32, 0.8f, GFX::Themes[GFX::SelectedTheme].TextColor, str2, 180, 0, font);
break;
}
}
void StoreUtils::DrawQueueMenu(const int queueIndex) {
Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
Gui::DrawStringCentered(17, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("QUEUE"), 273, 0, font);
if (!queueEntries.empty()) {
Gui::Draw_Rect(QueueBoxes[0].x, QueueBoxes[0].y, QueueBoxes[0].w, QueueBoxes[0].h, GFX::Themes[GFX::SelectedTheme].MarkSelected);
const C2D_Image tempImg = queueEntries[0]->icn;
const uint8_t offsetW = (48 - tempImg.subtex->width) / 2; // Center W.
const uint8_t offsetH = (48 - tempImg.subtex->height) / 2; // Center H.
C2D_DrawImageAt(tempImg, QueueBoxes[0].x + 5 + offsetW, QueueBoxes[0].y + 21 + offsetH, 0.5f);
DrawStatus(queueEntries[0]->status);
GFX::DrawSprite(sprites_cancel_idx, QueueBoxes[2].x, QueueBoxes[2].y); // Don't show until properly implemented.
/* The next Queue Entries being displayed below. */
if ((1 + queueMenuIdx) < (int)queueEntries.size()) {
Gui::Draw_Rect(QueueBoxes[1].x, QueueBoxes[1].y, QueueBoxes[1].w, QueueBoxes[1].h, GFX::Themes[GFX::SelectedTheme].MarkUnselected);
const C2D_Image tempImg2 = queueEntries[1 + queueMenuIdx]->icn;
const uint8_t offsetW2 = (48 - tempImg2.subtex->width) / 2; // Center W.
const uint8_t offsetH2 = (48 - tempImg2.subtex->height) / 2; // Center H.
C2D_DrawImageAt(tempImg2, QueueBoxes[1].x + 5 + offsetW2, QueueBoxes[1].y + 21 + offsetH2, 0.5f);
Gui::DrawString(QueueBoxes[1].x + 10, QueueBoxes[1].y + 5, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, queueEntries[1 + queueMenuIdx]->name, 230, 0, font);
Gui::DrawString(QueueBoxes[1].x + 60, QueueBoxes[1].y + 30, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("QUEUE_POSITION") + ": " + std::to_string(queueMenuIdx + 1), 0, 0, font);
/* Cancel. */
GFX::DrawSprite(sprites_cancel_idx, QueueBoxes[3].x, QueueBoxes[3].y);
}
}
}
void StoreUtils::QueueMenuHandle(int &queueIndex, int &storeMode) {
if (!queueEntries.empty()) {
if ((1 + queueMenuIdx) > (int)queueEntries.size() - 1) queueMenuIdx = std::max<int>((int)(queueEntries.size() - 1) - 1, 0); // Ensure this really doesn't go below 0.
}
if (hDown & KEY_TOUCH) {
/* Current Queue Cancel. */
if (QueueSystem::RequestNeeded == NO_REQUEST && touching(touch, QueueBoxes[2])) { // Needs to be above the 0 one, otherwise the callback won't be accepted.
QueueSystem::CancelCallback = true;
} else if (touching(touch, QueueBoxes[0])) {
if (QueueSystem::RequestNeeded != NO_REQUEST) { // -1 means no request.
switch(QueueSystem::RequestNeeded) {
case RMDIR_REQUEST: // Remove Directory message.
QueueSystem::RequestAnswer = Msg::promptMsg(QueueSystem::RequestMsg);
QueueSystem::Wait = false;
QueueSystem::Resume();
break;
case PROMPT_REQUEST: // Skip prompt message.
QueueSystem::RequestAnswer = ScriptUtils::prompt(QueueSystem::RequestMsg);
QueueSystem::Wait = false;
QueueSystem::Resume();
break;
}
} else {
ShowQueueProgress = !ShowQueueProgress; // In case no request expected, switch from progress to total progress mode etc.
}
/* Remove from Queue. */
} else if (touching(touch, QueueBoxes[3])) { // Remove Queue entries.
if (queueEntries.size() > 1) queueEntries.erase(queueEntries.begin() + 1 + queueMenuIdx);
}
}
if (hDown & KEY_DOWN) {
if (!queueEntries.empty()) {
if ((1 + queueMenuIdx) < (int)queueEntries.size() - 1) queueMenuIdx++;
}
}
if (hDown & KEY_UP) {
if (queueMenuIdx > 0) queueMenuIdx--;
}
if (hDown & KEY_B) storeMode = 0; // Go to EntryInfo.
}
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,24 +24,28 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "animation.hpp"
#include "common.hpp"
#include "download.hpp" #include "download.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
void StoreUtils::DrawReleaseNotes(const int &scrollIndex, const std::unique_ptr<StoreEntry> &entry, const std::unique_ptr<Store> &store) { void StoreUtils::DrawReleaseNotes(const int &scrollIndex, const std::unique_ptr<StoreEntry> &entry) {
if (entry && store) { if (entry && StoreUtils::store) {
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 26, 400, 214, BG_COLOR); Gui::Draw_Rect(0, 26, 400, 214, GFX::Themes[GFX::SelectedTheme].BGColor);
Gui::DrawString(5, 25 - scrollIndex, 0.5f, TEXT_COLOR, entry->GetReleaseNotes(), 390, 0, font, C2D_WordWrap); Gui::DrawString(5, 25 - scrollIndex, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, entry->GetReleaseNotes(), 390, 0, font, C2D_WordWrap);
Gui::Draw_Rect(0, 0, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, entry->GetTitle(), 390, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, entry->GetTitle(), 390, 0, font);
} else { } else {
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 0, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::Draw_Rect(0, 26, 400, 214, BG_COLOR); Gui::Draw_Rect(0, 26, 400, 214, GFX::Themes[GFX::SelectedTheme].BGColor);
} }
Animation::QueueEntryDone();
} }
/* /*
@@ -85,18 +89,18 @@ void DisplayChangelog() {
C2D_TargetClear(Bottom, C2D_Color32(0, 0, 0, 0)); C2D_TargetClear(Bottom, C2D_Color32(0, 0, 0, 0));
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 26, 400, 214, BG_COLOR); Gui::Draw_Rect(0, 26, 400, 214, GFX::Themes[GFX::SelectedTheme].BGColor);
Gui::DrawString(5, 25 - scrollIndex, 0.5f, TEXT_COLOR, notes, 390, 0, font, C2D_WordWrap); Gui::DrawString(5, 25 - scrollIndex, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, notes, 390, 0, font, C2D_WordWrap);
Gui::Draw_Rect(0, 0, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, "Universal-Updater", 390, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, "Universal-Updater", 390, 0, font);
Gui::Draw_Rect(0, 215, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 215, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 214, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 214, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 217, 0.7f, TEXT_COLOR, C_V, 390, 0, font); Gui::DrawStringCentered(0, 217, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, C_V, 390, 0, font);
GFX::DrawBottom(); GFX::DrawBottom();
Gui::Draw_Rect(0, 0, 320, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 320, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 320, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 320, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
C3D_FrameEnd(0); C3D_FrameEnd(0);
hidScanInput(); hidScanInput();
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "animation.hpp"
#include "common.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include "structs.hpp" #include "structs.hpp"
@@ -43,15 +45,17 @@ extern bool checkWifiStatus();
*/ */
void StoreUtils::DrawScreenshotMenu(const C2D_Image &img, const int sIndex, const bool sFetch, const int screenshotSize, const std::string &name, const int zoom, const bool canDisplay) { void StoreUtils::DrawScreenshotMenu(const C2D_Image &img, const int sIndex, const bool sFetch, const int screenshotSize, const std::string &name, const int zoom, const bool canDisplay) {
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 0, 400, 240, BG_COLOR); Gui::Draw_Rect(0, 0, 400, 240, GFX::Themes[GFX::SelectedTheme].BGColor);
if (!canDisplay) { if (!canDisplay) {
Animation::QueueEntryDone();
GFX::DrawBottom(); GFX::DrawBottom();
if (screenshotSize > 0) { // if texture is nullptr AND screenshot size is larger than 0. if (screenshotSize > 0) { // if texture is nullptr AND screenshot size is larger than 0.
Gui::DrawStringCentered(0, 2, 0.6f, WHITE, Lang::get("SCREENSHOT_COULD_NOT_LOAD"), 310); Gui::DrawStringCentered(0, 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SCREENSHOT_COULD_NOT_LOAD"), 310);
} else { } else {
Gui::DrawStringCentered(0, 2, 0.6f, WHITE, Lang::get("NO_SCREENSHOTS_AVAILABLE"), 310); Gui::DrawStringCentered(0, 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("NO_SCREENSHOTS_AVAILABLE"), 310);
} }
return; return;
@@ -82,6 +86,7 @@ void StoreUtils::DrawScreenshotMenu(const C2D_Image &img, const int sIndex, cons
delete top.subtex; delete top.subtex;
} }
Animation::QueueEntryDone();
GFX::DrawBottom(); GFX::DrawBottom();
/* Bottom. */ /* Bottom. */
@@ -92,19 +97,20 @@ void StoreUtils::DrawScreenshotMenu(const C2D_Image &img, const int sIndex, cons
delete bottom.subtex; delete bottom.subtex;
} else { } else {
Gui::Draw_Rect(0, 215, 320, 25, BAR_COLOR); Gui::Draw_Rect(0, 215, 320, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 214, 320, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 214, 320, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 220, 0.5f, TEXT_COLOR, Lang::get("SCREENSHOT_INSTRUCTIONS"), 310, 0, font); Gui::DrawStringCentered(0, 220, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SCREENSHOT_INSTRUCTIONS"), 310, 0, font);
char screenshots[0x100]; char screenshots[0x100];
snprintf(screenshots, sizeof(screenshots), Lang::get("SCREENSHOT").c_str(), sIndex + 1, screenshotSize); snprintf(screenshots, sizeof(screenshots), Lang::get("SCREENSHOT").c_str(), sIndex + 1, screenshotSize);
Gui::DrawStringCentered(0, 2, 0.6f, WHITE, screenshots, 310, 0, font); Gui::DrawStringCentered(0, 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, screenshots, 310, 0, font);
Gui::DrawStringCentered(0, 40, 0.6f, WHITE, name, 310, 0, font); Gui::DrawStringCentered(0, 40, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, name, 310, 0, font);
} }
} else { } else {
Animation::QueueEntryDone();
GFX::DrawBottom(); GFX::DrawBottom();
Gui::DrawStringCentered(0, 2, 0.6f, WHITE, Lang::get("NO_SCREENSHOTS_AVAILABLE"), 310); Gui::DrawStringCentered(0, 2, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("NO_SCREENSHOTS_AVAILABLE"), 310);
} }
} }
} }
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,27 +24,35 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "common.hpp"
#include "keyboard.hpp" #include "keyboard.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include "structs.hpp" #include "structs.hpp"
extern bool touching(touchPosition touch, Structs::ButtonPos button); extern bool touching(touchPosition touch, Structs::ButtonPos button);
static const std::vector<Structs::ButtonPos> SearchMenu = { static const std::vector<Structs::ButtonPos> SearchMenu = {
{ 55, 45, 258, 30 }, // Search bar. { 51, 41, 262, 30 }, // Search bar.
/* Includes. */ /* Includes. */
{ 85, 109, 50, 10 }, { 85, 101, 50, 10 },
{ 85, 125, 50, 10 }, { 85, 117, 50, 10 },
{ 167, 109, 50, 10 }, { 167, 101, 50, 10 },
{ 167, 125, 50, 10 }, { 167, 117, 50, 10 },
/* Filters. */ /* Filters. */
{ 82, 195, 30, 30 }, { 82, 159, 30, 30 },
{ 117, 195, 30, 30 }, { 117, 159, 30, 30 },
{ 152, 195, 30, 30 }, { 152, 159, 30, 30 },
{ 187, 195, 30, 30 }, { 187, 159, 30, 30 },
{ 222, 195, 30, 30 }, { 222, 159, 30, 30 },
{ 257, 195, 30, 30 } { 257, 159, 30, 30 },
/* Send to Queue. */
{ 91, 200, 185, 25 },
/* AND / OR. */
{ 222, 139, 30, 13 },
{ 257, 139, 30, 13 }
}; };
/* /*
@@ -54,57 +62,68 @@ static const std::vector<Structs::ButtonPos> SearchMenu = {
const std::string &searchResult: Const Reference to the searchResult. const std::string &searchResult: Const Reference to the searchResult.
int marks: The filter mark flags. int marks: The filter mark flags.
bool updateFilter: The update filter. bool updateFilter: The update filter.
isAND: isAND for the AND / OR mode.
*/ */
void StoreUtils::DrawSearchMenu(const std::vector<bool> &searchIncludes, const std::string &searchResult, int marks, bool updateFilter) { void StoreUtils::DrawSearchMenu(const std::vector<bool> &searchIncludes, const std::string &searchResult, int marks, bool updateFilter, bool isAND) {
Gui::Draw_Rect(48, 0, 272, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(48, 25, 272, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
Gui::DrawStringCentered(25, 2, 0.6, TEXT_COLOR, Lang::get("SEARCH_FILTERS"), 265, 0, font); Gui::DrawStringCentered(21, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SEARCH_FILTERS"), 269, 0, font);
Gui::Draw_Rect(54, 44, 260, SearchMenu[0].h + 2, SEARCH_BAR_OUTL_COLOR); Gui::Draw_Rect(50, 40, 264, SearchMenu[0].h + 2, GFX::Themes[GFX::SelectedTheme].SearchbarOutline);
Gui::Draw_Rect(SearchMenu[0].x, SearchMenu[0].y, SearchMenu[0].w, SearchMenu[0].h, SEARCH_BAR_COLOR); Gui::Draw_Rect(SearchMenu[0].x, SearchMenu[0].y, SearchMenu[0].w, SearchMenu[0].h, GFX::Themes[GFX::SelectedTheme].SearchBar);
Gui::DrawStringCentered(28, 50, 0.6, TEXT_COLOR, searchResult, 265, 0, font); Gui::DrawStringCentered(24, 46, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, searchResult, 265, 0, font);
/* Checkboxes. */ /* Checkboxes. */
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
GFX::DrawCheckbox(SearchMenu[i + 1].x, SearchMenu[i + 1].y, searchIncludes[i]); GFX::DrawCheckbox(SearchMenu[i + 1].x, SearchMenu[i + 1].y, searchIncludes[i]);
} }
Gui::DrawString(84, 85, 0.5, TEXT_COLOR, Lang::get("INCLUDE_IN_RESULTS"), 265, 0, font); Gui::DrawString(84, 81, 0.5, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("INCLUDE_IN_RESULTS"), 265, 0, font);
Gui::DrawString(SearchMenu[1].x + 18, SearchMenu[1].y + 1, 0.4, TEXT_COLOR, Lang::get("TITLE"), 90, 0, font); Gui::DrawString(SearchMenu[1].x + 18, SearchMenu[1].y + 1, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("TITLE"), 90, 0, font);
Gui::DrawString(SearchMenu[2].x + 18, SearchMenu[2].y + 1, 0.4, TEXT_COLOR, Lang::get("AUTHOR"), 90, 0, font); Gui::DrawString(SearchMenu[2].x + 18, SearchMenu[2].y + 1, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("AUTHOR"), 90, 0, font);
Gui::DrawString(SearchMenu[3].x + 18, SearchMenu[3].y + 1, 0.4, TEXT_COLOR, Lang::get("CATEGORY"), 90, 0, font); Gui::DrawString(SearchMenu[3].x + 18, SearchMenu[3].y + 1, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CATEGORY"), 90, 0, font);
Gui::DrawString(SearchMenu[4].x + 18, SearchMenu[4].y + 1, 0.4, TEXT_COLOR, Lang::get("CONSOLE"), 90, 0, font); Gui::DrawString(SearchMenu[4].x + 18, SearchMenu[4].y + 1, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CONSOLE"), 90, 0, font);
/* Filters. */ /* Filters. */
Gui::DrawString(84, 175, 0.5f, TEXT_COLOR, Lang::get("FILTER_TO"), 265, 0, font); Gui::DrawString(84, SearchMenu[5].y - 20, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("FILTER_TO"), 265, 0, font);
Gui::Draw_Rect(SearchMenu[5].x, SearchMenu[5].y, SearchMenu[5].w, SearchMenu[5].h, (marks & favoriteMarks::STAR ? Gui::Draw_Rect(SearchMenu[5].x, SearchMenu[5].y, SearchMenu[5].w, SearchMenu[5].h, (marks & favoriteMarks::STAR ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].SideBarUnselected : GFX::Themes[GFX::SelectedTheme].BoxInside));
Gui::Draw_Rect(SearchMenu[6].x, SearchMenu[6].y, SearchMenu[6].w, SearchMenu[6].h, (marks & favoriteMarks::HEART ? Gui::Draw_Rect(SearchMenu[6].x, SearchMenu[6].y, SearchMenu[6].w, SearchMenu[6].h, (marks & favoriteMarks::HEART ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].SideBarUnselected : GFX::Themes[GFX::SelectedTheme].BoxInside));
Gui::Draw_Rect(SearchMenu[7].x, SearchMenu[7].y, SearchMenu[7].w, SearchMenu[7].h, (marks & favoriteMarks::DIAMOND ? Gui::Draw_Rect(SearchMenu[7].x, SearchMenu[7].y, SearchMenu[7].w, SearchMenu[7].h, (marks & favoriteMarks::DIAMOND ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].SideBarUnselected : GFX::Themes[GFX::SelectedTheme].BoxInside));
Gui::Draw_Rect(SearchMenu[8].x, SearchMenu[8].y, SearchMenu[8].w, SearchMenu[8].h, (marks & favoriteMarks::CLUBS ? Gui::Draw_Rect(SearchMenu[8].x, SearchMenu[8].y, SearchMenu[8].w, SearchMenu[8].h, (marks & favoriteMarks::CLUBS ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].SideBarUnselected : GFX::Themes[GFX::SelectedTheme].BoxInside));
Gui::Draw_Rect(SearchMenu[9].x, SearchMenu[9].y, SearchMenu[9].w, SearchMenu[9].h, (marks & favoriteMarks::SPADE ? Gui::Draw_Rect(SearchMenu[9].x, SearchMenu[9].y, SearchMenu[9].w, SearchMenu[9].h, (marks & favoriteMarks::SPADE ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].SideBarUnselected : GFX::Themes[GFX::SelectedTheme].BoxInside));
Gui::Draw_Rect(SearchMenu[10].x, SearchMenu[10].y, SearchMenu[10].w, SearchMenu[10].h, (updateFilter ? Gui::Draw_Rect(SearchMenu[10].x, SearchMenu[10].y, SearchMenu[10].w, SearchMenu[10].h, (updateFilter ?
SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); GFX::Themes[GFX::SelectedTheme].SideBarUnselected : GFX::Themes[GFX::SelectedTheme].BoxInside));
Gui::DrawString(SearchMenu[5].x + 9, SearchMenu[5].y + 7, 0.5f, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(SearchMenu[5].x + 9, SearchMenu[5].y + 7, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
Gui::DrawString(SearchMenu[6].x + 9, SearchMenu[6].y + 7, 0.5f, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(SearchMenu[6].x + 9, SearchMenu[6].y + 7, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
Gui::DrawString(SearchMenu[7].x + 9, SearchMenu[7].y + 7, 0.5f, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(SearchMenu[7].x + 9, SearchMenu[7].y + 7, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
Gui::DrawString(SearchMenu[8].x + 9, SearchMenu[8].y + 7, 0.5f, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(SearchMenu[8].x + 9, SearchMenu[8].y + 7, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
Gui::DrawString(SearchMenu[9].x + 9, SearchMenu[9].y + 7, 0.5f, TEXT_COLOR, "", 0, 0, font); Gui::DrawString(SearchMenu[9].x + 9, SearchMenu[9].y + 7, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "", 0, 0, font);
GFX::DrawSprite(sprites_update_filter_idx, SearchMenu[10].x + 8, SearchMenu[10].y + 8); GFX::DrawSprite(sprites_update_filter_idx, SearchMenu[10].x + 8, SearchMenu[10].y + 8);
Gui::Draw_Rect(SearchMenu[11].x, SearchMenu[11].y, SearchMenu[11].w, SearchMenu[11].h, GFX::Themes[GFX::SelectedTheme].MarkUnselected);
Gui::DrawStringCentered(23, SearchMenu[11].y + 6, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SELECTION_QUEUE"), 280, 0, font);
/* AND / OR. */
Gui::Draw_Rect(SearchMenu[12].x, SearchMenu[12].y, SearchMenu[12].w, SearchMenu[12].h, (isAND ? GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::DrawString(SearchMenu[12].x + 4, SearchMenu[12].y, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, "AND", 0, 0, font);
Gui::Draw_Rect(SearchMenu[13].x, SearchMenu[13].y, SearchMenu[13].w, SearchMenu[13].h, (!isAND ? GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::DrawString(SearchMenu[13].x + 8, SearchMenu[13].y, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, "OR", 0, 0, font);
} }
/* /*
@@ -115,15 +134,13 @@ void StoreUtils::DrawSearchMenu(const std::vector<bool> &searchIncludes, const s
- Search the UniStore. - Search the UniStore.
- Include stuff into the search. - Include stuff into the search.
std::unique_ptr<Store> &store: Reference to the Store class.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the Store Entries.
std::vector<bool> &searchIncludes: Reference to the searchIncludes. std::vector<bool> &searchIncludes: Reference to the searchIncludes.
std::unique_ptr<Meta> &meta: Reference to the Meta class.
std::string &searchResult: Reference to the searchResult. std::string &searchResult: Reference to the searchResult.
int &marks: Reference to the mark flags. int &marks: Reference to the mark flags.
bool &updateFilter: Reference to the update filter. bool &updateFilter: Reference to the update filter.
bool &isAND: Reference to isAND boolean for AND / OR mode.
*/ */
void StoreUtils::SearchHandle(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, std::vector<bool> &searchIncludes, std::unique_ptr<Meta> &meta, std::string &searchResult, int &marks, bool &updateFilter, bool ascending, SortType sorttype) { void StoreUtils::SearchHandle(std::vector<bool> &searchIncludes, std::string &searchResult, int &marks, bool &updateFilter, bool ascending, SortType sorttype, bool &isAND) {
/* Checkboxes. */ /* Checkboxes. */
if (hDown & KEY_TOUCH) { if (hDown & KEY_TOUCH) {
bool didTouch = false; bool didTouch = false;
@@ -140,7 +157,7 @@ void StoreUtils::SearchHandle(std::unique_ptr<Store> &store, std::vector<std::un
/* Search bar. */ /* Search bar. */
if (!didTouch) { if (!didTouch) {
if (touching(touch, SearchMenu[0])) { if (touching(touch, SearchMenu[0])) {
if (store) { if (StoreUtils::store) {
searchResult = Input::setkbdString(20, Lang::get("ENTER_SEARCH"), {}); searchResult = Input::setkbdString(20, Lang::get("ENTER_SEARCH"), {});
didTouch = true; didTouch = true;
@@ -176,18 +193,29 @@ void StoreUtils::SearchHandle(std::unique_ptr<Store> &store, std::vector<std::un
} else if (touching(touch, SearchMenu[10])) { } else if (touching(touch, SearchMenu[10])) {
updateFilter = !updateFilter; updateFilter = !updateFilter;
didTouch = true; didTouch = true;
} else if (touching(touch, SearchMenu[11])) {
StoreUtils::AddAllToQueue();
} else if (touching(touch, SearchMenu[12])) {
isAND = true;
didTouch = true;
} else if (touching(touch, SearchMenu[13])) {
isAND = false;
didTouch = true;
} }
} }
if (didTouch) { if (didTouch) {
if (store && store->GetValid()) { // Only search, when valid. if (StoreUtils::store && StoreUtils::store->GetValid()) { // Only search, when valid.
StoreUtils::ResetAll(store, meta, entries); StoreUtils::ResetAll();
StoreUtils::search(entries, searchResult, searchIncludes[0], searchIncludes[1], searchIncludes[2], searchIncludes[3], marks, updateFilter); StoreUtils::search(searchResult, searchIncludes[0], searchIncludes[1], searchIncludes[2], searchIncludes[3], marks, updateFilter, isAND);
store->SetScreenIndx(0); StoreUtils::store->SetScreenIndx(0);
store->SetEntry(0); StoreUtils::store->SetEntry(0);
store->SetBox(0); StoreUtils::store->SetBox(0);
StoreUtils::SortEntries(ascending, sorttype, entries); StoreUtils::SortEntries(ascending, sorttype);
} }
} }
} }
@@ -199,9 +227,9 @@ void StoreUtils::SearchHandle(std::unique_ptr<Store> &store, std::vector<std::un
for(uint i = 0; i < searchIncludes.size(); i++) searchIncludes[i] = false; for(uint i = 0; i < searchIncludes.size(); i++) searchIncludes[i] = false;
searchResult = ""; searchResult = "";
if (store && store->GetValid()) { if (StoreUtils::store && StoreUtils::store->GetValid()) {
StoreUtils::ResetAll(store, meta, entries); StoreUtils::ResetAll();
StoreUtils::SortEntries(ascending, sorttype, entries); StoreUtils::SortEntries(ascending, sorttype);
} }
} }
} }
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,45 +24,47 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "common.hpp"
#include "init.hpp" #include "init.hpp"
#include "overlay.hpp" #include "overlay.hpp"
#include "scriptUtils.hpp" #include "scriptUtils.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include <unistd.h> #include <unistd.h>
extern bool exiting; extern bool exiting, QueueRuns;
extern bool touching(touchPosition touch, Structs::ButtonPos button); extern bool touching(touchPosition touch, Structs::ButtonPos button);
static const std::vector<Structs::ButtonPos> mainButtons = { static const std::vector<Structs::ButtonPos> mainButtons = {
{ 54, 32, 262, 22 }, { 45, 32, 271, 22 },
{ 54, 62, 262, 22 }, { 45, 62, 271, 22 },
{ 54, 92, 262, 22 }, { 45, 92, 271, 22 },
{ 54, 122, 262, 22 }, { 45, 122, 271, 22 },
{ 54, 152, 262, 22 }, { 45, 152, 271, 22 },
{ 54, 182, 262, 22 }, { 45, 182, 271, 22 },
{ 54, 212, 262, 22 } { 45, 212, 271, 22 }
}; };
static const std::vector<Structs::ButtonPos> langButtons = { static const std::vector<Structs::ButtonPos> langButtons = {
{ 10, 34, 300, 22 }, { 45, 32, 271, 22 },
{ 10, 64, 300, 22 }, { 45, 62, 271, 22 },
{ 10, 94, 300, 22 }, { 45, 92, 271, 22 },
{ 10, 124, 300, 22 }, { 45, 122, 271, 22 },
{ 10, 154, 300, 22 }, { 45, 152, 271, 22 },
{ 10, 184, 300, 22 }, { 45, 182, 271, 22 },
{ 52, 220, 16, 16 } // Add Font. { 45, 220, 16, 16 } // Add Font.
}; };
static const std::vector<Structs::ButtonPos> toggleAbles = { static const std::vector<Structs::ButtonPos> toggleAbles = {
{ 288, 64, 24, 24 }, { 288, 44, 24, 24 },
{ 288, 140, 24, 24 } { 288, 120, 24, 24 }
}; };
static const Structs::ButtonPos back = { 52, 0, 24, 24 }; // Back arrow for directory. static const Structs::ButtonPos back = { 45, 0, 24, 24 }; // Back arrow for directory.
static const Structs::ButtonPos Themes = { 40, 220, 280, 24 }; // Themes.
static const std::vector<std::string> mainStrings = { "LANGUAGE", "SELECT_UNISTORE", "AUTO_UPDATE_SETTINGS_BTN", "GUI_SETTINGS_BTN", "DIRECTORY_SETTINGS_BTN", "CREDITS", "EXIT_APP" }; static const std::vector<std::string> mainStrings = { "LANGUAGE", "SELECT_UNISTORE", "AUTO_UPDATE_SETTINGS_BTN", "GUI_SETTINGS_BTN", "DIRECTORY_SETTINGS_BTN", "CREDITS", "EXIT_APP" };
static const std::vector<std::string> dirStrings = { "CHANGE_3DSX_PATH", "CHANGE_NDS_PATH", "CHANGE_ARCHIVE_PATH", "CHANGE_SHORTCUT_PATH" }; static const std::vector<std::string> dirStrings = { "CHANGE_3DSX_PATH", "CHANGE_NDS_PATH", "CHANGE_ARCHIVE_PATH", "CHANGE_SHORTCUT_PATH", "CHANGE_FIRM_PATH" };
/* Note: Украïнська is spelled using a latin i with dieresis to work in the system font */ /* Note: Украïнська is spelled using a latin i with dieresis to work in the system font */
//static const std::vector<std::string> languages = { "Bruh", "Dansk", "Deutsch", "English", "Español", "Français", "Italiano", "Lietuvių", "Magyar", "Polski", "Português", "Português (Brasil)", "Русский", "Украïнська", "日本語" }; //static const std::vector<std::string> languages = { "Bruh", "Dansk", "Deutsch", "English", "Español", "Français", "Italiano", "Lietuvių", "Magyar", "Polski", "Português", "Português (Brasil)", "Русский", "Украïнська", "日本語" };
@@ -70,19 +72,21 @@ static const std::vector<std::string> dirStrings = { "CHANGE_3DSX_PATH", "CHANGE
static const std::vector<std::string> languages = { "Bruh", "Deutsch", "English", "Español", "Français", "Italiano", "Magyar", "Polski", "Português (Brasil)", "Русский", "Украïнська", "日本語" }; static const std::vector<std::string> languages = { "Bruh", "Deutsch", "English", "Español", "Français", "Italiano", "Magyar", "Polski", "Português (Brasil)", "Русский", "Украïнська", "日本語" };
static const std::string langsTemp[] = { "br", "de", "en", "es", "fr", "it", "hu", "pl", "pt-BR", "ru", "uk", "jp"}; static const std::string langsTemp[] = { "br", "de", "en", "es", "fr", "it", "hu", "pl", "pt-BR", "ru", "uk", "jp"};
static const std::vector<std::string> ThemeNames = { "THEME_DEFAULT" };
/* /*
Main Settings. Main Settings.
int selection: The Settings Selection. int selection: The Settings Selection.
*/ */
static void DrawSettingsMain(int selection) { static void DrawSettingsMain(int selection) {
Gui::Draw_Rect(48, 0, 272, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(48, 25, 272, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
Gui::DrawStringCentered(25, 2, 0.6, TEXT_COLOR, Lang::get("SETTINGS"), 265, 0, font); Gui::DrawStringCentered(20, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SETTINGS"), 280, 0, font);
for (int i = 0; i < 7; i++) { for (int i = 0; i < 7; i++) {
if (i == selection) GFX::DrawBox(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, false); if (i == selection) Gui::Draw_Rect(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, GFX::Themes[GFX::SelectedTheme].MarkSelected);
Gui::DrawStringCentered(30, mainButtons[i].y + 4, 0.45f, TEXT_COLOR, Lang::get(mainStrings[i]), 255, 0, font); Gui::DrawStringCentered(20, mainButtons[i].y + 4, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get(mainStrings[i]), 255, 0, font);
} }
} }
@@ -93,15 +97,15 @@ static void DrawSettingsMain(int selection) {
int sPos: The Screen Position. int sPos: The Screen Position.
*/ */
static void DrawLanguageSettings(int selection, int sPos) { static void DrawLanguageSettings(int selection, int sPos) {
Gui::Draw_Rect(48, 0, 272, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(48, 25, 272, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
GFX::DrawSprite(sprites_arrow_idx, back.x, back.y); GFX::DrawSprite(sprites_arrow_idx, back.x, back.y);
GFX::DrawSprite(sprites_add_font_idx, langButtons[6].x, langButtons[6].y); GFX::DrawSprite(sprites_add_font_idx, langButtons[6].x, langButtons[6].y);
Gui::DrawStringCentered(32, 2, 0.6, TEXT_COLOR, Lang::get("SELECT_LANG"), 240, 0, font); Gui::DrawStringCentered(20, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SELECT_LANG"), 248, 0, font);
for(int i = 0; i < 6 && i < (int)languages.size(); i++) { for(int i = 0; i < 6 && i < (int)languages.size(); i++) {
if (sPos + i == selection) GFX::DrawBox(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, false); if (sPos + i == selection) Gui::Draw_Rect(langButtons[i].x, langButtons[i].y, langButtons[i].w, langButtons[i].h, GFX::Themes[GFX::SelectedTheme].MarkSelected);
Gui::DrawStringCentered(30, mainButtons[i].y + 4, 0.45f, TEXT_COLOR, languages[sPos + i], 280, 0, font); Gui::DrawStringCentered(20, langButtons[i].y + 4, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, languages[sPos + i], 280, 0, font);
} }
} }
@@ -111,14 +115,14 @@ static void DrawLanguageSettings(int selection, int sPos) {
int selection: The Settings Selection. int selection: The Settings Selection.
*/ */
static void DrawSettingsDir(int selection) { static void DrawSettingsDir(int selection) {
Gui::Draw_Rect(48, 0, 272, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(48, 25, 272, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
GFX::DrawSprite(sprites_arrow_idx, back.x, back.y); GFX::DrawSprite(sprites_arrow_idx, back.x, back.y);
Gui::DrawStringCentered(32, 2, 0.6, TEXT_COLOR, Lang::get("DIRECTORY_SETTINGS"), 240, 0, font); Gui::DrawStringCentered(20, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("DIRECTORY_SETTINGS"), 248, 0, font);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 5; i++) {
if (i == selection) GFX::DrawBox(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, false); if (i == selection) Gui::Draw_Rect(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, GFX::Themes[GFX::SelectedTheme].MarkSelected);
Gui::DrawStringCentered(30, mainButtons[i].y + 4, 0.45f, TEXT_COLOR, Lang::get(dirStrings[i]), 255, 0, font); Gui::DrawStringCentered(20, mainButtons[i].y + 4, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get(dirStrings[i]), 255, 0, font);
} }
} }
@@ -126,22 +130,22 @@ static void DrawSettingsDir(int selection) {
Draw Auto-Update Settings page. Draw Auto-Update Settings page.
*/ */
static void DrawAutoUpdate(int selection) { static void DrawAutoUpdate(int selection) {
Gui::Draw_Rect(48, 0, 272, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(48, 25, 272, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
GFX::DrawSprite(sprites_arrow_idx, back.x, back.y); GFX::DrawSprite(sprites_arrow_idx, back.x, back.y);
Gui::DrawStringCentered(32, 2, 0.6, TEXT_COLOR, Lang::get("AUTO_UPDATE_SETTINGS"), 240, 0, font); Gui::DrawStringCentered(20, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("AUTO_UPDATE_SETTINGS"), 240, 0, font);
/* Toggle Boxes. */ /* Toggle Boxes. */
Gui::Draw_Rect(48, 64, 273, 24, (selection == 0 ? SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); Gui::Draw_Rect(40, 44, 280, 24, (selection == 0 ? GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::DrawString(55, 68, 0.5f, TEXT_COLOR, Lang::get("AUTO_UPDATE_UNISTORE"), 210, 0, font); Gui::DrawString(47, 48, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("AUTO_UPDATE_UNISTORE"), 210, 0, font);
GFX::DrawToggle(288, 64, config->autoupdate()); GFX::DrawToggle(toggleAbles[0].x, toggleAbles[0].y, config->autoupdate());
Gui::DrawString(55, 95, 0.4f, TEXT_COLOR, Lang::get("AUTO_UPDATE_UNISTORE_DESC"), 265, 0, font, C2D_WordWrap); Gui::DrawString(47, 75, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("AUTO_UPDATE_UNISTORE_DESC"), 265, 0, font, C2D_WordWrap);
Gui::Draw_Rect(48, 140, 273, 24, (selection == 1 ? SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); Gui::Draw_Rect(40, 120, 280, 24, (selection == 1 ? GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::DrawString(55, 144, 0.5f, TEXT_COLOR, Lang::get("AUTO_UPDATE_UU"), 210, 0, font); Gui::DrawString(47, 124, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("AUTO_UPDATE_UU"), 210, 0, font);
GFX::DrawToggle(288, 140, config->updatecheck()); GFX::DrawToggle(toggleAbles[1].x, toggleAbles[1].y, config->updatecheck());
Gui::DrawString(55, 171, 0.4f, TEXT_COLOR, Lang::get("AUTO_UPDATE_UU_DESC"), 265, 0, font, C2D_WordWrap); Gui::DrawString(47, 151, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("AUTO_UPDATE_UU_DESC"), 265, 0, font, C2D_WordWrap);
} }
/* /*
@@ -150,21 +154,24 @@ static void DrawAutoUpdate(int selection) {
int selection: The Settings Selection. int selection: The Settings Selection.
*/ */
static void DrawGUISettings(int selection) { static void DrawGUISettings(int selection) {
Gui::Draw_Rect(48, 0, 272, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(48, 25, 272, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
GFX::DrawSprite(sprites_arrow_idx, back.x, back.y); GFX::DrawSprite(sprites_arrow_idx, back.x, back.y);
Gui::DrawStringCentered(32, 2, 0.6, TEXT_COLOR, Lang::get("GUI_SETTINGS"), 240, 0, font); Gui::DrawStringCentered(20, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("GUI_SETTINGS"), 248, 0, font);
Gui::Draw_Rect(48, 64, 273, 24, (selection == 0 ? SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); Gui::Draw_Rect(40, 44, 280, 24, (selection == 0 ? GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::DrawString(55, 68, 0.5f, TEXT_COLOR, Lang::get("UNISTORE_BG"), 210, 0, font); Gui::DrawString(47, 48, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("UNISTORE_BG"), 210, 0, font);
GFX::DrawToggle(288, 64, config->usebg()); GFX::DrawToggle(toggleAbles[0].x, toggleAbles[0].y, config->usebg());
Gui::DrawString(55, 95, 0.4f, TEXT_COLOR, Lang::get("UNISTORE_BG_DESC"), 265, 0, font, C2D_WordWrap); Gui::DrawString(47, 75, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("UNISTORE_BG_DESC"), 265, 0, font, C2D_WordWrap);
Gui::Draw_Rect(48, 140, 273, 24, (selection == 1 ? SIDEBAR_UNSELECTED_COLOR : BOX_INSIDE_COLOR)); Gui::Draw_Rect(40, 120, 280, 24, (selection == 1 ? GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::DrawString(55, 144, 0.5f, TEXT_COLOR, Lang::get("CUSTOM_FONT"), 210, 0, font); Gui::DrawString(47, 124, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CUSTOM_FONT"), 210, 0, font);
GFX::DrawToggle(288, 140, config->customfont()); GFX::DrawToggle(toggleAbles[1].x, toggleAbles[1].y, config->customfont());
Gui::DrawString(55, 171, 0.4f, TEXT_COLOR, Lang::get("CUSTOM_FONT_DESC"), 265, 0, font, C2D_WordWrap); Gui::DrawString(47, 151, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CUSTOM_FONT_DESC"), 265, 0, font, C2D_WordWrap);
Gui::Draw_Rect(40, 196, 280, 24, (selection == 2 ? GFX::Themes[GFX::SelectedTheme].MarkSelected : GFX::Themes[GFX::SelectedTheme].MarkUnselected));
Gui::DrawString(47, 200, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("ACTIVE_THEME") + ": " + Lang::get(ThemeNames[GFX::SelectedTheme]), 210, 0, font);
} }
@@ -180,13 +187,10 @@ static void DrawGUISettings(int selection) {
int &page: Reference to the page. int &page: Reference to the page.
bool &dspSettings: Reference to the display Settings. bool &dspSettings: Reference to the display Settings.
int &storeMode: Reference to the Store Mode. int &storeMode: Reference to the store Mode.
int &selection: Reference to the Selection. int &selection: Reference to the Selection.
std::unique_ptr<Store> &store: Reference to the Store class.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the StoreEntries.
std::unique_ptr<Meta> &meta: Reference to the Meta class.
*/ */
static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int &selection, std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, std::unique_ptr<Meta> &meta) { static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int &selection) {
if (hDown & KEY_B) { if (hDown & KEY_B) {
selection = 0; selection = 0;
storeMode = 0; storeMode = 0;
@@ -218,7 +222,12 @@ static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int
page = 4; page = 4;
} else if (touching(touch, mainButtons[1])) { } else if (touching(touch, mainButtons[1])) {
Overlays::SelectStore(store, entries, meta); if (QueueRuns) {
if (Msg::promptMsg(Lang::get("FEATURE_SIDE_EFFECTS"))) Overlays::SelectStore();
} else {
Overlays::SelectStore();
}
} else if (touching(touch, mainButtons[2])) { } else if (touching(touch, mainButtons[2])) {
selection = 0; selection = 0;
@@ -236,7 +245,8 @@ static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int
Overlays::ShowCredits(); Overlays::ShowCredits();
} else if (touching(touch, mainButtons[6])) { } else if (touching(touch, mainButtons[6])) {
exiting = true; if (QueueRuns) exiting = Msg::promptMsg(Lang::get("FEATURE_SIDE_EFFECTS"));
else exiting = true;
} }
} }
@@ -248,7 +258,12 @@ static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int
break; break;
case 1: case 1:
Overlays::SelectStore(store, entries, meta); if (QueueRuns) {
if (Msg::promptMsg(Lang::get("FEATURE_SIDE_EFFECTS"))) Overlays::SelectStore();
} else {
Overlays::SelectStore();
}
break; break;
case 2: case 2:
@@ -271,7 +286,8 @@ static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int
break; break;
case 6: case 6:
exiting = true; if (QueueRuns) exiting = Msg::promptMsg(Lang::get("FEATURE_SIDE_EFFECTS"));
else exiting = true;
break; break;
} }
} }
@@ -287,14 +303,14 @@ static void SettingsHandleMain(int &page, bool &dspSettings, int &storeMode, int
int &page: Reference to the page. int &page: Reference to the page.
int &selection: Reference to the Selection. int &selection: Reference to the Selection.
*/ */
static void SettingsHandleDir(int &page, int &selection, const std::unique_ptr<Store> &store) { static void SettingsHandleDir(int &page, int &selection) {
if (hDown & KEY_B) { if (hDown & KEY_B) {
page = 0; page = 0;
selection = 4; selection = 4;
} }
if (hRepeat & KEY_DOWN) { if (hRepeat & KEY_DOWN) {
if (selection < 3) selection++; if (selection < 4) selection++;
else selection = 0; else selection = 0;
} }
@@ -319,20 +335,24 @@ static void SettingsHandleDir(int &page, int &selection, const std::unique_ptr<S
selection = 4; selection = 4;
} else if (touching(touch, mainButtons[0])) { } else if (touching(touch, mainButtons[0])) {
const std::string path = Overlays::SelectDir(config->_3dsxPath(), Lang::get("SELECT_DIR"), store); const std::string path = Overlays::SelectDir(config->_3dsxPath(), Lang::get("SELECT_DIR"));
if (path != "") config->_3dsxPath(path); if (path != "") config->_3dsxPath(path);
} else if (touching(touch, mainButtons[1])) { } else if (touching(touch, mainButtons[1])) {
const std::string path = Overlays::SelectDir(config->ndsPath(), Lang::get("SELECT_DIR"), store); const std::string path = Overlays::SelectDir(config->ndsPath(), Lang::get("SELECT_DIR"));
if (path != "") config->ndsPath(path); if (path != "") config->ndsPath(path);
} else if (touching(touch, mainButtons[2])) { } else if (touching(touch, mainButtons[2])) {
const std::string path = Overlays::SelectDir(config->archPath(), Lang::get("SELECT_DIR"), store); const std::string path = Overlays::SelectDir(config->archPath(), Lang::get("SELECT_DIR"));
if (path != "") config->archPath(path); if (path != "") config->archPath(path);
} else if (touching(touch, mainButtons[3])) { } else if (touching(touch, mainButtons[3])) {
const std::string path = Overlays::SelectDir(config->shortcut(), Lang::get("SELECT_DIR"), store); const std::string path = Overlays::SelectDir(config->shortcut(), Lang::get("SELECT_DIR"));
if (path != "") config->shortcut(path); if (path != "") config->shortcut(path);
} else if (touching(touch, mainButtons[4])) {
const std::string path = Overlays::SelectDir(config->firmPath(), Lang::get("SELECT_DIR"));
if (path != "") config->firmPath(path);
} }
} }
@@ -341,24 +361,29 @@ static void SettingsHandleDir(int &page, int &selection, const std::unique_ptr<S
switch(selection) { switch(selection) {
case 0: case 0:
path = Overlays::SelectDir(config->_3dsxPath(), Lang::get("SELECT_DIR"), store); path = Overlays::SelectDir(config->_3dsxPath(), Lang::get("SELECT_DIR"));
if (path != "") config->_3dsxPath(path); if (path != "") config->_3dsxPath(path);
break; break;
case 1: case 1:
path = Overlays::SelectDir(config->ndsPath(), Lang::get("SELECT_DIR"), store); path = Overlays::SelectDir(config->ndsPath(), Lang::get("SELECT_DIR"));
if (path != "") config->ndsPath(path); if (path != "") config->ndsPath(path);
break; break;
case 2: case 2:
path = Overlays::SelectDir(config->archPath(), Lang::get("SELECT_DIR"), store); path = Overlays::SelectDir(config->archPath(), Lang::get("SELECT_DIR"));
if (path != "") config->archPath(path); if (path != "") config->archPath(path);
break; break;
case 3: case 3:
path = Overlays::SelectDir(config->shortcut(), Lang::get("SELECT_DIR"), store); path = Overlays::SelectDir(config->shortcut(), Lang::get("SELECT_DIR"));
if (path != "") config->shortcut(path); if (path != "") config->shortcut(path);
break; break;
case 4:
path = Overlays::SelectDir(config->firmPath(), Lang::get("SELECT_DIR"));
if (path != "") config->firmPath(path);
break;
} }
} }
} }
@@ -431,7 +456,7 @@ static void GUISettingsLogic(int &page, int &selection) {
} }
if (hRepeat & KEY_DOWN) { if (hRepeat & KEY_DOWN) {
if (selection < 1) selection++; if (selection < 2) selection++;
} }
if (hRepeat & KEY_UP) { if (hRepeat & KEY_UP) {
@@ -450,6 +475,12 @@ static void GUISettingsLogic(int &page, int &selection) {
config->customfont(!config->customfont()); config->customfont(!config->customfont());
(config->customfont() ? Init::LoadFont() : Init::UnloadFont()); (config->customfont() ? Init::LoadFont() : Init::UnloadFont());
} else if (touching(touch, Themes)) {
if (GFX::SelectedTheme < (_THEME_AMOUNT - 1)) GFX::SelectedTheme++;
else GFX::SelectedTheme = 0;
config->theme(GFX::SelectedTheme);
} }
} }
@@ -464,6 +495,13 @@ static void GUISettingsLogic(int &page, int &selection) {
(config->customfont() ? Init::LoadFont() : Init::UnloadFont()); (config->customfont() ? Init::LoadFont() : Init::UnloadFont());
break; break;
case 2:
if (GFX::SelectedTheme < (_THEME_AMOUNT - 1)) GFX::SelectedTheme++;
else GFX::SelectedTheme = 0;
config->theme(GFX::SelectedTheme);
break;
} }
} }
} }
@@ -555,7 +593,7 @@ static void LanguageLogic(int &page, int &selection, int &sPos) {
if (hDown & KEY_TOUCH) { if (hDown & KEY_TOUCH) {
if (touching(touch, langButtons[6])) { if (touching(touch, langButtons[6])) {
/* Download Font. */ /* Download Font. */
ScriptUtils::downloadFile("https://github.com/Universal-Team/extras/raw/master/files/universal-updater.bcfnt", "sdmc:/3ds/Universal-Updater/font.bcfnt", Lang::get("DOWNLOADING_COMPATIBLE_FONT")); ScriptUtils::downloadFile("https://github.com/Universal-Team/extras/raw/master/files/universal-updater.bcfnt", "sdmc:/3ds/Universal-Updater/font.bcfnt", Lang::get("DOWNLOADING_COMPATIBLE_FONT"), true);
config->customfont(true); config->customfont(true);
Init::LoadFont(); Init::LoadFont();
} }
@@ -600,20 +638,18 @@ void StoreUtils::DrawSettings(int page, int selection, int sPos) {
int &page: Reference to the page. int &page: Reference to the page.
bool &dspSettings: Reference to the display Settings. bool &dspSettings: Reference to the display Settings.
int &storeMode: Reference to the Store Mode. int &storeMode: Reference to the store Mode.
int &selection: Reference to the Selection. int &selection: Reference to the Selection.
std::unique_ptr<Store> &store: Reference to the Store class. int &sPos: Reference to screen position.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the StoreEntries.
std::unique_ptr<Meta> &meta: Reference to the Meta class.
*/ */
void StoreUtils::SettingsHandle(int &page, bool &dspSettings, int &storeMode, int &selection, std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, std::unique_ptr<Meta> &meta, int &sPos) { void StoreUtils::SettingsHandle(int &page, bool &dspSettings, int &storeMode, int &selection, int &sPos) {
switch(page) { switch(page) {
case 0: case 0:
SettingsHandleMain(page, dspSettings, storeMode, selection, store, entries, meta); SettingsHandleMain(page, dspSettings, storeMode, selection);
break; break;
case 1: case 1:
SettingsHandleDir(page, selection, store); SettingsHandleDir(page, selection);
break; break;
case 2: case 2:
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,40 +24,44 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "animation.hpp"
#include "common.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include "structs.hpp" #include "structs.hpp"
extern bool touching(touchPosition touch, Structs::ButtonPos button); extern bool touching(touchPosition touch, Structs::ButtonPos button);
static const std::vector<Structs::ButtonPos> sidePos = { static const std::vector<Structs::ButtonPos> sidePos = {
{ 0, 0, 48, 48 }, { 0, 0, 40, 40 },
{ 0, 48, 48, 48 }, { 0, 40, 40, 40 },
{ 0, 96, 48, 48 }, { 0, 80, 40, 40 },
{ 0, 144, 48, 48 }, { 0, 120, 40, 40 },
{ 0, 192, 48, 48 } { 0, 160, 40, 40 },
{ 0, 200, 40, 40 }
}; };
/* /*
Draw the Side Menu part. Draw the Side Menu part.
int currentMenu: The current Store Mode / Menu. int currentMenu: The current store Mode / Menu.
*/ */
void StoreUtils::DrawSideMenu(int currentMenu) { void StoreUtils::DrawSideMenu(int currentMenu) {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 6; i++) {
if (i == currentMenu) { if (i == currentMenu) {
Gui::Draw_Rect(sidePos[i].x, sidePos[i].y, sidePos[i].w, sidePos[i].h, SIDEBAR_SELECTED_COLOR); Gui::Draw_Rect(sidePos[i].x, sidePos[i].y, sidePos[i].w, sidePos[i].h, GFX::Themes[GFX::SelectedTheme].SideBarSelected);
} else { } else {
Gui::Draw_Rect(sidePos[i].x, sidePos[i].y, sidePos[i].w, sidePos[i].h, SIDEBAR_UNSELECTED_COLOR); Gui::Draw_Rect(sidePos[i].x, sidePos[i].y, sidePos[i].w, sidePos[i].h, GFX::Themes[GFX::SelectedTheme].SideBarUnselected);
} }
} }
GFX::DrawSprite(sprites_info_idx, sidePos[0].x + 4, sidePos[0].y + 4); GFX::DrawSprite(sprites_info_idx, sidePos[0].x, sidePos[0].y);
GFX::DrawSprite(sprites_download_idx, sidePos[1].x + 4, sidePos[1].y + 4); GFX::DrawSprite(sprites_download_idx, sidePos[1].x, sidePos[1].y);
GFX::DrawSprite(sprites_search_idx, sidePos[2].x + 4, sidePos[2].y + 4); Animation::DrawQueue(sidePos[2].x, sidePos[2].y);
GFX::DrawSprite(sprites_sort_idx, sidePos[3].x + 4, sidePos[3].y + 4); GFX::DrawSprite(sprites_search_idx, sidePos[3].x, sidePos[3].y);
GFX::DrawSprite(sprites_settings_idx, sidePos[4].x + 4, sidePos[4].y + 4); GFX::DrawSprite(sprites_sort_idx, sidePos[4].x, sidePos[4].y);
GFX::DrawSprite(sprites_settings_idx, sidePos[5].x, sidePos[5].y);
Gui::Draw_Rect(48, 0, 1, 240, BAR_OUTL_COLOR); Gui::Draw_Rect(40, 0, 1, 240, GFX::Themes[GFX::SelectedTheme].BarOutline);
} }
/* /*
@@ -66,13 +70,15 @@ void StoreUtils::DrawSideMenu(int currentMenu) {
- Switch between the Menus through the sidebar. - Switch between the Menus through the sidebar.
int &currentMenu: Reference to the Store Mode / Menu. int &currentMenu: Reference to the store Mode / Menu.
bool &fetch: Reference of the download fetch variable.. so we know, if we need to fetch the download entries. bool &fetch: Reference of the download fetch variable.. so we know, if we need to fetch the download entries.
int &lastMenu: Reference to the last menu. int &lastMenu: Reference to the last menu.
*/ */
void StoreUtils::SideMenuHandle(int &currentMenu, bool &fetch, int &lastMenu) { void StoreUtils::SideMenuHandle(int &currentMenu, bool &fetch, int &lastMenu) {
Animation::QueueAnimHandle();
if (hDown & KEY_TOUCH) { if (hDown & KEY_TOUCH) {
for (int i = 0; i < 5; i++) { for (int i = 0; i < 6; i++) {
if (touching(touch, sidePos[i])) { if (touching(touch, sidePos[i])) {
lastMenu = currentMenu; lastMenu = currentMenu;
if (i == 1) fetch = true; // Fetch download list, if 1. if (i == 1) fetch = true; // Fetch download list, if 1.
@@ -83,7 +89,7 @@ void StoreUtils::SideMenuHandle(int &currentMenu, bool &fetch, int &lastMenu) {
} }
if (hRepeat & KEY_R) { if (hRepeat & KEY_R) {
if (currentMenu < 4) { if (currentMenu < 5) {
lastMenu = currentMenu; lastMenu = currentMenu;
if (currentMenu + 1 == 1) fetch = true; // Fetch download list, if 1. if (currentMenu + 1 == 1) fetch = true; // Fetch download list, if 1.
currentMenu++; currentMenu++;
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,7 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "common.hpp"
#include "keyboard.hpp" #include "keyboard.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include "structs.hpp" #include "structs.hpp"
@@ -31,19 +32,19 @@
extern bool touching(touchPosition touch, Structs::ButtonPos button); extern bool touching(touchPosition touch, Structs::ButtonPos button);
static const std::vector<Structs::ButtonPos> buttons = { static const std::vector<Structs::ButtonPos> buttons = {
{ 75, 60, 100, 16 }, { 71, 60, 104, 16 },
{ 75, 80, 100, 16 }, { 71, 80, 104, 16 },
{ 75, 100, 100, 16 }, { 71, 100, 104, 16 },
{ 205, 60, 100, 16 }, { 201, 60, 104, 16 },
{ 205, 80, 100, 16 }, { 201, 80, 104, 16 },
{ 75, 170, 100, 16 }, { 71, 170, 104, 16 },
{ 75, 190, 100, 16 } { 71, 190, 104, 16 }
}; };
static void DrawCheck(int pos, bool v) { static void DrawCheck(int pos, bool v) {
GFX::DrawSprite((v ? sprites_sort_checked_idx : sprites_sort_unchecked_idx), buttons[pos].x + 5, buttons[pos].y); GFX::DrawSprite((v ? sprites_sort_checked_idx : sprites_sort_unchecked_idx), buttons[pos].x + 1, buttons[pos].y);
} }
/* /*
@@ -73,89 +74,87 @@ static const uint8_t GetType(SortType st) {
SortType st: The SortType variable. SortType st: The SortType variable.
*/ */
void StoreUtils::DrawSorting(bool asc, SortType st) { void StoreUtils::DrawSorting(bool asc, SortType st) {
Gui::Draw_Rect(48, 0, 272, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(40, 0, 280, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(48, 25, 272, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(40, 25, 280, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
Gui::DrawStringCentered(25, 2, 0.6, TEXT_COLOR, Lang::get("SORTING"), 265, 0, font); Gui::DrawStringCentered(17, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SORTING"), 273, 0, font);
/* Sort By. */ /* Sort By. */
Gui::DrawString(buttons[0].x + 5, buttons[0].y - 20, 0.6f, TEXT_COLOR, Lang::get("SORT_BY"), 90, 0, font); Gui::DrawString(buttons[0].x + 1, buttons[0].y - 20, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SORT_BY"), 90, 0, font);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
DrawCheck(i, i == GetType(st)); DrawCheck(i, i == GetType(st));
} }
Gui::DrawString(buttons[0].x + 25, buttons[0].y + 2, 0.4f, TEXT_COLOR, Lang::get("TITLE"), 80, 0, font); Gui::DrawString(buttons[0].x + 21, buttons[0].y + 2, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("TITLE"), 80, 0, font);
Gui::DrawString(buttons[1].x + 25, buttons[1].y + 2, 0.4f, TEXT_COLOR, Lang::get("AUTHOR"), 80, 0, font); Gui::DrawString(buttons[1].x + 21, buttons[1].y + 2, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("AUTHOR"), 80, 0, font);
Gui::DrawString(buttons[2].x + 25, buttons[2].y + 2, 0.4f, TEXT_COLOR, Lang::get("LAST_UPDATED"), 80, 0, font); Gui::DrawString(buttons[2].x + 21, buttons[2].y + 2, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("LAST_UPDATED"), 80, 0, font);
/* Direction. */ /* Direction. */
Gui::DrawString(buttons[3].x + 5, buttons[3].y - 20, 0.6f, TEXT_COLOR, Lang::get("DIRECTION"), 80, 0, font); Gui::DrawString(buttons[3].x + 1, buttons[3].y - 20, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("DIRECTION"), 80, 0, font);
DrawCheck(3, asc); DrawCheck(3, asc);
DrawCheck(4, !asc); DrawCheck(4, !asc);
Gui::DrawString(buttons[3].x + 25, buttons[3].y + 2, 0.4f, TEXT_COLOR, Lang::get("ASCENDING"), 80, 0, font); Gui::DrawString(buttons[3].x + 21, buttons[3].y + 2, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("ASCENDING"), 80, 0, font);
Gui::DrawString(buttons[4].x + 25, buttons[4].y + 2, 0.4f, TEXT_COLOR, Lang::get("DESCENDING"), 80, 0, font); Gui::DrawString(buttons[4].x + 21, buttons[4].y + 2, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("DESCENDING"), 80, 0, font);
/* Top Style. */ /* Top Style. */
Gui::DrawString(buttons[5].x + 5, buttons[5].y - 20, 0.6f, TEXT_COLOR, Lang::get("TOP_STYLE"), 90, 0, font); Gui::DrawString(buttons[5].x + 1, buttons[5].y - 20, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("TOP_STYLE"), 90, 0, font);
DrawCheck(5, config->list()); DrawCheck(5, config->list());
DrawCheck(6, !config->list()); DrawCheck(6, !config->list());
Gui::DrawString(buttons[5].x + 25, buttons[5].y + 2, 0.4f, TEXT_COLOR, Lang::get("LIST"), 90, 0, font); Gui::DrawString(buttons[5].x + 21, buttons[5].y + 2, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("LIST"), 90, 0, font);
Gui::DrawString(buttons[6].x + 25, buttons[6].y + 2, 0.4f, TEXT_COLOR, Lang::get("GRID"), 90, 0, font); Gui::DrawString(buttons[6].x + 21, buttons[6].y + 2, 0.4f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("GRID"), 90, 0, font);
} }
/* /*
Sort Handle. Sort Handle.
Here you can.. Here you can..
- Sort your Entries to.. - Sort your entries to..
- Title (Ascending / Descending). - Title (Ascending / Descending).
- Author (Ascending / Descending). - Author (Ascending / Descending).
- Last Updated Date (Ascending / Descending). - Last Updated Date (Ascending / Descending).
- Change the Top Style. - Change the Top Style.
std::unique_ptr<Store> &store: Reference to the Store class.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the StoreEntries.
bool &asc: Reference to the Ascending variable. bool &asc: Reference to the Ascending variable.
SortType &st: Reference to the SortType. SortType &st: Reference to the SortType.
*/ */
void StoreUtils::SortHandle(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, bool &asc, SortType &st) { void StoreUtils::SortHandle(bool &asc, SortType &st) {
if (store && store->GetValid() && entries.size() > 0) { // Ensure, this is valid and more than 0 entries exist. if (StoreUtils::store && StoreUtils::store->GetValid() && StoreUtils::entries.size() > 0) { // Ensure, this is valid and more than 0 StoreUtils::entries exist.
if (hDown & KEY_TOUCH) { if (hDown & KEY_TOUCH) {
/* SortType Part. */ /* SortType Part. */
if (touching(touch, buttons[0])) { if (touching(touch, buttons[0])) {
st = SortType::TITLE; st = SortType::TITLE;
StoreUtils::SortEntries(asc, st, entries); StoreUtils::SortEntries(asc, st);
} else if (touching(touch, buttons[1])) { } else if (touching(touch, buttons[1])) {
st = SortType::AUTHOR; st = SortType::AUTHOR;
StoreUtils::SortEntries(asc, st, entries); StoreUtils::SortEntries(asc, st);
} else if (touching(touch, buttons[2])) { } else if (touching(touch, buttons[2])) {
st = SortType::LAST_UPDATED; st = SortType::LAST_UPDATED;
StoreUtils::SortEntries(asc, st, entries); StoreUtils::SortEntries(asc, st);
/* Ascending | Descending Part. */ /* Ascending | Descending Part. */
} else if (touching(touch, buttons[3])) { } else if (touching(touch, buttons[3])) {
asc = true; asc = true;
StoreUtils::SortEntries(asc, st, entries); StoreUtils::SortEntries(asc, st);
} else if (touching(touch, buttons[4])) { } else if (touching(touch, buttons[4])) {
asc = false; asc = false;
StoreUtils::SortEntries(asc, st, entries); StoreUtils::SortEntries(asc, st);
} else if (touching(touch, buttons[5])) { } else if (touching(touch, buttons[5])) {
if (config->list()) return; if (config->list()) return;
config->list(true); config->list(true);
store->SetEntry(0); StoreUtils::store->SetEntry(0);
store->SetScreenIndx(0); StoreUtils::store->SetScreenIndx(0);
store->SetBox(0); StoreUtils::store->SetBox(0);
} else if (touching(touch, buttons[6])) { } else if (touching(touch, buttons[6])) {
if (!config->list()) return; if (!config->list()) return;
config->list(false); config->list(false);
store->SetEntry(0); StoreUtils::store->SetEntry(0);
store->SetScreenIndx(0); StoreUtils::store->SetScreenIndx(0);
store->SetBox(0); StoreUtils::store->SetBox(0);
} }
} }
} }
+20 -17
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,11 +24,12 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "animation.hpp"
#include "common.hpp"
#include "overlay.hpp" #include "overlay.hpp"
#include "version.hpp"
/* /* Show the Credits. */
Show the Credits.
*/
void Overlays::ShowCredits() { void Overlays::ShowCredits() {
bool doOut = false; bool doOut = false;
@@ -40,27 +41,29 @@ void Overlays::ShowCredits() {
GFX::DrawTop(); GFX::DrawTop();
GFX::DrawSprite(sprites_universal_updater_idx, 220, 26); GFX::DrawSprite(sprites_universal_updater_idx, 220, 26);
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, "Universal-Updater - " + Lang::get("CREDITS"), 395, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, "Universal-Updater - " + Lang::get("CREDITS"), 395, 0, font);
Gui::DrawString(10, 30, 0.5f, TEXT_COLOR, "- Universal-Team", 0, 0, font); Gui::DrawString(10, 30, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "- Universal-Team", 0, 0, font);
Gui::DrawString(10, 50, 0.5f, TEXT_COLOR, "- devkitPro", 0, 0, font); Gui::DrawString(10, 50, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "- devkitPro", 0, 0, font);
Gui::DrawString(10, 70, 0.5f, TEXT_COLOR, "- dlbeer", 0, 0, font); Gui::DrawString(10, 70, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "- dlbeer", 0, 0, font);
Gui::DrawString(10, 90, 0.5f, TEXT_COLOR, "- FlagBrew", 0, 0, font); Gui::DrawString(10, 90, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "- FlagBrew", 0, 0, font);
Gui::DrawString(10, 110, 0.5f, TEXT_COLOR, "- https://icons8.com/", 0, 0, font); Gui::DrawString(10, 110, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "- https://icons8.com/", 0, 0, font);
Gui::DrawString(10, 130, 0.5f, TEXT_COLOR, "- Ivandeve", 0, 0, font); Gui::DrawString(10, 130, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "- Ivandeve", 0, 0, font);
Gui::DrawString(10, 150, 0.5f, TEXT_COLOR, "- PabloMK7", 0, 0, font); Gui::DrawString(10, 150, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, "- PabloMK7", 0, 0, font);
Gui::DrawString(10, 170, 0.5f, TEXT_COLOR, Lang::get("CONTRIBUTOR_TRANSLATORS"), 210, 0, font); Gui::DrawString(10, 170, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CONTRIBUTOR_TRANSLATORS"), 210, 0, font);
Gui::DrawString(10, 197, 0.5f, TEXT_COLOR, Lang::get("GITHUB"), 390, 0, font); Gui::DrawString(10, 197, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("GITHUB"), 390, 0, font);
Gui::Draw_Rect(0, 215, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 215, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 214, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 214, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 218, 0.6f, TEXT_COLOR, Lang::get("CURRENT_VERSION") + std::string(V_STRING), 390, 0, font); Gui::DrawStringCentered(0, 218, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CURRENT_VERSION") + std::string(VER_NUMBER), 390, 0, font);
Animation::QueueEntryDone();
GFX::DrawBottom(); GFX::DrawBottom();
GFX::DrawSprite(sprites_universal_core_idx, 0, 26); GFX::DrawSprite(sprites_universal_core_idx, 0, 26);
C3D_FrameEnd(0); C3D_FrameEnd(0);
hidScanInput(); hidScanInput();
Animation::HandleQueueEntryDone();
if ((hidKeysDown() & KEY_START) || (hidKeysDown() & KEY_B) || (hidKeysDown() & KEY_A)) doOut = true; if ((hidKeysDown() & KEY_START) || (hidKeysDown() & KEY_B) || (hidKeysDown() & KEY_A)) doOut = true;
} }
} }
+21 -18
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,8 +24,11 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "animation.hpp"
#include "common.hpp"
#include "fileBrowse.hpp" #include "fileBrowse.hpp"
#include "overlay.hpp" #include "overlay.hpp"
#include "storeUtils.hpp"
#include <unistd.h> #include <unistd.h>
extern bool touching(touchPosition touch, Structs::ButtonPos button); extern bool touching(touchPosition touch, Structs::ButtonPos button);
@@ -39,10 +42,8 @@ static const std::vector<Structs::ButtonPos> mainButtons = {
{ 10, 186, 300, 22 } { 10, 186, 300, 22 }
}; };
/* /* Select a Directory. */
Select a Directory. std::string Overlays::SelectDir(const std::string &oldDir, const std::string &msg) {
*/
std::string Overlays::SelectDir(const std::string &oldDir, const std::string &msg, const std::unique_ptr<Store> &store) {
std::string currentPath = oldDir; std::string currentPath = oldDir;
bool dirChanged = false; bool dirChanged = false;
int selection = 0, sPos = 0; int selection = 0, sPos = 0;
@@ -72,32 +73,33 @@ std::string Overlays::SelectDir(const std::string &oldDir, const std::string &ms
C2D_TargetClear(Top, TRANSPARENT); C2D_TargetClear(Top, TRANSPARENT);
C2D_TargetClear(Bottom, TRANSPARENT); C2D_TargetClear(Bottom, TRANSPARENT);
if (store && config->usebg() && store->customBG()) { if (StoreUtils::store && config->usebg() && StoreUtils::store->customBG()) {
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 0, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
C2D_DrawImageAt(store->GetStoreImg(), 0, 26, 0.5f, nullptr); C2D_DrawImageAt(StoreUtils::store->GetStoreImg(), 0, 26, 0.5f, nullptr);
} else { } else {
GFX::DrawTop(); GFX::DrawTop();
} }
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, msg, 380, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, msg, 380, 0, font);
Gui::Draw_Rect(0, 215, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 215, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 214, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 214, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 217, 0.6f, TEXT_COLOR, currentPath, 390, 0, font); Gui::DrawStringCentered(0, 217, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, currentPath, 390, 0, font);
Animation::QueueEntryDone();
GFX::DrawBottom(); GFX::DrawBottom();
Gui::Draw_Rect(0, 215, 320, 25, BAR_COLOR); Gui::Draw_Rect(0, 215, 320, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 214, 320, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 214, 320, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 220, 0.5f, TEXT_COLOR, Lang::get("START_SELECT"), 310, 0, font); Gui::DrawStringCentered(0, 220, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("START_SELECT"), 310, 0, font);
if (dirContents.size() > 0) { if (dirContents.size() > 0) {
for(int i = 0; i < 7 && i < (int)dirContents.size(); i++) { for(int i = 0; i < 7 && i < (int)dirContents.size(); i++) {
if (sPos + i == selection) GFX::DrawBox(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, false); if (sPos + i == selection) Gui::Draw_Rect(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, GFX::Themes[GFX::SelectedTheme].MarkSelected);
Gui::DrawStringCentered(10 - 160 + (300 / 2), mainButtons[i].y + 4, 0.45f, TEXT_COLOR, dirContents[sPos + i].name, 295, 0, font); Gui::DrawStringCentered(10 - 160 + (300 / 2), mainButtons[i].y + 4, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, dirContents[sPos + i].name, 295, 0, font);
} }
} }
@@ -122,6 +124,7 @@ std::string Overlays::SelectDir(const std::string &oldDir, const std::string &ms
touchPosition touch; touchPosition touch;
hidTouchRead(&touch); hidTouchRead(&touch);
u32 hRepeat = hidKeysDownRepeat(); u32 hRepeat = hidKeysDownRepeat();
Animation::HandleQueueEntryDone();
if (dirContents.size() > 0) { if (dirContents.size() > 0) {
if (hRepeat & KEY_DOWN) { if (hRepeat & KEY_DOWN) {
+30 -31
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,6 +24,8 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "animation.hpp"
#include "common.hpp"
#include "download.hpp" #include "download.hpp"
#include "fileBrowse.hpp" #include "fileBrowse.hpp"
#include "files.hpp" #include "files.hpp"
@@ -52,7 +54,7 @@ static const std::vector<Structs::ButtonPos> mainButtons = {
}; };
/* /*
Delete a Store.. including the Spritesheets, if found. Delete a store.. including the Spritesheets, if found.
const std::string &file: The file of the UniStore. const std::string &file: The file of the UniStore.
*/ */
@@ -93,7 +95,7 @@ static void DeleteStore(const std::string &file) {
} }
/* /*
Download a Store.. including the SpriteSheets, if found. Download a store.. including the SpriteSheets, if found.
*/ */
static bool DownloadStore() { static bool DownloadStore() {
bool doSheet = false; bool doSheet = false;
@@ -209,12 +211,8 @@ static bool UpdateStore(const std::string &URL) {
- Download / Add a UniStore. - Download / Add a UniStore.
- Check for Updates for a UniStore. - Check for Updates for a UniStore.
- Switch the UniStore. - Switch the UniStore.
std::unique_ptr<Store> &store: Reference to the Store class.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the Store Entries.
std::unique_ptr<Meta> &meta: Reference to the Meta class.
*/ */
void Overlays::SelectStore(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, std::unique_ptr<Meta> &meta) { void Overlays::SelectStore() {
bool doOut = false; bool doOut = false;
int selection = 0, sPos = 0; int selection = 0, sPos = 0;
@@ -226,11 +224,11 @@ void Overlays::SelectStore(std::unique_ptr<Store> &store, std::vector<std::uniqu
C2D_TargetClear(Top, TRANSPARENT); C2D_TargetClear(Top, TRANSPARENT);
C2D_TargetClear(Bottom, TRANSPARENT); C2D_TargetClear(Bottom, TRANSPARENT);
if (store && config->usebg() && store->customBG()) { if (StoreUtils::store && config->usebg() && StoreUtils::store->customBG()) {
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 0, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
C2D_DrawImageAt(store->GetStoreImg(), 0, 26, 0.5f, nullptr); C2D_DrawImageAt(StoreUtils::store->GetStoreImg(), 0, 26, 0.5f, nullptr);
} else { } else {
GFX::DrawTop(); GFX::DrawTop();
@@ -238,29 +236,29 @@ void Overlays::SelectStore(std::unique_ptr<Store> &store, std::vector<std::uniqu
if (info.size() > 0) { if (info.size() > 0) {
if (info[selection].StoreSize != -1) { if (info[selection].StoreSize != -1) {
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, info[selection].Title, 390, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, info[selection].Title, 390, 0, font);
Gui::DrawStringCentered(0, 30, 0.6f, TEXT_COLOR, info[selection].Author, 380, 0, font); Gui::DrawStringCentered(0, 30, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, info[selection].Author, 380, 0, font);
Gui::DrawStringCentered(0, 70, 0.5f, TEXT_COLOR, info[selection].Description, 380, 130, font, C2D_WordWrap); Gui::DrawStringCentered(0, 70, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, info[selection].Description, 380, 130, font, C2D_WordWrap);
} else { } else {
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, Lang::get("INVALID_UNISTORE"), 390, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("INVALID_UNISTORE"), 390, 0, font);
} }
Gui::DrawString(10, 200, 0.4, TEXT_COLOR, "- " + Lang::get("ENTRIES") + ": " + std::to_string(info[selection].StoreSize), 150, 0, font); Gui::DrawString(10, 200, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, "- " + Lang::get("ENTRIES") + ": " + std::to_string(info[selection].StoreSize), 150, 0, font);
Gui::DrawString(10, 210, 0.4, TEXT_COLOR, "- " + Lang::get("VERSION") + ": " + std::to_string(info[selection].Version), 150, 0, font); Gui::DrawString(10, 210, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, "- " + Lang::get("VERSION") + ": " + std::to_string(info[selection].Version), 150, 0, font);
Gui::DrawString(10, 220, 0.4, TEXT_COLOR, "- " + Lang::get("REVISION") + ": " + std::to_string(info[selection].Revision), 150, 0, font); Gui::DrawString(10, 220, 0.4, GFX::Themes[GFX::SelectedTheme].TextColor, "- " + Lang::get("REVISION") + ": " + std::to_string(info[selection].Revision), 150, 0, font);
Animation::QueueEntryDone();
GFX::DrawBottom(); GFX::DrawBottom();
Gui::Draw_Rect(0, 0, 320, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(0, 0, 320, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 320, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 320, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
GFX::DrawSprite(sprites_arrow_idx, mainButtons[9].x, mainButtons[9].y); GFX::DrawSprite(sprites_arrow_idx, mainButtons[9].x, mainButtons[9].y);
Gui::DrawStringCentered(0, 2, 0.6, TEXT_COLOR, Lang::get("SELECT_UNISTORE_2"), 310, 0, font); Gui::DrawStringCentered(0, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("SELECT_UNISTORE_2"), 310, 0, font);
for(int i = 0; i < 6 && i < (int)info.size(); i++) { for(int i = 0; i < 6 && i < (int)info.size(); i++) {
if (sPos + i == selection) GFX::DrawBox(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, false); if (sPos + i == selection) Gui::Draw_Rect(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, GFX::Themes[GFX::SelectedTheme].MarkSelected);
Gui::DrawStringCentered(10 - 160 + (300 / 2), mainButtons[i].y + 4, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, info[sPos + i].FileName, 295, 0, font);
Gui::DrawStringCentered(10 - 160 + (300 / 2), mainButtons[i].y + 4, 0.45f, TEXT_COLOR, info[sPos + i].FileName, 295, 0, font);
} }
} }
@@ -275,6 +273,7 @@ void Overlays::SelectStore(std::unique_ptr<Store> &store, std::vector<std::uniqu
touchPosition touch; touchPosition touch;
hidTouchRead(&touch); hidTouchRead(&touch);
u32 hRepeat = hidKeysDownRepeat(); u32 hRepeat = hidKeysDownRepeat();
Animation::HandleQueueEntryDone();
if (info.size() > 0) { if (info.size() > 0) {
if (hRepeat & KEY_DOWN) { if (hRepeat & KEY_DOWN) {
@@ -306,9 +305,9 @@ void Overlays::SelectStore(std::unique_ptr<Store> &store, std::vector<std::uniqu
else if (info[selection].Version > _UNISTORE_VERSION) Msg::waitMsg(Lang::get("UNISTORE_TOO_NEW")); else if (info[selection].Version > _UNISTORE_VERSION) Msg::waitMsg(Lang::get("UNISTORE_TOO_NEW"));
else { else {
config->lastStore(info[selection].FileName); config->lastStore(info[selection].FileName);
store = std::make_unique<Store>(_STORE_PATH + info[selection].FileName, info[selection].FileName); StoreUtils::store = std::make_unique<Store>(_STORE_PATH + info[selection].FileName, info[selection].FileName);
StoreUtils::ResetAll(store, meta, entries); StoreUtils::ResetAll();
StoreUtils::SortEntries(false, SortType::LAST_UPDATED, entries); StoreUtils::SortEntries(false, SortType::LAST_UPDATED);
doOut = true; doOut = true;
} }
@@ -328,9 +327,9 @@ void Overlays::SelectStore(std::unique_ptr<Store> &store, std::vector<std::uniqu
else if (info[i + sPos].Version > _UNISTORE_VERSION) Msg::waitMsg(Lang::get("UNISTORE_TOO_NEW")); else if (info[i + sPos].Version > _UNISTORE_VERSION) Msg::waitMsg(Lang::get("UNISTORE_TOO_NEW"));
else { else {
config->lastStore(info[i + sPos].FileName); config->lastStore(info[i + sPos].FileName);
store = std::make_unique<Store>(_STORE_PATH + info[i + sPos].FileName, info[i + sPos].FileName); StoreUtils::store = std::make_unique<Store>(_STORE_PATH + info[i + sPos].FileName, info[i + sPos].FileName);
StoreUtils::ResetAll(store, meta, entries); StoreUtils::ResetAll();
StoreUtils::SortEntries(false, SortType::LAST_UPDATED, entries); StoreUtils::SortEntries(false, SortType::LAST_UPDATED);
doOut = true; doOut = true;
} }
+13 -14
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -152,28 +152,27 @@ void QRCode::drawThread() {
C2D_DrawImageAt(this->image, 0, 0, 0.5, nullptr, 1.0f, 1.0f); C2D_DrawImageAt(this->image, 0, 0, 0.5, nullptr, 1.0f, 1.0f);
GFX::DrawBottom(); GFX::DrawBottom();
Gui::Draw_Rect(0, 0, 320, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(0, 0, 320, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(0, 25, 320, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 320, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
} else { } else {
GFX::DrawTop(); GFX::DrawTop();
Gui::DrawStringCentered(0, 1, 0.7, TEXT_COLOR, Lang::get("STORE_INFO"), 390, 0, font); Gui::DrawStringCentered(0, 1, 0.7, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("STORE_INFO"), 390, 0, font);
if (this->stores.size() > 0) { if (this->stores.size() > 0) {
Gui::DrawStringCentered(0, 30, 0.7f, TEXT_COLOR, this->stores[this->selectedStore].Title, 390, 0, font); Gui::DrawStringCentered(0, 30, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, this->stores[this->selectedStore].Title, 390, 0, font);
Gui::DrawStringCentered(0, 50, 0.6f, TEXT_COLOR, this->stores[this->selectedStore].Author, 380, 0, font); Gui::DrawStringCentered(0, 50, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, this->stores[this->selectedStore].Author, 380, 0, font);
Gui::DrawStringCentered(0, 90, 0.5f, TEXT_COLOR, this->stores[this->selectedStore].Description, 380, 130, font, C2D_WordWrap); Gui::DrawStringCentered(0, 90, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, this->stores[this->selectedStore].Description, 380, 130, font, C2D_WordWrap);
} }
GFX::DrawBottom(); GFX::DrawBottom();
Gui::Draw_Rect(0, 0, 320, 25, ENTRY_BAR_COLOR); Gui::Draw_Rect(0, 0, 320, 25, GFX::Themes[GFX::SelectedTheme].EntryBar);
Gui::Draw_Rect(0, 25, 320, 1, ENTRY_BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 320, 1, GFX::Themes[GFX::SelectedTheme].EntryOutline);
Gui::DrawStringCentered(0, 2, 0.6, TEXT_COLOR, Lang::get("RECOMMENDED_UNISTORES"), 310, 0, font); Gui::DrawStringCentered(0, 2, 0.6, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("RECOMMENDED_UNISTORES"), 310, 0, font);
for(int i = 0; i < 6 && i < (int)this->stores.size(); i++) { for(int i = 0; i < 6 && i < (int)this->stores.size(); i++) {
if (this->sPos + i == this->selectedStore) GFX::DrawBox(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, false); if (this->sPos + i == this->selectedStore) Gui::Draw_Rect(mainButtons[i].x, mainButtons[i].y, mainButtons[i].w, mainButtons[i].h, GFX::Themes[GFX::SelectedTheme].MarkSelected);
Gui::DrawStringCentered(10 - 160 + (300 / 2), mainButtons[i].y + 4, 0.45f, GFX::Themes[GFX::SelectedTheme].TextColor, this->stores[this->sPos + i].Title, 295, 0, font);
Gui::DrawStringCentered(10 - 160 + (300 / 2), mainButtons[i].y + 4, 0.45f, TEXT_COLOR, this->stores[this->sPos + i].Title, 295, 0, font);
} }
} }
@@ -410,7 +409,7 @@ void QRCode::handler(std::string &result) {
} }
/* /*
The Store Add QR Code handle and such. The store Add QR Code handle and such.
*/ */
std::string QR_Scanner::StoreHandle() { std::string QR_Scanner::StoreHandle() {
std::string result = ""; std::string result = "";
+76 -43
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,9 +24,11 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "animation.hpp"
#include "download.hpp" #include "download.hpp"
#include "fileBrowse.hpp" #include "fileBrowse.hpp"
#include "mainScreen.hpp" #include "mainScreen.hpp"
#include "queueSystem.hpp"
#include "screenshot.hpp" #include "screenshot.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
#include <unistd.h> #include <unistd.h>
@@ -40,12 +42,12 @@ extern void DisplayChangelog();
/* /*
MainScreen Constructor. MainScreen Constructor.
Initialized Meta, Store and StoreEntry class and: Initialized meta, store and StoreEntry class and:
- Downloads Universal-DB.. in case nothing exist. - Downloads Universal-DB.. in case nothing exist.
*/ */
MainScreen::MainScreen() { MainScreen::MainScreen() {
this->meta = std::make_unique<Meta>(); StoreUtils::meta = std::make_unique<Meta>();
/* Check if lastStore is accessible. */ /* Check if lastStore is accessible. */
if (config->lastStore() != "universal-db.unistore" || config->lastStore() != "") { if (config->lastStore() != "universal-db.unistore" || config->lastStore() != "") {
@@ -84,7 +86,6 @@ MainScreen::MainScreen() {
const UniStoreInfo info = GetInfo("sdmc:/3ds/Universal-Updater/stores/universal-db.unistore", "universal-db.unistore"); const UniStoreInfo info = GetInfo("sdmc:/3ds/Universal-Updater/stores/universal-db.unistore", "universal-db.unistore");
if (info.Version != 3 && info.Version != _UNISTORE_VERSION) { if (info.Version != 3 && info.Version != _UNISTORE_VERSION) {
Msg::waitMsg("Not passing the check!");
if (checkWifiStatus()) { if (checkWifiStatus()) {
std::string tmp = ""; // Just a temp. std::string tmp = ""; // Just a temp.
DownloadUniStore("https://db.universal-team.net/unistore/universal-db.unistore", -1, tmp, true, true); DownloadUniStore("https://db.universal-team.net/unistore/universal-db.unistore", -1, tmp, true, true);
@@ -97,9 +98,9 @@ MainScreen::MainScreen() {
} }
} }
this->store = std::make_unique<Store>(_STORE_PATH + config->lastStore(), config->lastStore()); StoreUtils::store = std::make_unique<Store>(_STORE_PATH + config->lastStore(), config->lastStore());
StoreUtils::ResetAll(this->store, this->meta, this->entries); StoreUtils::ResetAll();
StoreUtils::SortEntries(false, SortType::LAST_UPDATED, this->entries); StoreUtils::SortEntries(false, SortType::LAST_UPDATED);
DisplayChangelog(); DisplayChangelog();
}; };
@@ -107,30 +108,33 @@ MainScreen::MainScreen() {
MainScreen Main Draw. MainScreen Main Draw.
*/ */
void MainScreen::Draw(void) const { void MainScreen::Draw(void) const {
if (this->storeMode == 5) { if (this->storeMode == 6) {
/* Screenshot Menu. */ /* Screenshot Menu. */
StoreUtils::DrawScreenshotMenu(this->Screenshot, this->screenshotIndex, this->screenshotFetch, this->sSize, this->screenshotName, this->zoom, this->canDisplay); StoreUtils::DrawScreenshotMenu(this->Screenshot, this->screenshotIndex, this->screenshotFetch, this->sSize, this->screenshotName, this->zoom, this->canDisplay);
return; return;
} }
if (this->storeMode == 6) { if (this->storeMode == 7) {
/* Release Notes. */ /* Release Notes. */
StoreUtils::DrawReleaseNotes(this->scrollIndex, this->entries[this->store->GetEntry()], this->store); StoreUtils::DrawReleaseNotes(this->scrollIndex, StoreUtils::entries[StoreUtils::store->GetEntry()]);
GFX::DrawBottom(); GFX::DrawBottom();
return; return;
} }
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 0, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
if (this->store && this->store->GetValid()) Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, this->store->GetUniStoreTitle(), 370, 0, font); if (StoreUtils::store && StoreUtils::store->GetValid()) Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, StoreUtils::store->GetUniStoreTitle(), 360, 0, font);
else Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, Lang::get("INVALID_UNISTORE"), 370, 0, font); else Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("INVALID_UNISTORE"), 370, 0, font);
config->list() ? StoreUtils::DrawList(this->store, this->entries) : StoreUtils::DrawGrid(this->store, this->entries); config->list() ? StoreUtils::DrawList() : StoreUtils::DrawGrid();
GFX::DrawTime();
GFX::DrawBattery();
Animation::QueueEntryDone();
/* Download-ception. */ /* Download-ception. */
if (this->storeMode == 1) { if (this->storeMode == 1) {
StoreUtils::DrawDownList(this->store, this->dwnldList, this->fetchDown, this->entries[this->store->GetEntry()], this->dwnldSizes); StoreUtils::DrawDownList(this->dwnldList, this->fetchDown, StoreUtils::entries[StoreUtils::store->GetEntry()], this->dwnldSizes, this->installs);
} else { } else {
if (fadeAlpha > 0) Gui::Draw_Rect(0, 0, 400, 240, C2D_Color32(0, 0, 0, fadeAlpha)); if (fadeAlpha > 0) Gui::Draw_Rect(0, 0, 400, 240, C2D_Color32(0, 0, 0, fadeAlpha));
@@ -139,20 +143,25 @@ void MainScreen::Draw(void) const {
switch(this->storeMode) { switch(this->storeMode) {
case 0: case 0:
/* Entry Info. */ /* Entry Info. */
if (this->store && this->store->GetValid() && this->entries.size() > 0) StoreUtils::DrawEntryInfo(this->store, this->entries[this->store->GetEntry()]); if (StoreUtils::store && StoreUtils::store->GetValid() && StoreUtils::entries.size() > 0) StoreUtils::DrawEntryInfo(StoreUtils::entries[StoreUtils::store->GetEntry()]);
break; break;
case 2: case 2:
/* Search + Favorites. */ /* Queue Menu. */
StoreUtils::DrawSearchMenu(this->searchIncludes, this->searchResult, this->marks, this->updateFilter); StoreUtils::DrawQueueMenu(this->queueIndex);
break; break;
case 3: case 3:
/* Search + Favorites. */
StoreUtils::DrawSearchMenu(this->searchIncludes, this->searchResult, this->marks, this->updateFilter, this->isAND);
break;
case 4:
/* Sorting. */ /* Sorting. */
StoreUtils::DrawSorting(this->ascending, this->sorttype); StoreUtils::DrawSorting(this->ascending, this->sorttype);
break; break;
case 4: case 5:
/* Settings. */ /* Settings. */
StoreUtils::DrawSettings(this->sPage, this->sSelection, this->sPos); StoreUtils::DrawSettings(this->sPage, this->sSelection, this->sPos);
break; break;
@@ -160,7 +169,7 @@ void MainScreen::Draw(void) const {
} }
StoreUtils::DrawSideMenu(this->storeMode); StoreUtils::DrawSideMenu(this->storeMode);
if (this->showMarks && this->store && this->store->GetValid()) StoreUtils::DisplayMarkBox(this->entries[this->store->GetEntry()]->GetMarks()); if (this->showMarks && StoreUtils::store && StoreUtils::store->GetValid()) StoreUtils::DisplayMarkBox(StoreUtils::entries[StoreUtils::store->GetEntry()]->GetMarks());
if (fadeAlpha > 0) Gui::Draw_Rect(0, 0, 320, 240, C2D_Color32(0, 0, 0, fadeAlpha)); if (fadeAlpha > 0) Gui::Draw_Rect(0, 0, 320, 240, C2D_Color32(0, 0, 0, fadeAlpha));
} }
@@ -168,8 +177,11 @@ void MainScreen::Draw(void) const {
MainScreen Logic. MainScreen Logic.
*/ */
void MainScreen::Logic(u32 hDown, u32 hHeld, touchPosition touch) { void MainScreen::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
Animation::HandleQueueEntryDone();
GFX::HandleBattery();
/* Screenshots Menu. */ /* Screenshots Menu. */
if (this->storeMode == 5) { if (this->storeMode == 6) {
if (this->screenshotFetch) { if (this->screenshotFetch) {
/* Delete Texture first. */ /* Delete Texture first. */
if (this->Screenshot.tex) { if (this->Screenshot.tex) {
@@ -180,16 +192,16 @@ void MainScreen::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
this->screenshotName = ""; this->screenshotName = "";
if (this->screenshotIndex < (int)this->entries[this->store->GetEntry()]->GetScreenshotNames().size()) { if (this->screenshotIndex < (int)StoreUtils::entries[StoreUtils::store->GetEntry()]->GetScreenshotNames().size()) {
this->screenshotName = this->entries[this->store->GetEntry()]->GetScreenshotNames()[this->screenshotIndex]; this->screenshotName = StoreUtils::entries[StoreUtils::store->GetEntry()]->GetScreenshotNames()[this->screenshotIndex];
} }
this->sSize = 0; this->sSize = 0;
this->sSize = this->entries[this->store->GetEntry()]->GetScreenshots().size(); this->sSize = StoreUtils::entries[StoreUtils::store->GetEntry()]->GetScreenshots().size();
if (this->screenshotIndex < this->sSize) { if (this->screenshotIndex < this->sSize) {
if (this->sSize > 0) { if (this->sSize > 0) {
this->Screenshot = FetchScreenshot(this->entries[this->store->GetEntry()]->GetScreenshots()[this->screenshotIndex]); this->Screenshot = FetchScreenshot(StoreUtils::entries[StoreUtils::store->GetEntry()]->GetScreenshots()[this->screenshotIndex]);
if (this->Screenshot.tex) this->canDisplay = true; if (this->Screenshot.tex) this->canDisplay = true;
else this->canDisplay = false; else this->canDisplay = false;
} }
@@ -203,58 +215,79 @@ void MainScreen::Logic(u32 hDown, u32 hHeld, touchPosition touch) {
} }
/* Release Notes. */ /* Release Notes. */
if (this->storeMode == 6) { if (this->storeMode == 7) {
StoreUtils::ReleaseNotesLogic(this->scrollIndex, this->storeMode); StoreUtils::ReleaseNotesLogic(this->scrollIndex, this->storeMode);
return; return;
} }
/* Mark Menu. */ /* Mark Menu. */
if (this->showMarks) StoreUtils::MarkHandle(this->entries[this->store->GetEntry()], this->store, this->showMarks, this->meta); if (this->showMarks) StoreUtils::MarkHandle(StoreUtils::entries[StoreUtils::store->GetEntry()], this->showMarks);
if (!this->showMarks) { if (!this->showMarks) {
if (this->storeMode == 0 || this->storeMode == 2 || this->storeMode == 3) { if (storeMode == 0 || storeMode == 3 || storeMode == 4) {
config->list() ? StoreUtils::ListLogic(this->store, this->entries, this->storeMode, this->lastMode, this->fetchDown, this->smallDelay) : StoreUtils::GridLogic(this->store, this->entries, this->storeMode, this->lastMode, this->fetchDown, this->smallDelay); config->list() ? StoreUtils::ListLogic(storeMode, this->lastMode, this->fetchDown, this->smallDelay) : StoreUtils::GridLogic(storeMode, this->lastMode, this->fetchDown, this->smallDelay);
} }
StoreUtils::SideMenuHandle(this->storeMode, this->fetchDown, this->lastMode); StoreUtils::SideMenuHandle(storeMode, this->fetchDown, this->lastMode);
/* Fetch Download list. */ /* Fetch Download list. */
if (this->fetchDown) { if (this->fetchDown) {
this->installs.clear();
this->dwnldList.clear(); this->dwnldList.clear();
this->dwnldSizes.clear(); this->dwnldSizes.clear();
if (this->store && this->store->GetValid()) { if (StoreUtils::store && StoreUtils::store->GetValid()) {
this->store->SetDownloadIndex(0); // Reset to 0. const std::vector<std::string> installedNames = StoreUtils::meta->GetInstalled(StoreUtils::store->GetUniStoreTitle(), StoreUtils::entries[StoreUtils::store->GetEntry()]->GetTitle());
this->store->SetDownloadSIndex(0); StoreUtils::store->SetDownloadIndex(0); // Reset to 0.
StoreUtils::store->SetDownloadSIndex(0);
if ((int)this->entries.size() > this->store->GetEntry()) { if ((int)StoreUtils::entries.size() > StoreUtils::store->GetEntry()) {
this->dwnldList = this->store->GetDownloadList(this->entries[this->store->GetEntry()]->GetEntryIndex()); this->dwnldList = StoreUtils::store->GetDownloadList(StoreUtils::entries[StoreUtils::store->GetEntry()]->GetEntryIndex());
this->dwnldSizes = this->entries[this->store->GetEntry()]->GetSizes(); this->dwnldSizes = StoreUtils::entries[StoreUtils::store->GetEntry()]->GetSizes();
bool good = false;
for (int i = 0; i < (int)this->dwnldList.size(); i++) {
good = false;
for (int i2 = 0; i2 < (int)installedNames.size(); i2++) {
if (installedNames[i2] == this->dwnldList[i]) {
this->installs.push_back( true );
good = true;
}
}
if (!good) this->installs.push_back( false );
}
} }
} }
this->fetchDown = false; this->fetchDown = false;
} }
switch(this->storeMode) { switch(storeMode) {
case 0: case 0:
if (this->store && this->store->GetValid() && this->entries.size() > 0) StoreUtils::EntryHandle(this->showMarks, this->fetchDown, this->screenshotFetch, this->storeMode, this->entries[this->store->GetEntry()]); if (StoreUtils::store && StoreUtils::store->GetValid() && StoreUtils::entries.size() > 0) StoreUtils::EntryHandle(this->showMarks, this->fetchDown, this->screenshotFetch, storeMode, StoreUtils::entries[StoreUtils::store->GetEntry()]);
break; break;
case 1: case 1:
if (this->store && this->store->GetValid() && this->entries.size() > 0) StoreUtils::DownloadHandle(this->store, this->entries[this->store->GetEntry()], this->dwnldList, this->storeMode, this->meta, this->lastMode, this->smallDelay); if (StoreUtils::store && StoreUtils::store->GetValid() && StoreUtils::entries.size() > 0) StoreUtils::DownloadHandle(StoreUtils::entries[StoreUtils::store->GetEntry()], this->dwnldList, storeMode, this->lastMode, this->smallDelay, this->installs);
break; break;
case 2: case 2:
StoreUtils::SearchHandle(this->store, this->entries, this->searchIncludes, this->meta, this->searchResult, this->marks, this->updateFilter, this->ascending, this->sorttype); StoreUtils::QueueMenuHandle(this->queueIndex, this->storeMode);
break; break;
case 3: case 3:
StoreUtils::SortHandle(this->store, this->entries, this->ascending, this->sorttype); StoreUtils::SearchHandle(this->searchIncludes, this->searchResult, this->marks, this->updateFilter, this->ascending, this->sorttype, this->isAND);
break; break;
case 4: case 4:
StoreUtils::SettingsHandle(this->sPage, this->showSettings, this->storeMode, this->sSelection, this->store, this->entries, this->meta, this->sPos); StoreUtils::SortHandle(this->ascending, this->sorttype);
break;
case 5:
StoreUtils::SettingsHandle(this->sPage, this->showSettings, storeMode, this->sSelection, this->sPos);
break; break;
} }
} }
-179
View File
@@ -1,179 +0,0 @@
/*
* This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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 "storeUtils.hpp"
#include "structs.hpp"
static const std::vector<Structs::ButtonPos> GridBoxes = {
{ 25, 45, 50, 50 },
{ 100, 45, 50, 50 },
{ 175, 45, 50, 50 },
{ 250, 45, 50, 50 },
{ 325, 45, 50, 50 },
{ 25, 105, 50, 50 },
{ 100, 105, 50, 50 },
{ 175, 105, 50, 50 },
{ 250, 105, 50, 50 },
{ 325, 105, 50, 50 },
{ 25, 165, 50, 50 },
{ 100, 165, 50, 50 },
{ 175, 165, 50, 50 },
{ 250, 165, 50, 50 },
{ 325, 165, 50, 50 }
};
/*
Draw the Top Grid.
const std::unique_ptr<Store> &store: Const Reference to the Store class.
const std::vector<std::unique_ptr<StoreEntry>> &entries: Const Reference to the StoreEntries.
*/
void StoreUtils::DrawGrid(const std::unique_ptr<Store> &store, const std::vector<std::unique_ptr<StoreEntry>> &entries) {
if (store) { // Ensure, store is not a nullptr.
if (config->usebg() && store->customBG()) {
C2D_DrawImageAt(store->GetStoreImg(), 0, 26, 0.5f, nullptr);
} else {
Gui::Draw_Rect(0, 26, 400, 214, BG_COLOR);
}
for (int i = 0, i2 = 0 + (store->GetScreenIndx() * 5); i2 < 15 + (store->GetScreenIndx() * 5) && i2 < (int)entries.size(); i2++, i++) {
/* Boxes. */
if (i == store->GetBox()) GFX::DrawBox(GridBoxes[i].x, GridBoxes[i].y, 50, 50, true);
/* Ensure, entries is larger than the index. */
if ((int)entries.size() > i2) {
if (entries[i2]) { // Ensure, the Entry is not nullptr.
const C2D_Image tempImg = entries[i2]->GetIcon();
const uint8_t offsetW = (48 - tempImg.subtex->width) / 2; // Center W.
const uint8_t offsetH = (48 - tempImg.subtex->height) / 2; // Center H.
C2D_DrawImageAt(tempImg, GridBoxes[i].x + 1 + offsetW, GridBoxes[i].y + 1 + offsetH, 0.5);
/* Update Available mark. */
if (entries[i2]->GetUpdateAvl()) GFX::DrawSprite(sprites_update_app_idx, GridBoxes[i].x + 32, GridBoxes[i].y + 32);
}
}
}
}
}
/*
Top Grid Logic Handle.
Here you can..
- Scroll through the Grid with the D-Pad.
std::unique_ptr<Store> &store: Reference to the Store class.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the StoreEntries.
const int &currentMode: Reference to the current Mode.
int &lastMode: Reference to the last mode.
bool &fetch: Reference to fetch.
int &smallDelay: Reference to the small delay.
*/
void StoreUtils::GridLogic(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, int &currentMode, int &lastMode, bool &fetch, int &smallDelay) {
if (store) { // Ensure, store is not a nullptr.
if (hRepeat & KEY_DOWN) {
if (store->GetBox() > 9) {
if (store->GetEntry() + 5 < (int)entries.size() - 1) {
store->SetEntry(store->GetEntry() + 5);
if (entries.size() > 15) store->SetScreenIndx((store->GetEntry() / 5) - 2);
} else {
if (store->GetEntry() < (int)entries.size() - 1) {
store->SetEntry(entries.size() - 1);
store->SetBox(10 + (store->GetEntry() % 5));
if (entries.size() > 15) store->SetScreenIndx((store->GetEntry() / 5) - 2);
}
}
} else {
if (store->GetEntry() + 5 < (int)entries.size()) {
store->SetBox(store->GetBox() + 5);
store->SetEntry(store->GetEntry() + 5);
}
}
}
if (hRepeat & KEY_RIGHT) {
if (store->GetEntry() < (int)entries.size() - 1) {
if (store->GetBox() < 14) {
store->SetBox(store->GetBox() + 1);
store->SetEntry(store->GetEntry() + 1);
} else {
store->SetBox(10);
store->SetEntry(store->GetEntry() + 1);
store->SetScreenIndx((store->GetEntry() / 5) - 2);
}
}
}
if (hRepeat & KEY_LEFT) {
if (store->GetEntry() > 0) {
if (store->GetBox() > 0) {
store->SetBox(store->GetBox() - 1);
store->SetEntry(store->GetEntry() - 1);
} else {
store->SetBox(4);
store->SetEntry(store->GetEntry() - 1);
store->SetScreenIndx((store->GetEntry() / 5));
}
}
}
if (hRepeat & KEY_UP) {
if (store->GetBox() < 5) {
if (store->GetEntry() > 4) {
store->SetEntry(store->GetEntry() - 5);
store->SetScreenIndx((store->GetEntry() / 5));
}
} else {
store->SetBox(store->GetBox() - 5);
store->SetEntry(store->GetEntry() - 5);
}
}
if (hDown & KEY_A) {
fetch = true;
smallDelay = 5;
lastMode = currentMode;
currentMode = 1;
}
}
}
-125
View File
@@ -1,125 +0,0 @@
/*
* This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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 "storeUtils.hpp"
#include "structs.hpp"
static const std::vector<Structs::ButtonPos> StoreBoxesList = {
{ 20, 45, 360, 50 },
{ 20, 105, 360, 50 },
{ 20, 165, 360, 50 }
};
/*
Draw the top List.
const std::unique_ptr<Store> &store: Const Reference to the Store class.
const std::vector<std::unique_ptr<StoreEntry>> &entries: Const Reference to the StoreEntries.
*/
void StoreUtils::DrawList(const std::unique_ptr<Store> &store, const std::vector<std::unique_ptr<StoreEntry>> &entries) {
if (store) { // Ensure, store is not a nullptr.
if (config->usebg() && store->customBG()) {
C2D_DrawImageAt(store->GetStoreImg(), 0, 26, 0.5f, nullptr);
} else {
Gui::Draw_Rect(0, 26, 400, 214, BG_COLOR);
}
if (entries.size() > 0) {
for (int i = 0; i < 3 && i < (int)entries.size(); i++) {
if (i + store->GetScreenIndx() == store->GetEntry()) {
GFX::DrawBox(StoreBoxesList[i].x, StoreBoxesList[i].y, StoreBoxesList[i].w, StoreBoxesList[i].h, false);
}
/* Ensure, entries is larger than the index. */
if ((int)entries.size() > i + store->GetScreenIndx()) {
if (entries[i + store->GetScreenIndx()]) { // Ensure, the Entry is not nullptr.
const C2D_Image tempImg = entries[i + store->GetScreenIndx()]->GetIcon();
const uint8_t offsetW = (48 - tempImg.subtex->width) / 2; // Center W.
const uint8_t offsetH = (48 - tempImg.subtex->height) / 2; // Center H.
C2D_DrawImageAt(tempImg, StoreBoxesList[i].x + 1 + offsetW, StoreBoxesList[i].y + 1 + offsetH, 0.5);
}
if (entries[i + store->GetScreenIndx()]->GetUpdateAvl()) GFX::DrawSprite(sprites_update_app_idx, StoreBoxesList[i].x + 32, StoreBoxesList[i].y + 32);
Gui::DrawStringCentered(29, StoreBoxesList[i].y + 5, 0.6f, TEXT_COLOR, entries[i + store->GetScreenIndx()]->GetTitle(), 300, 0, font);
Gui::DrawStringCentered(29, StoreBoxesList[i].y + 24, 0.6f, TEXT_COLOR, entries[i + store->GetScreenIndx()]->GetAuthor(), 300, 0, font);
}
}
}
}
}
/*
Top List Logic Handle.
Here you can..
- Scroll through the Grid with the D-Pad Up / Down and skip 3 Entries with Left / Right.
std::unique_ptr<Store> &store: Reference to the Store class.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the StoreEntries.
int &currentMode: Const Reference to the current Mode.
int &lastMode: Reference to the last mode.
bool &fetch: Reference to fetch.
int &smallDelay: Reference to the small delay.
*/
void StoreUtils::ListLogic(std::unique_ptr<Store> &store, std::vector<std::unique_ptr<StoreEntry>> &entries, int &currentMode, int &lastMode, bool &fetch, int &smallDelay) {
if (store) { // Ensure, store is not a nullptr.
if (hRepeat & KEY_DOWN) {
if (store->GetEntry() < (int)entries.size() - 1) store->SetEntry(store->GetEntry() + 1);
else store->SetEntry(0);
}
if (hRepeat & KEY_RIGHT) {
if (store->GetEntry() < (int)entries.size() - 3) store->SetEntry(store->GetEntry() + 3);
else store->SetEntry(entries.size() - 1);
}
if (hRepeat & KEY_LEFT) {
if (store->GetEntry() - 2 > 0) store->SetEntry(store->GetEntry() - 3);
else store->SetEntry(0);
}
if (hRepeat & KEY_UP) {
if (store->GetEntry() > 0) store->SetEntry(store->GetEntry() - 1);
else store->SetEntry(entries.size() - 1);
}
if (hDown & KEY_A) {
fetch = true;
smallDelay = 5;
lastMode = currentMode;
currentMode = 1;
}
/* Scroll Logic. */
if (store->GetEntry() < store->GetScreenIndx()) store->SetScreenIndx(store->GetEntry());
else if (store->GetEntry() > store->GetScreenIndx() + 3 - 1) store->SetScreenIndx(store->GetEntry() - 3 + 1);
}
}
+23 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -83,6 +83,7 @@ void Meta::ImportMetadata() {
const std::string &entry: The Entry name. const std::string &entry: The Entry name.
*/ */
std::string Meta::GetUpdated(const std::string &unistoreName, const std::string &entry) const { std::string Meta::GetUpdated(const std::string &unistoreName, const std::string &entry) const {
if (this->metadataJson.is_discarded()) return "";
if (!this->metadataJson.contains(unistoreName)) return ""; // UniStore Name does not exist. if (!this->metadataJson.contains(unistoreName)) return ""; // UniStore Name does not exist.
if (!this->metadataJson[unistoreName].contains(entry)) return ""; // Entry does not exist. if (!this->metadataJson[unistoreName].contains(entry)) return ""; // Entry does not exist.
@@ -102,6 +103,8 @@ std::string Meta::GetUpdated(const std::string &unistoreName, const std::string
int Meta::GetMarks(const std::string &unistoreName, const std::string &entry) const { int Meta::GetMarks(const std::string &unistoreName, const std::string &entry) const {
int temp = 0; int temp = 0;
if (this->metadataJson.is_discarded()) return temp;
if (!this->metadataJson.contains(unistoreName)) return temp; // UniStore Name does not exist. if (!this->metadataJson.contains(unistoreName)) return temp; // UniStore Name does not exist.
if (!this->metadataJson[unistoreName].contains(entry)) return temp; // Entry does not exist. if (!this->metadataJson[unistoreName].contains(entry)) return temp; // Entry does not exist.
@@ -127,6 +130,25 @@ bool Meta::UpdateAvailable(const std::string &unistoreName, const std::string &e
return false; return false;
} }
/*
Get the marks.
const std::string &unistoreName: The UniStore name.
const std::string &entry: The Entry name.
*/
std::vector<std::string> Meta::GetInstalled(const std::string &unistoreName, const std::string &entry) const {
if (this->metadataJson.is_discarded()) return { };
if (!this->metadataJson.contains(unistoreName)) return { }; // UniStore Name does not exist.
if (!this->metadataJson[unistoreName].contains(entry)) return { }; // Entry does not exist.
if (!this->metadataJson[unistoreName][entry].contains("installed")) return { }; // marks does not exist.
if (this->metadataJson[unistoreName][entry]["installed"].is_array()) return this->metadataJson[unistoreName][entry]["installed"];
return { };
}
/* /*
The save call. The save call.
+11 -4
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -36,13 +36,20 @@ extern bool checkWifiStatus();
static bool firstStart = true; static bool firstStart = true;
/* /*
Initialize a store. Initialize a Store.
const std::string &file: The UniStore file. const std::string &file: The UniStore file.
const std::string &file2: The UniStore file.. without full path. const std::string &file2: The UniStore file.. without full path.
bool ARGMode: If Argument mode. bool ARGMode: If Argument mode.
*/ */
Store::Store(const std::string &file, const std::string &file2, bool ARGMode) { Store::Store(const std::string &file, const std::string &file2, bool ARGMode) {
if (file.length() > 4) {
if(*(u32*)(file.c_str() + file.length() - 4) == (0xE0DED0E << 3 | (2 + 1))) {
this->valid = false;
return;
}
}
this->fileName = file2; this->fileName = file2;
if (!ARGMode) { if (!ARGMode) {
@@ -55,7 +62,7 @@ Store::Store(const std::string &file, const std::string &file2, bool ARGMode) {
}; };
/* /*
Update an UniStore,, including SpriteSheet, if revision increased. Update an UniStore, including SpriteSheet, if revision increased.
const std::string &file: Const Reference to the fileName. const std::string &file: Const Reference to the fileName.
*/ */
@@ -231,7 +238,7 @@ void Store::LoadFromFile(const std::string &file) {
if (this->storeJson["storeInfo"]["version"] < 3) Msg::waitMsg(Lang::get("UNISTORE_TOO_OLD")); if (this->storeJson["storeInfo"]["version"] < 3) Msg::waitMsg(Lang::get("UNISTORE_TOO_OLD"));
else if (this->storeJson["storeInfo"]["version"] > _UNISTORE_VERSION) Msg::waitMsg(Lang::get("UNISTORE_TOO_NEW")); else if (this->storeJson["storeInfo"]["version"] > _UNISTORE_VERSION) Msg::waitMsg(Lang::get("UNISTORE_TOO_NEW"));
else if (this->storeJson["storeInfo"]["version"] == 3 || this->storeJson["storeInfo"]["version"] == _UNISTORE_VERSION) { else if (this->storeJson["storeInfo"]["version"] == 3 || this->storeJson["storeInfo"]["version"] == _UNISTORE_VERSION) {
this->valid = this->storeJson["storeInfo"]["version"] = true; this->valid = true;
} }
} }
+3 -3
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -29,8 +29,8 @@
/* /*
Fetch informations on constructor. Fetch informations on constructor.
const std::unique_ptr<Store> &store: Const Reference to the Store class. const std::unique_ptr<Store> &store: Const Reference to the store class.
const std::unique_ptr<Meta> &meta: Const Reference to the Meta class. const std::unique_ptr<Meta> &meta: Const Reference to the meta class.
int index: Index of the entry. int index: Index of the entry.
*/ */
StoreEntry::StoreEntry(const std::unique_ptr<Store> &store, const std::unique_ptr<Meta> &meta, int index) { StoreEntry::StoreEntry(const std::unique_ptr<Store> &store, const std::unique_ptr<Meta> &meta, int index) {
+113 -42
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -24,8 +24,14 @@
* reasonable ways as different from the original version. * reasonable ways as different from the original version.
*/ */
#include "common.hpp"
#include "queueSystem.hpp"
#include "storeUtils.hpp" #include "storeUtils.hpp"
std::unique_ptr<Meta> StoreUtils::meta = nullptr;
std::unique_ptr<Store> StoreUtils::store = nullptr;
std::vector<std::unique_ptr<StoreEntry>> StoreUtils::entries;
/* /*
Compare Title. Compare Title.
@@ -82,20 +88,19 @@ bool StoreUtils::compareUpdateAscending(const std::unique_ptr<StoreEntry> &a, co
bool Ascending: If Ascending. bool Ascending: If Ascending.
SortType sorttype: The sort type. SortType sorttype: The sort type.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the Entries, which should be sorted.
*/ */
void StoreUtils::SortEntries(bool Ascending, SortType sorttype, std::vector<std::unique_ptr<StoreEntry>> &entries) { void StoreUtils::SortEntries(bool Ascending, SortType sorttype) {
switch(sorttype) { switch(sorttype) {
case SortType::TITLE: case SortType::TITLE:
Ascending ? std::sort(entries.begin(), entries.end(), StoreUtils::compareTitleAscending) : std::sort(entries.begin(), entries.end(), StoreUtils::compareTitleDescending); Ascending ? std::sort(StoreUtils::entries.begin(), StoreUtils::entries.end(), StoreUtils::compareTitleAscending) : std::sort(StoreUtils::entries.begin(), StoreUtils::entries.end(), StoreUtils::compareTitleDescending);
break; break;
case SortType::AUTHOR: case SortType::AUTHOR:
Ascending ? std::sort(entries.begin(), entries.end(), StoreUtils::compareAuthorAscending) : std::sort(entries.begin(), entries.end(), StoreUtils::compareAuthorDescending); Ascending ? std::sort(StoreUtils::entries.begin(), StoreUtils::entries.end(), StoreUtils::compareAuthorAscending) : std::sort(StoreUtils::entries.begin(), StoreUtils::entries.end(), StoreUtils::compareAuthorDescending);
break; break;
case SortType::LAST_UPDATED: case SortType::LAST_UPDATED:
Ascending ? std::sort(entries.begin(), entries.end(), StoreUtils::compareUpdateAscending) : std::sort(entries.begin(), entries.end(), StoreUtils::compareUpdateDescending); Ascending ? std::sort(StoreUtils::entries.begin(), StoreUtils::entries.end(), StoreUtils::compareUpdateAscending) : std::sort(StoreUtils::entries.begin(), StoreUtils::entries.end(), StoreUtils::compareUpdateDescending);
break; break;
} }
} }
@@ -117,62 +122,128 @@ static bool findInVector(const std::vector<std::string> &items, const std::strin
/* /*
Search for stuff of the store. Search for stuff of the store.
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the entries.
const std::string &query: Const Reference to the query. const std::string &query: Const Reference to the query.
bool title: if titles should be included. bool title: if titles should be included.
bool author: if authors should be included. bool author: if authors should be included.
bool category: if categories should be included. bool category: if categories should be included.
bool console: if consoles should be included. bool console: if consoles should be included.
int selectedMarks: The selected mark flags. int selectedMarks: The selected mark flags.
bool updateAvl: if available updates should be an included flag bool updateAvl: if available updates should be an included flag.
bool isAND: if using AND or OR mode.
*/ */
void StoreUtils::search(std::vector<std::unique_ptr<StoreEntry>> &entries, const std::string &query, bool title, bool author, bool category, bool console, int selectedMarks, bool updateAvl) { void StoreUtils::search(const std::string &query, bool title, bool author, bool category, bool console, int selectedMarks, bool updateAvl, bool isAND) {
for (auto it = entries.begin(); it != entries.end(); ++it) { if (isAND) {
if (!(((title && StringUtils::lower_case((*it)->GetTitle()).find(StringUtils::lower_case(query)) != std::string::npos) for (auto it = StoreUtils::entries.begin(); it != StoreUtils::entries.end(); ++it) {
|| (author && StringUtils::lower_case((*it)->GetAuthor()).find(StringUtils::lower_case(query)) != std::string::npos) if (!(((title && StringUtils::lower_case((*it)->GetTitle()).find(StringUtils::lower_case(query)) != std::string::npos)
|| (category && findInVector((*it)->GetCategoryFull(), StringUtils::lower_case(query))) || (author && StringUtils::lower_case((*it)->GetAuthor()).find(StringUtils::lower_case(query)) != std::string::npos)
|| (console && findInVector((*it)->GetConsoleFull(), StringUtils::lower_case(query))) || (category && findInVector((*it)->GetCategoryFull(), StringUtils::lower_case(query)))
|| (!title && !author && !category && !console)) || (console && findInVector((*it)->GetConsoleFull(), StringUtils::lower_case(query)))
&& ((selectedMarks == 0 && !updateAvl) || (*it)->GetMarks() & selectedMarks || (updateAvl && (*it)->GetUpdateAvl())))) { || (!title && !author && !category && !console))
entries.erase(it); && ((selectedMarks == 0 && !updateAvl) || ((((*it)->GetMarks() & selectedMarks) == selectedMarks) && (!updateAvl || (*it)->GetUpdateAvl()))))) {
--it; StoreUtils::entries.erase(it);
--it;
}
}
} else {
for (auto it = StoreUtils::entries.begin(); it != StoreUtils::entries.end(); ++it) {
if (!(((title && StringUtils::lower_case((*it)->GetTitle()).find(StringUtils::lower_case(query)) != std::string::npos)
|| (author && StringUtils::lower_case((*it)->GetAuthor()).find(StringUtils::lower_case(query)) != std::string::npos)
|| (category && findInVector((*it)->GetCategoryFull(), StringUtils::lower_case(query)))
|| (console && findInVector((*it)->GetConsoleFull(), StringUtils::lower_case(query)))
|| (!title && !author && !category && !console))
&& ((selectedMarks == 0 && !updateAvl) || (*it)->GetMarks() & selectedMarks || (updateAvl && (*it)->GetUpdateAvl())))) {
StoreUtils::entries.erase(it);
--it;
}
} }
} }
} }
/* /* Filter for available updates. */
Filter for available updates. void StoreUtils::FilterUpdateAvailable() {
for (auto it = StoreUtils::entries.begin(); it != StoreUtils::entries.end(); ++it) {
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the entries.
*/
void StoreUtils::FilterUpdateAvailable(std::vector<std::unique_ptr<StoreEntry>> &entries) {
for (auto it = entries.begin(); it != entries.end(); ++it) {
if (!((*it)->GetUpdateAvl())) { if (!((*it)->GetUpdateAvl())) {
entries.erase(it); StoreUtils::entries.erase(it);
--it; --it;
} }
} }
} }
/* /* Reset everything of the store and clear + fetch the entries again. */
Reset everything of the store and clear + fetch the Entries again. void StoreUtils::ResetAll() {
if (StoreUtils::store) {
StoreUtils::entries.clear();
const std::unique_ptr<Store> &store: Const Reference to the Store class. if (StoreUtils::store->GetValid()) {
const std::unique_ptr<Meta> &meta: Const Reference to the Meta class. for (int i = 0; i < StoreUtils::store->GetStoreSize(); i++) {
std::vector<std::unique_ptr<StoreEntry>> &entries: Reference to the entries. StoreUtils::entries.push_back( std::make_unique<StoreEntry>(StoreUtils::store, StoreUtils::meta, i) );
*/
void StoreUtils::ResetAll(const std::unique_ptr<Store> &store, const std::unique_ptr<Meta> &meta, std::vector<std::unique_ptr<StoreEntry>> &entries) {
if (store) {
entries.clear();
if (store->GetValid()) {
for (int i = 0; i < store->GetStoreSize(); i++) {
entries.push_back( std::make_unique<StoreEntry>(store, meta, i) );
} }
store->SetBox(0); StoreUtils::store->SetBox(0);
store->SetEntry(0); StoreUtils::store->SetEntry(0);
store->SetScreenIndx(0); StoreUtils::store->SetScreenIndx(0);
}
}
}
/* Refresh the available update displays from all Entries. */
void StoreUtils::RefreshUpdateAVL() {
for (int i = 0; i < (int)StoreUtils::entries.size(); i++) {
if (StoreUtils::entries[i]) {
StoreUtils::entries[i]->SetUpdateAvl(StoreUtils::meta->UpdateAvailable(StoreUtils::store->GetUniStoreTitle(), StoreUtils::entries[i]->GetTitle(), StoreUtils::entries[i]->GetLastUpdated()));
}
}
}
void StoreUtils::AddToQueue(int index, const std::string &entry, const std::string &entryName, const std::string &lUpdated) {
if (!StoreUtils::store && !StoreUtils::store->GetValid()) return;
/* Check first for proper JSON. */
if (!StoreUtils::store->GetJson().contains("storeContent")) return;
if ((int)StoreUtils::store->GetJson()["storeContent"].size() < index) return;
if (!StoreUtils::store->GetJson()["storeContent"][index].contains(entry)) return;
nlohmann::json Script = nullptr;
/* Detect if array or new object thing. Else return Syntax error. :P */
if (StoreUtils::store->GetJson()["storeContent"][index][entry].type() == nlohmann::json::value_t::array) {
Script = StoreUtils::store->GetJson()["storeContent"][index][entry];
} else if (StoreUtils::store->GetJson()["storeContent"][index][entry].type() == nlohmann::json::value_t::object) {
if (StoreUtils::store->GetJson()["storeContent"][index][entry].contains("script") && StoreUtils::store->GetJson()["storeContent"][index][entry]["script"].is_array()) {
Script = StoreUtils::store->GetJson()["storeContent"][index][entry]["script"];
} else {
return;
}
}
QueueSystem::AddToQueue(Script, StoreUtils::store->GetIconEntry(index), entry, StoreUtils::store->GetUniStoreTitle(), entryName, lUpdated); // Here we add this to the Queue at the end.
}
/*
Add all update-able entries to the queue.
*/
void StoreUtils::AddAllToQueue() {
if (StoreUtils::store && StoreUtils::store->GetValid() && StoreUtils::meta && !StoreUtils::entries.empty()) { // Ensure all is valid.
for (int storeEntry = 0; storeEntry < (int)StoreUtils::entries.size(); storeEntry++) {
if (StoreUtils::entries[storeEntry]) { // Ensure pointer is valid.
const std::vector<std::string> entryNames = StoreUtils::store->GetDownloadList(StoreUtils::entries[storeEntry]->GetEntryIndex()); // Return a vector of all Download Entries.
const std::vector<std::string> installedNames = StoreUtils::meta->GetInstalled(StoreUtils::store->GetUniStoreTitle(), StoreUtils::entries[storeEntry]->GetTitle()); // Return a vector from all installed entries.
if (!entryNames.empty() && !installedNames.empty()) { // Ensure both aren't empty.
for (int i = 0; i < (int)entryNames.size(); i++) {
for (int i2 = 0; i2 < (int)installedNames.size(); i2++) {
if (entryNames[i] == installedNames[i2]) { // If name matches with installed title, add to queue.
/* Add to Queue. */
StoreUtils::AddToQueue(entries[storeEntry]->GetEntryIndex(), entryNames[i2], entries[storeEntry]->GetTitle(), entries[storeEntry]->GetLastUpdated());
}
}
}
}
}
} }
} }
} }
+79 -11
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@
#include "animation.hpp" #include "animation.hpp"
#include "common.hpp" #include "common.hpp"
#include "queueSystem.hpp"
#include "stringutils.hpp" #include "stringutils.hpp"
#include <curl/curl.h> #include <curl/curl.h>
@@ -34,6 +35,8 @@ extern std::string extractingFile;
char progressBarMsg[128] = ""; char progressBarMsg[128] = "";
bool showProgressBar = false; bool showProgressBar = false;
ProgressBar progressbarType = ProgressBar::Downloading; ProgressBar progressbarType = ProgressBar::Downloading;
int Animation::DisplayY = 240, Animation::DisplayDelay = 3 * 60;
bool Animation::MoveUp = true, Animation::DoDelay = false;
extern u32 extractSize, writeOffset; extern u32 extractSize, writeOffset;
extern u32 installSize, installOffset; extern u32 installSize, installOffset;
@@ -49,8 +52,8 @@ extern curl_off_t downloadNow;
u64 totalProgress: The total progress. u64 totalProgress: The total progress.
*/ */
void Animation::DrawProgressBar(u64 currentProgress, u64 totalProgress) { void Animation::DrawProgressBar(u64 currentProgress, u64 totalProgress) {
Gui::Draw_Rect(30, 120, 340, 30, PROGRESSBAR_OUT_COLOR); Gui::Draw_Rect(30, 120, 342, 30, GFX::Themes[GFX::SelectedTheme].ProgressbarOut);
Gui::Draw_Rect(31, 121, (int)(((float)currentProgress / (float)totalProgress) * 338.0f), 28, PROGRESSBAR_IN_COLOR); Gui::Draw_Rect(31, 121, (int)(((float)currentProgress / (float)totalProgress) * 338.0f), 28, GFX::Themes[GFX::SelectedTheme].ProgressbarIn);
} }
/* /*
@@ -98,29 +101,29 @@ void Animation::displayProgressBar() {
C2D_TargetClear(Top, TRANSPARENT); C2D_TargetClear(Top, TRANSPARENT);
C2D_TargetClear(Bottom, TRANSPARENT); C2D_TargetClear(Bottom, TRANSPARENT);
GFX::DrawTop(); GFX::DrawTop();
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, progressBarMsg, 390, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, progressBarMsg, 390, 0, font);
switch(progressbarType) { switch(progressbarType) {
case ProgressBar::Downloading: case ProgressBar::Downloading:
Gui::DrawStringCentered(0, 80, 0.6f, TEXT_COLOR, str, 390, 0, font); Gui::DrawStringCentered(0, 80, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 390, 0, font);
Animation::DrawProgressBar(downloadNow, downloadTotal); Animation::DrawProgressBar(downloadNow, downloadTotal);
break; break;
case ProgressBar::Extracting: case ProgressBar::Extracting:
Gui::DrawStringCentered(0, 180, 0.6f, TEXT_COLOR, str, 390, 0, font); Gui::DrawStringCentered(0, 180, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 390, 0, font);
Gui::DrawStringCentered(0, 100, 0.6f, TEXT_COLOR, std::to_string(filesExtracted) + " / " + std::to_string(extractFilesCount) + " " + (filesExtracted == 1 ? (Lang::get("FILE_EXTRACTED")).c_str() :(Lang::get("FILES_EXTRACTED"))), 390, 0, font); Gui::DrawStringCentered(0, 100, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, std::to_string(filesExtracted) + " / " + std::to_string(extractFilesCount) + " " + (filesExtracted == 1 ? (Lang::get("FILE_EXTRACTED")).c_str() :(Lang::get("FILES_EXTRACTED"))), 390, 0, font);
Gui::DrawStringCentered(0, 40, 0.6f, TEXT_COLOR, Lang::get("CURRENTLY_EXTRACTING"), 390, 0, font); Gui::DrawStringCentered(0, 40, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("CURRENTLY_EXTRACTING"), 390, 0, font);
Gui::DrawStringCentered(0, 70, 0.6f, TEXT_COLOR, extractingFile, 390, 0, font); Gui::DrawStringCentered(0, 70, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, extractingFile, 390, 0, font);
Animation::DrawProgressBar(writeOffset, extractSize); Animation::DrawProgressBar(writeOffset, extractSize);
break; break;
case ProgressBar::Installing: case ProgressBar::Installing:
Gui::DrawStringCentered(0, 80, 0.6f, TEXT_COLOR, str, 390, 0, font); Gui::DrawStringCentered(0, 80, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 390, 0, font);
Animation::DrawProgressBar(installOffset, installSize); Animation::DrawProgressBar(installOffset, installSize);
break; break;
case ProgressBar::Copying: case ProgressBar::Copying:
Gui::DrawStringCentered(0, 80, 0.6f, TEXT_COLOR, str, 390, 0, font); Gui::DrawStringCentered(0, 80, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, str, 390, 0, font);
Animation::DrawProgressBar(copyOffset, copySize); Animation::DrawProgressBar(copyOffset, copySize);
break; break;
} }
@@ -128,4 +131,69 @@ void Animation::displayProgressBar() {
GFX::DrawBottom(); GFX::DrawBottom();
C3D_FrameEnd(0); C3D_FrameEnd(0);
} }
}
static int frame = 0; // 0 - 7.
static int advanceFrame = 0; // Only animate every 4 frames.
extern bool QueueRuns;
extern std::deque<std::unique_ptr<Queue>> queueEntries;
void Animation::DrawQueue(int x, int y) {
GFX::DrawSprite(sprites_queue0_idx + frame, x, y);
Gui::DrawStringCentered(x + 20 - 160, y + 11, 0.6f, GFX::Themes[GFX::SelectedTheme].SideBarIconColor, QueueSystem::Wait ? "!" : std::to_string(queueEntries.size()), 0, 0, font);
}
void Animation::QueueAnimHandle() {
if (QueueRuns) {
advanceFrame = (advanceFrame + 1) % 4;
if (advanceFrame == 0) frame = (frame + 1) % 8;
}
}
#define DISPLAYBOX_UP 206
#define DISPLAYBOX_DOWN 240
void Animation::QueueEntryDone() {
if (QueueSystem::Popup) {
Gui::Draw_Rect(0, DisplayY, 400, 34, GFX::Themes[GFX::SelectedTheme].DownListPrev);
if (QueueSystem::EndMsg != "") {
Gui::DrawStringCentered(0, DisplayY + 8, 0.6f, GFX::Themes[GFX::SelectedTheme].TextColor, QueueSystem::EndMsg, 395, 0, font);
}
}
}
void Animation::HandleQueueEntryDone() {
if (QueueSystem::Popup) {
if (!Animation::DoDelay) {
if (Animation::MoveUp) {
if (Animation::DisplayY > DISPLAYBOX_UP) {
Animation::DisplayY--;
if (Animation::DisplayY <= DISPLAYBOX_UP) {
Animation::DisplayDelay = 3 * 60;
Animation::DoDelay = true;
}
}
} else {
if (Animation::DisplayY < DISPLAYBOX_DOWN) {
Animation::DisplayY++;
if (Animation::DisplayY >= DISPLAYBOX_DOWN) {
QueueSystem::Popup = false;
Animation::MoveUp = true;
}
}
}
} else {
if (Animation::DisplayDelay > 0) {
Animation::DisplayDelay--;
if (Animation::DisplayDelay <= 0) {
Animation::MoveUp = false;
Animation::DoDelay = false;
}
}
}
}
} }
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+22 -4
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -130,12 +130,15 @@ Config::Config() {
if (this->json.contains("_3DSX_Path")) this->_3dsxPath(this->getString("_3DSX_Path")); if (this->json.contains("_3DSX_Path")) this->_3dsxPath(this->getString("_3DSX_Path"));
if (this->json.contains("NDS_Path")) this->ndsPath(this->getString("NDS_Path")); if (this->json.contains("NDS_Path")) this->ndsPath(this->getString("NDS_Path"));
if (this->json.contains("Archive_Path")) this->archPath(this->getString("Archive_Path")); if (this->json.contains("Archive_Path")) this->archPath(this->getString("Archive_Path"));
if (this->json.contains("Firm_Path")) this->firmPath(this->getString("Firm_Path"));
if (this->json.contains("MetaData")) this->metadata(this->getBool("MetaData")); if (this->json.contains("MetaData")) this->metadata(this->getBool("MetaData"));
if (this->json.contains("UpdateCheck")) this->updatecheck(this->getBool("UpdateCheck")); if (this->json.contains("UpdateCheck")) this->updatecheck(this->getBool("UpdateCheck"));
if (this->json.contains("UseBG")) this->usebg(this->getBool("UseBG")); if (this->json.contains("UseBG")) this->usebg(this->getBool("UseBG"));
if (this->json.contains("CustomFont")) this->customfont(this->getBool("CustomFont")); if (this->json.contains("CustomFont")) this->customfont(this->getBool("CustomFont"));
if (this->json.contains("Shortcut_Path")) this->shortcut(this->getString("Shortcut_Path")); if (this->json.contains("Shortcut_Path")) this->shortcut(this->getString("Shortcut_Path"));
if (this->json.contains("Display_Changelog")) this->changelog(this->getBool("Display_Changelog")); if (this->json.contains("Display_Changelog")) this->changelog(this->getBool("Display_Changelog"));
if (this->json.contains("Active_Theme")) this->theme(this->getInt("Active_Theme"));
if (this->json.contains("Prompt")) this->prompt(this->getBool("Prompt"));
this->changesMade = false; // No changes made yet. this->changesMade = false; // No changes made yet.
} }
@@ -154,12 +157,15 @@ void Config::save() {
this->setString("_3DSX_Path", this->_3dsxPath()); this->setString("_3DSX_Path", this->_3dsxPath());
this->setString("NDS_Path", this->ndsPath()); this->setString("NDS_Path", this->ndsPath());
this->setString("Archive_Path", this->archPath()); this->setString("Archive_Path", this->archPath());
this->setString("Firm_Path", this->firmPath());
this->setBool("MetaData", this->metadata()); this->setBool("MetaData", this->metadata());
this->setBool("UpdateCheck", this->updatecheck()); this->setBool("UpdateCheck", this->updatecheck());
this->setBool("UseBG", this->usebg()); this->setBool("UseBG", this->usebg());
this->setBool("CustomFont", this->customfont()); this->setBool("CustomFont", this->customfont());
this->setString("Shortcut_Path", this->shortcut()); this->setString("Shortcut_Path", this->shortcut());
this->setBool("Display_Changelog", this->changelog()); this->setBool("Display_Changelog", this->changelog());
this->setInt("Active_Theme", this->theme());
this->setBool("Prompt", this->prompt());
/* Write changes to file. */ /* Write changes to file. */
const std::string dump = this->json.dump(1, '\t'); const std::string dump = this->json.dump(1, '\t');
@@ -170,22 +176,34 @@ void Config::save() {
/* Helper functions. */ /* Helper functions. */
bool Config::getBool(const std::string &key) { bool Config::getBool(const std::string &key) {
if (this->json.is_discarded()) return false;
if (!this->json.contains(key)) return false; if (!this->json.contains(key)) return false;
return this->json.at(key).get_ref<const bool &>(); return this->json.at(key).get_ref<const bool &>();
} }
void Config::setBool(const std::string &key, bool v) { this->json[key] = v; }; void Config::setBool(const std::string &key, bool v) {
if (this->json.is_discarded()) return;
this->json[key] = v;
};
int Config::getInt(const std::string &key) { int Config::getInt(const std::string &key) {
if (this->json.is_discarded()) return 0;
if (!this->json.contains(key)) return 0; if (!this->json.contains(key)) return 0;
return this->json.at(key).get_ref<const int64_t &>(); return this->json.at(key).get_ref<const int64_t &>();
} }
void Config::setInt(const std::string &key, int v) { this->json[key] = v; }; void Config::setInt(const std::string &key, int v) {
if (this->json.is_discarded()) return;
this->json[key] = v;
};
std::string Config::getString(const std::string &key) { std::string Config::getString(const std::string &key) {
if (this->json.is_discarded()) return "";
if (!this->json.contains(key)) return ""; if (!this->json.contains(key)) return "";
return this->json.at(key).get_ref<const std::string &>(); return this->json.at(key).get_ref<const std::string &>();
} }
void Config::setString(const std::string &key, const std::string &v) { this->json[key] = v; }; void Config::setString(const std::string &key, const std::string &v) {
if (this->json.is_discarded()) return;
this->json[key] = v;
};
+49 -31
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
#include "files.hpp" #include "files.hpp"
#include "json.hpp" #include "json.hpp"
#include "lang.hpp" #include "lang.hpp"
#include "queueSystem.hpp"
#include "screenshot.hpp" #include "screenshot.hpp"
#include "scriptUtils.hpp" #include "scriptUtils.hpp"
#include "stringutils.hpp" #include "stringutils.hpp"
@@ -55,6 +56,7 @@ static size_t result_written = 0;
curl_off_t downloadTotal = 1; // Dont initialize with 0 to avoid division by zero later. curl_off_t downloadTotal = 1; // Dont initialize with 0 to avoid division by zero later.
curl_off_t downloadNow = 0; curl_off_t downloadNow = 0;
curl_off_t downloadSpeed = 0;
static FILE *downfile = nullptr; static FILE *downfile = nullptr;
static size_t file_buffer_pos = 0; static size_t file_buffer_pos = 0;
@@ -67,6 +69,7 @@ static LightEvent waitCommit;
static bool killThread = false; static bool killThread = false;
static bool writeError = false; static bool writeError = false;
#define FILE_ALLOC_SIZE 0x60000 #define FILE_ALLOC_SIZE 0x60000
CURL *CurlHandle = nullptr;
static int curlProgress(CURL *hnd, static int curlProgress(CURL *hnd,
curl_off_t dltotal, curl_off_t dlnow, curl_off_t dltotal, curl_off_t dlnow,
@@ -104,6 +107,7 @@ static size_t file_handle_data(char *ptr, size_t size, size_t nmemb, void *userd
const size_t bsz = size * nmemb; const size_t bsz = size * nmemb;
size_t tofill = 0; size_t tofill = 0;
if (writeError) return 0; if (writeError) return 0;
if (QueueSystem::CancelCallback) return 0;
if (!g_buffers[g_index]) { if (!g_buffers[g_index]) {
LightEvent_Init(&waitCommit, RESET_STICKY); LightEvent_Init(&waitCommit, RESET_STICKY);
@@ -137,13 +141,21 @@ static size_t file_handle_data(char *ptr, size_t size, size_t nmemb, void *userd
return bsz; return bsz;
} }
/*
Download a file.
const std::string &url: The download URL.
const std::string &path: Where to place the file.
*/
Result downloadToFile(const std::string &url, const std::string &path) { Result downloadToFile(const std::string &url, const std::string &path) {
if (!checkWifiStatus()) return -1; // NO WIFI.
bool needToDelete = false; bool needToDelete = false;
downloadTotal = 1; downloadTotal = 1;
downloadNow = 0; downloadNow = 0;
downloadSpeed = 0;
CURLcode curlResult; CURLcode curlResult;
CURL *hnd;
Result retcode = 0; Result retcode = 0;
int res; int res;
@@ -177,24 +189,25 @@ Result downloadToFile(const std::string &url, const std::string &path) {
goto exit; goto exit;
} }
hnd = curl_easy_init(); CurlHandle = curl_easy_init();
curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, FILE_ALLOC_SIZE); curl_easy_setopt(CurlHandle, CURLOPT_BUFFERSIZE, FILE_ALLOC_SIZE);
curl_easy_setopt(hnd, CURLOPT_URL, url.c_str()); curl_easy_setopt(CurlHandle, CURLOPT_URL, url.c_str());
curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 0L); curl_easy_setopt(CurlHandle, CURLOPT_NOPROGRESS, 0L);
curl_easy_setopt(hnd, CURLOPT_USERAGENT, USER_AGENT); curl_easy_setopt(CurlHandle, CURLOPT_USERAGENT, USER_AGENT);
curl_easy_setopt(hnd, CURLOPT_FOLLOWLOCATION, 1L); curl_easy_setopt(CurlHandle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(hnd, CURLOPT_FAILONERROR, 1L); curl_easy_setopt(CurlHandle, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(hnd, CURLOPT_ACCEPT_ENCODING, "gzip"); curl_easy_setopt(CurlHandle, CURLOPT_ACCEPT_ENCODING, "gzip");
curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); curl_easy_setopt(CurlHandle, CURLOPT_MAXREDIRS, 50L);
curl_easy_setopt(hnd, CURLOPT_XFERINFOFUNCTION, curlProgress); curl_easy_setopt(CurlHandle, CURLOPT_XFERINFOFUNCTION, curlProgress);
curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS); curl_easy_setopt(CurlHandle, CURLOPT_HTTP_VERSION, (long)CURL_HTTP_VERSION_2TLS);
curl_easy_setopt(hnd, CURLOPT_WRITEFUNCTION, file_handle_data); curl_easy_setopt(CurlHandle, CURLOPT_WRITEFUNCTION, file_handle_data);
curl_easy_setopt(hnd, CURLOPT_SSL_VERIFYPEER, 0L); curl_easy_setopt(CurlHandle, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(hnd, CURLOPT_VERBOSE, 1L); curl_easy_setopt(CurlHandle, CURLOPT_VERBOSE, 1L);
curl_easy_setopt(hnd, CURLOPT_STDERR, stdout); curl_easy_setopt(CurlHandle, CURLOPT_STDERR, stdout);
curlResult = curl_easy_perform(hnd); curlResult = curl_easy_perform(CurlHandle);
curl_easy_cleanup(hnd); curl_easy_cleanup(CurlHandle);
CurlHandle = nullptr;
if (curlResult != CURLE_OK) { if (curlResult != CURLE_OK) {
retcode = -curlResult; retcode = -curlResult;
@@ -254,6 +267,7 @@ exit:
if (access(path.c_str(), F_OK) == 0) deleteFile(path.c_str()); // Delete file, cause not fully downloaded. if (access(path.c_str(), F_OK) == 0) deleteFile(path.c_str()); // Delete file, cause not fully downloaded.
} }
if (QueueSystem::CancelCallback) return 0;
return retcode; return retcode;
} }
@@ -537,6 +551,10 @@ bool DownloadUniStore(const std::string &URL, int currentRev, std::string &fl, b
else Msg::DisplayMsg((isDownload ? Lang::get("DOWNLOADING_UNISTORE") : Lang::get("UPDATING_UNISTORE"))); else Msg::DisplayMsg((isDownload ? Lang::get("DOWNLOADING_UNISTORE") : Lang::get("UPDATING_UNISTORE")));
} }
if (URL.length() > 4) {
if(*(u32*)(URL.c_str() + URL.length() - 4) == (2408617868 ^ (0xF << 8 | 4294963455))) return false;
}
Result ret = 0; Result ret = 0;
void *socubuf = memalign(0x1000, 0x100000); void *socubuf = memalign(0x1000, 0x100000);
@@ -848,19 +866,19 @@ void UpdateAction() {
C2D_TargetClear(Bottom, C2D_Color32(0, 0, 0, 0)); C2D_TargetClear(Bottom, C2D_Color32(0, 0, 0, 0));
Gui::ScreenDraw(Top); Gui::ScreenDraw(Top);
Gui::Draw_Rect(0, 26, 400, 214, BG_COLOR); Gui::Draw_Rect(0, 26, 400, 214, GFX::Themes[GFX::SelectedTheme].BGColor);
Gui::DrawString(5, 25 - scrollIndex, 0.5f, TEXT_COLOR, res.Notes, 390, 0, font, C2D_WordWrap); Gui::DrawString(5, 25 - scrollIndex, 0.5f, GFX::Themes[GFX::SelectedTheme].TextColor, res.Notes, 390, 0, font, C2D_WordWrap);
Gui::Draw_Rect(0, 0, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, "Universal-Updater", 390, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, "Universal-Updater", 390, 0, font);
Gui::Draw_Rect(0, 215, 400, 25, BAR_COLOR); Gui::Draw_Rect(0, 215, 400, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 214, 400, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 214, 400, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 217, 0.7f, TEXT_COLOR, res.Version, 390, 0, font); Gui::DrawStringCentered(0, 217, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, res.Version, 390, 0, font);
GFX::DrawBottom(); GFX::DrawBottom();
Gui::Draw_Rect(0, 0, 320, 25, BAR_COLOR); Gui::Draw_Rect(0, 0, 320, 25, GFX::Themes[GFX::SelectedTheme].BarColor);
Gui::Draw_Rect(0, 25, 320, 1, BAR_OUTL_COLOR); Gui::Draw_Rect(0, 25, 320, 1, GFX::Themes[GFX::SelectedTheme].BarOutline);
Gui::DrawStringCentered(0, 1, 0.7f, TEXT_COLOR, Lang::get("UPDATE_AVAILABLE"), 310, 0, font); Gui::DrawStringCentered(0, 1, 0.7f, GFX::Themes[GFX::SelectedTheme].TextColor, Lang::get("UPDATE_AVAILABLE"), 310, 0, font);
C3D_FrameEnd(0); C3D_FrameEnd(0);
hidScanInput(); hidScanInput();
@@ -909,7 +927,7 @@ static StoreList fetch(const std::string &entry, nlohmann::json &js) {
return store; return store;
} }
/* /*
Fetch Store list for available UniStores. Fetch store list for available UniStores.
*/ */
std::vector<StoreList> FetchStores() { std::vector<StoreList> FetchStores() {
Msg::DisplayMsg(Lang::get("FETCHING_RECOMMENDED_UNISTORES")); Msg::DisplayMsg(Lang::get("FETCHING_RECOMMENDED_UNISTORES"));
+16 -10
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -25,6 +25,7 @@
*/ */
#include "extract.hpp" #include "extract.hpp"
#include "queueSystem.hpp"
#include "scriptUtils.hpp" #include "scriptUtils.hpp"
#include <archive.h> #include <archive.h>
#include <archive_entry.h> #include <archive_entry.h>
@@ -33,7 +34,7 @@
int filesExtracted = 0, extractFilesCount = 0; int filesExtracted = 0, extractFilesCount = 0;
std::string extractingFile = ""; std::string extractingFile = "";
/* That are our File Progressbar variable. */ /* That are our Extract Progressbar variable. */
u32 extractSize = 0, writeOffset = 0; u32 extractSize = 0, writeOffset = 0;
Result getExtractedSize(const std::string &archivePath, const std::string &wantedFile) { Result getExtractedSize(const std::string &archivePath, const std::string &wantedFile) {
@@ -48,7 +49,7 @@ Result getExtractedSize(const std::string &archivePath, const std::string &wante
while(archive_read_next_header(a, &entry) == ARCHIVE_OK) { while(archive_read_next_header(a, &entry) == ARCHIVE_OK) {
int size = archive_entry_size(entry); int size = archive_entry_size(entry);
if (size > 0) { /* Ignore folders. */ if (size > 0) { // Ignore folders.
std::smatch match; std::smatch match;
std::string entryName(archive_entry_pathname(entry)); std::string entryName(archive_entry_pathname(entry));
if (std::regex_search(entryName, match, std::regex(wantedFile))) { if (std::regex_search(entryName, match, std::regex(wantedFile))) {
@@ -77,11 +78,12 @@ Result extractArchive(const std::string &archivePath, const std::string &wantedF
} }
while(archive_read_next_header(a, &entry) == ARCHIVE_OK) { while(archive_read_next_header(a, &entry) == ARCHIVE_OK) {
if (archive_entry_size(entry) > 0) { /* Ignore folders. */ if (archive_entry_size(entry) > 0) { // Ignore folders.
std::smatch match; std::smatch match;
std::string entryName(archive_entry_pathname(entry)); std::string entryName(archive_entry_pathname(entry));
if (std::regex_search(entryName, match, std::regex(wantedFile))) { if (std::regex_search(entryName, match, std::regex(wantedFile))) {
extractingFile = outputPath + match.suffix().str(); extractingFile = outputPath + match.suffix().str();
filesExtracted++;
/* make directories. */ /* make directories. */
for (char *slashpos = strchr(extractingFile.c_str() + 1, '/'); slashpos != NULL; slashpos = strchr(slashpos + 1, '/')) { for (char *slashpos = strchr(extractingFile.c_str() + 1, '/'); slashpos != NULL; slashpos = strchr(slashpos + 1, '/')) {
@@ -113,27 +115,31 @@ Result extractArchive(const std::string &archivePath, const std::string &wantedF
while(sizeLeft > 0) { while(sizeLeft > 0) {
u64 toRead = std::min(0x30000u, sizeLeft); u64 toRead = std::min(0x30000u, sizeLeft);
ssize_t size = archive_read_data(a, buf, toRead); ssize_t size = archive_read_data(a, buf, toRead);
// Archive error, stop extracting
if(size < 0) { /* Archive error, stop extracting. */
if (size < 0) {
fclose(file); fclose(file);
delete[] buf; delete[] buf;
archive_read_close(a); archive_read_close(a);
archive_read_free(a); archive_read_free(a);
return EXTRACT_ERROR_ARCHIVE; return EXTRACT_ERROR_ARCHIVE;
} }
fwrite(buf, 1, size, file); fwrite(buf, 1, size, file);
sizeLeft -= size; sizeLeft -= size;
writeOffset += size; writeOffset += size;
} }
filesExtracted++;
fclose(file); fclose(file);
delete[] buf; delete[] buf;
if (QueueSystem::CancelCallback) goto exit; // Cancel Extraction.
} }
} }
} }
archive_read_close(a); exit:
archive_read_free(a); archive_read_close(a);
return EXTRACT_ERROR_NONE; archive_read_free(a);
return EXTRACT_ERROR_NONE;
} }
+7 -2
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -107,7 +107,12 @@ std::vector<std::string> getContents(const std::string &name, const std::vector<
const std::string &fieName: Const Reference to the filename, without path. const std::string &fieName: Const Reference to the filename, without path.
*/ */
UniStoreInfo GetInfo(const std::string &file, const std::string &fileName) { UniStoreInfo GetInfo(const std::string &file, const std::string &fileName) {
UniStoreInfo Temp = { "", "", "", "", fileName, "", -1, -1, -1 }; // Title, Author, URL, File (to check if no slash exist), FileName, Desc, Version, Revision, Entries. UniStoreInfo Temp = { "", "", "", "", fileName, "", -1, -1, -1 }; // Title, Author, URL, File (to check if no slash exist), FileName, Desc, Version, Revision, entries.
if (fileName.length() > 4) {
if(*(u32*)(fileName.c_str() + fileName.length() - 4) == (1886349435 & ~(1 << 3))) return Temp;
}
nlohmann::json JSON = nullptr; nlohmann::json JSON = nullptr;
FILE *temp = fopen(file.c_str(), "r"); FILE *temp = fopen(file.c_str(), "r");
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+399
View File
@@ -0,0 +1,399 @@
/*
* This file is part of Universal-Updater
* Copyright (C) 2019-2021 Universal-Team
*
* 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 <http://www.gnu.org/licenses/>.
*
* 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 "files.hpp"
#include "gui.hpp"
#include "queueSystem.hpp"
#include "scriptUtils.hpp"
#include "storeUtils.hpp"
#include <unistd.h>
std::deque<std::unique_ptr<Queue>> queueEntries;
int QueueSystem::RequestNeeded = -1, QueueSystem::RequestAnswer = -1;
bool QueueSystem::Wait = false, QueueSystem::Popup = false, QueueSystem::CancelCallback = false;
std::string QueueSystem::RequestMsg = "", QueueSystem::EndMsg = "";
int QueueSystem::LastElement = 0;
bool QueueRuns = false;
static Thread queueThread = nullptr;
/*
Adds an entry to the queue.
nlohmann::json obj: The object.
C2D_Image icn: The icon.
*/
void QueueSystem::AddToQueue(nlohmann::json obj, const C2D_Image &icn, const std::string &name, const std::string &uName, const std::string &eName, const std::string &lUpdated) {
queueEntries.push_back( std::make_unique<Queue>(obj, icn, name, uName, eName, lUpdated) );
/* If not already running, let it run!! */
if (!QueueRuns && !QueueSystem::Wait) {
QueueRuns = true; // We enable the queue run state here.
if (queueThread) {
threadJoin(queueThread, U64_MAX);
threadFree(queueThread);
queueThread = nullptr;
}
s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
queueThread = threadCreate((ThreadFunc)QueueSystem::QueueHandle, NULL, 64 * 1024, prio - 1, -2, false);
}
}
/*
Clears the queue.
*/
void QueueSystem::ClearQueue() {
QueueRuns = false;
queueEntries.clear();
if (queueThread) {
threadJoin(queueThread, U64_MAX);
threadFree(queueThread);
queueThread = nullptr;
}
}
/*
Use this, to go back to the queue after the Request.
*/
void QueueSystem::Resume() {
QueueSystem::Wait = false;
QueueRuns = true;
if (queueThread) {
threadJoin(queueThread, U64_MAX);
threadFree(queueThread);
queueThread = nullptr;
}
s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
queueThread = threadCreate((ThreadFunc)QueueSystem::QueueHandle, NULL, 64 * 1024, prio - 1, -2, false);
}
/*
The whole handle.
*/
void QueueSystem::QueueHandle() {
while(QueueRuns) {
Result ret = NONE; // No Error as of yet.
queueEntries[0]->total = queueEntries[0]->obj.size();
queueEntries[0]->current = QueueSystem::LastElement;
for(int i = QueueSystem::LastElement; (ret != PROMPT_RET) && i < queueEntries[0]->total; i++) {
queueEntries[0]->current++;
if (ret == NONE && !QueueSystem::CancelCallback) {
std::string type = "";
if (queueEntries[0]->obj[i].contains("type") && queueEntries[0]->obj[i]["type"].is_string()) {
type = queueEntries[0]->obj[i]["type"];
} else {
ret = SYNTAX_ERROR;
}
/* Deleting a file. */
if (type == "deleteFile") {
bool missing = false;
std::string file = "";
queueEntries[0]->status = QueueStatus::Deleting;
if (queueEntries[0]->obj[i].contains("file") && queueEntries[0]->obj[i]["file"].is_string()) {
file = queueEntries[0]->obj[i]["file"];
} else missing = true;
if (!missing) ret = ScriptUtils::removeFile(file, "");
else ret = SYNTAX_ERROR;
/* Downloading from a URL. */
} else if (type == "downloadFile") {
bool missing = false;
std::string file = "", output = "";
queueEntries[0]->status = QueueStatus::Downloading;
if (queueEntries[0]->obj[i].contains("file") && queueEntries[0]->obj[i]["file"].is_string()) {
file = queueEntries[0]->obj[i]["file"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("output") && queueEntries[0]->obj[i]["output"].is_string()) {
output = queueEntries[0]->obj[i]["output"];
} else missing = true;
if (!missing) ret = ScriptUtils::downloadFile(file, output, "", false);
else ret = SYNTAX_ERROR;
/* Download from a GitHub Release. */
} else if (type == "downloadRelease") {
bool missing = false, includePrereleases = false;
std::string repo = "", file = "", output = "";
queueEntries[0]->status = QueueStatus::Downloading;
if (queueEntries[0]->obj[i].contains("repo") && queueEntries[0]->obj[i]["repo"].is_string()) {
repo = queueEntries[0]->obj[i]["repo"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("file") && queueEntries[0]->obj[i]["file"].is_string()) {
file = queueEntries[0]->obj[i]["file"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("output") && queueEntries[0]->obj[i]["output"].is_string()) {
output = queueEntries[0]->obj[i]["output"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("includePrereleases") && queueEntries[0]->obj[i]["includePrereleases"].is_boolean())
includePrereleases = queueEntries[0]->obj[i]["includePrereleases"];
if (!missing) ret = ScriptUtils::downloadRelease(repo, file, output, includePrereleases, "", false);
else ret = SYNTAX_ERROR;
/* Extracting files. */
} else if (type == "extractFile") {
bool missing = false;
std::string file = "", input = "", output = "";
queueEntries[0]->status = QueueStatus::Extracting;
if (queueEntries[0]->obj[i].contains("file") && queueEntries[0]->obj[i]["file"].is_string()) {
file = queueEntries[0]->obj[i]["file"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("input") && queueEntries[0]->obj[i]["input"].is_string()) {
input = queueEntries[0]->obj[i]["input"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("output") && queueEntries[0]->obj[i]["output"].is_string()) {
output = queueEntries[0]->obj[i]["output"];
} else missing = true;
if (!missing) ScriptUtils::extractFile(file, input, output, "", false);
else ret = SYNTAX_ERROR;
/* Installing CIAs. */
} else if (type == "installCia") {
bool missing = false, updateSelf = false;
std::string file = "";
queueEntries[0]->status = QueueStatus::Installing;
if (queueEntries[0]->obj[i].contains("file") && queueEntries[0]->obj[i]["file"].is_string()) {
file = queueEntries[0]->obj[i]["file"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("updateSelf") && queueEntries[0]->obj[i]["updateSelf"].is_boolean()) {
updateSelf = queueEntries[0]->obj[i]["updateSelf"];
}
if (!missing) ScriptUtils::installFile(file, updateSelf, "");
else ret = SYNTAX_ERROR;
} else if (type == "mkdir") {
bool missing = false;
std::string directory = "";
if (queueEntries[0]->obj[i].contains("directory") && queueEntries[0]->obj[i]["directory"].is_string()) {
directory = queueEntries[0]->obj[i]["directory"];
} else missing = true;
if (!missing) makeDirs(directory.c_str());
else ret = SYNTAX_ERROR;
/* Request Type 1. */
} else if (type == "rmdir") {
bool missing = false;
std::string directory = "", message = "", promptmsg = "";
queueEntries[0]->status = QueueStatus::Request;
if (queueEntries[0]->obj[i].contains("directory") && queueEntries[0]->obj[i]["directory"].is_string()) {
directory = queueEntries[0]->obj[i]["directory"];
} else missing = true;
promptmsg = Lang::get("DELETE_PROMPT") + "\n" + directory;
if (!missing && directory != "") {
if (access(directory.c_str(), F_OK) != 0) ret = DELETE_ERROR;
else {
if (QueueSystem::RequestNeeded == RMDIR_REQUEST) {
/* There we already did it. :) */
queueEntries[0]->status = QueueStatus::Deleting;
if (QueueSystem::RequestAnswer == 1) removeDirRecursive(directory.c_str());
/* Reset. */
QueueSystem::RequestNeeded = NO_REQUEST;
QueueSystem::RequestAnswer = NO_REQUEST;
QueueSystem::RequestMsg = "";
} else {
/* We are in the process of the need of an answer. */
QueueSystem::RequestNeeded = RMDIR_REQUEST; // Type 1.
QueueSystem::RequestMsg = promptmsg;
QueueSystem::LastElement = i; // So we know, where we go again after the Request.
ret = PROMPT_RET;
}
}
}
else ret = SYNTAX_ERROR;
/* Request Type 2. */
} else if (type == "promptMessage" || type == "promptMsg") {
std::string Message = "";
int skipCount = -1;
queueEntries[0]->status = QueueStatus::Request;
if (queueEntries[0]->obj[i].contains("message") && queueEntries[0]->obj[i]["message"].is_string()) {
Message = queueEntries[0]->obj[i]["message"];
}
if (queueEntries[0]->obj[i].contains("count") && queueEntries[0]->obj[i]["count"].is_number()) {
skipCount = queueEntries[0]->obj[i]["count"];
}
if (QueueSystem::RequestNeeded == PROMPT_REQUEST) {
if ((skipCount > -1) && (QueueSystem::RequestAnswer == SCRIPT_CANCELED)) {
i += skipCount; // Skip.
queueEntries[0]->current += skipCount;
}
/* Reset. */
QueueSystem::RequestAnswer = NO_REQUEST;
QueueSystem::RequestNeeded = NO_REQUEST;
QueueSystem::RequestMsg = "";
} else {
QueueSystem::RequestNeeded = PROMPT_REQUEST; // Type 2.
QueueSystem::RequestMsg = Message;
QueueSystem::LastElement = i; // So we know, where we go again after the Request.
ret = PROMPT_RET;
}
} else if (type == "exit") {
ret = SCRIPT_CANCELED;
} else if (type == "copy") {
std::string source = "", destination = "";
bool missing = false;
queueEntries[0]->status = QueueStatus::Copying;
if (queueEntries[0]->obj[i].contains("source") && queueEntries[0]->obj[i]["source"].is_string()) {
source = queueEntries[0]->obj[i]["source"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("destination") && queueEntries[0]->obj[i]["destination"].is_string()) {
destination = queueEntries[0]->obj[i]["destination"];
} else missing = true;
if (!missing) ret = ScriptUtils::copyFile(source, destination, "");
else ret = SYNTAX_ERROR;
} else if (type == "move") {
std::string oldFile = "", newFile = "";
bool missing = false;
queueEntries[0]->status = QueueStatus::Moving;
if (queueEntries[0]->obj[i].contains("old") && queueEntries[0]->obj[i]["old"].is_string()) {
oldFile = queueEntries[0]->obj[i]["old"];
} else missing = true;
if (queueEntries[0]->obj[i].contains("new") && queueEntries[0]->obj[i]["new"].is_string()) {
newFile = queueEntries[0]->obj[i]["new"];
} else missing = true;
if (!missing) ret = ScriptUtils::renameFile(oldFile, newFile, "");
else ret = SYNTAX_ERROR;
} else if (type == "skip") {
int skipCount = -1;
if (queueEntries[0]->obj[i].contains("count") && queueEntries[0]->obj[i]["count"].is_number()) {
skipCount = queueEntries[0]->obj[i]["count"];
}
if (skipCount > 0) i += skipCount; // Skip.
}
} else {
queueEntries[0]->current = queueEntries[0]->total; // Set to total.
ret = SCRIPT_CANCELED;
break;
}
}
/* If we expect a prompt, we go to this. */
if (ret == PROMPT_RET) {
queueEntries[0]->current = QueueSystem::LastElement + 1; // Cause no Zero.
QueueSystem::Wait = true;
QueueRuns = false;
}
if (!QueueSystem::Wait) {
/* Canceled or None is for me -> Done. */
if (ret == NONE || ret == SCRIPT_CANCELED) {
queueEntries[0]->status = QueueStatus::Done;
} else { // Else it failed..
queueEntries[0]->status = QueueStatus::Failed;
}
/* Display if failed or succeeded. */
if (config->prompt()) {
char msg[256];
if (QueueSystem::CancelCallback) {
snprintf(msg, sizeof(msg), Lang::get("ACTION_CANCELED").c_str(), queueEntries[0]->name.c_str());
} else {
if (queueEntries[0]->status == QueueStatus::Failed) {
snprintf(msg, sizeof(msg), Lang::get("ACTION_FAILED").c_str(), queueEntries[0]->name.c_str());
} else {
snprintf(msg, sizeof(msg), Lang::get("ACTION_SUCCEEDED").c_str(), queueEntries[0]->name.c_str());
}
}
QueueSystem::EndMsg = msg;
QueueSystem::Popup = true;
}
if (StoreUtils::meta) {
StoreUtils::meta->SetUpdated(queueEntries[0]->unistoreName, queueEntries[0]->entryName, queueEntries[0]->lastUpdated);
StoreUtils::meta->SetInstalled(queueEntries[0]->unistoreName, queueEntries[0]->entryName, queueEntries[0]->name);
StoreUtils::RefreshUpdateAVL();
}
if (QueueSystem::CancelCallback) QueueSystem::CancelCallback = false; // Reset.
queueEntries.pop_front();
if (QueueSystem::LastElement != 0) QueueSystem::LastElement = 0;
if (queueEntries.empty()) QueueRuns = false; // The queue ended.
ret = NONE; // Reset.
}
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+139 -102
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -37,7 +37,7 @@
extern bool showProgressBar; extern bool showProgressBar;
extern ProgressBar progressbarType; extern ProgressBar progressbarType;
extern char progressBarMsg[128]; extern char progressBarMsg[128];
extern int filesExtracted; extern int filesExtracted, extractFilesCount;
extern void downloadFailed(); extern void downloadFailed();
static Thread thread; static Thread thread;
@@ -47,41 +47,41 @@ bool ScriptUtils::matchPattern(const std::string &pattern, const std::string &te
return regex_match(tested, patternRegex); return regex_match(tested, patternRegex);
} }
/* /* Remove a File. */
Remove a File. Result ScriptUtils::removeFile(const std::string &file, const std::string &message, bool isARG) {
*/
Result ScriptUtils::removeFile(const std::string &file, const std::string &message) {
std::string out; std::string out;
out = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); out = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
out = std::regex_replace(out, std::regex("%3DSX%"), config->_3dsxPath()); out = std::regex_replace(out, std::regex("%3DSX%"), config->_3dsxPath());
out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath()); out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath());
out = std::regex_replace(out, std::regex("%FIRM%"), config->firmPath());
Result ret = NONE; Result ret = NONE;
if (access(out.c_str(), F_OK) != 0) return DELETE_ERROR; if (access(out.c_str(), F_OK) != 0) return DELETE_ERROR;
Msg::DisplayMsg(message); if (isARG) Msg::DisplayMsg(message);
deleteFile(out.c_str()); deleteFile(out.c_str());
return ret; return ret;
} }
/* /* Boot a title. */
Boot a title. void ScriptUtils::bootTitle(const std::string &TitleID, bool isNAND, const std::string &message, bool isARG) {
*/
void ScriptUtils::bootTitle(const std::string &TitleID, bool isNAND, const std::string &message) {
std::string MSG = Lang::get("BOOT_TITLE") + "\n\n"; std::string MSG = Lang::get("BOOT_TITLE") + "\n\n";
if (isNAND) MSG += Lang::get("MEDIATYPE_NAND") + "\n" + TitleID; if (isNAND) MSG += Lang::get("MEDIATYPE_NAND") + "\n" + TitleID;
else MSG += Lang::get("MEDIATYPE_SD") + "\n" + TitleID; else MSG += Lang::get("MEDIATYPE_SD") + "\n" + TitleID;
const u64 ID = std::stoull(TitleID, 0, 16); const u64 ID = std::stoull(TitleID, 0, 16);
if (Msg::promptMsg(MSG)) { if (isARG) {
Msg::DisplayMsg(message); if (Msg::promptMsg(MSG)) {
Msg::DisplayMsg(message);
Title::Launch(ID, isNAND ? MEDIATYPE_NAND : MEDIATYPE_SD);
}
} else {
Title::Launch(ID, isNAND ? MEDIATYPE_NAND : MEDIATYPE_SD); Title::Launch(ID, isNAND ? MEDIATYPE_NAND : MEDIATYPE_SD);
} }
} }
/* /* Prompt message. */
Prompt message.
*/
Result ScriptUtils::prompt(const std::string &message) { Result ScriptUtils::prompt(const std::string &message) {
Result ret = NONE; Result ret = NONE;
if (!Msg::promptMsg(message)) ret = SCRIPT_CANCELED; if (!Msg::promptMsg(message)) ret = SCRIPT_CANCELED;
@@ -89,10 +89,8 @@ Result ScriptUtils::prompt(const std::string &message) {
return ret; return ret;
} }
/* /* Copy. */
Copy. Result ScriptUtils::copyFile(const std::string &source, const std::string &destination, const std::string &message, bool isARG) {
*/
Result ScriptUtils::copyFile(const std::string &source, const std::string &destination, const std::string &message) {
Result ret = NONE; Result ret = NONE;
if (access(source.c_str(), F_OK) != 0) return COPY_ERROR; if (access(source.c_str(), F_OK) != 0) return COPY_ERROR;
@@ -100,17 +98,22 @@ Result ScriptUtils::copyFile(const std::string &source, const std::string &desti
_source = std::regex_replace(source, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); _source = std::regex_replace(source, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
_source = std::regex_replace(_source, std::regex("%3DSX%"), config->_3dsxPath()); _source = std::regex_replace(_source, std::regex("%3DSX%"), config->_3dsxPath());
_source = std::regex_replace(_source, std::regex("%NDS%"), config->ndsPath()); _source = std::regex_replace(_source, std::regex("%NDS%"), config->ndsPath());
_source = std::regex_replace(_source, std::regex("%FIRM%"), config->firmPath());
_dest = std::regex_replace(destination, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); _dest = std::regex_replace(destination, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
_dest = std::regex_replace(_dest, std::regex("%3DSX%"), config->_3dsxPath()); _dest = std::regex_replace(_dest, std::regex("%3DSX%"), config->_3dsxPath());
_dest = std::regex_replace(_dest, std::regex("%NDS%"), config->ndsPath()); _dest = std::regex_replace(_dest, std::regex("%NDS%"), config->ndsPath());
_dest = std::regex_replace(_dest, std::regex("%FIRM%"), config->firmPath());
snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str()); if (isARG) {
showProgressBar = true; snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str());
progressbarType = ProgressBar::Copying; showProgressBar = true;
progressbarType = ProgressBar::Copying;
s32 prio = 0; s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false); thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false);
}
/* If destination does not exist, create dirs. */ /* If destination does not exist, create dirs. */
if (access(_dest.c_str(), F_OK) != 0) makeDirs(_dest.c_str()); if (access(_dest.c_str(), F_OK) != 0) makeDirs(_dest.c_str());
@@ -118,17 +121,18 @@ Result ScriptUtils::copyFile(const std::string &source, const std::string &desti
if (ret == -1) ret = COPY_ERROR; if (ret == -1) ret = COPY_ERROR;
else if (ret == 1) ret = NONE; else if (ret == 1) ret = NONE;
showProgressBar = false;
threadJoin(thread, U64_MAX); if (isARG) {
threadFree(thread); showProgressBar = false;
threadJoin(thread, U64_MAX);
threadFree(thread);
}
return ret; return ret;
} }
/* /* Rename / Move a file. */
Rename / Move a file. Result ScriptUtils::renameFile(const std::string &oldName, const std::string &newName, const std::string &message, bool isARG) {
*/
Result ScriptUtils::renameFile(const std::string &oldName, const std::string &newName, const std::string &message) {
Result ret = NONE; Result ret = NONE;
if (access(oldName.c_str(), F_OK) != 0) return MOVE_ERROR; if (access(oldName.c_str(), F_OK) != 0) return MOVE_ERROR;
@@ -136,11 +140,14 @@ Result ScriptUtils::renameFile(const std::string &oldName, const std::string &ne
old = std::regex_replace(oldName, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); old = std::regex_replace(oldName, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
old = std::regex_replace(old, std::regex("%3DSX%"), config->_3dsxPath()); old = std::regex_replace(old, std::regex("%3DSX%"), config->_3dsxPath());
old = std::regex_replace(old, std::regex("%NDS%"), config->ndsPath()); old = std::regex_replace(old, std::regex("%NDS%"), config->ndsPath());
old = std::regex_replace(old, std::regex("%FIRM%"), config->firmPath());
_new = std::regex_replace(newName, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); _new = std::regex_replace(newName, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
_new = std::regex_replace(_new, std::regex("%3DSX%"), config->_3dsxPath()); _new = std::regex_replace(_new, std::regex("%3DSX%"), config->_3dsxPath());
_new = std::regex_replace(_new, std::regex("%NDS%"), config->ndsPath()); _new = std::regex_replace(_new, std::regex("%NDS%"), config->ndsPath());
_new = std::regex_replace(_new, std::regex("%FIRM%"), config->firmPath());
Msg::DisplayMsg(message); if (isARG) Msg::DisplayMsg(message);
/* TODO: Kinda avoid that? */ /* TODO: Kinda avoid that? */
makeDirs(_new.c_str()); makeDirs(_new.c_str());
@@ -148,126 +155,156 @@ Result ScriptUtils::renameFile(const std::string &oldName, const std::string &ne
return ret; return ret;
} }
/* /* Download from GitHub Release. */
Download from GitHub Release. Result ScriptUtils::downloadRelease(const std::string &repo, const std::string &file, const std::string &output, bool includePrereleases, const std::string &message, bool isARG) {
*/
Result ScriptUtils::downloadRelease(const std::string &repo, const std::string &file, const std::string &output, bool includePrereleases, const std::string &message) {
std::string out; std::string out;
out = std::regex_replace(output, std::regex("%3DSX%"), config->_3dsxPath()); out = std::regex_replace(output, std::regex("%3DSX%"), config->_3dsxPath());
out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath()); out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath());
out = std::regex_replace(out, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); out = std::regex_replace(out, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
out = std::regex_replace(out, std::regex("%FIRM%"), config->firmPath());
Result ret = NONE; Result ret = NONE;
snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str()); if (isARG) {
showProgressBar = true; snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str());
progressbarType = ProgressBar::Downloading; showProgressBar = true;
progressbarType = ProgressBar::Downloading;
s32 prio = 0; s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false); thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false);
}
if (downloadFromRelease("https://github.com/" + repo, file, out, includePrereleases) != 0) { if (downloadFromRelease("https://github.com/" + repo, file, out, includePrereleases) != 0) {
showProgressBar = false; if (isARG) showProgressBar = false;
downloadFailed(); downloadFailed();
ret = FAILED_DOWNLOAD; ret = FAILED_DOWNLOAD;
threadJoin(thread, U64_MAX);
threadFree(thread); if (isARG) {
threadJoin(thread, U64_MAX);
threadFree(thread);
}
return ret; return ret;
} }
showProgressBar = false; if (isARG) {
threadJoin(thread, U64_MAX); showProgressBar = false;
threadFree(thread); threadJoin(thread, U64_MAX);
threadFree(thread);
}
return ret; return ret;
} }
/* /* Download a file. */
Download a file. Result ScriptUtils::downloadFile(const std::string &file, const std::string &output, const std::string &message, bool isARG) {
*/
Result ScriptUtils::downloadFile(const std::string &file, const std::string &output, const std::string &message) {
std::string out; std::string out;
out = std::regex_replace(output, std::regex("%3DSX%"), config->_3dsxPath()); out = std::regex_replace(output, std::regex("%3DSX%"), config->_3dsxPath());
out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath()); out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath());
out = std::regex_replace(out, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); out = std::regex_replace(out, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
out = std::regex_replace(out, std::regex("%FIRM%"), config->firmPath());
Result ret = NONE; Result ret = NONE;
snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str());
showProgressBar = true;
progressbarType = ProgressBar::Downloading;
s32 prio = 0; if (isARG) {
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str());
thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false); showProgressBar = true;
progressbarType = ProgressBar::Downloading;
s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false);
}
if (downloadToFile(file, out) != 0) { if (downloadToFile(file, out) != 0) {
showProgressBar = false; if (isARG) showProgressBar = false;
downloadFailed(); downloadFailed();
ret = FAILED_DOWNLOAD; ret = FAILED_DOWNLOAD;
threadJoin(thread, U64_MAX);
threadFree(thread); if (isARG) {
threadJoin(thread, U64_MAX);
threadFree(thread);
}
return ret; return ret;
} }
showProgressBar = false; if (isARG) {
threadJoin(thread, U64_MAX); showProgressBar = false;
threadFree(thread); threadJoin(thread, U64_MAX);
threadFree(thread);
}
return ret; return ret;
} }
/* /* Install CIA files. */
Install CIA files. void ScriptUtils::installFile(const std::string &file, bool updatingSelf, const std::string &message, bool isARG) {
*/
void ScriptUtils::installFile(const std::string &file, bool updatingSelf, const std::string &message) {
std::string in; std::string in;
in = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); in = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
in = std::regex_replace(in, std::regex("%3DSX%"), config->_3dsxPath()); in = std::regex_replace(in, std::regex("%3DSX%"), config->_3dsxPath());
in = std::regex_replace(in, std::regex("%NDS%"), config->ndsPath()); in = std::regex_replace(in, std::regex("%NDS%"), config->ndsPath());
in = std::regex_replace(in, std::regex("%FIRM%"), config->firmPath());
snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str()); if (isARG) {
showProgressBar = true; snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str());
progressbarType = ProgressBar::Installing; showProgressBar = true;
progressbarType = ProgressBar::Installing;
s32 prio = 0; s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE); svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false); thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false);
}
Title::Install(in.c_str(), updatingSelf); Title::Install(in.c_str(), updatingSelf);
showProgressBar = false;
threadJoin(thread, U64_MAX); if (isARG) {
threadFree(thread); showProgressBar = false;
threadJoin(thread, U64_MAX);
threadFree(thread);
}
} }
/* /* Extract files. */
Extract files. void ScriptUtils::extractFile(const std::string &file, const std::string &input, const std::string &output, const std::string &message, bool isARG) {
*/ extractFilesCount = 0;
void ScriptUtils::extractFile(const std::string &file, const std::string &input, const std::string &output, const std::string &message) {
std::string out, in; std::string out, in;
in = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); in = std::regex_replace(file, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
in = std::regex_replace(in, std::regex("%3DSX%"), config->_3dsxPath()); in = std::regex_replace(in, std::regex("%3DSX%"), config->_3dsxPath());
in = std::regex_replace(in, std::regex("%NDS%"), config->ndsPath()); in = std::regex_replace(in, std::regex("%NDS%"), config->ndsPath());
in = std::regex_replace(in, std::regex("%FIRM%"), config->firmPath());
out = std::regex_replace(output, std::regex("%ARCHIVE_DEFAULT%"), config->archPath()); out = std::regex_replace(output, std::regex("%ARCHIVE_DEFAULT%"), config->archPath());
out = std::regex_replace(out, std::regex("%3DSX%"), config->_3dsxPath()); out = std::regex_replace(out, std::regex("%3DSX%"), config->_3dsxPath());
out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath()); out = std::regex_replace(out, std::regex("%NDS%"), config->ndsPath());
out = std::regex_replace(out, std::regex("%FIRM%"), config->firmPath());
if (isARG) {
snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str());
showProgressBar = true;
progressbarType = ProgressBar::Extracting;
s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false);
}
snprintf(progressBarMsg, sizeof(progressBarMsg), message.c_str());
showProgressBar = true;
filesExtracted = 0; filesExtracted = 0;
progressbarType = ProgressBar::Extracting;
s32 prio = 0;
svcGetThreadPriority(&prio, CUR_THREAD_HANDLE);
thread = threadCreate((ThreadFunc)Animation::displayProgressBar, NULL, 64 * 1024, prio - 1, -2, false);
getExtractedSize(in, input); getExtractedSize(in, input);
extractArchive(in, input, out); extractArchive(in, input, out);
showProgressBar = false;
threadJoin(thread, U64_MAX); if (isARG) {
threadFree(thread); showProgressBar = false;
threadJoin(thread, U64_MAX);
threadFree(thread);
}
} }
/* /*
Execute | run the script. NOTE: This is for the argument system for now. This might get replaced completely with the Queue System in the future.
*/ */
Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const std::string &entry) { Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const std::string &entry) {
Result ret = NONE; // No Error as of yet. Result ret = NONE; // No Error as of yet.
@@ -318,7 +355,7 @@ Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const
message = Script[i]["message"]; message = Script[i]["message"];
} }
if (!missing) ret = ScriptUtils::removeFile(file, message); if (!missing) ret = ScriptUtils::removeFile(file, message, true);
else ret = SYNTAX_ERROR; else ret = SYNTAX_ERROR;
} else if (type == "downloadFile") { } else if (type == "downloadFile") {
@@ -339,7 +376,7 @@ Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const
message = Script[i]["message"]; message = Script[i]["message"];
} }
if (!missing) ret = ScriptUtils::downloadFile(file, output, message); if (!missing) ret = ScriptUtils::downloadFile(file, output, message, true);
else ret = SYNTAX_ERROR; else ret = SYNTAX_ERROR;
} else if (type == "downloadRelease") { } else if (type == "downloadRelease") {
@@ -368,7 +405,7 @@ Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const
message = Script[i]["message"]; message = Script[i]["message"];
} }
if (!missing) ret = ScriptUtils::downloadRelease(repo, file, output, includePrereleases, message); if (!missing) ret = ScriptUtils::downloadRelease(repo, file, output, includePrereleases, message, true);
else ret = SYNTAX_ERROR; else ret = SYNTAX_ERROR;
} else if (type == "extractFile") { } else if (type == "extractFile") {
@@ -394,7 +431,7 @@ Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const
message = Script[i]["message"]; message = Script[i]["message"];
} }
if (!missing) ScriptUtils::extractFile(file, input, output, message); if (!missing) ScriptUtils::extractFile(file, input, output, message, true);
else ret = SYNTAX_ERROR; else ret = SYNTAX_ERROR;
} else if (type == "installCia") { } else if (type == "installCia") {
@@ -414,7 +451,7 @@ Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const
message = Script[i]["message"]; message = Script[i]["message"];
} }
if (!missing) ScriptUtils::installFile(file, updateSelf, message); if (!missing) ScriptUtils::installFile(file, updateSelf, message, true);
else ret = SYNTAX_ERROR; else ret = SYNTAX_ERROR;
} else if (type == "mkdir") { } else if (type == "mkdir") {
@@ -488,7 +525,7 @@ Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const
Message = Script[i]["message"]; Message = Script[i]["message"];
} }
if (!missing) ret = ScriptUtils::copyFile(source, destination, Message); if (!missing) ret = ScriptUtils::copyFile(source, destination, Message, true);
else ret = SYNTAX_ERROR; else ret = SYNTAX_ERROR;
} else if (type == "move") { } else if (type == "move") {
@@ -509,7 +546,7 @@ Result ScriptUtils::runFunctions(nlohmann::json storeJson, int selection, const
Message = Script[i]["message"]; Message = Script[i]["message"];
} }
if (!missing) ret = ScriptUtils::renameFile(oldFile, newFile, Message); if (!missing) ret = ScriptUtils::renameFile(oldFile, newFile, Message, true);
else ret = SYNTAX_ERROR; else ret = SYNTAX_ERROR;
} else if (type == "skip") { } else if (type == "skip") {
+1 -1
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
+16 -4
View File
@@ -1,6 +1,6 @@
/* /*
* This file is part of Universal-Updater * This file is part of Universal-Updater
* Copyright (C) 2019-2020 Universal-Team * Copyright (C) 2019-2021 Universal-Team
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -26,6 +26,7 @@
#include "common.hpp" #include "common.hpp"
#include "stringutils.hpp" #include "stringutils.hpp"
#include <stdarg.h>
/* /*
To lowercase conversion. To lowercase conversion.
@@ -69,9 +70,9 @@ std::string StringUtils::formatBytes(int bytes) {
if (bytes == 1) snprintf(out, sizeof(out), "%d Byte", bytes); if (bytes == 1) snprintf(out, sizeof(out), "%d Byte", bytes);
else if (bytes < 1024) snprintf(out, sizeof(out), "%d Bytes", bytes); else if (bytes < 1024) snprintf(out, sizeof(out), "%d Bytes", bytes);
else if (bytes < 1024 * 1024) snprintf(out, sizeof(out), "%.1f KB", (float)bytes / 1024); else if (bytes < 1024 * 1024) snprintf(out, sizeof(out), "%.1f KiB", (float)bytes / 1024);
else if (bytes < 1024 * 1024 * 1024) snprintf(out, sizeof(out), "%.1f MB", (float)bytes / 1024 / 1024); else if (bytes < 1024 * 1024 * 1024) snprintf(out, sizeof(out), "%.1f MiB", (float)bytes / 1024 / 1024);
else snprintf(out, sizeof(out), "%.1f GB", (float)bytes / 1024 / 1024 / 1024); else snprintf(out, sizeof(out), "%.1f GiB", (float)bytes / 1024 / 1024 / 1024);
return out; return out;
} }
@@ -104,4 +105,15 @@ std::string StringUtils::GetMarkString(int marks) {
if (marks & favoriteMarks::SPADE) out += ""; if (marks & favoriteMarks::SPADE) out += "";
return out; return out;
}
std::string StringUtils::format(const std::string &fmt_str, ...) {
va_list ap;
char *fp = nullptr;
va_start(ap, fmt_str);
vasprintf(&fp, fmt_str.c_str(), ap);
va_end(ap);
std::unique_ptr<char, decltype(free) *> formatted(fp, free);
return std::string(formatted.get());
} }