Improve open file dialog API

Allows filetype description on Windows/Linux
Avoids Menus.c needing to call internal webclient interop_SaveNode function
For texture packs in webclient: Avoid saving into temp file, then reading into a copy in memory, then writing the copy into texpacks folder. Now just saves directly into texpacks folder
This commit is contained in:
UnknownShadow200 2022-10-14 22:03:51 +11:00
parent ff6f40d953
commit 5d8f9bf6da
12 changed files with 67 additions and 47 deletions

View File

@ -1572,15 +1572,11 @@ static void TexturePackScreen_LoadEntries(struct ListScreen* s) {
StringsBuffer_Sort(&s->entries);
}
extern void interop_UploadTexPack(const char* path);
static void TexturePackScreen_UploadCallback(const cc_string* path) {
#ifdef CC_BUILD_WEB
char str[NATIVE_STR_LEN];
cc_string relPath = *path;
Platform_EncodeUtf8(str, path);
Utils_UNSAFE_GetFilename(&relPath);
interop_UploadTexPack(str);
ListScreen_Reload(&ListScreen);
TexturePack_SetDefault(&relPath);
#else
@ -1590,8 +1586,15 @@ static void TexturePackScreen_UploadCallback(const cc_string* path) {
}
static void TexturePackScreen_UploadFunc(void* s, void* w) {
static const char* const filters[] = { ".zip", NULL };
Window_OpenFileDialog(filters, TexturePackScreen_UploadCallback);
static const char* const filters[] = {
".zip", NULL
};
static struct OpenFileDialogArgs args = {
"Texture packs", filters,
TexturePackScreen_UploadCallback,
OFD_UPLOAD_PERSIST, "texpacks"
};
Window_OpenFileDialog(&args);
}
void TexturePackScreen_Show(void) {
@ -1770,7 +1773,13 @@ static void LoadLevelScreen_UploadFunc(void* s, void* w) {
static const char* const filters[] = {
".cw", ".dat", ".lvl", ".mine", ".fcm", NULL
};
cc_result res = Window_OpenFileDialog(filters, LoadLevelScreen_UploadCallback);
static struct OpenFileDialogArgs args = {
"Classic map files", filters,
LoadLevelScreen_UploadCallback,
OFD_UPLOAD_DELETE, "tmp"
};
cc_result res = Window_OpenFileDialog(&args);
if (res) Logger_SimpleWarn(res, "showing open file dialog");
}

View File

@ -128,9 +128,20 @@ void Window_ProcessEvents(void);
void Cursor_SetPosition(int x, int y);
/* Shows a dialog box window. */
CC_API void Window_ShowDialog(const char* title, const char* msg);
#define OFD_UPLOAD_DELETE 0 /* (webclient) Deletes the uploaded file after invoking callback function */
#define OFD_UPLOAD_PERSIST 1 /* (webclient) Saves the uploded file into IndexedDB */
typedef void (*OpenFileDialogCallback)(const cc_string* path);
/* Shows an 'load file' dialog window. */
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback);
struct OpenFileDialogArgs {
const char* description; /* Describes the types of files supported (e.g. "Texture packs") */
const char* const* filters;
OpenFileDialogCallback Callback;
int uploadAction; /* Action webclient takes after invoking callback function */
const char* uploadFolder; /* For webclient, folder to upload the file to */
};
/* Shows an 'load file' dialog window */
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args);
/* Allocates a framebuffer that can be drawn/transferred to the window. */
/* NOTE: Do NOT free bmp->Scan0, use Window_FreeFramebuffer. */

View File

@ -359,7 +359,7 @@ static void ShowDialogCore(const char* title, const char* msg) {
(*env)->DeleteLocalRef(env, args[1].l);
}
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}

View File

@ -591,7 +591,7 @@ static void ShowDialogCore(const char* title, const char* msg) {
showingDialog = false;
}
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}

View File

@ -526,7 +526,7 @@ static void CallOpenFileCallback(const char* rawPath) {
open_callback = NULL;
}
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
if (!open_panel) {
open_panel = new BFilePanel(B_OPEN_PANEL);
open_panel->SetRefFilter(new CC_BRefFilter());
@ -534,8 +534,8 @@ cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallba
// so this is technically a memory leak.. but meh
}
open_callback = callback;
open_filters = filters;
open_callback = args->Callback;
open_filters = args->filters;
open_panel->Show();
return 0;
}

View File

@ -277,7 +277,7 @@ static void ShowDialogCore(const char* title, const char* msg) {
SDL_ShowSimpleMessageBox(0, title, msg, win_handle);
}
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
return ERR_NOT_SUPPORTED;
}

View File

@ -544,24 +544,24 @@ EMSCRIPTEN_KEEPALIVE void Window_OnFileUploaded(const char* src) {
uploadCallback = NULL;
}
extern void interop_OpenFileDialog(const char* filter);
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_string path; char pathBuffer[NATIVE_STR_LEN];
char filter[NATIVE_STR_LEN];
extern void interop_OpenFileDialog(const char* filter, int action, const char* folder);
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
const char* const* filters = args->filters;
cc_string filter; char filterBuffer[1024];
int i;
/* Filter tokens are , separated - e.g. ".cw,.dat */
String_InitArray(path, pathBuffer);
String_InitArray_NT(filter, filterBuffer);
for (i = 0; filters[i]; i++)
{
if (i) String_Append(&path, ',');
String_AppendConst(&path, filters[i]);
if (i) String_Append(&filter, ',');
String_AppendConst(&filter, filters[i]);
}
Platform_EncodeUtf8(filter, &path);
filter.buffer[filter.length] = '\0';
uploadCallback = callback;
uploadCallback = args->Callback;
/* Calls Window_OnFileUploaded on success */
interop_OpenFileDialog(filter);
interop_OpenFileDialog(filter.buffer, args->uploadAction, args->uploadFolder);
return 0;
}

View File

@ -551,7 +551,8 @@ static void ShowDialogCore(const char* title, const char* msg) {
MessageBoxA(win_handle, msg, title, 0);
}
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
const char* const* filters = args->filters;
cc_string path; char pathBuffer[NATIVE_STR_LEN];
WCHAR str[MAX_PATH] = { 0 };
OPENFILENAMEW ofn = { 0 };
@ -560,7 +561,7 @@ cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallba
/* Filter tokens are \0 separated - e.g. "Maps (*.cw;*.dat)\0*.cw;*.dat\0 */
String_InitArray(path, pathBuffer);
String_AppendConst(&path, "All supported files (");
String_Format1(&path, "%c (", args->description);
for (i = 0; filters[i]; i++)
{
if (i) String_Append(&path, ';');
@ -592,7 +593,7 @@ cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallba
for (i = 0; i < MAX_PATH && str[i]; i++) {
String_Append(&path, Convert_CodepointToCP437(str[i]));
}
callback(&path);
args->Callback(&path);
return 0;
}

View File

@ -967,14 +967,15 @@ static void ShowDialogCore(const char* title, const char* msg) {
XFlush(m.dpy); /* flush so window disappears immediately */
}
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
const char* const* filters = args->filters;
cc_string path; char pathBuffer[1024];
char result[4096] = { 0 };
int len, i;
FILE* fp;
String_InitArray_NT(path, pathBuffer);
String_AppendConst(&path, "zenity --file-selection --file-filter='All supported files (");
String_Format1(&path, "zenity --file-selection --file-filter='%c (", args->description);
for (i = 0; filters[i]; i++)
{
@ -1001,7 +1002,7 @@ cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallba
if (len) {
String_InitArray(path, pathBuffer);
String_AppendUtf8(&path, result, len);
callback(&path);
args->Callback(&path);
}
pclose(fp);
return 0;

View File

@ -515,7 +515,8 @@ void ShowDialogCore(const char* title, const char* msg) {
CFRelease(msgCF);
}
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
const char* const* filters = args->filters;
NSOpenPanel* dlg = [NSOpenPanel openPanel];
NSArray* files;
NSString* str;
@ -547,7 +548,7 @@ cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallba
cc_string path; char pathBuffer[NATIVE_STR_LEN];
String_InitArray(path, pathBuffer);
String_AppendUtf8(&path, src, len);
callback(&path);
args->Callback(&path);
return 0;
}

View File

@ -478,8 +478,8 @@ void Window_LockLandscapeOrientation(cc_bool lock) {
[UIViewController attemptRotationToDeviceOrientation];
}
cc_result Window_OpenFileDialog(const char* const* filters, OpenFileDialogCallback callback) {
NSArray<NSString*>* types = @[ @"public.png" ]; // TODO fill in
cc_result Window_OpenFileDialog(const struct OpenFileDialogArgs* args) {
NSArray<NSString*>* types = @[ @"public.png" ]; // TODO fill in with args->filters
UIDocumentPickerViewController* dlg;
dlg = [UIDocumentPickerViewController alloc];

View File

@ -107,14 +107,6 @@ mergeInto(LibraryManager.library, {
}
},
interop_DownloadMap__deps: ['interop_SaveBlob'],
interop_UploadTexPack: function(path) {
// Move from temp into texpacks folder
// TODO: This is pretty awful and should be rewritten
var name = UTF8ToString(path);
var data = CCFS.readFile(name);
CCFS.writeFile('texpacks/' + name.substring(1), data);
_interop_SaveNode('texpacks/' + name.substring(1));
},
//########################################################################################################################
@ -835,8 +827,10 @@ mergeInto(LibraryManager.library, {
window.cc_divElem = null;
window.cc_inputElem = null;
},
interop_OpenFileDialog: function(filter) {
interop_OpenFileDialog: function(filter, action, folder) {
var elem = window.cc_uploadElem;
var root = UTF8ToString(folder);
if (!elem) {
elem = document.createElement('input');
elem.setAttribute('type', 'file');
@ -852,9 +846,12 @@ mergeInto(LibraryManager.library, {
reader.onload = function(e) {
var data = new Uint8Array(e.target.result);
CCFS.writeFile('/' + name, data);
ccall('Window_OnFileUploaded', 'void', ['string'], ['/' + name]);
CCFS.unlink('/' + name);
var path = root + '/' + name;
CCFS.writeFile(path, data);
ccall('Window_OnFileUploaded', 'void', ['string'], [path]);
if (action == 0) CCFS.unlink(path); // OFD_UPLOAD_DELETE
if (action == 1) _interop_SaveNode(path); // OFD_UPLOAD_PERSIST
};
reader.readAsArrayBuffer(files[i]);
}