lock flow

This commit is contained in:
Antelle 2015-11-17 23:57:32 +03:00
parent e779d1bcc7
commit ae29852b60
11 changed files with 148 additions and 21 deletions

View File

@ -12,15 +12,15 @@ var Alerts = {
alert: function(config) {
var view = new ModalView({ model: config });
view.render();
view.on('result', function(res) {
view.on('result', function(res, check) {
if (res && config.success) {
config.success(res);
config.success(res, check);
}
if (!res && config.cancel) {
config.cancel();
}
if (config.complete) {
config.complete(res);
config.complete(res, check);
}
});
},

View File

@ -84,6 +84,7 @@ var AppModel = Backbone.Model.extend({
},
closeAllFiles: function() {
this.files.each(function(file) { file.close(); });
this.files.reset();
this.menu.groupsSection.removeAllItems();
this.menu.tagsSection.set('scrollable', false);

View File

@ -13,7 +13,8 @@ var AppSettingsModel = Backbone.Model.extend({
menuViewWidth: null,
tagsViewHeight: null,
autoUpdate: 'install',
clipboradSeconds: 0
clipboardSeconds: 0,
autoSave: false
},
initialize: function() {

View File

@ -34,6 +34,7 @@ var FileModel = Backbone.Model.extend({
},
db: null,
data: null,
initialize: function() {
},
@ -80,6 +81,7 @@ var FileModel = Backbone.Model.extend({
postOpen: function(fileData) {
var that = this;
this.data = fileData;
if (!this.get('offline')) {
if (this.get('availOffline')) {
Storage.cache.save(this.get('name'), fileData, function (err) {
@ -158,6 +160,22 @@ var FileModel = Backbone.Model.extend({
}, this);
},
close: function() {
this.set({
keyFileName: '',
passwordLength: 0,
modified: false,
open: false,
opening: false,
error: false,
created: false,
groups: null,
passwordChanged: false,
keyFileChanged: false,
syncing: false
});
},
getGroup: function(id) {
var found = null;
if (id) {
@ -208,7 +226,7 @@ var FileModel = Backbone.Model.extend({
}
},
autoSave: function() {
autoSave: function(complete) {
var that = this;
that.set('syncing', true);
switch (that.get('storage')) {
@ -216,14 +234,18 @@ var FileModel = Backbone.Model.extend({
that.getData(function(data) {
Launcher.writeFile(that.get('path'), data);
that.saved(that.get('path'), that.get('storage'));
if (complete) { complete(); }
});
break;
case 'dropbox':
that.getData(function(data) {
DropboxLink.saveFile(that.get('path'), data, true, function (err) {
if (!err) {
if (err) {
that.set('syncing', false);
} else {
that.saved(that.get('path'), that.get('storage'));
}
if (complete) { complete(err); }
});
});
break;
@ -233,9 +255,8 @@ var FileModel = Backbone.Model.extend({
},
getData: function(cb) {
var data = this.db.save(cb);
return data;
this.data = this.db.save(cb);
return this.data;
},
getXml: function(cb) {

View File

@ -251,14 +251,87 @@ var AppView = Backbone.View.extend({
},
lockWorkspace: function() {
var that = this;
if (this.model.files.hasUnsavedFiles()) {
Alerts.yesno({
header: 'Unsaved changes',
body: 'You have unsaved changes that will be lost. Continue?',
success: this.model.closeAllFiles.bind(this.model)
});
if (this.model.settings.get('autoSave')) {
this.saveAndLock();
} else {
Alerts.alert({
icon: 'lock',
header: 'Lock',
body: 'You have unsaved changes that will be lost. Continue?',
buttons: [
{ result: 'save', title: 'Save changes' },
{ result: 'discard', title: 'Discard changes', error: true },
{ result: '', title: 'Cancel' }
],
checkbox: 'Auto save changes each time I lock the app',
success: function(result, autoSaveChecked) {
if (result === 'save') {
if (autoSaveChecked) {
that.model.settings.set('autoSave', autoSaveChecked);
}
that.saveAndLock();
} else if (result === 'discard') {
that.model.closeAllFiles();
}
}
});
}
} else {
this.model.closeAllFiles();
this.closeAllFilesAndShowFirst();
}
},
saveAndLock: function() {
var pendingCallbacks = 0,
errorFiles = [],
that = this;
if (this.model.files.some(function(file) { return file.get('modified') && !file.get('path'); })) {
Alerts.error({
header: 'Cannot auto-save',
body: 'Some opened files cannot be saved automatically. To enable auto-save, you can sync them to Dropbox.'
});
return;
}
this.model.files.forEach(function(file) {
if (!file.get('modified')) {
return;
}
if (file.get('path')) {
try {
file.autoSave(fileSaved.bind(this, file));
pendingCallbacks++;
} catch (e) {
console.error('Failed to auto-save file', file.get('path'), e);
}
}
}, this);
if (!pendingCallbacks) {
this.closeAllFilesAndShowFirst();
}
function fileSaved(file, err) {
if (err) {
errorFiles.push(file.get('name'));
}
if (--pendingCallbacks === 0) {
if (errorFiles.length) {
Alerts.error({
header: 'Save Error',
body: 'Failed to auto-save file' + (errorFiles.length > 1 ? 's: ' : '') + ' ' + errorFiles.join(', ')
});
} else {
that.closeAllFilesAndShowFirst();
}
}
}
},
closeAllFilesAndShowFirst: function() {
var firstFile = this.model.files.find(function(file) { return !file.get('demo'); });
this.model.closeAllFiles();
if (firstFile) {
this.views.open.showClosedFile(firstFile);
}
},

View File

@ -65,7 +65,8 @@ var ModalView = Backbone.View.extend({
},
closeWithResult: function(result) {
this.trigger('result', result);
var checked = this.model.checkbox ? this.$el.find('#modal__check').is(':checked') : undefined;
this.trigger('result', result, checked);
this.$el.addClass('modal--hidden');
this.undelegateEvents();
setTimeout(this.remove.bind(this), 100);

View File

@ -37,10 +37,14 @@ var OpenView = Backbone.View.extend({
dropboxLoading: null,
initialize: function () {
this.file = new FileModel();
this.setFileModel(new FileModel());
this.fileData = null;
this.keyFileData = null;
this.passwordInput = new SecureInput();
},
setFileModel: function(file) {
this.file = file;
this.listenTo(this.file, 'change:open', this.fileOpenChanged);
this.listenTo(this.file, 'change:opening', this.fileOpeningChanged);
this.listenTo(this.file, 'change:error', this.fileErrorChanged);
@ -202,6 +206,12 @@ var OpenView = Backbone.View.extend({
}
},
showClosedFile: function(file) {
this.setFileModel(file);
this.fileData = file.data;
this.displayOpenFile();
},
openFile: function() {
if (!this.file.get('opening')) {
this.openAny('fileData');

View File

@ -17,6 +17,7 @@ var SettingsGeneralView = Backbone.View.extend({
'change .settings__general-expand': 'changeExpandGroups',
'change .settings__general-auto-update': 'changeAutoUpdate',
'change .settings__general-clipboard': 'changeClipboard',
'change .settings__general-auto-save': 'changeAutoSave',
'click .settings__general-update-btn': 'checkUpdate',
'click .settings__general-restart-btn': 'restartApp',
'click .settings__general-download-update-btn': 'downloadUpdate',
@ -42,6 +43,7 @@ var SettingsGeneralView = Backbone.View.extend({
expandGroups: AppSettingsModel.instance.get('expandGroups'),
canClearClipboard: !!Launcher,
clipboardSeconds: AppSettingsModel.instance.get('clipboardSeconds'),
autoSave: AppSettingsModel.instance.get('autoSave'),
devTools: Launcher && Launcher.devTools,
canAutoUpdate: !!Launcher,
autoUpdate: Updater.getAutoUpdateType(),
@ -112,6 +114,11 @@ var SettingsGeneralView = Backbone.View.extend({
Updater.check(true);
},
changeAutoSave: function(e) {
var autoSave = e.target.checked || false;
AppSettingsModel.instance.set('autoSave', autoSave);
},
restartApp: function() {
if (Launcher) {
Launcher.requestRestart();

View File

@ -53,4 +53,7 @@
width: 90%;
}
}
&__check-wrap {
margin-top: $base-spacing;
}
}

View File

@ -2,11 +2,16 @@
<div class="modal__content">
<i class="modal__icon fa fa-<%= icon %>"></i>
<div class="modal__header"><%= header %></div>
<div class="modal__body"><%= body %></div>
<div class="modal__body">
<%= body %>
<% if (typeof checkbox !== 'undefined') { %>
<div class="modal__check-wrap"><input type="checkbox" id="modal__check" /><label for="modal__check"><%- checkbox %></label></div>
<% } %>
</div>
<div class="modal__buttons">
<% buttons.forEach(function(btn) { %>
<button class="<%= btn.result ? '' : 'btn-error' %>" data-result="<%= btn.result %>"><%= btn.title %></button>
<button class="<%= btn.result && !btn.error ? '' : 'btn-error' %>" data-result="<%= btn.result %>"><%= btn.title %></button>
<% }); %>
</div>
</div>
</div>
</div>

View File

@ -51,8 +51,8 @@
<label for="settings__general-expand">Show entries from all subgroups</label>
</div>
<% if (canClearClipboard) { %>
<h2>Function</h2>
<% if (canClearClipboard) { %>
<div>
<label for="settings__general-clipboard">Clear clipboard after copy:</label>
<select class="settings__general-clipboard settings__select input-base" id="settings__general-clipboard">
@ -64,6 +64,11 @@
</select>
</div>
<% } %>
<div>
<input type="checkbox" class="settings__input input-base settings__general-auto-save" id="settings__general-auto-save"
<%- autoSave ? 'checked' : '' %> />
<label for="settings__general-auto-save">Auto-save on lock</label>
</div>
<% if (devTools) { %>
<h2>Advanced</h2>