Added localstorage save + read

This commit is contained in:
jdescottes
2014-02-10 01:00:16 +01:00
parent 676bf1c7fd
commit 85084b8279
10 changed files with 169 additions and 88 deletions

View File

@@ -56,6 +56,13 @@
position: relative; position: relative;
} }
.tool-icon.local-storage-icon {
background-image: url(../img/local-storage-icon.png);
background-position: 10px 12px;
background-size: 30px;
position: relative;
}
.tool-icon.import-icon { .tool-icon.import-icon {
background-image: url(../img/import-icon.png); background-image: url(../img/import-icon.png);
background-position: 10px 5px; background-position: 10px 5px;
@@ -247,12 +254,10 @@
} }
#save-status { #save-status {
margin-left: 10px; margin-top: 10px;
} }
.status { .status {
height: 1.5rem; height: 1.5rem;
word-break : break-all;
vertical-align: middle; vertical-align: middle;
font-weight: normal; font-weight: normal;
text-shadow: none; text-shadow: none;
@@ -264,4 +269,33 @@
[name*=checkbox] { [name*=checkbox] {
vertical-align: middle; vertical-align: middle;
}
.local-piskels-list {
width: 100%;
}
.local-piskel-item {
height: 3em;
}
.local-piskel-name {
width: 40%;
}
.local-piskel-save-date {
font-weight : normal;
}
.local-piskels-list a {
text-decoration: none;
}
.local-piskels-list a:hover {
text-decoration: underline;
}
.local-piskel-load-link {
color : gold;
}
.local-piskel-delete-link {
color : red;
} }

View File

@@ -9,8 +9,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head> </head>
<body> <body>
<div <div
id="loading-mask" id="loading-mask"
style=" style="
position:fixed; position:fixed;
top:0;right:0;bottom:0;left:0; top:0;right:0;bottom:0;left:0;
@@ -55,6 +55,7 @@
<iframe src="templates/settings/resize.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe> <iframe src="templates/settings/resize.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/export-gif.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe> <iframe src="templates/settings/export-gif.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/import.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe> <iframe src="templates/settings/import.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/localstorage.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
<iframe src="templates/settings/save.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe> <iframe src="templates/settings/save.html" onload="iframeloader.onLoad(event)" data-iframe-loader="store"></iframe>
</div> </div>
</div> </div>

View File

@@ -103,8 +103,6 @@
"content" : "Loading animation with id : [" + framesheetId + "]" "content" : "Loading animation with id : [" + framesheetId + "]"
}]); }]);
this.loadFramesheetFromService(framesheetId); this.loadFramesheetFromService(framesheetId);
} else {
this.localStorageService.displayRestoreNotification();
} }
}, },
@@ -118,6 +116,10 @@
} }
}, },
isLoggedIn : function () {
return pskl.appEnginePiskelData_ && pskl.appEnginePiskelData_.isLoggedIn;
},
initTooltips_ : function () { initTooltips_ : function () {
$('body').tooltip({ $('body').tooltip({
selector: '[rel=tooltip]' selector: '[rel=tooltip]'

View File

@@ -13,7 +13,12 @@
this.nameInput = $('#save-name'); this.nameInput = $('#save-name');
this.descriptionInput = $('#save-description'); this.descriptionInput = $('#save-description');
this.isPublicCheckbox = $('input[name=save-public-checkbox]'); this.isPublicCheckbox = $('input[name=save-public-checkbox]');
this.saveButton = $('#save-button'); this.saveCloudButton = $('#save-cloud-button');
this.saveLocalButton = $('#save-local-button');
// Only available in app-engine mode ...
this.piskelName = $('.piskel-name').get(0);
this.status = $('#save-status'); this.status = $('#save-status');
var descriptor = this.piskelController.piskel.getDescriptor(); var descriptor = this.piskelController.piskel.getDescriptor();
@@ -22,21 +27,22 @@
this.isPublicCheckbox.prop('checked', descriptor.isPublic); this.isPublicCheckbox.prop('checked', descriptor.isPublic);
if (!pskl.app.isAppEngineVersion) { if (!pskl.app.isLoggedIn()) {
this.nameInput.attr('disabled', 'disabled'); this.saveCloudButton.attr('disabled', 'disabled');
this.descriptionInput.attr('disabled', 'disabled'); this.status.html('You are not logged in. Only Local Save is available.');
this.isPublicCheckbox.attr('disabled', 'disabled'); } else {
this.saveForm.submit(this.onSaveFormSubmit_.bind(this));
} }
this.saveForm.submit(this.onSaveFormSubmit_.bind(this)); this.saveLocalButton.click(this.onSaveLocalClick_.bind(this));
}; };
ns.SaveController.prototype.onSaveFormSubmit_ = function (evt) { ns.SaveController.prototype.onSaveFormSubmit_ = function (evt) {
evt.preventDefault(); evt.preventDefault();
evt.stopPropagation(); evt.stopPropagation();
var name = this.nameInput.val(); var name = this.getName();
var description = this.descriptionInput.val(); var description = this.getDescription();
var isPublic = !!this.isPublicCheckbox.prop('checked'); var isPublic = !!this.isPublicCheckbox.prop('checked');
var descriptor = new pskl.model.piskel.Descriptor(name, description, isPublic); var descriptor = new pskl.model.piskel.Descriptor(name, description, isPublic);
@@ -50,10 +56,40 @@
}); });
}; };
ns.SaveController.prototype.onSaveLocalClick_ = function (evt) {
var localStorageService = pskl.app.localStorageService;
var isOk = true;
var name = this.getName();
var description = this.getDescription();
if (localStorageService.getPiskel(name)) {
isOk = window.confirm('There is already a piskel saved as ' + name + '. Override ?');
}
if (isOk) {
this.beforeSaving_();
localStorageService.save(name, description, pskl.app.piskelController.serialize());
window.setTimeout(function () {
this.onSaveSuccess_();
this.afterSaving_();
}.bind(this), 1000);
}
};
ns.SaveController.prototype.getName = function () {
return this.nameInput.val();
};
ns.SaveController.prototype.getDescription = function () {
return this.descriptionInput.val();
};
ns.SaveController.prototype.beforeSaving_ = function () { ns.SaveController.prototype.beforeSaving_ = function () {
this.saveButton.attr('disabled', true); this.saveCloudButton.attr('disabled', true);
this.status.html('Saving ...'); this.status.html('Saving ...');
$('.piskel-name').get(0).classList.add('piskel-name-saving');
if (this.piskelName) {
this.piskelName.classList.add('piskel-name-saving');
}
}; };
ns.SaveController.prototype.onSaveSuccess_ = function () { ns.SaveController.prototype.onSaveSuccess_ = function () {
@@ -66,9 +102,12 @@
}; };
ns.SaveController.prototype.afterSaving_ = function () { ns.SaveController.prototype.afterSaving_ = function () {
this.saveButton.attr('disabled', false); this.saveCloudButton.attr('disabled', false);
this.status.html(''); this.status.html('');
$('.piskel-name').get(0).classList.remove('piskel-name-saving');
if (this.piskelName) {
this.piskelName.classList.remove('piskel-name-saving');
}
window.setTimeout($.publish.bind($, Events.HIDE_NOTIFICATION), 2000); window.setTimeout($.publish.bind($, Events.HIDE_NOTIFICATION), 2000);
}; };

View File

@@ -18,6 +18,10 @@
template : 'templates/settings/import.html', template : 'templates/settings/import.html',
controller : ns.ImportController controller : ns.ImportController
}, },
'localstorage' : {
template : 'templates/settings/localstorage.html',
controller : ns.LocalStorageController
},
'save' : { 'save' : {
template : 'templates/settings/save.html', template : 'templates/settings/save.html',
controller : ns.SaveController controller : ns.SaveController

View File

@@ -7,83 +7,74 @@
throw "Bad LocalStorageService initialization: <undefined piskelController>"; throw "Bad LocalStorageService initialization: <undefined piskelController>";
} }
this.piskelController = piskelController; this.piskelController = piskelController;
this.localStorageThrottler_ = null;
}; };
/** ns.LocalStorageService.prototype.init = function() {};
* @public
*/ // localStorage.setItem('piskel_bkp', pskl.app.piskelController.serialize())
ns.LocalStorageService.prototype.init = function(piskelController) {
$.subscribe(Events.LOCALSTORAGE_REQUEST, $.proxy(this.persistToLocalStorageRequest_, this)); ns.LocalStorageService.prototype.save = function(name, description, piskel) {
this.removeFromKeys_(name);
this.addToKeys_(name, description, Date.now());
window.localStorage.setItem('piskel.' + name, piskel);
}; };
/** ns.LocalStorageService.prototype.load = function(name) {
* @private var piskelString = this.getPiskel(name);
*/ var key = this.getKey_(name);
ns.LocalStorageService.prototype.persistToLocalStorageRequest_ = function () {
// Persist to localStorage when drawing. We throttle localStorage accesses
// for high frequency drawing (eg mousemove).
if(this.localStorageThrottler_ !== null) {
window.clearTimeout(this.localStorageThrottler_);
}
this.localStorageThrottler_ = window.setTimeout($.proxy(function() {
this.persistToLocalStorage_();
this.localStorageThrottler_ = null;
}, this), 1000);
};
/** pskl.utils.serialization.Deserializer.deserialize(JSON.parse(piskelString), function (piskel) {
* @private piskel.setDescriptor(new pskl.model.piskel.Descriptor(name, key.description, true));
*/
ns.LocalStorageService.prototype.persistToLocalStorage_ = function() {
console.log('[LocalStorage service]: Snapshot stored');
window.localStorage.snapShot = this.piskelController.serialize();
};
/**
* @private
*/
ns.LocalStorageService.prototype.restoreFromLocalStorage_ = function() {
var framesheet = JSON.parse(window.localStorage.snapShot);
pskl.utils.serialization.Deserializer.deserialize(framesheet, function (piskel) {
pskl.app.piskelController.setPiskel(piskel); pskl.app.piskelController.setPiskel(piskel);
}); });
}; };
/** ns.LocalStorageService.prototype.remove = function(name) {
* @private this.removeFromKeys_(name);
*/ window.localStorage.removeItem('piskel.' + name);
ns.LocalStorageService.prototype.cleanLocalStorage_ = function() {
console.log('[LocalStorage service]: Snapshot removed');
delete window.localStorage.snapShot;
}; };
/** ns.LocalStorageService.prototype.saveKeys_ = function(keys) {
* @public window.localStorage.setItem('piskel.keys', JSON.stringify(keys));
*/ };
ns.LocalStorageService.prototype.displayRestoreNotification = function() {
if(window.localStorage && window.localStorage.snapShot) {
var reloadLink = "<a href='#' class='localstorage-restore onclick='pskl.app.restoreFromLocalStorage()'>reload</a>";
var discardLink = "<a href='#' class='localstorage-discard' onclick='pskl.app.cleanLocalStorage()'>discard</a>";
var content = "Non saved version found. " + reloadLink + " or " + discardLink;
$.publish(Events.SHOW_NOTIFICATION, [{ ns.LocalStorageService.prototype.removeFromKeys_ = function(name) {
"content": content, var keys = this.getKeys();
"behavior": $.proxy(function(rootNode) { var otherKeys = keys.filter(function (key) {
rootNode = $(rootNode); return key.name !== name;
rootNode.click($.proxy(function(evt) { });
var target = $(evt.target);
if(target.hasClass("localstorage-restore")) { this.saveKeys_(otherKeys);
this.restoreFromLocalStorage_(); };
}
else if (target.hasClass("localstorage-discard")) { ns.LocalStorageService.prototype.getKey_ = function(name) {
this.cleanLocalStorage_(); var matches = this.getKeys().filter(function (key) {
} return key.name === name;
$.publish(Events.HIDE_NOTIFICATION); });
}, this)); if (matches.length > 0) {
}, this) return matches[0];
}]); } else {
return null;
} }
}; };
ns.LocalStorageService.prototype.addToKeys_ = function(name, description, date) {
var keys = this.getKeys();
keys.push({
name : name,
description : description,
date : date
});
this.saveKeys_(keys);
};
ns.LocalStorageService.prototype.getPiskel = function(name) {
return window.localStorage.getItem('piskel.' + name);
};
ns.LocalStorageService.prototype.getKeys = function(name) {
var keysString = window.localStorage.getItem('piskel.keys');
return JSON.parse(keysString) || [];
};
})(); })();

View File

@@ -20,11 +20,12 @@
deserializer.deserialize(); deserializer.deserialize();
}; };
ns.Deserializer.prototype.deserialize = function () { ns.Deserializer.prototype.deserialize = function (name) {
var data = this.data_; var data = this.data_;
var piskelData = data.piskel; var piskelData = data.piskel;
name = name || 'Deserialized piskel';
var descriptor = new pskl.model.piskel.Descriptor('Deserialized piskel', ''); var descriptor = new pskl.model.piskel.Descriptor(name, '');
this.piskel_ = new pskl.model.Piskel(piskelData.width, piskelData.height, descriptor); this.piskel_ = new pskl.model.Piskel(piskelData.width, piskelData.height, descriptor);
this.layersToLoad_ = piskelData.layers.length; this.layersToLoad_ = piskelData.layers.length;

View File

@@ -72,6 +72,7 @@ exports.scripts = [
"js/controller/settings/ApplicationSettingsController.js", "js/controller/settings/ApplicationSettingsController.js",
"js/controller/settings/ResizeController.js", "js/controller/settings/ResizeController.js",
"js/controller/settings/GifExportController.js", "js/controller/settings/GifExportController.js",
"js/controller/settings/LocalStorageController.js",
"js/controller/settings/SaveController.js", "js/controller/settings/SaveController.js",
"js/controller/settings/ImportController.js", "js/controller/settings/ImportController.js",
// Settings controller // Settings controller

View File

@@ -27,6 +27,13 @@
rel="tooltip" data-placement="left"> rel="tooltip" data-placement="left">
</div> </div>
<div
data-setting="localstorage"
class="tool-icon local-storage-icon"
title="Browse piskels saved locally"
rel="tooltip" data-placement="left">
</div>
<div <div
data-setting="gif" data-setting="gif"
class="tool-icon upload-cloud-icon" class="tool-icon upload-cloud-icon"

View File

@@ -15,8 +15,9 @@
Public : <input type="checkbox" value="1" name="save-public-checkbox"/> Public : <input type="checkbox" value="1" name="save-public-checkbox"/>
</label> </label>
</div> </div>
<input type="submit" class="button button-primary" id="save-button" value="Save" /> <input type="submit" class="button button-primary" id="save-cloud-button" value="Upload" />
<span id="save-status" class="status"></span> <input type="button" class="button" id="save-local-button" value="Local save" />
<div id="save-status" class="status"></div>
</form> </form>
</div> </div>
</div> </div>