diff --git a/source/funkin/util/FileUtil.hx b/source/funkin/util/FileUtil.hx index c30eacba8..3494e620b 100644 --- a/source/funkin/util/FileUtil.hx +++ b/source/funkin/util/FileUtil.hx @@ -18,7 +18,7 @@ class FileUtil /** * Browses for a single file, then calls `onSelect(path)` when a path chosen. * Note that on HTML5 this will immediately fail, you should call `openFile(onOpen:Resource->Void)` instead. - * + * * @param typeFilter Filters what kinds of files can be selected. * @return Whether the file dialog was opened successfully. */ @@ -26,9 +26,9 @@ class FileUtil ?dialogTitle:String):Bool { #if desktop - var filter = convertTypeFilter(typeFilter); + var filter:String = convertTypeFilter(typeFilter); - var fileDialog = new FileDialog(); + var fileDialog:FileDialog = new FileDialog(); if (onSelect != null) fileDialog.onSelect.add(onSelect); if (onCancel != null) fileDialog.onCancel.add(onCancel); @@ -46,7 +46,7 @@ class FileUtil /** * Browses for a directory, then calls `onSelect(path)` when a path chosen. * Note that on HTML5 this will immediately fail. - * + * * @param typeFilter TODO What does this do? * @return Whether the file dialog was opened successfully. */ @@ -54,9 +54,9 @@ class FileUtil ?dialogTitle:String):Bool { #if desktop - var filter = convertTypeFilter(typeFilter); + var filter:String = convertTypeFilter(typeFilter); - var fileDialog = new FileDialog(); + var fileDialog:FileDialog = new FileDialog(); if (onSelect != null) fileDialog.onSelect.add(onSelect); if (onCancel != null) fileDialog.onCancel.add(onCancel); @@ -74,16 +74,16 @@ class FileUtil /** * Browses for multiple file, then calls `onSelect(paths)` when a path chosen. * Note that on HTML5 this will immediately fail. - * + * * @return Whether the file dialog was opened successfully. */ public static function browseForMultipleFiles(?typeFilter:Array, ?onSelect:Array->Void, ?onCancel:Void->Void, ?defaultPath:String, ?dialogTitle:String):Bool { #if desktop - var filter = convertTypeFilter(typeFilter); + var filter:String = convertTypeFilter(typeFilter); - var fileDialog = new FileDialog(); + var fileDialog:FileDialog = new FileDialog(); if (onSelect != null) fileDialog.onSelectMultiple.add(onSelect); if (onCancel != null) fileDialog.onCancel.add(onCancel); @@ -101,7 +101,7 @@ class FileUtil /** * Browses for a file location to save to, then calls `onSelect(path)` when a path chosen. * Note that on HTML5 you can't do much with this, you should call `saveFile(resource:haxe.io.Bytes)` instead. - * + * * @param typeFilter TODO What does this do? * @return Whether the file dialog was opened successfully. */ @@ -109,9 +109,9 @@ class FileUtil ?dialogTitle:String):Bool { #if desktop - var filter = convertTypeFilter(typeFilter); + var filter:String = convertTypeFilter(typeFilter); - var fileDialog = new FileDialog(); + var fileDialog:FileDialog = new FileDialog(); if (onSelect != null) fileDialog.onSelect.add(onSelect); if (onCancel != null) fileDialog.onCancel.add(onCancel); @@ -129,36 +129,36 @@ class FileUtil /** * Browses for a single file location, then reads it and passes it to `onOpen(resource:haxe.io.Bytes)`. * Works great on desktop and HTML5. - * + * * @param typeFilter TODO What does this do? * @return Whether the file dialog was opened successfully. */ public static function openFile(?typeFilter:Array, ?onOpen:Bytes->Void, ?onCancel:Void->Void, ?defaultPath:String, ?dialogTitle:String):Bool { #if desktop - var filter = convertTypeFilter(typeFilter); + var filter:String = convertTypeFilter(typeFilter); - var fileDialog = new FileDialog(); + var fileDialog:FileDialog = new FileDialog(); if (onOpen != null) fileDialog.onOpen.add(onOpen); if (onCancel != null) fileDialog.onCancel.add(onCancel); fileDialog.open(filter, defaultPath, dialogTitle); return true; #elseif html5 - var onFileLoaded = function(event) { + var onFileLoaded:Event->Void = function(event) { var loadedFileRef:FileReference = event.target; trace('Loaded file: ' + loadedFileRef.name); onOpen(loadedFileRef.data); } - var onFileSelected = function(event) { + var onFileSelected:Event->Void = function(event) { var selectedFileRef:FileReference = event.target; trace('Selected file: ' + selectedFileRef.name); selectedFileRef.addEventListener(Event.COMPLETE, onFileLoaded); selectedFileRef.load(); } - var fileRef = new FileReference(); + var fileRef:FileReference = new FileReference(); fileRef.addEventListener(Event.SELECT, onFileSelected); fileRef.browse(typeFilter); return true; @@ -171,24 +171,24 @@ class FileUtil /** * Browses for a single file location, then writes the provided `haxe.io.Bytes` data and calls `onSave(path)` when done. * Works great on desktop and HTML5. - * + * * @return Whether the file dialog was opened successfully. */ public static function saveFile(data:Bytes, ?onSave:String->Void, ?onCancel:Void->Void, ?defaultFileName:String, ?dialogTitle:String):Bool { #if desktop - var filter = defaultFileName != null ? Path.extension(defaultFileName) : null; + var filter:String = defaultFileName != null ? Path.extension(defaultFileName) : null; - var fileDialog = new FileDialog(); + var fileDialog:FileDialog = new FileDialog(); if (onSave != null) fileDialog.onSelect.add(onSave); if (onCancel != null) fileDialog.onCancel.add(onCancel); fileDialog.save(data, filter, defaultFileName, dialogTitle); return true; #elseif html5 - var filter = defaultFileName != null ? Path.extension(defaultFileName) : null; + var filter:String = defaultFileName != null ? Path.extension(defaultFileName) : null; - var fileDialog = new FileDialog(); + var fileDialog:FileDialog = new FileDialog(); if (onSave != null) fileDialog.onSave.add(onSave); if (onCancel != null) fileDialog.onCancel.add(onCancel); @@ -204,7 +204,7 @@ class FileUtil * Prompts the user to save multiple files. * On desktop, this will prompt the user for a directory, then write all of the files to there. * On HTML5, this will zip the files up and prompt the user to save that. - * + * * @param typeFilter TODO What does this do? * @return Whether the file dialog was opened successfully. */ @@ -213,7 +213,7 @@ class FileUtil { #if desktop // Prompt the user for a directory, then write all of the files to there. - var onSelectDir = function(targetPath:String) { + var onSelectDir:String->Void = function(targetPath:String):Void { var paths:Array = []; for (resource in resources) { @@ -230,7 +230,7 @@ class FileUtil writeBytesToPath(filePath, resource.data, force ? Force : Skip); } } - catch (e:Dynamic) + catch (_) { trace('Failed to write file (probably already exists): $filePath' + filePath); continue; @@ -240,7 +240,7 @@ class FileUtil onSaveAll(paths); } - browseForDirectory(null, onSelectDir, onCancel, defaultPath, "Choose directory to save all files to..."); + browseForDirectory(null, onSelectDir, onCancel, defaultPath, 'Choose directory to save all files to...'); return true; #elseif html5 @@ -260,14 +260,14 @@ class FileUtil ?force:Bool = false):Bool { // Create a ZIP file. - var zipBytes = createZIPFromEntries(resources); + var zipBytes:Bytes = createZIPFromEntries(resources); - var onSave = function(path:String) { + var onSave:String->Void = function(path:String) { onSave([path]); }; // Prompt the user to save the ZIP file. - saveFile(zipBytes, onSave, onCancel, defaultPath, "Save files as ZIP..."); + saveFile(zipBytes, onSave, onCancel, defaultPath, 'Save files as ZIP...'); return true; } @@ -282,7 +282,7 @@ class FileUtil { #if desktop // Create a ZIP file. - var zipBytes = createZIPFromEntries(resources); + var zipBytes:Bytes = createZIPFromEntries(resources); // Write the ZIP. writeBytesToPath(path, zipBytes, force ? Force : Skip); @@ -293,13 +293,70 @@ class FileUtil #end } + /** + * Read string file contents directly from a given path. + * Only works on desktop. + * + * @param path The path to the file. + * @return The file contents. + */ + public static function readStringFromPath(path:String):String + { + #if sys + return sys.io.File.getContent(path); + #else + return null; + #end + } + + /** + * Read bytes file contents directly from a given path. + * Only works on desktop. + * + * @param path The path to the file. + * @return The file contents. + */ + public static function readBytesFromPath(path:String):Bytes + { + #if sys + return Bytes.ofString(sys.io.File.getContent(path)); + #else + return null; + #end + } + + /** + * Read JSON file contents directly from a given path. + * Only works on desktop. + * + * @param path The path to the file. + * @return The JSON data. + */ + public static function readJSONFromPath(path:String):Dynamic + { + #if sys + try + { + return SerializerUtil.fromJSON(sys.io.File.getContent(path)); + } + catch (ex) + { + return null; + } + #else + return null; + #end + } + /** * Write string file contents directly to a given path. * Only works on desktop. - * + * + * @param path The path to the file. + * @param data The string to write. * @param mode Whether to Force, Skip, or Ask to overwrite an existing file. */ - public static function writeStringToPath(path:String, data:String, mode:FileWriteMode = Skip) + public static function writeStringToPath(path:String, data:String, mode:FileWriteMode = Skip):Void { #if sys createDirIfNotExists(Path.directory(path)); @@ -335,10 +392,12 @@ class FileUtil /** * Write byte file contents directly to a given path. * Only works on desktop. - * + * + * @param path The path to the file. + * @param data The bytes to write. * @param mode Whether to Force, Skip, or Ask to overwrite an existing file. */ - public static function writeBytesToPath(path:String, data:Bytes, mode:FileWriteMode = Skip) + public static function writeBytesToPath(path:String, data:Bytes, mode:FileWriteMode = Skip):Void { #if sys createDirIfNotExists(Path.directory(path)); @@ -374,8 +433,11 @@ class FileUtil /** * Write string file contents directly to the end of a file at the given path. * Only works on desktop. + * + * @param path The path to the file. + * @param data The string to append. */ - public static function appendStringToPath(path:String, data:String) + public static function appendStringToPath(path:String, data:String):Void { #if sys sys.io.File.append(path, false).writeString(data); @@ -387,8 +449,10 @@ class FileUtil /** * Create a directory if it doesn't already exist. * Only works on desktop. + * + * @param dir The path to the directory. */ - public static function createDirIfNotExists(dir:String) + public static function createDirIfNotExists(dir:String):Void { #if sys if (!sys.FileSystem.exists(dir)) @@ -404,6 +468,8 @@ class FileUtil /** * Get the path to a temporary directory we can use for writing files. * Only works on desktop. + * + * @return The path to the temporary directory. */ public static function getTempDir():String { @@ -421,9 +487,11 @@ class FileUtil if (path != null) break; } - return tempDir = Path.join([path, 'funkin/']); + tempDir = Path.join([path, 'funkin/']); + return tempDir; #else - return tempDir = '/tmp/funkin/'; + tempDir = '/tmp/funkin/'; + return tempDir; #end #else return null; @@ -432,15 +500,15 @@ class FileUtil /** * Create a Bytes object containing a ZIP file, containing the provided entries. - * + * * @param entries The entries to add to the ZIP file. * @return The ZIP file as a Bytes object. */ public static function createZIPFromEntries(entries:Array):Bytes { - var o = new haxe.io.BytesOutput(); + var o:haxe.io.BytesOutput = new haxe.io.BytesOutput(); - var zipWriter = new haxe.zip.Writer(o); + var zipWriter:haxe.zip.Writer = new haxe.zip.Writer(o); zipWriter.write(entries.list()); return o.getBytes(); @@ -448,15 +516,27 @@ class FileUtil /** * Create a ZIP file entry from a file name and its string contents. - * + * * @param name The name of the file. You can use slashes to create subdirectories. * @param content The string contents of the file. * @return The resulting entry. */ public static function makeZIPEntry(name:String, content:String):Entry { - var data = haxe.io.Bytes.ofString(content, UTF8); + var data:Bytes = haxe.io.Bytes.ofString(content, UTF8); + return makeZIPEntryFromBytes(name, data); + } + + /** + * Create a ZIP file entry from a file name and its string contents. + * + * @param name The name of the file. You can use slashes to create subdirectories. + * @param data The byte data of the file. + * @return The resulting entry. + */ + public static function makeZIPEntryFromBytes(name:String, data:haxe.io.Bytes):Entry + { return { fileName: name, fileSize: data.length, @@ -474,15 +554,15 @@ class FileUtil static function convertTypeFilter(typeFilter:Array):String { - var filter = null; + var filter:String = null; if (typeFilter != null) { - var filters = []; + var filters:Array = []; for (type in typeFilter) { - filters.push(StringTools.replace(StringTools.replace(type.extension, "*.", ""), ";", ",")); + filters.push(StringTools.replace(StringTools.replace(type.extension, '*.', ''), ';', ',')); } - filter = filters.join(";"); + filter = filters.join(';'); } return filter;