Remember open files in Electron
parent
6c1b5845eb
commit
b40af7310a
15
src/app.js
15
src/app.js
|
@ -47,6 +47,7 @@ var redos = []; //array of <canvas>
|
|||
//var frames = []; //array of {delay: N, undos: [<canvas>], redos: [<canvas>], canvas: <canvas>}? array of Frames?
|
||||
|
||||
var file_name;
|
||||
var document_file_path;
|
||||
var saved = true;
|
||||
|
||||
|
||||
|
@ -92,17 +93,19 @@ var $toolbox = $ToolBox(tools);
|
|||
// so it can display names of the tools, and maybe authors and previews (and not necessarily icons)
|
||||
var $colorbox = $ColorBox();
|
||||
|
||||
// TODO: open from file path in Electron
|
||||
// and set this via program arguments
|
||||
// if(window.document_file_path){
|
||||
// open_from_file_path(window.document_file_path);
|
||||
// }
|
||||
|
||||
reset_file();
|
||||
reset_colors();
|
||||
reset_canvas(); // (with newly reset colors)
|
||||
reset_magnification();
|
||||
|
||||
if(window.document_file_path_to_open){
|
||||
open_from_file_path(document_file_path_to_open, function(err){
|
||||
if(err){
|
||||
return show_error_message("Failed to open file " + document_file_path_to_open, err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$canvas.on("user-resized", function(e, _x, _y, width, height){
|
||||
undoable(0, function(){
|
||||
canvas.width = Math.max(1, width);
|
||||
|
|
|
@ -6,13 +6,78 @@ global.module = undefined;
|
|||
|
||||
var dialog = require("electron").remote.dialog;
|
||||
var fs = require("fs");
|
||||
var path = require("path");
|
||||
var argv = require("electron").remote.process.argv;
|
||||
|
||||
if (process.platform == "win32" && argv.length >= 2) {
|
||||
if (argv[1] === ".") { // in development, "path/to/electron.exe" "." "maybe/a/file.png" ...maybe?
|
||||
window.document_file_path_to_open = argv[2];
|
||||
} else { // in production, "path/to/JS Paint.exe" "maybe/a/file.png"
|
||||
window.document_file_path_to_open = argv[1];
|
||||
}
|
||||
}
|
||||
|
||||
window.open_from_file_path = function(file_path, callback, canceled){
|
||||
fs.readFile(file_path, function(err, buffer) {
|
||||
if(err){
|
||||
return callback(err);
|
||||
}
|
||||
var file = new File([new Uint8Array(buffer)], path.basename(file_path));
|
||||
// can't set file.path directly, but we can do this:
|
||||
Object.defineProperty(file, 'path', {
|
||||
value: file_path,
|
||||
});
|
||||
|
||||
open_from_File(file, callback, canceled);
|
||||
});
|
||||
};
|
||||
|
||||
window.save_to_file_path = function(filePath, formatName, savedCallback){
|
||||
var mimeType = {
|
||||
"JPEG": "image/jpeg",
|
||||
"PNG": "image/png",
|
||||
"GIF": "image/gif",
|
||||
"WebP": "image/webp",
|
||||
// "Monochrome Bitmap": "image/bitmap",
|
||||
// "16 Color Bitmap": "image/bitmap",
|
||||
// "256 Color Bitmap": "image/bitmap",
|
||||
// "24-bit Bitmap": "image/bitmap",
|
||||
}[formatName];
|
||||
if(!mimeType){
|
||||
return show_error_message("Can't save as " + formatName + ". Format is not supported.");
|
||||
}
|
||||
// if(mimeType === "image/gif"){
|
||||
// new GIF();
|
||||
// }
|
||||
canvas.toBlob(function(blob){
|
||||
if(blob.type !== mimeType){
|
||||
return show_error_message("Failed to save as " + formatName + " (your browser doesn't support exporting a canvas as \"" + mimeType + "\")");
|
||||
}
|
||||
sanity_check_blob(blob, function(){
|
||||
blob_to_buffer(blob, function(err, buffer){
|
||||
if(err){
|
||||
return show_error_message("Failed to save! (Technically, failed to convert a Blob to a Buffer.)", err);
|
||||
}
|
||||
fs.writeFile(filePath, buffer, function(err){
|
||||
if(err){
|
||||
return show_error_message("Failed to save file!", err);
|
||||
}
|
||||
var fileName = path.basename(filePath);
|
||||
savedCallback(filePath, fileName);
|
||||
});
|
||||
});
|
||||
});
|
||||
}, mimeType);
|
||||
};
|
||||
|
||||
// TODO: window.platform.saveCanvasAs etc. or platformIntegration or system or something
|
||||
window.systemSaveCanvasAs = function(canvas, fileName, savedCallback){
|
||||
window.systemSaveCanvasAs = function(canvas, suggestedFileName, savedCallback){
|
||||
var getExtension = function(filePathOrName){
|
||||
var splitByDots = filePathOrName.split(/\./g);
|
||||
return splitByDots[splitByDots.length - 1].toLowerCase();
|
||||
};
|
||||
var extension = getExtension(fileName);
|
||||
// TODO: default to existing extension, except it would be awkward to rearrange the list...
|
||||
// var suggestedExtension = getExtension(suggestedFileName);
|
||||
var filters = [
|
||||
// top one is considered default by electron
|
||||
{name: "PNG", extensions: ["png"]},
|
||||
|
@ -28,10 +93,9 @@ window.systemSaveCanvasAs = function(canvas, fileName, savedCallback){
|
|||
{name: "WebP", extensions: ["webp"]},
|
||||
];
|
||||
// TODO: pass BrowserWindow to make dialog modal?
|
||||
// TODO: pass defaultPath of last opened file (w/ different file name)?
|
||||
// also maybe sanitize fileName?
|
||||
// TODO: should suggestedFileName be sanitized in some way?
|
||||
dialog.showSaveDialog({
|
||||
defaultPath: fileName,
|
||||
defaultPath: suggestedFileName,
|
||||
filters: filters,
|
||||
}, function(filePath) {
|
||||
if(!filePath){
|
||||
|
@ -42,45 +106,12 @@ window.systemSaveCanvasAs = function(canvas, fileName, savedCallback){
|
|||
// TODO: Linux/Unix?? you're not supposed to need file extensions
|
||||
return show_error_message("Missing file extension - try adding .png to the file name");
|
||||
}
|
||||
var typeNameMatched = ((filters.find(function(filter){return filter.extensions.indexOf(extension) > -1})) || {}).name;
|
||||
if(!typeNameMatched){
|
||||
var formatNameMatched = ((filters.find(function(filter){return filter.extensions.indexOf(extension) > -1})) || {}).name;
|
||||
if(!formatNameMatched){
|
||||
return show_error_message("Can't save as *." +extension + " - try adding .png to the file name");
|
||||
}
|
||||
|
||||
var mimeType = {
|
||||
"JPEG": "image/jpeg",
|
||||
"PNG": "image/png",
|
||||
"GIF": "image/gif",
|
||||
"WebP": "image/webp",
|
||||
// "Monochrome Bitmap": "image/bitmap",
|
||||
// "16 Color Bitmap": "image/bitmap",
|
||||
// "256 Color Bitmap": "image/bitmap",
|
||||
// "24-bit Bitmap": "image/bitmap",
|
||||
}[typeNameMatched];
|
||||
if(!mimeType){
|
||||
return show_error_message("Can't save as " + typeNameMatched + ". Format is not supported.");
|
||||
}
|
||||
// if(mimeType === "image/gif"){
|
||||
// new GIF();
|
||||
// }
|
||||
canvas.toBlob(function(blob){
|
||||
if(blob.type !== mimeType){
|
||||
return show_error_message("Failed to save as " + typeNameMatched + " (your browser doesn't support exporting a canvas as \"" + mimeType + "\")");
|
||||
}
|
||||
sanity_check_blob(blob, function(){
|
||||
blob_to_buffer(blob, function(err, buffer){
|
||||
if(err){
|
||||
return show_error_message("Failed to save! (Technically, failed to convert a Blob to a Buffer.)", err);
|
||||
}
|
||||
fs.writeFile(filePath, buffer, function(err){
|
||||
if(err){
|
||||
return show_error_message("Failed to save file!", err);
|
||||
}
|
||||
savedCallback();
|
||||
});
|
||||
});
|
||||
});
|
||||
}, mimeType);
|
||||
save_to_file_path(filePath, formatNameMatched, savedCallback);
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ function reset_colors(){
|
|||
}
|
||||
|
||||
function reset_file(){
|
||||
// document_file_path = null;
|
||||
document_file_path = null;
|
||||
file_name = "untitled";
|
||||
update_title();
|
||||
saved = true;
|
||||
|
@ -121,6 +121,7 @@ function open_from_File(file, callback, canceled){
|
|||
|
||||
open_from_Image(img, function(){
|
||||
file_name = file.name;
|
||||
document_file_path = file.path; // available in Electron
|
||||
update_title();
|
||||
saved = true;
|
||||
callback();
|
||||
|
@ -165,7 +166,6 @@ function file_new(){
|
|||
// there's this little thing called Inversion of Control...
|
||||
// also paste_from_file_select_dialog
|
||||
function file_open(){
|
||||
// TODO: remember file as "open" in electron
|
||||
get_FileList_from_file_select_dialog(function(files){
|
||||
open_from_FileList(files, "selected");
|
||||
});
|
||||
|
@ -200,19 +200,29 @@ function file_load_from_url(){
|
|||
function file_save(){
|
||||
deselect();
|
||||
if(file_name.match(/\.svg$/)){
|
||||
//TODO: only affect suggested name in save dialog, don't change file_name
|
||||
file_name = file_name.replace(/\.svg$/, "") + ".png";
|
||||
//TODO: update_title();?
|
||||
return file_save_as();
|
||||
}
|
||||
// TODO: save over "open" file in electron
|
||||
if(document_file_path){
|
||||
// TODO: save as JPEG by default if the previously opened/saved file was a JPEG?
|
||||
return save_to_file_path(document_file_path, "PNG", function(saved_file_path, saved_file_name){
|
||||
saved = true;
|
||||
document_file_path = saved_file_path;
|
||||
file_name = saved_file_name;
|
||||
update_title();
|
||||
});
|
||||
}
|
||||
file_save_as();
|
||||
}
|
||||
|
||||
function file_save_as(){
|
||||
deselect();
|
||||
// TODO: remember file as "open", i.e. name in title bar and have File > Save save over the file
|
||||
save_canvas_as(canvas, file_name.replace(/\.(bmp|dib|a?png|gif|jpe?g|jpe|jfif|tiff?|webp|raw)$/, "") + ".png", function(){
|
||||
save_canvas_as(canvas, file_name.replace(/\.(bmp|dib|a?png|gif|jpe?g|jpe|jfif|tiff?|webp|raw)$/, "") + ".png", function(saved_file_path, saved_file_name){
|
||||
saved = true;
|
||||
document_file_path = saved_file_path;
|
||||
file_name = saved_file_name;
|
||||
update_title();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -983,10 +993,10 @@ function image_stretch_and_skew(){
|
|||
}
|
||||
|
||||
// TODO: establish a better pattern for this (platform-specific functions, with browser-generic fallbacks)
|
||||
// Note: we can't just poke in a different save_canvas_as function in electron-injected.js because electron-injected.js is loaded first
|
||||
function save_canvas_as(canvas, fileName, savedCallbackUnreliable){
|
||||
// Note: we can't just poke in a different save_canvas_as function in electron-injected.js because electron-injected.js is loaded first
|
||||
if(window.systemSaveCanvasAs){
|
||||
return window.systemSaveCanvasAs(canvas, fileName, savedCallbackUnreliable);
|
||||
return systemSaveCanvasAs(canvas, fileName, savedCallbackUnreliable);
|
||||
}
|
||||
|
||||
// TODO: file name + type dialog
|
||||
|
|
Loading…
Reference in New Issue