diff --git a/src/js/Events.js b/src/js/Events.js index 65f921f..23b9602 100644 --- a/src/js/Events.js +++ b/src/js/Events.js @@ -82,6 +82,8 @@ var Events = { PERFORMANCE_REPORT_CHANGED : 'PERFORMANCE_REPORT_CHANGED', + PISKEL_FILE_IMPORT_FAILED : 'PISKEL_FILE_IMPORT_FAILED', + // Tests MOUSE_EVENT : 'MOUSE_EVENT', KEYBOARD_EVENT : 'KEYBOARD_EVENT', diff --git a/src/js/app.js b/src/js/app.js index 026cc06..ca1f875 100644 --- a/src/js/app.js +++ b/src/js/app.js @@ -126,6 +126,7 @@ this.storageService.init(); this.importService = new pskl.service.ImportService(this.piskelController); + this.importService.init(); this.imageUploadService = new pskl.service.ImageUploadService(); this.imageUploadService.init(); diff --git a/src/js/controller/settings/ImportController.js b/src/js/controller/settings/ImportController.js index 4909f39..8a44d59 100644 --- a/src/js/controller/settings/ImportController.js +++ b/src/js/controller/settings/ImportController.js @@ -79,9 +79,15 @@ ns.ImportController.prototype.openPiskelFile_ = function (file) { if (this.isPiskel_(file)) { - pskl.utils.PiskelFileUtils.loadFromFile(file, function (piskel) { - pskl.app.piskelController.setPiskel(piskel); - }); + pskl.utils.PiskelFileUtils.loadFromFile(file, + // onSuccess + function (piskel) { + pskl.app.piskelController.setPiskel(piskel); + }, + // onError + function (reason) { + $.publish(Events.PISKEL_FILE_IMPORT_FAILED, [reason]); + }); this.closeDrawer_(); } }; diff --git a/src/js/service/FileDropperService.js b/src/js/service/FileDropperService.js index 84957da..01cf5c4 100644 --- a/src/js/service/FileDropperService.js +++ b/src/js/service/FileDropperService.js @@ -35,7 +35,7 @@ if (isImage) { this.readImageFile_(file); } else if (isPiskel) { - pskl.utils.PiskelFileUtils.loadFromFile(file, this.onPiskelFileLoaded_); + pskl.utils.PiskelFileUtils.loadFromFile(file, this.onPiskelFileLoaded_, this.onPiskelFileError_); } else if (isPalette) { pskl.app.paletteImportService.read(file, this.onPaletteLoaded_.bind(this)); } @@ -57,6 +57,10 @@ } }; + ns.FileDropperService.prototype.onPiskelFileError_ = function (reason) { + $.publish(Events.PISKEL_FILE_IMPORT_FAILED, [reason]); + }; + ns.FileDropperService.prototype.processImageSource_ = function (imageSource) { this.importedImage_ = new Image(); this.importedImage_.onload = this.onImageLoaded_.bind(this); diff --git a/src/js/service/ImportService.js b/src/js/service/ImportService.js index ac633a0..adbb125 100644 --- a/src/js/service/ImportService.js +++ b/src/js/service/ImportService.js @@ -6,11 +6,25 @@ * @param {!PiskelController} piskelController * @constructor */ - ns.ImportService = - function (piskelController) { + ns.ImportService = function (piskelController) { this.piskelController_ = piskelController; }; + ns.ImportService.prototype.init = function () { + $.subscribe(Events.PISKEL_FILE_IMPORT_FAILED, this.onPiskelFileImportFailed_); + }; + + /** + * Called when a piskel load failed event is published. Display an appropriate error message. + * TODO: for some failure reasons, we might want to display a dialog with more details. + */ + ns.ImportService.prototype.onPiskelFileImportFailed_ = function (evt, reason) { + $.publish(Events.SHOW_NOTIFICATION, [{ + 'content': 'Piskel file import failed (' + reason + ')', + 'hideDelay' : 10000 + }]); + }; + /** * Given an image object and some options, create a new Piskel and open it * for editing. diff --git a/src/js/utils/PiskelFileUtils.js b/src/js/utils/PiskelFileUtils.js index 4d7680e..2313032 100644 --- a/src/js/utils/PiskelFileUtils.js +++ b/src/js/utils/PiskelFileUtils.js @@ -2,6 +2,12 @@ var ns = $.namespace('pskl.utils'); ns.PiskelFileUtils = { + FAILURE : { + EMPTY : 'No data found in piskel file', + INVALID : 'Invalid piskel file, contact us on twitter @piskelapp', + DESERIALIZATION : 'Piskel data deserialization failed' + }, + /** * Load a piskel from a piskel file. * After deserialization is successful, the provided success callback will be called. @@ -29,10 +35,22 @@ }, decodePiskelFile : function (rawPiskel, onSuccess, onError) { - var serializedPiskel = JSON.parse(rawPiskel); + var serializedPiskel; + if (rawPiskel.length === 0) { + onError(ns.PiskelFileUtils.FAILURE.EMPTY); + return; + } + + try { + serializedPiskel = JSON.parse(rawPiskel); + } catch (e) { + onError(ns.PiskelFileUtils.FAILURE.INVALID); + return; + } + var piskel = serializedPiskel.piskel; - pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, function (piskel) { - onSuccess(piskel); + pskl.utils.serialization.Deserializer.deserialize(serializedPiskel, onSuccess, function () { + onError(ns.PiskelFileUtils.FAILURE.DESERIALIZATION); }); } }; diff --git a/src/js/utils/serialization/Deserializer.js b/src/js/utils/serialization/Deserializer.js index 561be7c..d02b3cd 100644 --- a/src/js/utils/serialization/Deserializer.js +++ b/src/js/utils/serialization/Deserializer.js @@ -9,16 +9,20 @@ this.layers_ = []; }; - ns.Deserializer.deserialize = function (data, callback) { - var deserializer; - if (data.modelVersion == Constants.MODEL_VERSION) { - deserializer = new ns.Deserializer(data, callback); - } else if (data.modelVersion == 1) { - deserializer = new ns.backward.Deserializer_v1(data, callback); - } else { - deserializer = new ns.backward.Deserializer_v0(data, callback); + ns.Deserializer.deserialize = function (data, onSuccess, onError) { + try { + var deserializer; + if (data.modelVersion == Constants.MODEL_VERSION) { + deserializer = new ns.Deserializer(data, onSuccess); + } else if (data.modelVersion == 1) { + deserializer = new ns.backward.Deserializer_v1(data, onSuccess); + } else { + deserializer = new ns.backward.Deserializer_v0(data, onSuccess); + } + deserializer.deserialize(); + } catch (e) { + onError(e); } - deserializer.deserialize(); }; ns.Deserializer.prototype.deserialize = function () {