Various fixes.

* Allow more than three choices in prompts.
* Allow specifying a title version when installing CDN titles outside of the ticket list.
* Fix titles displayed during TitleDB update.
* Update title version and install status after TitleDB install/update.
This commit is contained in:
Steveice10 2017-04-27 17:35:20 -07:00
parent a9c4e5fe85
commit 33a61872c0
41 changed files with 659 additions and 434 deletions

View File

Before

Width:  |  Height:  |  Size: 327 B

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 285 B

View File

@ -254,8 +254,7 @@ void screen_init() {
screen_load_texture_file(TEXTURE_LOGO, "logo.png", true);
screen_load_texture_file(TEXTURE_SELECTION_OVERLAY, "selection_overlay.png", true);
screen_load_texture_file(TEXTURE_SCROLL_BAR, "scroll_bar.png", true);
screen_load_texture_file(TEXTURE_BUTTON_SMALL, "button_small.png", true);
screen_load_texture_file(TEXTURE_BUTTON_LARGE, "button_large.png", true);
screen_load_texture_file(TEXTURE_BUTTON, "button.png", true);
screen_load_texture_file(TEXTURE_PROGRESS_BAR_BG, "progress_bar_bg.png", true);
screen_load_texture_file(TEXTURE_PROGRESS_BAR_CONTENT, "progress_bar_content.png", true);
screen_load_texture_file(TEXTURE_META_INFO_BOX, "meta_info_box.png", true);

View File

@ -21,24 +21,23 @@
#define TEXTURE_LOGO 11
#define TEXTURE_SELECTION_OVERLAY 12
#define TEXTURE_SCROLL_BAR 13
#define TEXTURE_BUTTON_SMALL 14
#define TEXTURE_BUTTON_LARGE 15
#define TEXTURE_PROGRESS_BAR_BG 16
#define TEXTURE_PROGRESS_BAR_CONTENT 17
#define TEXTURE_META_INFO_BOX 18
#define TEXTURE_META_INFO_BOX_SHADOW 19
#define TEXTURE_BATTERY_CHARGING 20
#define TEXTURE_BATTERY_0 21
#define TEXTURE_BATTERY_1 22
#define TEXTURE_BATTERY_2 23
#define TEXTURE_BATTERY_3 24
#define TEXTURE_BATTERY_4 25
#define TEXTURE_BATTERY_5 26
#define TEXTURE_WIFI_DISCONNECTED 27
#define TEXTURE_WIFI_0 28
#define TEXTURE_WIFI_1 29
#define TEXTURE_WIFI_2 30
#define TEXTURE_WIFI_3 31
#define TEXTURE_BUTTON 14
#define TEXTURE_PROGRESS_BAR_BG 15
#define TEXTURE_PROGRESS_BAR_CONTENT 16
#define TEXTURE_META_INFO_BOX 17
#define TEXTURE_META_INFO_BOX_SHADOW 18
#define TEXTURE_BATTERY_CHARGING 19
#define TEXTURE_BATTERY_0 20
#define TEXTURE_BATTERY_1 21
#define TEXTURE_BATTERY_2 22
#define TEXTURE_BATTERY_3 23
#define TEXTURE_BATTERY_4 24
#define TEXTURE_BATTERY_5 25
#define TEXTURE_WIFI_DISCONNECTED 26
#define TEXTURE_WIFI_0 27
#define TEXTURE_WIFI_1 28
#define TEXTURE_WIFI_2 29
#define TEXTURE_WIFI_3 30
#define MAX_COLORS 14
@ -64,7 +63,6 @@ u32 screen_allocate_free_texture();
void screen_load_texture(u32 id, void* data, u32 size, u32 width, u32 height, GPU_TEXCOLOR format, bool linearFilter);
void screen_load_texture_file(u32 id, const char* path, bool linearFilter);
void screen_load_texture_tiled(u32 id, void* tiledData, u32 size, u32 width, u32 height, GPU_TEXCOLOR format, bool linearFilter);
void screen_load_texture_screenshot(u32 id, gfxScreen_t screen);
void screen_unload_texture(u32 id);
void screen_get_texture_size(u32* width, u32* height, u32 id);
void screen_begin_frame();

View File

@ -53,40 +53,6 @@ static int util_get_lines(PrintConsole* console, const char* str) {
return lines;
}
static char util_dec2hex(short int c)
{
if (0 <= c && c <= 9) return c + '0';
else if (10 <= c && c <= 15) return c + 'A' - 10;
else return -1;
}
void util_urlencode(char url[])
{
int i = 0;
int res_len = 0;
int len = strlen(url);
char res[1024];
for (i = 0; i < len; ++i) {
char c = url[i];
if (
('0' <= c && c <= '9') || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
c == ':' || c == '/' || c == '.' || c == '%' || c == '+' || c == '?' || c == '=' || c == '&' || c == '#'
) res[res_len++] = c;
else {
int j = (short int)c;
if (j < 0) j += 256;
int i1, i0;
i1 = j / 16;
i0 = j - i1 * 16;
res[res_len++] = '%';
res[res_len++] = util_dec2hex(i1);
res[res_len++] = util_dec2hex(i0);
}
}
res[res_len] = '\0';
strcpy(url, res);
}
void util_panic(const char* s, ...) {
va_list list;
va_start(list, s);
@ -709,6 +675,39 @@ u16* util_select_bnr_title(BNR* bnr) {
#define MAKE_HTTP_USER_AGENT(major, minor, micro) ("Mozilla/5.0 (Nintendo 3DS; Mobile; rv:10.0) Gecko/20100101 FBI/" #major "." #minor "." #micro)
#define HTTP_USER_AGENT MAKE_HTTP_USER_AGENT(VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO)
static char util_dec2hex(u8 c) {
if(c >= 0 && c <= 9) {
return (char) ('0' + c);
} else if(c >= 10 && c <= 15) {
return (char) ('A' + (c - 10));
} else {
return -1;
}
}
static void util_encode_url(char* out, const char* in, size_t size) {
u32 pos = 0;
size_t len = strlen(in);
for(u32 i = 0; i < len && pos < size; i++) {
char c = in[i];
if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == ':' || c == '/' || c == '.' || c == '%' || c == '+' || c == '?' || c == '=' || c == '&' || c == '#') {
out[pos++] = c;
} else {
out[pos++] = '%';
if(pos < size) {
out[pos++] = util_dec2hex((u8) (((u8) c) / 16));
}
if(pos < size) {
out[pos++] = util_dec2hex((u8) (((u8) c) % 16));
}
}
}
out[pos < size ? pos : size - 1] = '\0';
}
Result util_http_open(httpcContext* context, u32* responseCode, const char* url, bool userAgent) {
return util_http_open_ranged(context, responseCode, url, userAgent, 0, 0);
}
@ -719,9 +718,7 @@ Result util_http_open_ranged(httpcContext* context, u32* responseCode, const cha
}
char currUrl[1024];
strncpy(currUrl, url, sizeof(currUrl));
util_urlencode(currUrl);
util_encode_url(currUrl, url, sizeof(currUrl));
char range[64];
if(rangeEnd > rangeStart) {

View File

@ -577,7 +577,7 @@ static void error_draw_top(ui_view* view, void* data, float x1, float y1, float
}
}
static void error_onresponse(ui_view* view, void* data, bool response) {
static void error_onresponse(ui_view* view, void* data, u32 response) {
free(data);
}
@ -596,7 +596,7 @@ ui_view* error_display(void* data, void (*drawTop)(ui_view* view, void* data, fl
vsnprintf(errorData->fullText, 4096, text, list);
va_end(list);
return prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, error_draw_top, error_onresponse);
return prompt_display_notify("Error", errorData->fullText, COLOR_TEXT, errorData, error_draw_top, error_onresponse);
}
ui_view* error_display_res(void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), Result result, const char* text, ...) {
@ -621,7 +621,7 @@ ui_view* error_display_res(void* data, void (*drawTop)(ui_view* view, void* data
int description = R_DESCRIPTION(result);
snprintf(errorData->fullText, 4096, "%s\nResult code: 0x%08lX\nLevel: %s (%d)\nSummary: %s (%d)\nModule: %s (%d)\nDesc: %s (%d)", textBuf, result, level_to_string(result), level, summary_to_string(result), summary, module_to_string(result), module, description_to_string(result), description);
return prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, error_draw_top, error_onresponse);
return prompt_display_notify("Error", errorData->fullText, COLOR_TEXT, errorData, error_draw_top, error_onresponse);
}
ui_view* error_display_errno(void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2), int err, const char* text, ...) {
@ -646,5 +646,5 @@ ui_view* error_display_errno(void* data, void (*drawTop)(ui_view* view, void* da
snprintf(errorData->fullText, 4096, "%s\nI/O Error: %s (%d)", textBuf, strerror(err), err);
return prompt_display("Error", errorData->fullText, COLOR_TEXT, false, errorData, error_draw_top, error_onresponse);
return prompt_display_notify("Error", errorData->fullText, COLOR_TEXT, errorData, error_draw_top, error_onresponse);
}

81
source/ui/kbd.c Normal file
View File

@ -0,0 +1,81 @@
#include <malloc.h>
#include <3ds.h>
#include "error.h"
#include "kbd.h"
#include "ui.h"
typedef struct {
const char* hint;
const char* initialText;
SwkbdType type;
u32 features;
SwkbdValidInput validation;
u32 maxSize;
char* response;
void* data;
void (*onResponse)(ui_view* view, void* data, SwkbdButton button, const char* response);
} kbd_data;
static void kbd_update(ui_view* view, void* data, float bx1, float by1, float bx2, float by2) {
kbd_data* kbdData = (kbd_data*) data;
SwkbdState swkbd;
swkbdInit(&swkbd, kbdData->type, 2, kbdData->maxSize < 65000 ? (int) kbdData->maxSize : 65000);
swkbdSetHintText(&swkbd, kbdData->hint);
swkbdSetInitialText(&swkbd, kbdData->initialText);
swkbdSetFeatures(&swkbd, kbdData->features);
swkbdSetValidation(&swkbd, kbdData->validation, 0, 0);
SwkbdButton button = swkbdInputText(&swkbd, kbdData->response, kbdData->maxSize);
ui_pop();
if(kbdData->onResponse != NULL) {
kbdData->onResponse(view, kbdData->data, button, kbdData->response);
}
free(kbdData->response);
free(kbdData);
ui_destroy(view);
}
ui_view* kbd_display(const char* hint, const char* initialText, SwkbdType type, u32 features, SwkbdValidInput validation, u32 maxSize, void* data, void (*onResponse)(ui_view* view, void* data, SwkbdButton button, const char* response)) {
kbd_data* kbdData = (kbd_data*) calloc(1, sizeof(kbd_data));
if(kbdData == NULL) {
error_display(NULL, NULL, "Failed to allocate keyboard data.");
return NULL;
}
kbdData->hint = hint;
kbdData->initialText = initialText;
kbdData->type = type;
kbdData->features = features;
kbdData->validation = validation;
kbdData->maxSize = maxSize;
kbdData->response = (char*) calloc(1, maxSize);
if(kbdData->response == NULL) {
error_display(NULL, NULL, "Failed to allocate keyboard response buffer.");
free(kbdData);
return NULL;
}
kbdData->data = data;
kbdData->onResponse = onResponse;
ui_view* view = ui_create();
view->name = "";
view->info = "";
view->data = kbdData;
view->update = kbd_update;
view->drawTop = NULL;
view->drawBottom = NULL;
ui_push(view);
return view;
}

5
source/ui/kbd.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
typedef struct ui_view_s ui_view;
ui_view* kbd_display(const char* hint, const char* initialText, SwkbdType type, u32 features, SwkbdValidInput validation, u32 maxSize, void* data, void (*onResponse)(ui_view* view, void* data, SwkbdButton button, const char* response));

View File

@ -1,4 +1,6 @@
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <3ds.h>
@ -10,13 +12,15 @@
typedef struct {
const char* text;
u32 color;
bool option;
char options[PROMPT_OPTIONS_MAX][PROMPT_OPTION_TEXT_MAX];
u32 optionButtons[PROMPT_OPTIONS_MAX];
u32 numOptions;
void* data;
void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2);
void (*onResponse)(ui_view* view, void* data, bool response);
void (*onResponse)(ui_view* view, void* data, u32 response);
} prompt_data;
static void prompt_notify_response(ui_view* view, prompt_data* promptData, bool response) {
static void prompt_notify_response(ui_view* view, prompt_data* promptData, u32 response) {
ui_pop();
if(promptData->onResponse != NULL) {
@ -30,47 +34,28 @@ static void prompt_notify_response(ui_view* view, prompt_data* promptData, bool
static void prompt_update(ui_view* view, void* data, float bx1, float by1, float bx2, float by2) {
prompt_data* promptData = (prompt_data*) data;
if(!promptData->option && (hidKeysDown() & ~KEY_TOUCH)) {
prompt_notify_response(view, promptData, false);
return;
}
if(promptData->option && (hidKeysDown() & (KEY_A | KEY_B))) {
prompt_notify_response(view, promptData, (bool) (hidKeysDown() & KEY_A));
return;
u32 down = hidKeysDown();
for(u32 i = 0; i < promptData->numOptions; i++) {
if(down & (promptData->optionButtons[i] & ~KEY_TOUCH)) {
prompt_notify_response(view, promptData, i);
return;
}
}
if(hidKeysDown() & KEY_TOUCH) {
touchPosition pos;
hidTouchRead(&pos);
if(promptData->option) {
u32 buttonWidth;
u32 buttonHeight;
screen_get_texture_size(&buttonWidth, &buttonHeight, TEXTURE_BUTTON_SMALL);
float buttonWidth = (bx2 - bx1 - (10 * (promptData->numOptions + 1))) / promptData->numOptions;
u32 buttonHeight;
screen_get_texture_size(NULL, &buttonHeight, TEXTURE_BUTTON);
float yesButtonX = bx1 + (bx2 - bx1) / 2 - 5 - buttonWidth;
float yesButtonY = by2 - 5 - buttonHeight;
if(pos.px >= yesButtonX && pos.py >= yesButtonY && pos.px < yesButtonX + buttonWidth && pos.py < yesButtonY + buttonHeight) {
prompt_notify_response(view, promptData, true);
return;
}
for(u32 i = 0; i < promptData->numOptions; i++) {
float buttonX = bx1 + 10 + (buttonWidth + 10) * i;
float buttonY = by2 - 5 - buttonHeight;
float noButtonX = bx1 + (bx2 - bx1) / 2 + 5;
float noButtonY = by2 - 5 - buttonHeight;
if(pos.px >= noButtonX && pos.py >= noButtonY && pos.px < noButtonX + buttonWidth && pos.py < noButtonY + buttonHeight) {
prompt_notify_response(view, promptData, false);
return;
}
} else {
u32 buttonWidth;
u32 buttonHeight;
screen_get_texture_size(&buttonWidth, &buttonHeight, TEXTURE_BUTTON_LARGE);
float okayButtonX = bx1 + (bx2 - bx1 - buttonWidth) / 2;
float okayButtonY = by2 - 5 - buttonHeight;
if(pos.px >= okayButtonX && pos.py >= okayButtonY && pos.px < okayButtonX + buttonWidth && pos.py < okayButtonY + buttonHeight) {
prompt_notify_response(view, promptData, false);
if(pos.px >= buttonX && pos.py >= buttonY && pos.px < buttonX + buttonWidth && pos.py < buttonY + buttonHeight) {
prompt_notify_response(view, promptData, i);
return;
}
}
@ -85,47 +70,80 @@ static void prompt_draw_top(ui_view* view, void* data, float x1, float y1, float
}
}
static const char* button_strings[32] = {
"A",
"B",
"Select",
"Start",
"D-Pad Right",
"D-Pad Left",
"D-Pad Up",
"D-Pad Down",
"R",
"L",
"X",
"Y",
"",
"",
"ZL",
"ZR",
"",
"",
"",
"",
"",
"",
"",
"",
"C-Stick Right",
"C-Stick Left",
"C-Stick Up",
"C-Stick Down",
"Circle Pad Right",
"Circle Pad Left",
"Circle Pad Up",
"Circle Pad Down"
};
static void prompt_button_to_string(char* out, size_t size, u32 button) {
if(button == PROMPT_BUTTON_ANY) {
snprintf(out, size, "Any Button");
return;
}
size_t pos = 0;
for(u8 bit = 0; bit < 32 && pos < size; bit++) {
if(button & (1 << bit)) {
if(pos > 0) {
pos += snprintf(out + pos, size - pos, "/");
}
pos += snprintf(out + pos, size - pos, button_strings[bit]);
}
}
}
static void prompt_draw_bottom(ui_view* view, void* data, float x1, float y1, float x2, float y2) {
prompt_data* promptData = (prompt_data*) data;
u32 buttonWidth;
float buttonWidth = (x2 - x1 - (10 * (promptData->numOptions + 1))) / promptData->numOptions;
u32 buttonHeight;
if(promptData->option) {
screen_get_texture_size(&buttonWidth, &buttonHeight, TEXTURE_BUTTON_SMALL);
screen_get_texture_size(NULL, &buttonHeight, TEXTURE_BUTTON);
float yesButtonX = x1 + (x2 - x1) / 2 - 5 - buttonWidth;
float yesButtonY = y2 - 5 - buttonHeight;
screen_draw_texture(TEXTURE_BUTTON_SMALL, yesButtonX, yesButtonY, buttonWidth, buttonHeight);
char button[64];
char text[PROMPT_OPTION_TEXT_MAX + 65];
for(u32 i = 0; i < promptData->numOptions; i++) {
float buttonX = x1 + 10 + (buttonWidth + 10) * i;
float buttonY = y2 - 5 - buttonHeight;
screen_draw_texture(TEXTURE_BUTTON, buttonX, buttonY, buttonWidth, buttonHeight);
float noButtonX = x1 + (x2 - x1) / 2 + 5;
float noButtonY = y2 - 5 - buttonHeight;
screen_draw_texture(TEXTURE_BUTTON_SMALL, noButtonX, noButtonY, buttonWidth, buttonHeight);
prompt_button_to_string(button, 64, promptData->optionButtons[i]);
snprintf(text, sizeof(text), "%s\n(%s)", promptData->options[i], button);
static const char* yes = "Yes (A)";
static const char* no = "No (B)";
float yesWidth;
float yesHeight;
screen_get_string_size(&yesWidth, &yesHeight, yes, 0.5f, 0.5f);
screen_draw_string(yes, yesButtonX + (buttonWidth - yesWidth) / 2, yesButtonY + (buttonHeight - yesHeight) / 2, 0.5f, 0.5f, promptData->color, true);
float noWidth;
float noHeight;
screen_get_string_size(&noWidth, &noHeight, no, 0.5f, 0.5f);
screen_draw_string(no, noButtonX + (buttonWidth - noWidth) / 2, noButtonY + (buttonHeight - noHeight) / 2, 0.5f, 0.5f, promptData->color, true);
} else {
screen_get_texture_size(&buttonWidth, &buttonHeight, TEXTURE_BUTTON_LARGE);
float okayButtonX = x1 + (x2 - x1 - buttonWidth) / 2;
float okayButtonY = y2 - 5 - buttonHeight;
screen_draw_texture(TEXTURE_BUTTON_LARGE, okayButtonX, okayButtonY, buttonWidth, buttonHeight);
static const char* okay = "Okay (Any Button)";
float okayWidth;
float okayHeight;
screen_get_string_size(&okayWidth, &okayHeight, okay, 0.5f, 0.5f);
screen_draw_string(okay, okayButtonX + (buttonWidth - okayWidth) / 2, okayButtonY + (buttonHeight - okayHeight) / 2, 0.5f, 0.5f, promptData->color, true);
float textWidth;
float textHeight;
screen_get_string_size(&textWidth, &textHeight, text, 0.5f, 0.5f);
screen_draw_string(text, buttonX + (buttonWidth - textWidth) / 2, buttonY + (buttonHeight - textHeight) / 2, 0.5f, 0.5f, promptData->color, true);
}
float textWidth;
@ -134,8 +152,8 @@ static void prompt_draw_bottom(ui_view* view, void* data, float x1, float y1, fl
screen_draw_string(promptData->text, x1 + (x2 - x1 - textWidth) / 2, y1 + (y2 - 5 - buttonHeight - y1 - textHeight) / 2, 0.5f, 0.5f, promptData->color, true);
}
ui_view* prompt_display(const char* name, const char* text, u32 color, bool option, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2),
void (*onResponse)(ui_view* view, void* data, bool response)) {
ui_view* prompt_display_multi_choice(const char* name, const char* text, u32 color, const char** options, u32* optionButtons, u32 numOptions, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2),
void (*onResponse)(ui_view* view, void* data, u32 response)) {
prompt_data* promptData = (prompt_data*) calloc(1, sizeof(prompt_data));
if(promptData == NULL) {
error_display(NULL, NULL, "Failed to allocate prompt data.");
@ -145,7 +163,13 @@ ui_view* prompt_display(const char* name, const char* text, u32 color, bool opti
promptData->text = text;
promptData->color = color;
promptData->option = option;
for(u32 i = 0; i < numOptions && i < PROMPT_OPTIONS_MAX; i++) {
strncpy(promptData->options[i], options[i], PROMPT_OPTION_TEXT_MAX);
promptData->optionButtons[i] = optionButtons[i];
}
promptData->numOptions = numOptions;
promptData->data = data;
promptData->drawTop = drawTop;
promptData->onResponse = onResponse;
@ -160,4 +184,18 @@ ui_view* prompt_display(const char* name, const char* text, u32 color, bool opti
ui_push(view);
return view;
}
ui_view* prompt_display_notify(const char* name, const char* text, u32 color, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2),
void (*onResponse)(ui_view* view, void* data, u32 response)) {
static const char* options[1] = {"OK"};
static u32 optionButtons[1] = {PROMPT_BUTTON_ANY};
return prompt_display_multi_choice(name, text, color, options, optionButtons, 1, data, drawTop, onResponse);
}
ui_view* prompt_display_yes_no(const char* name, const char* text, u32 color, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2),
void (*onResponse)(ui_view* view, void* data, u32 response)) {
static const char* options[2] = {"Yes", "No"};
static u32 optionButtons[2] = {KEY_A, KEY_B};
return prompt_display_multi_choice(name, text, color, options, optionButtons, 2, data, drawTop, onResponse);
}

View File

@ -2,5 +2,19 @@
typedef struct ui_view_s ui_view;
ui_view* prompt_display(const char* name, const char* text, u32 color, bool option, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2),
void (*onResponse)(ui_view* view, void* data, bool response));
#define PROMPT_OPTIONS_MAX 4
#define PROMPT_OPTION_TEXT_MAX 64
#define PROMPT_BUTTON_ANY 0xFFFFFFFF
#define PROMPT_OK 0
#define PROMPT_YES 0
#define PROMPT_NO 1
ui_view* prompt_display_multi_choice(const char* name, const char* text, u32 color, const char** options, u32* optionButtons, u32 numOptions, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2),
void (*onResponse)(ui_view* view, void* data, u32 response));
ui_view* prompt_display_notify(const char* name, const char* text, u32 color, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2),
void (*onResponse)(ui_view* view, void* data, u32 response));
ui_view* prompt_display_yes_no(const char* name, const char* text, u32 color, void* data, void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2),
void (*onResponse)(ui_view* view, void* data, u32 response));

View File

@ -38,7 +38,7 @@ void action_delete_all_pending_titles(linked_list* items, list_item* selected);
void action_delete_ticket(linked_list* items, list_item* selected);
void action_delete_tickets_unused(linked_list* items, list_item* selected);
void action_install_cdn(linked_list* items, list_item* selected);
void action_install_cdn_noprompt(volatile bool* done, ticket_info* info, bool finishedPrompt);
void action_install_cdn_noprompt(volatile bool* done, ticket_info* info, bool finishedPrompt, bool promptVersion);
void action_delete_title(linked_list* items, list_item* selected);
void action_delete_title_ticket(linked_list* items, list_item* selected);
@ -53,7 +53,7 @@ void action_import_secure_value(linked_list* items, list_item* selected);
void action_export_secure_value(linked_list* items, list_item* selected);
void action_delete_secure_value(linked_list* items, list_item* selected);
void action_url_install(const char* confirmMessage, const char* urls, void* userData, void (*finished)(void* data),
void action_install_url(const char* confirmMessage, const char* urls, void* userData, void (*finished)(void* data),
void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index));
void action_install_titledb(linked_list* items, list_item* selected);

View File

@ -87,7 +87,7 @@ static bool action_delete_error(void* data, u32 index, Result res) {
delete_data* deleteData = (delete_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Delete cancelled.", COLOR_TEXT, NULL, NULL, NULL);
return false;
} else {
ui_view* view = error_display_res(data, action_delete_draw_top, res, "Failed to delete content.");
@ -122,7 +122,7 @@ static void action_delete_update(ui_view* view, void* data, float* progress, cha
info_destroy(view);
if(R_SUCCEEDED(deleteData->deleteInfo.result)) {
prompt_display("Success", "Deleted.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Deleted.", COLOR_TEXT, NULL, NULL, NULL);
}
action_delete_free_data(deleteData);
@ -138,10 +138,10 @@ static void action_delete_update(ui_view* view, void* data, float* progress, cha
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->deleteInfo.processed, deleteData->deleteInfo.total);
}
static void action_delete_onresponse(ui_view* view, void* data, bool response) {
static void action_delete_onresponse(ui_view* view, void* data, u32 response) {
delete_data* deleteData = (delete_data*) data;
if(response) {
if(response == PROMPT_YES) {
Result res = task_data_op(&deleteData->deleteInfo);
if(R_SUCCEEDED(res)) {
info_display("Deleting", "Press B to cancel.", true, data, action_delete_update, action_delete_draw_top);
@ -178,7 +178,7 @@ static void action_delete_loading_update(ui_view* view, void* data, float* progr
loadingData->deleteData->deleteInfo.total = linked_list_size(&loadingData->deleteData->contents);
loadingData->deleteData->deleteInfo.processed = loadingData->deleteData->deleteInfo.total;
prompt_display("Confirmation", loadingData->message, COLOR_TEXT, true, loadingData->deleteData, action_delete_draw_top, action_delete_onresponse);
prompt_display_yes_no("Confirmation", loadingData->message, COLOR_TEXT, loadingData->deleteData, action_delete_draw_top, action_delete_onresponse);
} else {
error_display_res(NULL, NULL, loadingData->popData.result, "Failed to populate content list.");

View File

@ -37,14 +37,14 @@ static void action_delete_ext_save_data_update(ui_view* view, void* data, float*
linked_list_remove(deleteData->items, deleteData->selected);
task_free_ext_save_data(deleteData->selected);
prompt_display("Success", "Ext save data deleted.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Ext save data deleted.", COLOR_TEXT, NULL, NULL, NULL);
}
free(data);
}
static void action_delete_ext_save_data_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_delete_ext_save_data_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Deleting Ext Save Data", "", false, data, action_delete_ext_save_data_update, action_delete_ext_save_data_draw_top);
} else {
free(data);
@ -62,5 +62,5 @@ void action_delete_ext_save_data(linked_list* items, list_item* selected) {
data->items = items;
data->selected = selected;
prompt_display("Confirmation", "Delete the selected ext save data?", COLOR_TEXT, true, data, action_delete_ext_save_data_draw_top, action_delete_ext_save_data_onresponse);
prompt_display_notify("Confirmation", "Delete the selected ext save data?", COLOR_TEXT, data, action_delete_ext_save_data_draw_top, action_delete_ext_save_data_onresponse);
}

View File

@ -71,7 +71,7 @@ static bool action_delete_pending_titles_error(void* data, u32 index, Result res
delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Delete cancelled.", COLOR_TEXT, NULL, NULL, NULL);
return false;
} else {
ui_view* view = error_display_res(data, action_delete_pending_titles_draw_top, res, "Failed to delete pending title.");
@ -100,7 +100,7 @@ static void action_delete_pending_titles_update(ui_view* view, void* data, float
info_destroy(view);
if(R_SUCCEEDED(deleteData->deleteInfo.result)) {
prompt_display("Success", "Pending title(s) deleted.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Pending title(s) deleted.", COLOR_TEXT, NULL, NULL, NULL);
}
action_delete_pending_titles_free_data(deleteData);
@ -116,10 +116,10 @@ static void action_delete_pending_titles_update(ui_view* view, void* data, float
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->deleteInfo.processed, deleteData->deleteInfo.total);
}
static void action_delete_pending_titles_onresponse(ui_view* view, void* data, bool response) {
static void action_delete_pending_titles_onresponse(ui_view* view, void* data, u32 response) {
delete_pending_titles_data* deleteData = (delete_pending_titles_data*) data;
if(response) {
if(response == PROMPT_YES) {
Result res = task_data_op(&deleteData->deleteInfo);
if(R_SUCCEEDED(res)) {
info_display("Deleting Pending Title(s)", "Press B to cancel.", true, data, action_delete_pending_titles_update, action_delete_pending_titles_draw_top);
@ -156,7 +156,7 @@ static void action_delete_pending_titles_loading_update(ui_view* view, void* dat
loadingData->deleteData->deleteInfo.total = linked_list_size(&loadingData->deleteData->contents);
loadingData->deleteData->deleteInfo.processed = loadingData->deleteData->deleteInfo.total;
prompt_display("Confirmation", loadingData->message, COLOR_TEXT, true, loadingData->deleteData, action_delete_pending_titles_draw_top, action_delete_pending_titles_onresponse);
prompt_display_yes_no("Confirmation", loadingData->message, COLOR_TEXT, loadingData->deleteData, action_delete_pending_titles_draw_top, action_delete_pending_titles_onresponse);
} else {
error_display_res(NULL, NULL, loadingData->popData.result, "Failed to populate pending title list.");
@ -232,7 +232,7 @@ void action_delete_pending_titles(linked_list* items, list_item* selected, const
data->deleteInfo.total = 1;
data->deleteInfo.processed = data->deleteInfo.total;
prompt_display("Confirmation", message, COLOR_TEXT, true, data, action_delete_pending_titles_draw_top, action_delete_pending_titles_onresponse);
prompt_display_yes_no("Confirmation", message, COLOR_TEXT, data, action_delete_pending_titles_draw_top, action_delete_pending_titles_onresponse);
}
}

View File

@ -25,16 +25,16 @@ static void action_delete_secure_value_update(ui_view* view, void* data, float*
if(R_FAILED(res)) {
error_display_res(info, ui_draw_title_info, res, "Failed to delete secure value.");
} else {
prompt_display("Success", "Secure value deleted.", COLOR_TEXT, false, info, ui_draw_title_info, NULL);
prompt_display_notify("Success", "Secure value deleted.", COLOR_TEXT, info, ui_draw_title_info, NULL);
}
}
static void action_delete_secure_value_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_delete_secure_value_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Deleting Secure Value", "", false, data, action_delete_secure_value_update, ui_draw_title_info);
}
}
void action_delete_secure_value(linked_list* items, list_item* selected) {
prompt_display("Confirmation", "Delete the secure value of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_delete_secure_value_onresponse);
prompt_display_yes_no("Confirmation", "Delete the secure value of the selected title?", COLOR_TEXT, selected->data, ui_draw_title_info, action_delete_secure_value_onresponse);
}

View File

@ -38,14 +38,14 @@ static void action_delete_system_save_data_update(ui_view* view, void* data, flo
linked_list_remove(deleteData->items, deleteData->selected);
task_free_system_save_data(deleteData->selected);
prompt_display("Success", "System save data deleted.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "System save data deleted.", COLOR_TEXT, NULL, NULL, NULL);
}
free(data);
}
static void action_delete_system_save_data_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_delete_system_save_data_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Deleting System Save Data", "", false, data, action_delete_system_save_data_update, action_delete_system_save_data_draw_top);
} else {
free(data);
@ -63,5 +63,5 @@ void action_delete_system_save_data(linked_list* items, list_item* selected) {
data->items = items;
data->selected = selected;
prompt_display("Confirmation", "Delete the selected system save data?", COLOR_TEXT, true, data, action_delete_system_save_data_draw_top, action_delete_system_save_data_onresponse);
prompt_display_yes_no("Confirmation", "Delete the selected system save data?", COLOR_TEXT, data, action_delete_system_save_data_draw_top, action_delete_system_save_data_onresponse);
}

View File

@ -67,7 +67,7 @@ static bool action_delete_tickets_error(void* data, u32 index, Result res) {
delete_tickets_data* deleteData = (delete_tickets_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Delete cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Delete cancelled.", COLOR_TEXT, NULL, NULL, NULL);
return false;
} else {
ui_view* view = error_display_res(data, action_delete_tickets_draw_top, res, "Failed to delete ticket(s).");
@ -96,7 +96,7 @@ static void action_delete_tickets_update(ui_view* view, void* data, float* progr
info_destroy(view);
if(R_SUCCEEDED(deleteData->deleteInfo.result)) {
prompt_display("Success", "Ticket(s) deleted.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Ticket(s) deleted.", COLOR_TEXT, NULL, NULL, NULL);
}
action_delete_tickets_free_data(deleteData);
@ -112,10 +112,10 @@ static void action_delete_tickets_update(ui_view* view, void* data, float* progr
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu", deleteData->deleteInfo.processed, deleteData->deleteInfo.total);
}
static void action_delete_tickets_onresponse(ui_view* view, void* data, bool response) {
static void action_delete_tickets_onresponse(ui_view* view, void* data, u32 response) {
delete_tickets_data* deleteData = (delete_tickets_data*) data;
if(response) {
if(response == PROMPT_YES) {
Result res = task_data_op(&deleteData->deleteInfo);
if(R_SUCCEEDED(res)) {
info_display("Deleting", "Press B to cancel.", true, data, action_delete_tickets_update, action_delete_tickets_draw_top);
@ -164,7 +164,7 @@ static void action_delete_tickets_loading_update(ui_view* view, void* data, floa
loadingData->deleteData->deleteInfo.total = linked_list_size(&loadingData->deleteData->contents);
loadingData->deleteData->deleteInfo.processed = loadingData->deleteData->deleteInfo.total;
prompt_display("Confirmation", loadingData->message, COLOR_TEXT, true, loadingData->deleteData, action_delete_tickets_draw_top, action_delete_tickets_onresponse);
prompt_display_yes_no("Confirmation", loadingData->message, COLOR_TEXT, loadingData->deleteData, action_delete_tickets_draw_top, action_delete_tickets_onresponse);
} else {
error_display_res(NULL, NULL, loadingData->popData.result, "Failed to populate ticket list.");
@ -238,7 +238,7 @@ static void action_delete_tickets_internal(linked_list* items, list_item* select
data->deleteInfo.total = 1;
data->deleteInfo.processed = data->deleteInfo.total;
prompt_display("Confirmation", message, COLOR_TEXT, true, data, action_delete_tickets_draw_top, action_delete_tickets_onresponse);
prompt_display_yes_no("Confirmation", message, COLOR_TEXT, data, action_delete_tickets_draw_top, action_delete_tickets_onresponse);
}
}

View File

@ -42,14 +42,14 @@ static void action_delete_title_update(ui_view* view, void* data, float* progres
linked_list_remove(deleteData->items, deleteData->selected);
task_free_title(deleteData->selected);
prompt_display("Success", "Title deleted.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Title deleted.", COLOR_TEXT, NULL, NULL, NULL);
}
free(data);
}
static void action_delete_title_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_delete_title_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Deleting Title", "", false, data, action_delete_title_update, action_delete_title_draw_top);
} else {
free(data);
@ -68,7 +68,7 @@ static void action_delete_title_internal(linked_list* items, list_item* selected
data->selected = selected;
data->ticket = ticket;
prompt_display("Confirmation", message, COLOR_TEXT, true, data, action_delete_title_draw_top, action_delete_title_onresponse);
prompt_display_yes_no("Confirmation", message, COLOR_TEXT, data, action_delete_title_draw_top, action_delete_title_onresponse);
}
void action_delete_title(linked_list* items, list_item* selected) {

View File

@ -93,7 +93,7 @@ static bool action_erase_twl_save_error(void* data, u32 index, Result res) {
erase_twl_save_data* eraseData = (erase_twl_save_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Erase cancelled.", COLOR_TEXT, false, eraseData->title, ui_draw_title_info, NULL);
prompt_display_notify("Failure", "Erase cancelled.", COLOR_TEXT, eraseData->title, ui_draw_title_info, NULL);
} else {
error_display_res(eraseData->title, ui_draw_title_info, res, "Failed to erase save.");
}
@ -109,7 +109,7 @@ static void action_erase_twl_save_update(ui_view* view, void* data, float* progr
info_destroy(view);
if(R_SUCCEEDED(eraseData->eraseInfo.result)) {
prompt_display("Success", "Save erased.", COLOR_TEXT, false, eraseData->title, ui_draw_title_info, NULL);
prompt_display_notify("Success", "Save erased.", COLOR_TEXT, eraseData->title, ui_draw_title_info, NULL);
}
free(data);
@ -125,8 +125,8 @@ static void action_erase_twl_save_update(ui_view* view, void* data, float* progr
snprintf(text, PROGRESS_TEXT_MAX, "%.2f %s / %.2f %s\n%.2f %s/s", util_get_display_size(eraseData->eraseInfo.currProcessed), util_get_display_size_units(eraseData->eraseInfo.currProcessed), util_get_display_size(eraseData->eraseInfo.currTotal), util_get_display_size_units(eraseData->eraseInfo.currTotal), util_get_display_size(eraseData->eraseInfo.copyBytesPerSecond), util_get_display_size_units(eraseData->eraseInfo.copyBytesPerSecond));
}
static void action_erase_twl_save_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_erase_twl_save_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
erase_twl_save_data* eraseData = (erase_twl_save_data*) data;
Result res = task_data_op(&eraseData->eraseInfo);
@ -182,5 +182,5 @@ void action_erase_twl_save(linked_list* items, list_item* selected) {
data->eraseInfo.finished = true;
prompt_display("Confirmation", "Erase the save of the selected title?", COLOR_TEXT, true, data, action_erase_twl_save_draw_top, action_erase_twl_save_onresponse);
prompt_display_yes_no("Confirmation", "Erase the save of the selected title?", COLOR_TEXT, data, action_erase_twl_save_draw_top, action_erase_twl_save_onresponse);
}

View File

@ -25,7 +25,7 @@ static void action_export_secure_value_update(ui_view* view, void* data, float*
ui_pop();
info_destroy(view);
prompt_display("Failure", "Secure value not set.", COLOR_TEXT, false, info, ui_draw_title_info, NULL);
prompt_display_notify("Failure", "Secure value not set.", COLOR_TEXT, info, ui_draw_title_info, NULL);
return;
}
@ -59,18 +59,18 @@ static void action_export_secure_value_update(ui_view* view, void* data, float*
info_destroy(view);
if(R_SUCCEEDED(res)) {
prompt_display("Success", "Secure value exported.", COLOR_TEXT, false, info, ui_draw_title_info, NULL);
prompt_display_notify("Success", "Secure value exported.", COLOR_TEXT, info, ui_draw_title_info, NULL);
} else {
error_display_res(info, ui_draw_title_info, res, "Failed to export secure value.");
}
}
static void action_export_secure_value_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_export_secure_value_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Exporting Secure Value", "", false, data, action_export_secure_value_update, ui_draw_title_info);
}
}
void action_export_secure_value(linked_list* items, list_item* selected) {
prompt_display("Confirmation", "Export the secure value of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_export_secure_value_onresponse);
prompt_display_yes_no("Confirmation", "Export the secure value of the selected title?", COLOR_TEXT, selected->data, ui_draw_title_info, action_export_secure_value_onresponse);
}

View File

@ -115,7 +115,7 @@ static bool action_export_twl_save_error(void* data, u32 index, Result res) {
export_twl_save_data* exportData = (export_twl_save_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Export cancelled.", COLOR_TEXT, false, exportData->title, ui_draw_title_info, NULL);
prompt_display_notify("Failure", "Export cancelled.", COLOR_TEXT, exportData->title, ui_draw_title_info, NULL);
} else {
error_display_res(exportData->title, ui_draw_title_info, res, "Failed to export save.");
}
@ -131,7 +131,7 @@ static void action_export_twl_save_update(ui_view* view, void* data, float* prog
info_destroy(view);
if(R_SUCCEEDED(exportData->exportInfo.result)) {
prompt_display("Success", "Save exported.", COLOR_TEXT, false, exportData->title, ui_draw_title_info, NULL);
prompt_display_notify("Success", "Save exported.", COLOR_TEXT, exportData->title, ui_draw_title_info, NULL);
}
free(data);
@ -147,8 +147,8 @@ static void action_export_twl_save_update(ui_view* view, void* data, float* prog
snprintf(text, PROGRESS_TEXT_MAX, "%.2f %s / %.2f %s\n%.2f %s/s", util_get_display_size(exportData->exportInfo.currProcessed), util_get_display_size_units(exportData->exportInfo.currProcessed), util_get_display_size(exportData->exportInfo.currTotal), util_get_display_size_units(exportData->exportInfo.currTotal), util_get_display_size(exportData->exportInfo.copyBytesPerSecond), util_get_display_size_units(exportData->exportInfo.copyBytesPerSecond));
}
static void action_export_twl_save_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_export_twl_save_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
export_twl_save_data* exportData = (export_twl_save_data*) data;
Result res = task_data_op(&exportData->exportInfo);
@ -204,5 +204,5 @@ void action_export_twl_save(linked_list* items, list_item* selected) {
data->exportInfo.finished = true;
prompt_display("Confirmation", "Export the save of the selected title?", COLOR_TEXT, true, data, action_export_twl_save_draw_top, action_export_twl_save_onresponse);
prompt_display_yes_no("Confirmation", "Export the save of the selected title?", COLOR_TEXT, data, action_export_twl_save_draw_top, action_export_twl_save_onresponse);
}

View File

@ -65,18 +65,18 @@ static void action_extract_smdh_update(ui_view* view, void* data, float* progres
info_destroy(view);
if(R_SUCCEEDED(res)) {
prompt_display("Success", "SMDH extracted.", COLOR_TEXT, false, info, ui_draw_title_info, NULL);
prompt_display_notify("Success", "SMDH extracted.", COLOR_TEXT, info, ui_draw_title_info, NULL);
} else {
error_display_res(info, ui_draw_title_info, res, "Failed to extract SMDH.");
}
}
static void action_extract_smdh_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_extract_smdh_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Extracting SMDH", "", false, data, action_extract_smdh_update, ui_draw_title_info);
}
}
void action_extract_smdh(linked_list* items, list_item* selected) {
prompt_display("Confirmation", "Extract the SMDH of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_extract_smdh_onresponse);
prompt_display_yes_no("Confirmation", "Extract the SMDH of the selected title?", COLOR_TEXT, selected->data, ui_draw_title_info, action_extract_smdh_onresponse);
}

View File

@ -43,18 +43,18 @@ static void action_import_secure_value_update(ui_view* view, void* data, float*
info_destroy(view);
if(R_SUCCEEDED(res)) {
prompt_display("Success", "Secure value imported.", COLOR_TEXT, false, info, ui_draw_title_info, NULL);
prompt_display_notify("Success", "Secure value imported.", COLOR_TEXT, info, ui_draw_title_info, NULL);
} else {
error_display_res(info, ui_draw_title_info, res, "Failed to import secure value.");
}
}
static void action_import_secure_value_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_import_secure_value_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Importing Secure Value", "", false, data, action_import_secure_value_update, ui_draw_title_info);
}
}
void action_import_secure_value(linked_list* items, list_item* selected) {
prompt_display("Confirmation", "Import the secure value of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_import_secure_value_onresponse);
prompt_display_yes_no("Confirmation", "Import the secure value of the selected title?", COLOR_TEXT, selected->data, ui_draw_title_info, action_import_secure_value_onresponse);
}

View File

@ -23,7 +23,7 @@ static void action_import_seed_update(ui_view* view, void* data, float* progress
info_destroy(view);
if(R_SUCCEEDED(res)) {
prompt_display("Success", "Seed imported.", COLOR_TEXT, false, info, ui_draw_title_info, NULL);
prompt_display_notify("Success", "Seed imported.", COLOR_TEXT, info, ui_draw_title_info, NULL);
} else if(res == R_FBI_HTTP_RESPONSE_CODE) {
error_display(NULL, NULL, "Failed to import seed.\nHTTP server returned response code %d", responseCode);
} else {
@ -31,12 +31,12 @@ static void action_import_seed_update(ui_view* view, void* data, float* progress
}
}
static void action_import_seed_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_import_seed_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Importing Seed", "", false, data, action_import_seed_update, ui_draw_title_info);
}
}
void action_import_seed(linked_list* items, list_item* selected) {
prompt_display("Confirmation", "Import the seed of the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_import_seed_onresponse);
prompt_display_yes_no("Confirmation", "Import the seed of the selected title?", COLOR_TEXT, selected->data, ui_draw_title_info, action_import_seed_onresponse);
}

View File

@ -101,7 +101,7 @@ static bool action_import_twl_save_error(void* data, u32 index, Result res) {
import_twl_save_data* importData = (import_twl_save_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Import cancelled.", COLOR_TEXT, false, importData->title, ui_draw_title_info, NULL);
prompt_display_notify("Failure", "Import cancelled.", COLOR_TEXT, importData->title, ui_draw_title_info, NULL);
} else {
error_display_res(importData->title, ui_draw_title_info, res, "Failed to import save.");
}
@ -117,7 +117,7 @@ static void action_import_twl_save_update(ui_view* view, void* data, float* prog
info_destroy(view);
if(R_SUCCEEDED(importData->importInfo.result)) {
prompt_display("Success", "Save imported.", COLOR_TEXT, false, importData->title, ui_draw_title_info, NULL);
prompt_display_notify("Success", "Save imported.", COLOR_TEXT, importData->title, ui_draw_title_info, NULL);
}
free(data);
@ -133,8 +133,8 @@ static void action_import_twl_save_update(ui_view* view, void* data, float* prog
snprintf(text, PROGRESS_TEXT_MAX, "%.2f %s / %.2f %s\n%.2f %s/s", util_get_display_size(importData->importInfo.currProcessed), util_get_display_size_units(importData->importInfo.currProcessed), util_get_display_size(importData->importInfo.currTotal), util_get_display_size_units(importData->importInfo.currTotal), util_get_display_size(importData->importInfo.copyBytesPerSecond), util_get_display_size_units(importData->importInfo.copyBytesPerSecond));
}
static void action_import_twl_save_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_import_twl_save_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
import_twl_save_data* importData = (import_twl_save_data*) data;
Result res = task_data_op(&importData->importInfo);
@ -190,5 +190,5 @@ void action_import_twl_save(linked_list* items, list_item* selected) {
data->importInfo.finished = true;
prompt_display("Confirmation", "Import the save of the selected title?", COLOR_TEXT, true, data, action_import_twl_save_draw_top, action_import_twl_save_onresponse);
prompt_display_yes_no("Confirmation", "Import the save of the selected title?", COLOR_TEXT, data, action_import_twl_save_draw_top, action_import_twl_save_onresponse);
}

View File

@ -8,6 +8,7 @@
#include "../task/task.h"
#include "../../error.h"
#include "../../info.h"
#include "../../kbd.h"
#include "../../list.h"
#include "../../prompt.h"
#include "../../ui.h"
@ -175,7 +176,7 @@ bool action_install_cdn_error(void* data, u32 index, Result res) {
install_cdn_data* installData = (install_cdn_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, installData->ticket, ui_draw_ticket_info, NULL);
prompt_display_notify("Failure", "Install cancelled.", COLOR_TEXT, installData->ticket, ui_draw_ticket_info, NULL);
} else if(res == R_FBI_HTTP_RESPONSE_CODE) {
error_display(installData->ticket, ui_draw_ticket_info, "Failed to install CDN title.\nHTTP server returned response code %d", installData->responseCode);
} else {
@ -219,7 +220,7 @@ static void action_install_cdn_update(ui_view* view, void* data, float* progress
if(R_SUCCEEDED(installData->installInfo.result) && R_SUCCEEDED(res)) {
if(installData->finishedPrompt) {
prompt_display("Success", "Install finished.", COLOR_TEXT, false, installData->ticket, ui_draw_ticket_info, NULL);
prompt_display_notify("Success", "Install finished.", COLOR_TEXT, installData->ticket, ui_draw_ticket_info, NULL);
}
} else {
AM_InstallTitleAbort();
@ -242,38 +243,55 @@ static void action_install_cdn_update(ui_view* view, void* data, float* progress
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu\n%.2f %s / %.2f %s\n%.2f %s/s", installData->installInfo.processed, installData->installInfo.total, util_get_display_size(installData->installInfo.currProcessed), util_get_display_size_units(installData->installInfo.currProcessed), util_get_display_size(installData->installInfo.currTotal), util_get_display_size_units(installData->installInfo.currTotal), util_get_display_size(installData->installInfo.copyBytesPerSecond), util_get_display_size_units(installData->installInfo.copyBytesPerSecond));
}
static void action_install_cdn_start(install_cdn_data* data) {
FS_MediaType dest = util_get_title_destination(data->ticket->titleId);
static void action_install_cdn_n3ds_onresponse(ui_view* view, void* data, u32 response) {
install_cdn_data* installData = (install_cdn_data*) data;
AM_DeleteTitle(dest, data->ticket->titleId);
if(dest == MEDIATYPE_SD) {
AM_QueryAvailableExternalTitleDatabase(NULL);
}
if(response == PROMPT_YES) {
FS_MediaType dest = util_get_title_destination(installData->ticket->titleId);
Result res = 0;
if(R_SUCCEEDED(res = AM_InstallTitleBegin(dest, data->ticket->titleId, false))) {
if(R_SUCCEEDED(res = task_data_op(&data->installInfo))) {
info_display("Installing CDN Title", "Press B to cancel.", true, data, action_install_cdn_update, action_install_cdn_draw_top);
} else {
AM_InstallTitleAbort();
AM_DeleteTitle(dest, installData->ticket->titleId);
if(dest == MEDIATYPE_SD) {
AM_QueryAvailableExternalTitleDatabase(NULL);
}
}
if(R_FAILED(res)) {
error_display_res(data->ticket, ui_draw_ticket_info, res, "Failed to initiate CDN title installation.");
Result res = 0;
action_install_cdn_free_data(data);
if(R_SUCCEEDED(res = AM_InstallTitleBegin(dest, installData->ticket->titleId, false))) {
if(R_SUCCEEDED(res = task_data_op(&installData->installInfo))) {
info_display("Installing CDN Title", "Press B to cancel.", true, data, action_install_cdn_update, action_install_cdn_draw_top);
} else {
AM_InstallTitleAbort();
}
}
if(R_FAILED(res)) {
error_display_res(installData->ticket, ui_draw_ticket_info, res, "Failed to initiate CDN title installation.");
action_install_cdn_free_data(data);
}
} else {
action_install_cdn_free_data(installData);
}
}
static void action_install_cdn_n3ds_onresponse(ui_view* view, void* data, bool response) {
if(response) {
action_install_cdn_start((install_cdn_data*) data);
static void action_install_cdn_version_onresponse(ui_view* view, void* data, SwkbdButton button, const char* response) {
install_cdn_data* installData = (install_cdn_data*) data;
if(button == SWKBD_BUTTON_CONFIRM) {
strncpy(installData->tmdVersion, response, sizeof(installData->tmdVersion));
bool n3ds = false;
if(R_SUCCEEDED(APT_CheckNew3DS(&n3ds)) && !n3ds && ((installData->ticket->titleId >> 28) & 0xF) == 2) {
prompt_display_yes_no("Confirmation", "Title is intended for New 3DS systems.\nContinue?", COLOR_TEXT, data, action_install_cdn_draw_top, action_install_cdn_n3ds_onresponse);
} else {
action_install_cdn_n3ds_onresponse(NULL, data, PROMPT_YES);
}
} else {
action_install_cdn_free_data(installData);
}
}
static void action_install_cdn_internal(volatile bool* done, ticket_info* info, bool finishedPrompt, char* tmdVersion) {
void action_install_cdn_noprompt(volatile bool* done, ticket_info* info, bool finishedPrompt, bool promptVersion) {
install_cdn_data* data = (install_cdn_data*) calloc(1, sizeof(install_cdn_data));
if(data == NULL) {
error_display(NULL, NULL, "Failed to allocate install CDN data.");
@ -286,9 +304,6 @@ static void action_install_cdn_internal(volatile bool* done, ticket_info* info,
data->finishedPrompt = finishedPrompt;
memset(data->tmdVersion, '\0', sizeof(data->tmdVersion));
if(tmdVersion != NULL) {
strncpy(data->tmdVersion, tmdVersion, sizeof(data->tmdVersion));
}
data->contentCount = 0;
memset(data->contentIndices, 0, sizeof(data->contentIndices));
@ -327,31 +342,25 @@ static void action_install_cdn_internal(volatile bool* done, ticket_info* info,
data->installInfo.finished = true;
bool n3ds = false;
if(R_SUCCEEDED(APT_CheckNew3DS(&n3ds)) && !n3ds && ((data->ticket->titleId >> 28) & 0xF) == 2) {
prompt_display("Confirmation", "Title is intended for New 3DS systems.\nContinue?", COLOR_TEXT, true, data, action_install_cdn_draw_top, action_install_cdn_n3ds_onresponse);
if(promptVersion) {
kbd_display("Enter version (empty for default)", "", SWKBD_TYPE_NUMPAD, 0, SWKBD_ANYTHING, sizeof(data->tmdVersion), data, action_install_cdn_version_onresponse);
} else {
action_install_cdn_start(data);
action_install_cdn_version_onresponse(NULL, data, SWKBD_BUTTON_CONFIRM, "");
}
}
void action_install_cdn_noprompt(volatile bool* done, ticket_info* info, bool finishedPrompt) {
action_install_cdn_internal(done, info, finishedPrompt, NULL);
}
#define CDN_PROMPT_DEFAULT_VERSION 0
#define CDN_PROMPT_SELECT_VERSION 1
#define CDN_PROMPT_NO 2
static void action_install_cdn_onresponse(ui_view* view, void* data, bool response) {
if(response) {
SwkbdState swkbd;
swkbdInit(&swkbd, SWKBD_TYPE_NUMPAD, 1, -1);
swkbdSetHintText(&swkbd, "Enter version (empty for default)");
char textBuf[16];
swkbdInputText(&swkbd, textBuf, sizeof(textBuf));
action_install_cdn_internal(NULL, (ticket_info*) data, true, textBuf);
static void action_install_cdn_onresponse(ui_view* view, void* data, u32 response) {
if(response != CDN_PROMPT_NO) {
action_install_cdn_noprompt(NULL, (ticket_info*) data, true, response == CDN_PROMPT_SELECT_VERSION);
}
}
void action_install_cdn(linked_list* items, list_item* selected) {
prompt_display("Confirmation", "Install the selected title from the CDN?", COLOR_TEXT, true, selected->data, ui_draw_ticket_info, action_install_cdn_onresponse);
static const char* options[3] = {"Default\nVersion", "Select\nVersion", "No"};
static u32 optionButtons[3] = {KEY_A, KEY_X, KEY_B};
prompt_display_multi_choice("Confirmation", "Install the selected title from the CDN?", COLOR_TEXT, options, optionButtons, 3, selected->data, ui_draw_ticket_info, action_install_cdn_onresponse);
}

View File

@ -30,8 +30,8 @@ typedef struct {
data_op_data installInfo;
} install_cias_data;
static void action_install_cias_n3ds_onresponse(ui_view* view, void* data, bool response) {
((install_cias_data*) data)->n3dsContinue = response;
static void action_install_cias_n3ds_onresponse(ui_view* view, void* data, u32 response) {
((install_cias_data*) data)->n3dsContinue = response == PROMPT_YES;
}
static void action_install_cias_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) {
@ -126,7 +126,7 @@ static Result action_install_cias_open_dst(void* data, u32 index, void* initialR
bool n3ds = false;
if(R_SUCCEEDED(APT_CheckNew3DS(&n3ds)) && !n3ds && ((info->ciaInfo.titleId >> 28) & 0xF) == 2) {
ui_view* view = prompt_display("Confirmation", "Title is intended for New 3DS systems.\nContinue?", COLOR_TEXT, true, data, action_install_cias_draw_top, action_install_cias_n3ds_onresponse);
ui_view* view = prompt_display_yes_no("Confirmation", "Title is intended for New 3DS systems.\nContinue?", COLOR_TEXT, data, action_install_cias_draw_top, action_install_cias_n3ds_onresponse);
if(view != NULL) {
svcWaitSynchronization(view->active, U64_MAX);
}
@ -197,7 +197,7 @@ bool action_install_cias_error(void* data, u32 index, Result res) {
install_cias_data* installData = (install_cias_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Install cancelled.", COLOR_TEXT, NULL, NULL, NULL);
return false;
} else if(res != R_FBI_WRONG_SYSTEM) {
ui_view* view = error_display_res(data, action_install_cias_draw_top, res, "Failed to install CIA file.");
@ -234,7 +234,7 @@ static void action_install_cias_update(ui_view* view, void* data, float* progres
info_destroy(view);
if(R_SUCCEEDED(installData->installInfo.result)) {
prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Install finished.", COLOR_TEXT, NULL, NULL, NULL);
}
action_install_cias_free_data(installData);
@ -250,10 +250,10 @@ static void action_install_cias_update(ui_view* view, void* data, float* progres
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu\n%.2f %s / %.2f %s\n%.2f %s/s", installData->installInfo.processed, installData->installInfo.total, util_get_display_size(installData->installInfo.currProcessed), util_get_display_size_units(installData->installInfo.currProcessed), util_get_display_size(installData->installInfo.currTotal), util_get_display_size_units(installData->installInfo.currTotal), util_get_display_size(installData->installInfo.copyBytesPerSecond), util_get_display_size_units(installData->installInfo.copyBytesPerSecond));
}
static void action_install_cias_onresponse(ui_view* view, void* data, bool response) {
static void action_install_cias_onresponse(ui_view* view, void* data, u32 response) {
install_cias_data* installData = (install_cias_data*) data;
if(response) {
if(response == PROMPT_YES) {
Result res = task_data_op(&installData->installInfo);
if(R_SUCCEEDED(res)) {
info_display("Installing CIA(s)", "Press B to cancel.", true, data, action_install_cias_update, action_install_cias_draw_top);
@ -290,7 +290,7 @@ static void action_install_cias_loading_update(ui_view* view, void* data, float*
loadingData->installData->installInfo.total = linked_list_size(&loadingData->installData->contents);
loadingData->installData->installInfo.processed = loadingData->installData->installInfo.total;
prompt_display("Confirmation", loadingData->message, COLOR_TEXT, true, loadingData->installData, action_install_cias_draw_top, action_install_cias_onresponse);
prompt_display_yes_no("Confirmation", loadingData->message, COLOR_TEXT, loadingData->installData, action_install_cias_draw_top, action_install_cias_onresponse);
} else {
error_display_res(NULL, NULL, loadingData->popData.result, "Failed to populate CIA list.");

View File

@ -25,6 +25,7 @@ typedef struct {
bool delete;
bool cdn;
bool selectCdnVersion;
data_op_data installInfo;
} install_tickets_data;
@ -122,7 +123,7 @@ static Result action_install_tickets_close_dst(void* data, u32 index, bool succe
Result res = AM_InstallTicketFinish(handle);
if(R_SUCCEEDED(res) && installData->cdn) {
volatile bool done = false;
action_install_cdn_noprompt(&done, &((file_info*) ((list_item*) linked_list_get(&installData->contents, index))->data)->ticketInfo, false);
action_install_cdn_noprompt(&done, &((file_info*) ((list_item*) linked_list_get(&installData->contents, index))->data)->ticketInfo, false, installData->selectCdnVersion);
while(!done) {
svcSleepThread(100000000);
@ -159,7 +160,7 @@ static bool action_install_tickets_error(void* data, u32 index, Result res) {
install_tickets_data* installData = (install_tickets_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Install cancelled.", COLOR_TEXT, NULL, NULL, NULL);
return false;
} else {
ui_view* view = error_display_res(data, action_install_tickets_draw_top, res, "Failed to install ticket.");
@ -196,7 +197,7 @@ static void action_install_tickets_update(ui_view* view, void* data, float* prog
info_destroy(view);
if(R_SUCCEEDED(installData->installInfo.result)) {
prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Install finished.", COLOR_TEXT, NULL, NULL, NULL);
}
action_install_tickets_free_data(installData);
@ -212,10 +213,15 @@ static void action_install_tickets_update(ui_view* view, void* data, float* prog
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu\n%.2f %s / %.2f %s\n%.2f %s/s", installData->installInfo.processed, installData->installInfo.total, util_get_display_size(installData->installInfo.currProcessed), util_get_display_size_units(installData->installInfo.currProcessed), util_get_display_size(installData->installInfo.currTotal), util_get_display_size_units(installData->installInfo.currTotal), util_get_display_size(installData->installInfo.copyBytesPerSecond), util_get_display_size_units(installData->installInfo.copyBytesPerSecond));
}
static void action_install_tickets_cdn_check_onresponse(ui_view* view, void* data, bool response) {
#define CDN_PROMPT_DEFAULT_VERSION 0
#define CDN_PROMPT_SELECT_VERSION 1
#define CDN_PROMPT_NO 2
static void action_install_tickets_cdn_check_onresponse(ui_view* view, void* data, u32 response) {
install_tickets_data* installData = (install_tickets_data*) data;
installData->cdn = response;
installData->cdn = response != CDN_PROMPT_NO;
installData->selectCdnVersion = response == CDN_PROMPT_SELECT_VERSION;
Result res = task_data_op(&installData->installInfo);
if(R_SUCCEEDED(res)) {
@ -227,9 +233,11 @@ static void action_install_tickets_cdn_check_onresponse(ui_view* view, void* dat
}
}
static void action_install_tickets_onresponse(ui_view* view, void* data, bool response) {
if(response) {
prompt_display("Optional", "Install ticket titles from CDN?", COLOR_TEXT, true, data, action_install_tickets_draw_top, action_install_tickets_cdn_check_onresponse);
static void action_install_tickets_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
static const char* options[3] = {"Default\nVersion", "Select\nVersion", "No"};
static u32 optionButtons[3] = {KEY_A, KEY_X, KEY_B};
prompt_display_multi_choice("Optional", "Install ticket titles from CDN?", COLOR_TEXT, options, optionButtons, 3, data, action_install_tickets_draw_top, action_install_tickets_cdn_check_onresponse);
} else {
action_install_tickets_free_data((install_tickets_data*) data);
}
@ -258,7 +266,7 @@ static void action_install_tickets_loading_update(ui_view* view, void* data, flo
loadingData->installData->installInfo.total = linked_list_size(&loadingData->installData->contents);
loadingData->installData->installInfo.processed = loadingData->installData->installInfo.total;
prompt_display("Confirmation", loadingData->message, COLOR_TEXT, true, loadingData->installData, action_install_tickets_draw_top, action_install_tickets_onresponse);
prompt_display_yes_no("Confirmation", loadingData->message, COLOR_TEXT, loadingData->installData, action_install_tickets_draw_top, action_install_tickets_onresponse);
} else {
error_display_res(NULL, NULL, loadingData->popData.result, "Failed to populate ticket list.");

View File

@ -13,9 +13,13 @@ static void action_install_titledb_draw_top(ui_view* view, void* data, float x1,
ui_draw_titledb_info(view, ((list_item*) data)->data, x1, y1, x2, y2);
}
static void action_update_titledb_finished(void* data) {
task_populate_titledb_update_status((list_item*) data);
}
void action_install_titledb(linked_list* items, list_item* selected) {
char url[64];
snprintf(url, INSTALL_URL_MAX, "https://3ds.titledb.com/v1/cia/%lu/download", ((titledb_info*) selected->data)->id);
action_url_install("Install the selected title from TitleDB?", url, selected, NULL, action_install_titledb_draw_top);
action_install_url("Install the selected title from TitleDB?", url, selected, action_update_titledb_finished, action_install_titledb_draw_top);
}

View File

@ -21,6 +21,7 @@ typedef struct {
void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index);
bool cdn;
bool selectCdnVersion;
bool cdnDecided;
u32 responseCode;
@ -30,9 +31,9 @@ typedef struct {
ticket_info ticketInfo;
data_op_data installInfo;
} url_install_data;
} install_url_data;
static void action_url_install_free_data(url_install_data* data) {
static void action_install_url_free_data(install_url_data* data) {
if(data->finished != NULL) {
data->finished(data->userData);
}
@ -40,36 +41,41 @@ static void action_url_install_free_data(url_install_data* data) {
free(data);
}
static void action_url_install_cdn_check_onresponse(ui_view* view, void* data, bool response) {
url_install_data* installData = (url_install_data*) data;
#define CDN_PROMPT_DEFAULT_VERSION 0
#define CDN_PROMPT_SELECT_VERSION 1
#define CDN_PROMPT_NO 2
installData->cdn = response;
static void action_install_url_cdn_check_onresponse(ui_view* view, void* data, u32 response) {
install_url_data* installData = (install_url_data*) data;
installData->cdn = response != CDN_PROMPT_NO;
installData->selectCdnVersion = response == CDN_PROMPT_SELECT_VERSION;
installData->cdnDecided = true;
}
static void action_url_install_n3ds_onresponse(ui_view* view, void* data, bool response) {
((url_install_data*) data)->n3dsContinue = response;
static void action_install_url_n3ds_onresponse(ui_view* view, void* data, u32 response) {
((install_url_data*) data)->n3dsContinue = response == PROMPT_YES;
}
static void action_url_install_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) {
url_install_data* installData = (url_install_data*) data;
static void action_install_url_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2) {
install_url_data* installData = (install_url_data*) data;
if(installData->drawTop != NULL) {
installData->drawTop(view, installData->userData, x1, y1, x2, y2, installData->installInfo.processed);
}
}
static Result action_url_install_is_src_directory(void* data, u32 index, bool* isDirectory) {
static Result action_install_url_is_src_directory(void* data, u32 index, bool* isDirectory) {
*isDirectory = false;
return 0;
}
static Result action_url_install_make_dst_directory(void* data, u32 index) {
static Result action_install_url_make_dst_directory(void* data, u32 index) {
return 0;
}
static Result action_url_install_open_src(void* data, u32 index, u32* handle) {
url_install_data* installData = (url_install_data*) data;
static Result action_install_url_open_src(void* data, u32 index, u32* handle) {
install_url_data* installData = (install_url_data*) data;
Result res = 0;
@ -87,11 +93,11 @@ static Result action_url_install_open_src(void* data, u32 index, u32* handle) {
return res;
}
static Result action_url_install_close_src(void* data, u32 index, bool succeeded, u32 handle) {
static Result action_install_url_close_src(void* data, u32 index, bool succeeded, u32 handle) {
return util_http_close((httpcContext*) handle);
}
static Result action_url_install_get_src_size(void* data, u32 handle, u64* size) {
static Result action_install_url_get_src_size(void* data, u32 handle, u64* size) {
u32 downloadSize = 0;
Result res = util_http_get_size((httpcContext*) handle, &downloadSize);
@ -99,12 +105,12 @@ static Result action_url_install_get_src_size(void* data, u32 handle, u64* size)
return res;
}
static Result action_url_install_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) {
static Result action_install_url_read_src(void* data, u32 handle, u32* bytesRead, void* buffer, u64 offset, u32 size) {
return util_http_read((httpcContext*) handle, bytesRead, buffer, size);
}
static Result action_url_install_open_dst(void* data, u32 index, void* initialReadBlock, u64 size, u32* handle) {
url_install_data* installData = (url_install_data*) data;
static Result action_install_url_open_dst(void* data, u32 index, void* initialReadBlock, u64 size, u32* handle) {
install_url_data* installData = (install_url_data*) data;
Result res = 0;
@ -116,7 +122,9 @@ static Result action_url_install_open_dst(void* data, u32 index, void* initialRe
if(*(u16*) initialReadBlock == 0x0100) {
if(!installData->cdnDecided) {
ui_view* view = prompt_display("Optional", "Install ticket titles from CDN?", COLOR_TEXT, true, data, action_url_install_draw_top, action_url_install_cdn_check_onresponse);
static const char* options[3] = {"Default\nVersion", "Select\nVersion", "No"};
static u32 optionButtons[3] = {KEY_A, KEY_X, KEY_B};
ui_view* view = prompt_display_multi_choice("Optional", "Install ticket titles from CDN?", COLOR_TEXT, options, optionButtons, 3, data, action_install_url_draw_top, action_install_url_cdn_check_onresponse);
if(view != NULL) {
svcWaitSynchronization(view->active, U64_MAX);
}
@ -135,7 +143,7 @@ static Result action_url_install_open_dst(void* data, u32 index, void* initialRe
bool n3ds = false;
if(R_SUCCEEDED(APT_CheckNew3DS(&n3ds)) && !n3ds && ((titleId >> 28) & 0xF) == 2) {
ui_view* view = prompt_display("Confirmation", "Title is intended for New 3DS systems.\nContinue?", COLOR_TEXT, true, data, action_url_install_draw_top, action_url_install_n3ds_onresponse);
ui_view* view = prompt_display_yes_no("Confirmation", "Title is intended for New 3DS systems.\nContinue?", COLOR_TEXT, data, action_install_url_draw_top, action_install_url_n3ds_onresponse);
if(view != NULL) {
svcWaitSynchronization(view->active, U64_MAX);
}
@ -168,8 +176,8 @@ static Result action_url_install_open_dst(void* data, u32 index, void* initialRe
return res;
}
static Result action_url_install_close_dst(void* data, u32 index, bool succeeded, u32 handle) {
url_install_data* installData = (url_install_data*) data;
static Result action_install_url_close_dst(void* data, u32 index, bool succeeded, u32 handle) {
install_url_data* installData = (install_url_data*) data;
if(succeeded) {
Result res = 0;
@ -179,7 +187,7 @@ static Result action_url_install_close_dst(void* data, u32 index, bool succeeded
if(R_SUCCEEDED(res) && installData->cdn) {
volatile bool done = false;
action_install_cdn_noprompt(&done, &installData->ticketInfo, false);
action_install_cdn_noprompt(&done, &installData->ticketInfo, false, installData->selectCdnVersion);
while(!done) {
svcSleepThread(100000000);
@ -205,31 +213,31 @@ static Result action_url_install_close_dst(void* data, u32 index, bool succeeded
}
}
static Result action_url_install_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) {
static Result action_install_url_write_dst(void* data, u32 handle, u32* bytesWritten, void* buffer, u64 offset, u32 size) {
return FSFILE_Write(handle, bytesWritten, offset, buffer, size, 0);
}
static Result action_url_install_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) {
static Result action_install_url_suspend_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) {
return 0;
}
static Result action_url_install_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) {
static Result action_install_url_restore_copy(void* data, u32 index, u32* srcHandle, u32* dstHandle) {
return 0;
}
static Result action_url_install_suspend(void* data, u32 index) {
static Result action_install_url_suspend(void* data, u32 index) {
return 0;
}
static Result action_url_install_restore(void* data, u32 index) {
static Result action_install_url_restore(void* data, u32 index) {
return 0;
}
static bool action_url_install_error(void* data, u32 index, Result res) {
url_install_data* installData = (url_install_data*) data;
static bool action_install_url_error(void* data, u32 index, Result res) {
install_url_data* installData = (install_url_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Install cancelled.", COLOR_TEXT, NULL, NULL, NULL);
return false;
} else if(res != R_FBI_WRONG_SYSTEM) {
char* url = installData->urls[index];
@ -238,15 +246,15 @@ static bool action_url_install_error(void* data, u32 index, Result res) {
if(res == R_FBI_HTTP_RESPONSE_CODE) {
if(strlen(url) > 38) {
view = error_display(data, action_url_install_draw_top, "Failed to install from URL.\n%.35s...\nHTTP server returned response code %d", url, installData->responseCode);
view = error_display(data, action_install_url_draw_top, "Failed to install from URL.\n%.35s...\nHTTP server returned response code %d", url, installData->responseCode);
} else {
view = error_display(data, action_url_install_draw_top, "Failed to install from URL.\n%.38s\nHTTP server returned response code %d", url, installData->responseCode);
view = error_display(data, action_install_url_draw_top, "Failed to install from URL.\n%.38s\nHTTP server returned response code %d", url, installData->responseCode);
}
} else {
if(strlen(url) > 38) {
view = error_display_res(data, action_url_install_draw_top, res, "Failed to install from URL.\n%.35s...", url);
view = error_display_res(data, action_install_url_draw_top, res, "Failed to install from URL.\n%.35s...", url);
} else {
view = error_display_res(data, action_url_install_draw_top, res, "Failed to install from URL.\n%.38s", url);
view = error_display_res(data, action_install_url_draw_top, res, "Failed to install from URL.\n%.38s", url);
}
}
@ -258,18 +266,18 @@ static bool action_url_install_error(void* data, u32 index, Result res) {
return index < installData->installInfo.total - 1;
}
static void action_url_install_install_update(ui_view* view, void* data, float* progress, char* text) {
url_install_data* installData = (url_install_data*) data;
static void action_install_url_install_update(ui_view* view, void* data, float* progress, char* text) {
install_url_data* installData = (install_url_data*) data;
if(installData->installInfo.finished) {
ui_pop();
info_destroy(view);
if(R_SUCCEEDED(installData->installInfo.result)) {
prompt_display("Success", "Install finished.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Install finished.", COLOR_TEXT, NULL, NULL, NULL);
}
action_url_install_free_data(installData);
action_install_url_free_data(installData);
return;
}
@ -282,26 +290,26 @@ static void action_url_install_install_update(ui_view* view, void* data, float*
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu\n%.2f %s / %.2f %s\n%.2f %s/s", installData->installInfo.processed, installData->installInfo.total, util_get_display_size(installData->installInfo.currProcessed), util_get_display_size_units(installData->installInfo.currProcessed), util_get_display_size(installData->installInfo.currTotal), util_get_display_size_units(installData->installInfo.currTotal), util_get_display_size(installData->installInfo.copyBytesPerSecond), util_get_display_size_units(installData->installInfo.copyBytesPerSecond));
}
static void action_url_install_confirm_onresponse(ui_view* view, void* data, bool response) {
url_install_data* installData = (url_install_data*) data;
static void action_install_url_confirm_onresponse(ui_view* view, void* data, u32 response) {
install_url_data* installData = (install_url_data*) data;
if(response) {
if(response == PROMPT_YES) {
Result res = task_data_op(&installData->installInfo);
if(R_SUCCEEDED(res)) {
info_display("Installing From URL(s)", "Press B to cancel.", true, data, action_url_install_install_update, action_url_install_draw_top);
info_display("Installing From URL(s)", "Press B to cancel.", true, data, action_install_url_install_update, action_install_url_draw_top);
} else {
error_display_res(NULL, NULL, res, "Failed to initiate installation.");
action_url_install_free_data(installData);
action_install_url_free_data(installData);
}
} else {
action_url_install_free_data(installData);
action_install_url_free_data(installData);
}
}
void action_url_install(const char* confirmMessage, const char* urls, void* userData, void (*finished)(void* data),
void action_install_url(const char* confirmMessage, const char* urls, void* userData, void (*finished)(void* data),
void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index)) {
url_install_data* data = (url_install_data*) calloc(1, sizeof(url_install_data));
install_url_data* data = (install_url_data*) calloc(1, sizeof(install_url_data));
if(data == NULL) {
error_display(NULL, NULL, "Failed to allocate URL install data.");
@ -346,6 +354,7 @@ void action_url_install(const char* confirmMessage, const char* urls, void* user
data->drawTop = drawTop;
data->cdn = false;
data->selectCdnVersion = false;
data->cdnDecided = false;
data->responseCode = 0;
@ -361,27 +370,27 @@ void action_url_install(const char* confirmMessage, const char* urls, void* user
data->installInfo.copyBufferSize = 128 * 1024;
data->installInfo.copyEmpty = false;
data->installInfo.isSrcDirectory = action_url_install_is_src_directory;
data->installInfo.makeDstDirectory = action_url_install_make_dst_directory;
data->installInfo.isSrcDirectory = action_install_url_is_src_directory;
data->installInfo.makeDstDirectory = action_install_url_make_dst_directory;
data->installInfo.openSrc = action_url_install_open_src;
data->installInfo.closeSrc = action_url_install_close_src;
data->installInfo.getSrcSize = action_url_install_get_src_size;
data->installInfo.readSrc = action_url_install_read_src;
data->installInfo.openSrc = action_install_url_open_src;
data->installInfo.closeSrc = action_install_url_close_src;
data->installInfo.getSrcSize = action_install_url_get_src_size;
data->installInfo.readSrc = action_install_url_read_src;
data->installInfo.openDst = action_url_install_open_dst;
data->installInfo.closeDst = action_url_install_close_dst;
data->installInfo.writeDst = action_url_install_write_dst;
data->installInfo.openDst = action_install_url_open_dst;
data->installInfo.closeDst = action_install_url_close_dst;
data->installInfo.writeDst = action_install_url_write_dst;
data->installInfo.suspendCopy = action_url_install_suspend_copy;
data->installInfo.restoreCopy = action_url_install_restore_copy;
data->installInfo.suspendCopy = action_install_url_suspend_copy;
data->installInfo.restoreCopy = action_install_url_restore_copy;
data->installInfo.suspend = action_url_install_suspend;
data->installInfo.restore = action_url_install_restore;
data->installInfo.suspend = action_install_url_suspend;
data->installInfo.restore = action_install_url_restore;
data->installInfo.error = action_url_install_error;
data->installInfo.error = action_install_url_error;
data->installInfo.finished = true;
prompt_display("Confirmation", confirmMessage, COLOR_TEXT, true, data, action_url_install_draw_top, action_url_install_confirm_onresponse);
prompt_display_yes_no("Confirmation", confirmMessage, COLOR_TEXT, data, action_install_url_draw_top, action_install_url_confirm_onresponse);
}

View File

@ -29,12 +29,12 @@ static void action_launch_title_update(ui_view* view, void* data, float* progres
}
}
static void action_launch_title_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void action_launch_title_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Launching Title", "", false, data, action_launch_title_update, ui_draw_title_info);
}
}
void action_launch_title(linked_list* items, list_item* selected) {
prompt_display("Confirmation", "Launch the selected title?", COLOR_TEXT, true, selected->data, ui_draw_title_info, action_launch_title_onresponse);
prompt_display_yes_no("Confirmation", "Launch the selected title?", COLOR_TEXT, selected->data, ui_draw_title_info, action_launch_title_onresponse);
}

View File

@ -1,6 +1,5 @@
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <3ds.h>
@ -8,6 +7,7 @@
#include "../task/task.h"
#include "../../error.h"
#include "../../info.h"
#include "../../kbd.h"
#include "../../list.h"
#include "../../prompt.h"
#include "../../ui.h"
@ -15,20 +15,24 @@
#include "../../../core/screen.h"
#include "../../../core/util.h"
void action_new_folder(linked_list* items, list_item* selected) {
SwkbdState swkbd;
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, -1);
swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY, 0, 0);
swkbdSetHintText(&swkbd, "Enter folder name");
typedef struct {
linked_list* items;
list_item* selected;
} new_folder_data;
char textBuf[FILE_NAME_MAX];
if(swkbdInputText(&swkbd, textBuf, sizeof(textBuf)) == SWKBD_BUTTON_CONFIRM) {
static void action_new_folder_onresponse(ui_view* view, void* data, SwkbdButton button, const char* response) {
new_folder_data* newFolderData = (new_folder_data*) data;
if(button == SWKBD_BUTTON_CONFIRM) {
Result res = 0;
file_info* parentDir = (file_info*) selected->data;
file_info* parentDir = (file_info*) newFolderData->selected->data;
char fileName[FILE_NAME_MAX] = {'\0'};
util_escape_file_name(fileName, response, sizeof(fileName));
char path[FILE_PATH_MAX] = {'\0'};
snprintf(path, FILE_PATH_MAX, "%s%s", parentDir->path, textBuf);
snprintf(path, FILE_PATH_MAX, "%s%s", parentDir->path, fileName);
FS_Path* fsPath = util_make_path_utf8(path);
if(fsPath != NULL) {
@ -42,13 +46,29 @@ void action_new_folder(linked_list* items, list_item* selected) {
if(R_SUCCEEDED(res)) {
list_item* folderItem = NULL;
if(R_SUCCEEDED(task_create_file_item(&folderItem, parentDir->archive, path, FS_ATTRIBUTE_DIRECTORY))) {
linked_list_add(items, folderItem);
linked_list_sort(items, NULL, util_compare_file_infos);
linked_list_add(newFolderData->items, folderItem);
linked_list_sort(newFolderData->items, NULL, util_compare_file_infos);
}
prompt_display("Success", "Folder created.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Folder created.", COLOR_TEXT, NULL, NULL, NULL);
} else {
error_display_res(NULL, NULL, res, "Failed to create folder.");
}
}
free(newFolderData);
}
void action_new_folder(linked_list* items, list_item* selected) {
new_folder_data* data = (new_folder_data*) calloc(1, sizeof(new_folder_data));
if(data == NULL) {
error_display(NULL, NULL, "Failed to allocate new folder data.");
return;
}
data->items = items;
data->selected = selected;
kbd_display("Enter folder name", "", SWKBD_TYPE_NORMAL, 0, SWKBD_NOTEMPTY_NOTBLANK, FILE_NAME_MAX, data, action_new_folder_onresponse);
}

View File

@ -233,7 +233,7 @@ static bool action_paste_contents_error(void* data, u32 index, Result res) {
paste_contents_data* pasteData = (paste_contents_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Paste cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Paste cancelled.", COLOR_TEXT, NULL, NULL, NULL);
return false;
} else {
ui_view* view = error_display_res(data, action_paste_contents_draw_top, res, "Failed to paste content.");
@ -270,7 +270,7 @@ static void action_paste_contents_update(ui_view* view, void* data, float* progr
info_destroy(view);
if(R_SUCCEEDED(pasteData->pasteInfo.result)) {
prompt_display("Success", "Contents pasted.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Contents pasted.", COLOR_TEXT, NULL, NULL, NULL);
}
action_paste_contents_free_data(pasteData);
@ -286,9 +286,9 @@ static void action_paste_contents_update(ui_view* view, void* data, float* progr
snprintf(text, PROGRESS_TEXT_MAX, "%lu / %lu\n%.2f %s / %.2f %s\n%.2f %s/s", pasteData->pasteInfo.processed, pasteData->pasteInfo.total, util_get_display_size(pasteData->pasteInfo.currProcessed), util_get_display_size_units(pasteData->pasteInfo.currProcessed), util_get_display_size(pasteData->pasteInfo.currTotal), util_get_display_size_units(pasteData->pasteInfo.currTotal), util_get_display_size(pasteData->pasteInfo.copyBytesPerSecond), util_get_display_size_units(pasteData->pasteInfo.copyBytesPerSecond));
}
static void action_paste_contents_onresponse(ui_view* view, void* data, bool response) {
static void action_paste_contents_onresponse(ui_view* view, void* data, u32 response) {
paste_contents_data* pasteData = (paste_contents_data*) data;
if(response) {
if(response == PROMPT_YES) {
Result res = task_data_op(&pasteData->pasteInfo);
if(R_SUCCEEDED(res)) {
info_display("Pasting Contents", "Press B to cancel.", true, data, action_paste_contents_update, action_paste_contents_draw_top);
@ -323,7 +323,7 @@ static void action_paste_contents_loading_update(ui_view* view, void* data, floa
loadingData->pasteData->pasteInfo.total = linked_list_size(&loadingData->pasteData->contents);
loadingData->pasteData->pasteInfo.processed = loadingData->pasteData->pasteInfo.total;
prompt_display("Confirmation", "Paste clipboard contents to the current directory?", COLOR_TEXT, true, loadingData->pasteData, action_paste_contents_draw_top, action_paste_contents_onresponse);
prompt_display_yes_no("Confirmation", "Paste clipboard contents to the current directory?", COLOR_TEXT, loadingData->pasteData, action_paste_contents_draw_top, action_paste_contents_onresponse);
} else {
error_display_res(NULL, NULL, loadingData->popData.result, "Failed to populate clipboard content list.");
@ -343,7 +343,7 @@ static void action_paste_contents_loading_update(ui_view* view, void* data, floa
void action_paste_contents(linked_list* items, list_item* selected) {
if(!clipboard_has_contents()) {
prompt_display("Failure", "Clipboard empty.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Clipboard empty.", COLOR_TEXT, NULL, NULL, NULL);
return;
}

View File

@ -8,6 +8,7 @@
#include "../task/task.h"
#include "../../error.h"
#include "../../info.h"
#include "../../kbd.h"
#include "../../list.h"
#include "../../prompt.h"
#include "../../ui.h"
@ -15,27 +16,31 @@
#include "../../../core/screen.h"
#include "../../../core/util.h"
void action_rename(linked_list* items, list_item* selected) {
file_info* targetInfo = (file_info*) selected->data;
typedef struct {
linked_list* items;
list_item* selected;
} rename_data;
SwkbdState swkbd;
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, -1);
swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY, 0, 0);
swkbdSetInitialText(&swkbd, targetInfo->name);
swkbdSetHintText(&swkbd, "Enter new name");
static void action_rename_onresponse(ui_view* view, void* data, SwkbdButton button, const char* response) {
rename_data* renameData = (rename_data*) data;
char textBuf[FILE_NAME_MAX];
if(swkbdInputText(&swkbd, textBuf, sizeof(textBuf)) == SWKBD_BUTTON_CONFIRM) {
if(button == SWKBD_BUTTON_CONFIRM) {
Result res = 0;
list_item* selected = renameData->selected;
file_info* targetInfo = (file_info*) selected->data;
char fileName[FILE_NAME_MAX] = {'\0'};
util_escape_file_name(fileName, response, sizeof(fileName));
char parentPath[FILE_PATH_MAX] = {'\0'};
util_get_parent_path(parentPath, targetInfo->path, FILE_PATH_MAX);
char dstPath[FILE_PATH_MAX] = {'\0'};
if(targetInfo->attributes & FS_ATTRIBUTE_DIRECTORY) {
snprintf(dstPath, FILE_PATH_MAX, "%s%s/", parentPath, textBuf);
snprintf(dstPath, FILE_PATH_MAX, "%s%s/", parentPath, fileName);
} else {
snprintf(dstPath, FILE_PATH_MAX, "%s%s", parentPath, textBuf);
snprintf(dstPath, FILE_PATH_MAX, "%s%s", parentPath, fileName);
}
FS_Path* srcFsPath = util_make_path_utf8(targetInfo->path);
@ -60,17 +65,33 @@ void action_rename(linked_list* items, list_item* selected) {
if(R_SUCCEEDED(res)) {
if(strncmp(selected->name, "<current directory>", LIST_ITEM_NAME_MAX) != 0 && strncmp(selected->name, "<current file>", LIST_ITEM_NAME_MAX) != 0) {
strncpy(selected->name, textBuf, LIST_ITEM_NAME_MAX);
strncpy(selected->name, fileName, LIST_ITEM_NAME_MAX);
}
strncpy(targetInfo->name, textBuf, FILE_NAME_MAX);
strncpy(targetInfo->name, fileName, FILE_NAME_MAX);
strncpy(targetInfo->path, dstPath, FILE_PATH_MAX);
linked_list_sort(items, NULL, util_compare_file_infos);
linked_list_sort(renameData->items, NULL, util_compare_file_infos);
prompt_display("Success", "Renamed.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Renamed.", COLOR_TEXT, NULL, NULL, NULL);
} else {
error_display_res(NULL, NULL, res, "Failed to perform rename.");
}
}
free(renameData);
}
void action_rename(linked_list* items, list_item* selected) {
rename_data* data = (rename_data*) calloc(1, sizeof(rename_data));
if(data == NULL) {
error_display(NULL, NULL, "Failed to allocate rename data.");
return;
}
data->items = items;
data->selected = selected;
kbd_display("Enter new name", ((file_info*) selected->data)->name, SWKBD_TYPE_NORMAL, 0, SWKBD_NOTEMPTY_NOTBLANK, FILE_NAME_MAX, data, action_rename_onresponse);
}

View File

@ -11,31 +11,54 @@
#include "../../../core/linkedlist.h"
static void action_update_titledb_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, u32 index) {
linked_list* items = (linked_list*) data;
linked_list* updates = (linked_list*) data;
if(index < linked_list_size(items)) {
ui_draw_titledb_info(view, ((list_item*) linked_list_get(items, index))->data, x1, y1, x2, y2);
if(index < linked_list_size(updates)) {
ui_draw_titledb_info(view, ((list_item*) linked_list_get(updates, index))->data, x1, y1, x2, y2);
}
}
static void action_update_titledb_finished(void* data) {
linked_list* updates = (linked_list*) data;
linked_list_iter iter;
linked_list_iterate(updates, &iter);
while(linked_list_iter_has_next(&iter)) {
task_populate_titledb_update_status((list_item*) linked_list_iter_next(&iter));
}
linked_list_destroy(updates);
free(updates);
}
void action_update_titledb(linked_list* items, list_item* selected) {
char* urls = (char*) calloc(1, INSTALL_URL_MAX * INSTALL_URLS_MAX);
if(urls != NULL) {
linked_list_iter iter;
linked_list_iterate(items, &iter);
linked_list* updates = (linked_list*) calloc(1, sizeof(linked_list));
if(updates != NULL) {
linked_list_init(updates);
size_t pos = 0;
while(linked_list_iter_has_next(&iter) && pos < INSTALL_URL_MAX * INSTALL_URLS_MAX) {
titledb_info* info = (titledb_info*) ((list_item*) linked_list_iter_next(&iter))->data;
linked_list_iter iter;
linked_list_iterate(items, &iter);
if(info->installed && info->installedVersion < info->latestVersion) {
pos += snprintf(urls + pos, (INSTALL_URL_MAX * INSTALL_URLS_MAX) - pos, "https://3ds.titledb.com/v1/cia/%lu/download\n", info->id);
size_t pos = 0;
while(linked_list_iter_has_next(&iter) && pos < INSTALL_URL_MAX * INSTALL_URLS_MAX) {
list_item* item = (list_item*) linked_list_iter_next(&iter);
titledb_info* info = (titledb_info*) item->data;
if(info->installed && info->installedVersion < info->latestVersion) {
linked_list_add(updates, item);
pos += snprintf(urls + pos, (INSTALL_URL_MAX * INSTALL_URLS_MAX) - pos, "https://3ds.titledb.com/v1/cia/%lu/download\n", info->id);
}
}
action_install_url("Update installed titles from TitleDB?", urls, updates, action_update_titledb_finished, action_update_titledb_draw_top);
free(urls);
} else {
error_display_res(NULL, NULL, R_FBI_OUT_OF_MEMORY, "Failed to allocate update list.");
}
action_url_install("Update installed titles from TitleDB?", urls, items, NULL, action_update_titledb_draw_top);
free(urls);
} else {
error_display_res(NULL, NULL, R_FBI_OUT_OF_MEMORY, "Failed to allocate URL text buffer.");
}

View File

@ -93,7 +93,7 @@ static Result dumpnand_restore(void* data, u32 index) {
static bool dumpnand_error(void* data, u32 index, Result res) {
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Dump cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Dump cancelled.", COLOR_TEXT, NULL, NULL, NULL);
} else {
error_display_res(NULL, NULL, res, "Failed to dump NAND.");
}
@ -109,7 +109,7 @@ static void dumpnand_update(ui_view* view, void* data, float* progress, char* te
info_destroy(view);
if(R_SUCCEEDED(dumpData->result)) {
prompt_display("Success", "NAND dumped.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "NAND dumped.", COLOR_TEXT, NULL, NULL, NULL);
}
free(dumpData);
@ -125,8 +125,8 @@ static void dumpnand_update(ui_view* view, void* data, float* progress, char* te
snprintf(text, PROGRESS_TEXT_MAX, "%.2f %s / %.2f %s\n%.2f %s/s", util_get_display_size(dumpData->currProcessed), util_get_display_size_units(dumpData->currProcessed), util_get_display_size(dumpData->currTotal), util_get_display_size_units(dumpData->currTotal), util_get_display_size(dumpData->copyBytesPerSecond), util_get_display_size_units(dumpData->copyBytesPerSecond));
}
static void dumpnand_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void dumpnand_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
data_op_data* dumpData = (data_op_data*) data;
Result res = task_data_op(dumpData);
@ -180,5 +180,5 @@ void dumpnand_open() {
data->finished = true;
prompt_display("Confirmation", "Dump raw NAND image to the SD card?", COLOR_TEXT, true, data, NULL, dumpnand_onresponse);
prompt_display_yes_no("Confirmation", "Dump raw NAND image to the SD card?", COLOR_TEXT, data, NULL, dumpnand_onresponse);
}

View File

@ -95,7 +95,7 @@ static void files_action_update(ui_view* view, void* data, linked_list* items, l
Result res = 0;
if(R_SUCCEEDED(res = clipboard_set_contents(actionData->parent->archive, info->path, selected == &copy_all_contents))) {
prompt_display("Success", selected == &copy_all_contents ? "Current directory contents copied to clipboard." : (info->attributes & FS_ATTRIBUTE_DIRECTORY) ? "Current directory copied to clipboard." : "File copied to clipboard.", COLOR_TEXT, false, info, ui_draw_file_info, NULL);
prompt_display_notify("Success", selected == &copy_all_contents ? "Current directory contents copied to clipboard." : (info->attributes & FS_ATTRIBUTE_DIRECTORY) ? "Current directory copied to clipboard." : "File copied to clipboard.", COLOR_TEXT, info, ui_draw_file_info, NULL);
} else {
error_display_res(info, ui_draw_file_info, res, "Failed to copy to clipboard.");
}
@ -420,16 +420,16 @@ void files_open(FS_ArchiveID archiveId, FS_Path archivePath) {
list_display("Files", "A: Select, B: Back, X: Refresh, Select: Options", data, files_update, files_draw_top);
}
static void files_open_nand_warning_onresponse(ui_view* view, void* data, bool response) {
static void files_open_nand_warning_onresponse(ui_view* view, void* data, u32 response) {
FS_ArchiveID archive = (FS_ArchiveID) data;
if(response) {
if(response == PROMPT_YES) {
files_open(archive, fsMakePath(PATH_EMPTY, ""));
}
}
void files_open_nand_warning(FS_ArchiveID archive) {
prompt_display("Confirmation", "Modifying the NAND is dangerous and can render\n the system inoperable.\nMake sure you know what you are doing.\n\nProceed?", COLOR_TEXT, true, (void*) archive, NULL, files_open_nand_warning_onresponse);
prompt_display_yes_no("Confirmation", "Modifying the NAND is dangerous and can render\n the system inoperable.\nMake sure you know what you are doing.\n\nProceed?", COLOR_TEXT, (void*) archive, NULL, files_open_nand_warning_onresponse);
}
void files_open_sd() {

View File

@ -13,6 +13,7 @@
#include "task/task.h"
#include "../error.h"
#include "../info.h"
#include "../kbd.h"
#include "../list.h"
#include "../prompt.h"
#include "../ui.h"
@ -174,7 +175,7 @@ static void remoteinstall_network_update(ui_view* view, void* data, float* progr
}
remoteinstall_set_last_urls(urls);
action_url_install("Install from the received URL(s)?", urls, data, remoteinstall_network_close_client, NULL);
action_install_url("Install from the received URL(s)?", urls, data, remoteinstall_network_close_client, NULL);
free(urls);
} else if(errno != EAGAIN) {
@ -196,7 +197,7 @@ static void remoteinstall_network_update(ui_view* view, void* data, float* progr
snprintf(text, PROGRESS_TEXT_MAX, "Waiting for connection...\nIP: %s\nPort: 5000", inet_ntoa(addr));
}
void remoteinstall_receive_urls_network() {
static void remoteinstall_receive_urls_network() {
remoteinstall_network_data* data = (remoteinstall_network_data*) calloc(1, sizeof(remoteinstall_network_data));
if(data == NULL) {
error_display(NULL, NULL, "Failed to allocate network install data.");
@ -365,7 +366,7 @@ static void remoteinstall_qr_update(ui_view* view, void* data, float* progress,
remoteinstall_set_last_urls((const char*) qrData.payload);
action_url_install("Install from the scanned QR code?", (const char*) qrData.payload, NULL, NULL, NULL);
action_install_url("Install from the scanned QR code?", (const char*) qrData.payload, NULL, NULL, NULL);
return;
}
}
@ -373,7 +374,7 @@ static void remoteinstall_qr_update(ui_view* view, void* data, float* progress,
snprintf(text, PROGRESS_TEXT_MAX, "Waiting for QR code...");
}
void remoteinstall_scan_qr_code() {
static void remoteinstall_scan_qr_code() {
remoteinstall_qr_data* data = (remoteinstall_qr_data*) calloc(1, sizeof(remoteinstall_qr_data));
if(data == NULL) {
error_display(NULL, NULL, "Failed to allocate QR install data.");
@ -418,34 +419,25 @@ void remoteinstall_scan_qr_code() {
info_display("QR Code Install", "B: Return", false, data, remoteinstall_qr_update, remoteinstall_qr_draw_top);
}
void remoteinstall_manually_enter_urls() {
SwkbdState swkbd;
swkbdInit(&swkbd, SWKBD_TYPE_NORMAL, 2, -1);
swkbdSetValidation(&swkbd, SWKBD_NOTEMPTY, 0, 0);
swkbdSetFeatures(&swkbd, SWKBD_MULTILINE);
swkbdSetHintText(&swkbd, "Enter URL(s)");
static void remoteinstall_manually_enter_urls_onresponse(ui_view* view, void* data, SwkbdButton button, const char* response) {
if(button == SWKBD_BUTTON_CONFIRM) {
remoteinstall_set_last_urls(response);
char* textBuf = (char*) calloc(1, INSTALL_URL_MAX * INSTALL_URLS_MAX);
if(textBuf != NULL) {
if(swkbdInputText(&swkbd, textBuf, INSTALL_URL_MAX * INSTALL_URLS_MAX) == SWKBD_BUTTON_CONFIRM) {
remoteinstall_set_last_urls(textBuf);
action_url_install("Install from the entered URL(s)?", textBuf, NULL, NULL, NULL);
}
free(textBuf);
} else {
error_display_res(NULL, NULL, R_FBI_OUT_OF_MEMORY, "Failed to allocate URL text buffer.");
action_install_url("Install from the entered URL(s)?", response, NULL, NULL, NULL);
}
}
void remoteinstall_repeat_last_request() {
static void remoteinstall_manually_enter_urls() {
kbd_display("Enter URL(s)", "", SWKBD_TYPE_NORMAL, SWKBD_MULTILINE, SWKBD_NOTEMPTY_NOTBLANK, INSTALL_URL_MAX * INSTALL_URLS_MAX, NULL, remoteinstall_manually_enter_urls_onresponse);
}
static void remoteinstall_repeat_last_request() {
char* textBuf = (char*) calloc(1, INSTALL_URL_MAX * INSTALL_URLS_MAX);
if(textBuf != NULL) {
if(remoteinstall_get_last_urls(textBuf, INSTALL_URL_MAX * INSTALL_URLS_MAX)) {
action_url_install("Install from the last requested URL(s)?", textBuf, NULL, NULL, NULL);
action_install_url("Install from the last requested URL(s)?", textBuf, NULL, NULL, NULL);
} else {
prompt_display("Failure", "No previously requested URL(s) could be found.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "No previously requested URL(s) could be found.", COLOR_TEXT, NULL, NULL, NULL);
}
free(textBuf);
@ -454,10 +446,10 @@ void remoteinstall_repeat_last_request() {
}
}
void remoteinstall_forget_last_request() {
static void remoteinstall_forget_last_request() {
Result forgetRes = remoteinstall_set_last_urls(NULL);
if(R_SUCCEEDED(forgetRes)) {
prompt_display("Success", "Last requested URL(s) forgotten.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Last requested URL(s) forgotten.", COLOR_TEXT, NULL, NULL, NULL);
} else {
error_display_res(NULL, NULL, forgetRes, "Failed to forget last requested URL(s).");
}

View File

@ -14,6 +14,24 @@
#include "../../../json/json.h"
#include "../../../stb_image/stb_image.h"
void task_populate_titledb_update_status(list_item* item) {
titledb_info* info = (titledb_info*) item->data;
AM_TitleEntry entry;
info->installed = R_SUCCEEDED(AM_GetTitleInfo(util_get_title_destination(info->titleId), 1, &info->titleId, &entry));
info->installedVersion = info->installed ? entry.version : (u16) 0;
if(info->installed) {
if(info->installedVersion < info->latestVersion) {
item->color = COLOR_TITLEDB_OUTDATED;
} else {
item->color = COLOR_TITLEDB_INSTALLED;
}
} else {
item->color = COLOR_TITLEDB_NOT_INSTALLED;
}
}
static Result task_populate_titledb_download(u32* downloadSize, void* buffer, u32 maxSize, const char* url) {
Result res = 0;
@ -92,28 +110,16 @@ static void task_populate_titledb_thread(void* arg) {
}
}
AM_TitleEntry entry;
titledbInfo->installed = R_SUCCEEDED(AM_GetTitleInfo(util_get_title_destination(titledbInfo->titleId), 1, &titledbInfo->titleId, &entry));
titledbInfo->installedVersion = titledbInfo->installed ? entry.version : (u16) 0;
if(strlen(titledbInfo->meta.shortDescription) > 0) {
strncpy(item->name, titledbInfo->meta.shortDescription, LIST_ITEM_NAME_MAX);
} else {
snprintf(item->name, LIST_ITEM_NAME_MAX, "%016llX", titledbInfo->titleId);
}
if(titledbInfo->installed) {
if(titledbInfo->installedVersion < titledbInfo->latestVersion) {
item->color = COLOR_TITLEDB_OUTDATED;
} else {
item->color = COLOR_TITLEDB_INSTALLED;
}
} else {
item->color = COLOR_TITLEDB_NOT_INSTALLED;
}
item->data = titledbInfo;
task_populate_titledb_update_status(item);
linked_list_iter iter;
linked_list_iterate(data->items, &iter);

View File

@ -255,6 +255,7 @@ void task_free_title(list_item* item);
void task_clear_titles(linked_list* items);
Result task_populate_titles(populate_titles_data* data);
void task_populate_titledb_update_status(list_item* item);
void task_free_titledb(list_item* item);
void task_clear_titledb(linked_list* items);
Result task_populate_titledb(populate_titledb_data* data);

View File

@ -120,7 +120,7 @@ static bool update_error(void* data, u32 index, Result res) {
update_data* updateData = (update_data*) data;
if(res == R_FBI_CANCELLED) {
prompt_display("Failure", "Install cancelled.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Failure", "Install cancelled.", COLOR_TEXT, NULL, NULL, NULL);
} else if(res == R_FBI_HTTP_RESPONSE_CODE) {
error_display(NULL, NULL, "Failed to update FBI.\nHTTP server returned response code %d", updateData->responseCode);
} else {
@ -138,7 +138,7 @@ static void update_install_update(ui_view* view, void* data, float* progress, ch
info_destroy(view);
if(R_SUCCEEDED(updateData->installInfo.result)) {
prompt_display("Success", "Update complete.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "Update complete.", COLOR_TEXT, NULL, NULL, NULL);
}
free(updateData);
@ -263,15 +263,15 @@ static void update_check_update(ui_view* view, void* data, float* progress, char
error_display_res(NULL, NULL, res, "Failed to check for update.");
}
} else {
prompt_display("Success", "No updates available.", COLOR_TEXT, false, NULL, NULL, NULL);
prompt_display_notify("Success", "No updates available.", COLOR_TEXT, NULL, NULL, NULL);
}
free(data);
}
}
static void update_onresponse(ui_view* view, void* data, bool response) {
if(response) {
static void update_onresponse(ui_view* view, void* data, u32 response) {
if(response == PROMPT_YES) {
info_display("Checking For Updates", "", false, data, update_check_update, NULL);
} else {
free(data);
@ -319,5 +319,5 @@ void update_open() {
data->installInfo.finished = true;
prompt_display("Confirmation", "Check for FBI updates?", COLOR_TEXT, true, data, NULL, update_onresponse);
prompt_display_yes_no("Confirmation", "Check for FBI updates?", COLOR_TEXT, data, NULL, update_onresponse);
}