mirror of https://github.com/keeweb/keeweb.git
move views
This commit is contained in:
parent
ad0963e412
commit
7730486f30
|
@ -150,7 +150,7 @@ ready(() => {
|
|||
|
||||
function showView() {
|
||||
appModel.prepare();
|
||||
new AppView({ model: appModel }).render();
|
||||
new AppView(appModel).render();
|
||||
Backbone.trigger('app-ready');
|
||||
logStartupTime();
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ const Resizable = {
|
|||
let size = dragInfo.startSize + e.offset;
|
||||
size = Math.max(dragInfo.min, Math.min(dragInfo.max, size));
|
||||
this.$el[dragInfo.prop](size);
|
||||
this.trigger('view-resize', size);
|
||||
this.emit('view-resize', size);
|
||||
Backbone.trigger('page-geometry', { source: 'resizable' });
|
||||
},
|
||||
|
||||
|
@ -28,7 +28,7 @@ const Resizable = {
|
|||
this.$el.css(dragInfo.prop, 'auto');
|
||||
}
|
||||
this.fixSize(dragInfo);
|
||||
this.trigger('view-resize', null);
|
||||
this.emit('view-resize', null);
|
||||
Backbone.trigger('page-geometry', { source: 'resizable' });
|
||||
},
|
||||
|
||||
|
|
|
@ -6,9 +6,10 @@ import { Logger } from 'util/logger';
|
|||
|
||||
class View extends EventEmitter {
|
||||
parent = undefined;
|
||||
replace = false;
|
||||
template = undefined;
|
||||
events = {};
|
||||
model = undefined;
|
||||
options = {};
|
||||
views = {};
|
||||
hidden = false;
|
||||
removed = false;
|
||||
|
@ -19,13 +20,7 @@ class View extends EventEmitter {
|
|||
super();
|
||||
|
||||
this.model = model;
|
||||
|
||||
if (options.parent) {
|
||||
this.parent = options.parent;
|
||||
}
|
||||
if (options.replace) {
|
||||
this.replace = options.replace;
|
||||
}
|
||||
this.options = options;
|
||||
|
||||
this.setMaxListeners(100);
|
||||
}
|
||||
|
@ -55,24 +50,31 @@ class View extends EventEmitter {
|
|||
renderElement(templateData) {
|
||||
const html = this.template(templateData);
|
||||
if (this.el) {
|
||||
morphdom(this.el, html);
|
||||
const mountRoot = this.options.ownParent ? this.el.firstChild : this.el;
|
||||
morphdom(mountRoot, html);
|
||||
} else {
|
||||
if (this.parent) {
|
||||
let parent = this.parent;
|
||||
let parent = this.options.parent || this.parent;
|
||||
if (parent) {
|
||||
if (typeof parent === 'string') {
|
||||
parent = document.querySelector(this.parent);
|
||||
parent = document.querySelector(parent);
|
||||
}
|
||||
if (!parent) {
|
||||
throw new Error(`Error rendering ${this.constructor.name}: parent not found`);
|
||||
}
|
||||
if (this.replace) {
|
||||
if (this.options.replace) {
|
||||
Tip.destroyTips(parent);
|
||||
parent.innerHTML = '';
|
||||
}
|
||||
const el = document.createElement('div');
|
||||
el.innerHTML = html;
|
||||
this.el = el.firstChild;
|
||||
parent.appendChild(this.el);
|
||||
const root = el.firstChild;
|
||||
if (this.options.ownParent) {
|
||||
parent.appendChild(root);
|
||||
this.el = parent;
|
||||
} else {
|
||||
this.el = root;
|
||||
parent.appendChild(this.el);
|
||||
}
|
||||
} else {
|
||||
throw new Error(
|
||||
`Error rendering ${this.constructor.name}: I don't know how to insert the view`
|
||||
|
@ -145,6 +147,7 @@ class View extends EventEmitter {
|
|||
}
|
||||
|
||||
stopListening(model, event, callback) {
|
||||
// TODO: remove a pending callback
|
||||
model.off(event, callback);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Backbone from 'backbone';
|
||||
import { View } from 'view-engine/view';
|
||||
import { IdleTracker } from 'comp/browser/idle-tracker';
|
||||
import { KeyHandler } from 'comp/browser/key-handler';
|
||||
import { Launcher } from 'comp/launcher';
|
||||
|
@ -22,32 +23,31 @@ import { MenuView } from 'views/menu/menu-view';
|
|||
import { OpenView } from 'views/open-view';
|
||||
import { SettingsView } from 'views/settings/settings-view';
|
||||
import { TagView } from 'views/tag-view';
|
||||
import template from 'templates/app.hbs';
|
||||
|
||||
const AppView = Backbone.View.extend({
|
||||
el: 'body',
|
||||
class AppView extends View {
|
||||
parent = 'body';
|
||||
|
||||
template: require('templates/app.hbs'),
|
||||
template = template;
|
||||
|
||||
events: {
|
||||
'contextmenu': 'contextMenu',
|
||||
'drop': 'drop',
|
||||
'dragenter': 'dragover',
|
||||
'dragover': 'dragover',
|
||||
events = {
|
||||
contextmenu: 'contextMenu',
|
||||
drop: 'drop',
|
||||
dragenter: 'dragover',
|
||||
dragover: 'dragover',
|
||||
'click a[target=_blank]': 'extLinkClick',
|
||||
'mousedown': 'bodyClick'
|
||||
},
|
||||
mousedown: 'bodyClick'
|
||||
};
|
||||
|
||||
views: null,
|
||||
titlebarStyle = 'default';
|
||||
|
||||
titlebarStyle: 'default',
|
||||
|
||||
initialize() {
|
||||
this.views = {};
|
||||
this.views.menu = new MenuView({ model: this.model.menu });
|
||||
constructor(model) {
|
||||
super(model);
|
||||
this.views.menu = new MenuView(this.model.menu, { ownParent: true });
|
||||
this.views.menuDrag = new DragView('x', { parent: '.app__menu-drag' });
|
||||
this.views.footer = new FooterView(this.model);
|
||||
this.views.listWrap = new ListWrapView(this.model);
|
||||
this.views.list = new ListView({ model: this.model });
|
||||
this.views.list = new ListView(this.model);
|
||||
this.views.listDrag = new DragView('x', { parent: '.app__list-drag' });
|
||||
this.views.list.dragView = this.views.listDrag;
|
||||
this.views.details = new DetailsView();
|
||||
|
@ -95,13 +95,12 @@ const AppView = Backbone.View.extend({
|
|||
window.onresize = this.windowResize.bind(this);
|
||||
window.onblur = this.windowBlur.bind(this);
|
||||
|
||||
KeyHandler.onKey(Keys.DOM_VK_ESCAPE, this.escPressed, this);
|
||||
KeyHandler.onKey(Keys.DOM_VK_BACK_SPACE, this.backspacePressed, this);
|
||||
this.onKey(Keys.DOM_VK_ESCAPE, this.escPressed);
|
||||
this.onKey(Keys.DOM_VK_BACK_SPACE, this.backspacePressed);
|
||||
if (Launcher && Launcher.devTools) {
|
||||
KeyHandler.onKey(
|
||||
Keys.DOM_VK_I,
|
||||
this.openDevTools,
|
||||
this,
|
||||
KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT
|
||||
);
|
||||
}
|
||||
|
@ -110,7 +109,7 @@ const AppView = Backbone.View.extend({
|
|||
|
||||
this.setWindowClass();
|
||||
this.fixClicksInEdge();
|
||||
},
|
||||
}
|
||||
|
||||
setWindowClass() {
|
||||
const getBrowserCssClass = Features.getBrowserCssClass();
|
||||
|
@ -120,7 +119,7 @@ const AppView = Backbone.View.extend({
|
|||
if (this.titlebarStyle !== 'default') {
|
||||
this.$el.addClass('titlebar-' + this.titlebarStyle);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
fixClicksInEdge() {
|
||||
// MS Edge doesn't want to handle clicks by default
|
||||
|
@ -133,26 +132,24 @@ const AppView = Backbone.View.extend({
|
|||
.focus();
|
||||
setTimeout(() => msEdgeScrewer.remove(), 0);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
this.$el.html(
|
||||
this.template({
|
||||
beta: this.model.isBeta,
|
||||
titlebarStyle: this.titlebarStyle
|
||||
})
|
||||
);
|
||||
super.render({
|
||||
beta: this.model.isBeta,
|
||||
titlebarStyle: this.titlebarStyle
|
||||
});
|
||||
this.panelEl = this.$el.find('.app__panel:first');
|
||||
this.views.listWrap.render();
|
||||
this.views.menu.setElement(this.$el.find('.app__menu')).render();
|
||||
this.views.menu.render();
|
||||
this.views.menuDrag.render();
|
||||
this.views.footer.render();
|
||||
this.views.list.setElement(this.$el.find('.app__list')).render();
|
||||
this.views.list.render();
|
||||
this.views.listDrag.render();
|
||||
this.views.details.setElement(this.$el.find('.app__details')).render();
|
||||
this.showLastOpenFile();
|
||||
return this;
|
||||
},
|
||||
}
|
||||
|
||||
showOpenFile() {
|
||||
this.hideContextMenu();
|
||||
|
@ -167,17 +164,13 @@ const AppView = Backbone.View.extend({
|
|||
this.hideSettings();
|
||||
this.hideOpenFile();
|
||||
this.hideKeyChange();
|
||||
this.views.open = new OpenView({ model: this.model });
|
||||
this.views.open.setElement(this.$el.find('.app__body')).render();
|
||||
this.views.open.on(
|
||||
'close',
|
||||
() => {
|
||||
Backbone.trigger('closed-open-view');
|
||||
},
|
||||
this
|
||||
);
|
||||
this.views.open.on('close', this.showEntries, this);
|
||||
},
|
||||
this.views.open = new OpenView(this.model);
|
||||
this.views.open.render();
|
||||
this.views.open.on('close', () => {
|
||||
Backbone.trigger('closed-open-view');
|
||||
});
|
||||
this.views.open.on('close', () => this.showEntries());
|
||||
}
|
||||
|
||||
showLastOpenFile() {
|
||||
this.showOpenFile();
|
||||
|
@ -186,14 +179,14 @@ const AppView = Backbone.View.extend({
|
|||
this.views.open.currentSelectedIndex = 0;
|
||||
this.views.open.showOpenFileInfo(lastOpenFile);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
launcherOpenFile(file) {
|
||||
if (file && file.data && /\.kdbx$/i.test(file.data)) {
|
||||
this.showOpenFile();
|
||||
this.views.open.showOpenLocalFile(file.data, file.key);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
updateApp() {
|
||||
if (
|
||||
|
@ -203,7 +196,7 @@ const AppView = Backbone.View.extend({
|
|||
) {
|
||||
window.location.reload();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
showEntries() {
|
||||
this.views.menu.show();
|
||||
|
@ -217,14 +210,14 @@ const AppView = Backbone.View.extend({
|
|||
this.hideOpenFile();
|
||||
this.hideSettings();
|
||||
this.hideKeyChange();
|
||||
},
|
||||
}
|
||||
|
||||
hideOpenFile() {
|
||||
if (this.views.open) {
|
||||
this.views.open.remove();
|
||||
this.views.open = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
hidePanelView() {
|
||||
if (this.views.panel) {
|
||||
|
@ -232,7 +225,7 @@ const AppView = Backbone.View.extend({
|
|||
this.views.panel = null;
|
||||
this.panelEl.addClass('hide');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
showPanelView(view) {
|
||||
this.views.listWrap.hide();
|
||||
|
@ -243,7 +236,7 @@ const AppView = Backbone.View.extend({
|
|||
view.render();
|
||||
this.views.panel = view;
|
||||
this.panelEl.removeClass('hide');
|
||||
},
|
||||
}
|
||||
|
||||
hideSettings() {
|
||||
if (this.views.settings) {
|
||||
|
@ -251,14 +244,14 @@ const AppView = Backbone.View.extend({
|
|||
this.views.settings.remove();
|
||||
this.views.settings = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
hideKeyChange() {
|
||||
if (this.views.keyChange) {
|
||||
this.views.keyChange.hide();
|
||||
this.views.keyChange = null;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
showSettings(selectedMenuItem) {
|
||||
this.model.menu.setMenu('settings');
|
||||
|
@ -278,15 +271,15 @@ const AppView = Backbone.View.extend({
|
|||
}
|
||||
this.model.menu.select({ item: selectedMenuItem });
|
||||
this.views.menu.switchVisibility(false);
|
||||
},
|
||||
}
|
||||
|
||||
showEditGroup(group) {
|
||||
this.showPanelView(new GrpView(group));
|
||||
},
|
||||
}
|
||||
|
||||
showEditTag() {
|
||||
this.showPanelView(new TagView(this.model));
|
||||
},
|
||||
}
|
||||
|
||||
showKeyChange(file, viewConfig) {
|
||||
if (Alerts.alertDisplayed) {
|
||||
|
@ -310,7 +303,7 @@ const AppView = Backbone.View.extend({
|
|||
this.views.keyChange.render();
|
||||
this.views.keyChange.on('accept', this.keyChangeAccept.bind(this));
|
||||
this.views.keyChange.on('cancel', this.showEntries.bind(this));
|
||||
},
|
||||
}
|
||||
|
||||
fileListUpdated() {
|
||||
if (this.model.files.hasOpenFiles()) {
|
||||
|
@ -319,7 +312,7 @@ const AppView = Backbone.View.extend({
|
|||
this.showOpenFile();
|
||||
}
|
||||
this.fixClicksInEdge();
|
||||
},
|
||||
}
|
||||
|
||||
showFileSettings(e) {
|
||||
const menuItem = this.model.menu.filesSection
|
||||
|
@ -334,7 +327,7 @@ const AppView = Backbone.View.extend({
|
|||
} else {
|
||||
this.showSettings(menuItem);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
toggleOpenFile() {
|
||||
if (this.views.open) {
|
||||
|
@ -344,7 +337,7 @@ const AppView = Backbone.View.extend({
|
|||
} else {
|
||||
this.showOpenFile();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
beforeUnload(e) {
|
||||
const exitEvent = {
|
||||
|
@ -419,70 +412,70 @@ const AppView = Backbone.View.extend({
|
|||
Launcher.minimizeApp();
|
||||
return Launcher.preventExit(e);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
windowResize() {
|
||||
Backbone.trigger('page-geometry', { source: 'window' });
|
||||
},
|
||||
}
|
||||
|
||||
windowBlur(e) {
|
||||
if (e.target === window) {
|
||||
Backbone.trigger('page-blur');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
enterFullScreen() {
|
||||
this.$el.addClass('fullscreen');
|
||||
},
|
||||
}
|
||||
|
||||
leaveFullScreen() {
|
||||
this.$el.removeClass('fullscreen');
|
||||
},
|
||||
}
|
||||
|
||||
escPressed() {
|
||||
if (this.views.open && this.model.files.hasOpenFiles()) {
|
||||
this.showEntries();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
backspacePressed(e) {
|
||||
if (e.target === document.body) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
openDevTools() {
|
||||
if (Launcher && Launcher.devTools) {
|
||||
Launcher.openDevTools();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
selectAll() {
|
||||
this.menuSelect({ item: this.model.menu.allItemsSection.get('items').first() });
|
||||
},
|
||||
}
|
||||
|
||||
menuSelect(opt) {
|
||||
this.model.menu.select(opt);
|
||||
if (this.views.panel && !this.views.panel.isHidden()) {
|
||||
this.showEntries();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
userIdle() {
|
||||
this.lockWorkspace(true);
|
||||
},
|
||||
}
|
||||
|
||||
osLocked() {
|
||||
if (this.model.settings.get('lockOnOsLock')) {
|
||||
this.lockWorkspace(true);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
appMinimized() {
|
||||
if (this.model.settings.get('lockOnMinimize')) {
|
||||
this.lockWorkspace(true);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
lockWorkspace(autoInit) {
|
||||
if (Alerts.alertDisplayed) {
|
||||
|
@ -518,7 +511,7 @@ const AppView = Backbone.View.extend({
|
|||
} else {
|
||||
this.closeAllFilesAndShowFirst();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
handleAutoSaveTimer() {
|
||||
if (this.model.settings.get('autoSaveInterval') !== 0) {
|
||||
|
@ -531,7 +524,7 @@ const AppView = Backbone.View.extend({
|
|||
this.model.settings.get('autoSaveInterval') * 1000 * 60
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
saveAndLock(complete) {
|
||||
let pendingCallbacks = 0;
|
||||
|
@ -574,7 +567,7 @@ const AppView = Backbone.View.extend({
|
|||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
closeAllFilesAndShowFirst() {
|
||||
let fileToShow = this.model.files.find(file => !file.get('demo') && !file.get('created'));
|
||||
|
@ -592,27 +585,27 @@ const AppView = Backbone.View.extend({
|
|||
this.views.open.showOpenFileInfo(fileInfo);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
saveAll() {
|
||||
this.model.files.forEach(function(file) {
|
||||
this.model.syncFile(file);
|
||||
}, this);
|
||||
},
|
||||
}
|
||||
|
||||
syncAllByTimer() {
|
||||
if (this.model.settings.get('autoSave')) {
|
||||
this.saveAll();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
remoteKeyChanged(e) {
|
||||
this.showKeyChange(e.file, { remote: true });
|
||||
},
|
||||
}
|
||||
|
||||
keyChangePending(e) {
|
||||
this.showKeyChange(e.file, { expired: true });
|
||||
},
|
||||
}
|
||||
|
||||
keyChangeAccept(e) {
|
||||
this.showEntries();
|
||||
|
@ -632,7 +625,7 @@ const AppView = Backbone.View.extend({
|
|||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
toggleSettings(page) {
|
||||
let menuItem = page ? this.model.menu[page + 'Section'] : null;
|
||||
|
@ -658,16 +651,16 @@ const AppView = Backbone.View.extend({
|
|||
this.model.menu.select({ item: menuItem });
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
this.views.menu.switchVisibility();
|
||||
},
|
||||
}
|
||||
|
||||
toggleDetails(visible) {
|
||||
this.$el.find('.app').toggleClass('app--details-visible', visible);
|
||||
this.views.menu.switchVisibility(false);
|
||||
},
|
||||
}
|
||||
|
||||
editGroup(group) {
|
||||
if (group && !(this.views.panel instanceof GrpView)) {
|
||||
|
@ -675,7 +668,7 @@ const AppView = Backbone.View.extend({
|
|||
} else {
|
||||
this.showEntries();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
editTag(tag) {
|
||||
if (tag && !(this.views.panel instanceof TagView)) {
|
||||
|
@ -684,7 +677,7 @@ const AppView = Backbone.View.extend({
|
|||
} else {
|
||||
this.showEntries();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
editGeneratorPresets() {
|
||||
if (!(this.views.panel instanceof GeneratorPresetsView)) {
|
||||
|
@ -695,17 +688,17 @@ const AppView = Backbone.View.extend({
|
|||
} else {
|
||||
this.showEntries();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
isContextMenuAllowed(e) {
|
||||
return ['input', 'textarea'].indexOf(e.target.tagName.toLowerCase()) < 0;
|
||||
},
|
||||
}
|
||||
|
||||
contextMenu(e) {
|
||||
if (this.isContextMenuAllowed(e)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
showContextMenu(e) {
|
||||
if (e.options && this.isContextMenuAllowed(e)) {
|
||||
|
@ -723,19 +716,19 @@ const AppView = Backbone.View.extend({
|
|||
menu.on('select', e => this.contextMenuSelect(e));
|
||||
this.views.contextMenu = menu;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
hideContextMenu() {
|
||||
if (this.views.contextMenu) {
|
||||
this.views.contextMenu.remove();
|
||||
delete this.views.contextMenu;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
contextMenuSelect(e) {
|
||||
this.hideContextMenu();
|
||||
Backbone.trigger('context-menu-select', e);
|
||||
},
|
||||
}
|
||||
|
||||
showSingleInstanceAlert() {
|
||||
this.hideOpenFile();
|
||||
|
@ -747,24 +740,24 @@ const AppView = Backbone.View.extend({
|
|||
click: false,
|
||||
buttons: []
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
dragover(e) {
|
||||
e.preventDefault();
|
||||
e.originalEvent.dataTransfer.dropEffect = 'none';
|
||||
},
|
||||
}
|
||||
|
||||
drop(e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
}
|
||||
|
||||
setTheme() {
|
||||
SettingsManager.setTheme(this.model.settings.get('theme'));
|
||||
},
|
||||
}
|
||||
|
||||
setFontSize() {
|
||||
SettingsManager.setFontSize(this.model.settings.get('fontSize'));
|
||||
},
|
||||
}
|
||||
|
||||
setLocale() {
|
||||
SettingsManager.setLocale(this.model.settings.get('locale'));
|
||||
|
@ -773,19 +766,19 @@ const AppView = Backbone.View.extend({
|
|||
this.showSettings();
|
||||
}
|
||||
this.$el.find('.app__beta:first').text(Locale.appBeta);
|
||||
},
|
||||
}
|
||||
|
||||
extLinkClick(e) {
|
||||
if (Launcher) {
|
||||
e.preventDefault();
|
||||
Launcher.openLink(e.target.href);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
bodyClick(e) {
|
||||
IdleTracker.regUserAction();
|
||||
Backbone.trigger('click', e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { AppView };
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Backbone from 'backbone';
|
||||
import { View } from 'view-engine/view';
|
||||
import { Shortcuts } from 'comp/app/shortcuts';
|
||||
import { KeyHandler } from 'comp/browser/key-handler';
|
||||
import { Keys } from 'const/keys';
|
||||
|
@ -7,11 +8,14 @@ import { Features } from 'util/features';
|
|||
import { StringFormat } from 'util/formatting/string-format';
|
||||
import { Locale } from 'util/locale';
|
||||
import { DropdownView } from 'views/dropdown-view';
|
||||
import template from 'templates/list-search.hbs';
|
||||
|
||||
const ListSearchView = Backbone.View.extend({
|
||||
template: require('templates/list-search.hbs'),
|
||||
class ListSearchView extends View {
|
||||
parent = '.list__header';
|
||||
|
||||
events: {
|
||||
template = template;
|
||||
|
||||
events = {
|
||||
'keydown .list__search-field': 'inputKeyDown',
|
||||
'keypress .list__search-field': 'inputKeyPress',
|
||||
'input .list__search-field': 'inputChange',
|
||||
|
@ -21,18 +25,17 @@ const ListSearchView = Backbone.View.extend({
|
|||
'click .list__search-icon-search': 'advancedSearchClick',
|
||||
'click .list__search-btn-menu': 'toggleMenu',
|
||||
'change .list__search-adv input[type=checkbox]': 'toggleAdvCheck'
|
||||
},
|
||||
};
|
||||
|
||||
views: null,
|
||||
inputEl = null;
|
||||
sortOptions = null;
|
||||
sortIcons = null;
|
||||
createOptions = null;
|
||||
advancedSearchEnabled = false;
|
||||
advancedSearch = null;
|
||||
|
||||
inputEl: null,
|
||||
sortOptions: null,
|
||||
sortIcons: null,
|
||||
createOptions: null,
|
||||
advancedSearchEnabled: false,
|
||||
advancedSearch: null,
|
||||
|
||||
initialize() {
|
||||
constructor(model) {
|
||||
super(model);
|
||||
this.sortOptions = [
|
||||
{
|
||||
value: 'title',
|
||||
|
@ -116,24 +119,16 @@ const ListSearchView = Backbone.View.extend({
|
|||
this.advancedSearch = _.extend({}, this.model.advancedSearch);
|
||||
}
|
||||
this.setLocale();
|
||||
KeyHandler.onKey(Keys.DOM_VK_F, this.findKeyPress, this, KeyHandler.SHORTCUT_ACTION);
|
||||
KeyHandler.onKey(Keys.DOM_VK_N, this.newKeyPress, this, KeyHandler.SHORTCUT_OPT);
|
||||
KeyHandler.onKey(Keys.DOM_VK_DOWN, this.downKeyPress, this);
|
||||
KeyHandler.onKey(Keys.DOM_VK_UP, this.upKeyPress, this);
|
||||
this.onKey(Keys.DOM_VK_F, this.findKeyPress, KeyHandler.SHORTCUT_ACTION);
|
||||
this.onKey(Keys.DOM_VK_N, this.newKeyPress, KeyHandler.SHORTCUT_OPT);
|
||||
this.onKey(Keys.DOM_VK_DOWN, this.downKeyPress);
|
||||
this.onKey(Keys.DOM_VK_UP, this.upKeyPress);
|
||||
this.listenTo(this, 'show', this.viewShown);
|
||||
this.listenTo(this, 'hide', this.viewHidden);
|
||||
this.listenTo(Backbone, 'filter', this.filterChanged);
|
||||
this.listenTo(Backbone, 'set-locale', this.setLocale);
|
||||
this.listenTo(Backbone, 'page-blur', this.pageBlur);
|
||||
},
|
||||
|
||||
remove() {
|
||||
KeyHandler.offKey(Keys.DOM_VK_F, this.findKeyPress, this);
|
||||
KeyHandler.offKey(Keys.DOM_VK_N, this.newKeyPress, this);
|
||||
KeyHandler.offKey(Keys.DOM_VK_DOWN, this.downKeyPress, this);
|
||||
KeyHandler.offKey(Keys.DOM_VK_UP, this.upKeyPress, this);
|
||||
Backbone.View.prototype.remove.apply(this);
|
||||
},
|
||||
}
|
||||
|
||||
setLocale() {
|
||||
this.sortOptions.forEach(opt => {
|
||||
|
@ -150,27 +145,29 @@ const ListSearchView = Backbone.View.extend({
|
|||
{ value: 'entry', icon: 'key', text: StringFormat.capFirst(Locale.entry) + entryDesc },
|
||||
{ value: 'group', icon: 'folder', text: StringFormat.capFirst(Locale.group) }
|
||||
];
|
||||
this.render();
|
||||
},
|
||||
if (this.el) {
|
||||
this.render();
|
||||
}
|
||||
}
|
||||
|
||||
pageBlur() {
|
||||
this.inputEl.blur();
|
||||
},
|
||||
}
|
||||
|
||||
viewShown() {
|
||||
this.listenTo(KeyHandler, 'keypress', this.documentKeyPress);
|
||||
},
|
||||
}
|
||||
|
||||
viewHidden() {
|
||||
this.stopListening(KeyHandler, 'keypress', this.documentKeyPress);
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
let searchVal;
|
||||
if (this.inputEl) {
|
||||
searchVal = this.inputEl.val();
|
||||
}
|
||||
this.renderTemplate({
|
||||
super.render({
|
||||
adv: this.advancedSearch,
|
||||
advEnabled: this.advancedSearchEnabled
|
||||
});
|
||||
|
@ -179,7 +176,7 @@ const ListSearchView = Backbone.View.extend({
|
|||
this.inputEl.val(searchVal);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
}
|
||||
|
||||
inputKeyDown(e) {
|
||||
switch (e.which) {
|
||||
|
@ -200,22 +197,22 @@ const ListSearchView = Backbone.View.extend({
|
|||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
},
|
||||
}
|
||||
|
||||
inputKeyPress(e) {
|
||||
e.stopPropagation();
|
||||
},
|
||||
}
|
||||
|
||||
inputChange() {
|
||||
Backbone.trigger('add-filter', { text: this.inputEl.val() });
|
||||
},
|
||||
}
|
||||
|
||||
inputFocus(e) {
|
||||
$(e.target).select();
|
||||
},
|
||||
}
|
||||
|
||||
documentKeyPress(e) {
|
||||
if (this._hidden) {
|
||||
if (this.hidden) {
|
||||
return;
|
||||
}
|
||||
const code = e.charCode;
|
||||
|
@ -227,35 +224,35 @@ const ListSearchView = Backbone.View.extend({
|
|||
this.inputEl[0].setSelectionRange(1, 1);
|
||||
this.inputChange();
|
||||
e.preventDefault();
|
||||
},
|
||||
}
|
||||
|
||||
findKeyPress(e) {
|
||||
if (!this._hidden) {
|
||||
if (!this.hidden) {
|
||||
e.preventDefault();
|
||||
this.hideSearchOptions();
|
||||
this.inputEl.select().focus();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
newKeyPress(e) {
|
||||
if (!this._hidden) {
|
||||
if (!this.hidden) {
|
||||
e.preventDefault();
|
||||
this.hideSearchOptions();
|
||||
this.trigger('create-entry');
|
||||
this.emit('create-entry');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
downKeyPress(e) {
|
||||
e.preventDefault();
|
||||
this.hideSearchOptions();
|
||||
this.trigger('select-next');
|
||||
},
|
||||
this.emit('select-next');
|
||||
}
|
||||
|
||||
upKeyPress(e) {
|
||||
e.preventDefault();
|
||||
this.hideSearchOptions();
|
||||
this.trigger('select-prev');
|
||||
},
|
||||
this.emit('select-prev');
|
||||
}
|
||||
|
||||
filterChanged(filter) {
|
||||
this.hideSearchOptions();
|
||||
|
@ -272,22 +269,22 @@ const ListSearchView = Backbone.View.extend({
|
|||
this.advancedSearchEnabled = adv;
|
||||
this.$el.find('.list__search-adv').toggleClass('hide', !this.advancedSearchEnabled);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
createOptionsClick(e) {
|
||||
e.stopImmediatePropagation();
|
||||
if (e.shiftKey) {
|
||||
this.hideSearchOptions();
|
||||
this.trigger('create-entry');
|
||||
this.emit('create-entry');
|
||||
return;
|
||||
}
|
||||
this.toggleCreateOptions();
|
||||
},
|
||||
}
|
||||
|
||||
sortOptionsClick(e) {
|
||||
this.toggleSortOptions();
|
||||
e.stopImmediatePropagation();
|
||||
},
|
||||
}
|
||||
|
||||
advancedSearchClick() {
|
||||
this.advancedSearchEnabled = !this.advancedSearchEnabled;
|
||||
|
@ -299,17 +296,17 @@ const ListSearchView = Backbone.View.extend({
|
|||
advanced = this.model.advancedSearch;
|
||||
}
|
||||
Backbone.trigger('add-filter', { advanced });
|
||||
},
|
||||
}
|
||||
|
||||
toggleMenu() {
|
||||
Backbone.trigger('toggle-menu');
|
||||
},
|
||||
}
|
||||
|
||||
toggleAdvCheck(e) {
|
||||
const setting = $(e.target).data('id');
|
||||
this.advancedSearch[setting] = e.target.checked;
|
||||
Backbone.trigger('add-filter', { advanced: this.advancedSearch });
|
||||
},
|
||||
}
|
||||
|
||||
hideSearchOptions() {
|
||||
if (this.views.searchDropdown) {
|
||||
|
@ -319,7 +316,7 @@ const ListSearchView = Backbone.View.extend({
|
|||
.find('.list__search-btn-sort,.list__search-btn-new')
|
||||
.removeClass('sel--active');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
toggleSortOptions() {
|
||||
if (this.views.searchDropdown && this.views.searchDropdown.isSort) {
|
||||
|
@ -343,7 +340,7 @@ const ListSearchView = Backbone.View.extend({
|
|||
options: this.sortOptions
|
||||
});
|
||||
this.views.searchDropdown = view;
|
||||
},
|
||||
}
|
||||
|
||||
toggleCreateOptions() {
|
||||
if (this.views.searchDropdown && this.views.searchDropdown.isCreate) {
|
||||
|
@ -365,7 +362,7 @@ const ListSearchView = Backbone.View.extend({
|
|||
options: this.createOptions.concat(this.getCreateEntryTemplateOptions())
|
||||
});
|
||||
this.views.searchDropdown = view;
|
||||
},
|
||||
}
|
||||
|
||||
getCreateEntryTemplateOptions() {
|
||||
const entryTemplates = this.model.getEntryTemplates();
|
||||
|
@ -390,35 +387,35 @@ const ListSearchView = Backbone.View.extend({
|
|||
text: StringFormat.capFirst(Locale.template)
|
||||
});
|
||||
return options;
|
||||
},
|
||||
}
|
||||
|
||||
sortDropdownSelect(e) {
|
||||
this.hideSearchOptions();
|
||||
Backbone.trigger('set-sort', e.item);
|
||||
},
|
||||
}
|
||||
|
||||
createDropdownSelect(e) {
|
||||
this.hideSearchOptions();
|
||||
switch (e.item) {
|
||||
case 'entry':
|
||||
this.trigger('create-entry');
|
||||
this.emit('create-entry');
|
||||
break;
|
||||
case 'group':
|
||||
this.trigger('create-group');
|
||||
this.emit('create-group');
|
||||
break;
|
||||
case 'tmpl':
|
||||
this.trigger('create-template');
|
||||
this.emit('create-template');
|
||||
break;
|
||||
default:
|
||||
if (this.entryTemplates[e.item]) {
|
||||
this.trigger('create-entry', { template: this.entryTemplates[e.item] });
|
||||
this.emit('create-entry', { template: this.entryTemplates[e.item] });
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
addArrow(str) {
|
||||
return str.replace('{}', '→');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { ListSearchView };
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import Backbone from 'backbone';
|
||||
import { View } from 'view-engine/view';
|
||||
import { EntryCollection } from 'collections/entry-collection';
|
||||
import { DragDropInfo } from 'comp/app/drag-drop-info';
|
||||
import { Alerts } from 'comp/ui/alerts';
|
||||
|
@ -10,27 +11,30 @@ import { Resizable } from 'view-engine/resizable';
|
|||
import { Scrollable } from 'view-engine/scrollable';
|
||||
import { DropdownView } from 'views/dropdown-view';
|
||||
import { ListSearchView } from 'views/list-search-view';
|
||||
import template from 'templates/list.hbs';
|
||||
import emptyTemplate from 'templates/list-empty.hbs';
|
||||
|
||||
const ListView = Backbone.View.extend({
|
||||
template: require('templates/list.hbs'),
|
||||
emptyTemplate: require('templates/list-empty.hbs'),
|
||||
class ListView extends View {
|
||||
parent = '.app__list';
|
||||
|
||||
events: {
|
||||
template = template;
|
||||
|
||||
emptyTemplate = emptyTemplate;
|
||||
|
||||
events = {
|
||||
'click .list__item': 'itemClick',
|
||||
'click .list__table-options': 'tableOptionsClick',
|
||||
'dragstart .list__item': 'itemDragStart'
|
||||
},
|
||||
};
|
||||
|
||||
views: null,
|
||||
minWidth = 200;
|
||||
minHeight = 200;
|
||||
maxWidth = 500;
|
||||
maxHeight = 500;
|
||||
|
||||
minWidth: 200,
|
||||
minHeight: 200,
|
||||
maxWidth: 500,
|
||||
maxHeight: 500,
|
||||
itemsEl = null;
|
||||
|
||||
itemsEl: null,
|
||||
|
||||
tableColumns: [
|
||||
tableColumns = [
|
||||
{ val: 'title', name: 'title', enabled: true },
|
||||
{ val: 'user', name: 'user', enabled: true },
|
||||
{ val: 'url', name: 'website', enabled: true },
|
||||
|
@ -38,12 +42,13 @@ const ListView = Backbone.View.extend({
|
|||
{ val: 'notes', name: 'notes', enabled: true },
|
||||
{ val: 'groupName', name: 'group', enabled: false },
|
||||
{ val: 'fileName', name: 'file', enabled: false }
|
||||
],
|
||||
];
|
||||
|
||||
constructor(model) {
|
||||
super(model);
|
||||
|
||||
initialize() {
|
||||
this.initScroll();
|
||||
this.views = {};
|
||||
this.views.search = new ListSearchView({ model: this.model });
|
||||
this.views.search = new ListSearchView(this.model);
|
||||
|
||||
this.listenTo(this.views.search, 'select-prev', this.selectPrev);
|
||||
this.listenTo(this.views.search, 'select-next', this.selectNext);
|
||||
|
@ -62,13 +67,13 @@ const ListView = Backbone.View.extend({
|
|||
this.readTableColumnsEnabled();
|
||||
|
||||
this.items = new EntryCollection();
|
||||
},
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.itemsEl) {
|
||||
this.$el.html(this.template());
|
||||
super.render();
|
||||
this.itemsEl = this.$el.find('.list__items>.scroller');
|
||||
this.views.search.setElement(this.$el.find('.list__header')).render();
|
||||
this.views.search.render();
|
||||
this.setTableView();
|
||||
|
||||
this.createScroll({
|
||||
|
@ -105,7 +110,7 @@ const ListView = Backbone.View.extend({
|
|||
}
|
||||
this.pageResized();
|
||||
return this;
|
||||
},
|
||||
}
|
||||
|
||||
getItemsTemplate() {
|
||||
if (this.model.settings.get('tableView')) {
|
||||
|
@ -113,11 +118,11 @@ const ListView = Backbone.View.extend({
|
|||
} else {
|
||||
return this.renderPlainItems;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
renderPlainItems(itemsHtml) {
|
||||
return itemsHtml.items;
|
||||
},
|
||||
}
|
||||
|
||||
getItemTemplate() {
|
||||
if (this.model.settings.get('tableView')) {
|
||||
|
@ -125,11 +130,11 @@ const ListView = Backbone.View.extend({
|
|||
} else {
|
||||
return require('templates/list-item-short.hbs');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getDescField() {
|
||||
return this.model.sort.replace('-', '');
|
||||
},
|
||||
}
|
||||
|
||||
itemClick(e) {
|
||||
const id = $(e.target)
|
||||
|
@ -140,33 +145,33 @@ const ListView = Backbone.View.extend({
|
|||
this.selectItem(item);
|
||||
}
|
||||
Backbone.trigger('toggle-details', true);
|
||||
},
|
||||
}
|
||||
|
||||
selectPrev() {
|
||||
const ix = this.items.indexOf(this.items.get(this.model.activeEntryId));
|
||||
if (ix > 0) {
|
||||
this.selectItem(this.items.at(ix - 1));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
selectNext() {
|
||||
const ix = this.items.indexOf(this.items.get(this.model.activeEntryId));
|
||||
if (ix < this.items.length - 1) {
|
||||
this.selectItem(this.items.at(ix + 1));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
createEntry(arg) {
|
||||
const newEntry = this.model.createNewEntry(arg);
|
||||
this.items.unshift(newEntry);
|
||||
this.render();
|
||||
this.selectItem(newEntry);
|
||||
},
|
||||
}
|
||||
|
||||
createGroup() {
|
||||
const newGroup = this.model.createNewGroup();
|
||||
Backbone.trigger('edit-group', newGroup);
|
||||
},
|
||||
}
|
||||
|
||||
createTemplate() {
|
||||
if (!this.model.settings.get('templateHelpShown')) {
|
||||
|
@ -189,7 +194,7 @@ const ListView = Backbone.View.extend({
|
|||
this.items.unshift(templateEntry);
|
||||
this.render();
|
||||
this.selectItem(templateEntry);
|
||||
},
|
||||
}
|
||||
|
||||
selectItem(item) {
|
||||
this.model.activeEntryId = item.id;
|
||||
|
@ -205,25 +210,25 @@ const ListView = Backbone.View.extend({
|
|||
} else if (itemRect.bottom > listRect.bottom) {
|
||||
listEl.scrollTop += itemRect.bottom - listRect.bottom;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
viewShown() {
|
||||
this.views.search.show();
|
||||
},
|
||||
}
|
||||
|
||||
viewHidden() {
|
||||
this.views.search.hide();
|
||||
},
|
||||
}
|
||||
|
||||
setTableView() {
|
||||
const isTable = this.model.settings.get('tableView');
|
||||
this.dragView.setCoord(isTable ? 'y' : 'x');
|
||||
this.setDefaultSize();
|
||||
},
|
||||
}
|
||||
|
||||
setDefaultSize() {
|
||||
this.setSize(this.model.settings.get('listViewWidth'));
|
||||
},
|
||||
}
|
||||
|
||||
setSize(size) {
|
||||
this.$el.css({ width: 'auto', height: 'auto' });
|
||||
|
@ -232,27 +237,27 @@ const ListView = Backbone.View.extend({
|
|||
} else {
|
||||
this.$el.css('flex', null);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
viewResized(size) {
|
||||
this.setSize(size);
|
||||
this.throttleSetViewSizeSetting(size);
|
||||
},
|
||||
}
|
||||
|
||||
throttleSetViewSizeSetting: _.throttle(size => {
|
||||
throttleSetViewSizeSetting = _.throttle(size => {
|
||||
AppSettingsModel.instance.set('listViewWidth', size);
|
||||
}, 1000),
|
||||
}, 1000);
|
||||
|
||||
filterChanged(filter) {
|
||||
this.items = filter.entries;
|
||||
this.render();
|
||||
},
|
||||
}
|
||||
|
||||
entryUpdated() {
|
||||
const scrollTop = this.itemsEl[0].scrollTop;
|
||||
this.render();
|
||||
this.itemsEl[0].scrollTop = scrollTop;
|
||||
},
|
||||
}
|
||||
|
||||
itemDragStart(e) {
|
||||
e.stopPropagation();
|
||||
|
@ -262,7 +267,7 @@ const ListView = Backbone.View.extend({
|
|||
e.originalEvent.dataTransfer.setData('text/entry', id);
|
||||
e.originalEvent.dataTransfer.effectAllowed = 'move';
|
||||
DragDropInfo.dragObject = this.items.get(id);
|
||||
},
|
||||
}
|
||||
|
||||
tableOptionsClick(e) {
|
||||
e.stopImmediatePropagation();
|
||||
|
@ -287,14 +292,14 @@ const ListView = Backbone.View.extend({
|
|||
options
|
||||
});
|
||||
this.views.optionsDropdown = view;
|
||||
},
|
||||
}
|
||||
|
||||
hideOptionsDropdown() {
|
||||
if (this.views.optionsDropdown) {
|
||||
this.views.optionsDropdown.remove();
|
||||
delete this.views.optionsDropdown;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
optionsDropdownSelect(e) {
|
||||
const col = _.find(this.tableColumns, c => c.val === e.item);
|
||||
|
@ -302,7 +307,7 @@ const ListView = Backbone.View.extend({
|
|||
e.el.find('i:first').toggleClass('fa-check-square-o fa-square-o');
|
||||
this.render();
|
||||
this.saveTableColumnsEnabled();
|
||||
},
|
||||
}
|
||||
|
||||
readTableColumnsEnabled() {
|
||||
const tableViewColumns = AppSettingsModel.instance.get('tableViewColumns');
|
||||
|
@ -311,7 +316,7 @@ const ListView = Backbone.View.extend({
|
|||
col.enabled = tableViewColumns.indexOf(col.name) >= 0;
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
saveTableColumnsEnabled() {
|
||||
const tableViewColumns = this.tableColumns
|
||||
|
@ -319,9 +324,9 @@ const ListView = Backbone.View.extend({
|
|||
.map(column => column.name);
|
||||
AppSettingsModel.instance.set('tableViewColumns', tableViewColumns);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_.extend(ListView.prototype, Resizable);
|
||||
_.extend(ListView.prototype, Scrollable);
|
||||
Object.assign(ListView.prototype, Resizable);
|
||||
Object.assign(ListView.prototype, Scrollable);
|
||||
|
||||
export { ListView };
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
import Backbone from 'backbone';
|
||||
import { View } from 'view-engine/view';
|
||||
import { DragDropInfo } from 'comp/app/drag-drop-info';
|
||||
import { KeyHandler } from 'comp/browser/key-handler';
|
||||
import { Alerts } from 'comp/ui/alerts';
|
||||
import { Keys } from 'const/keys';
|
||||
import { Locale } from 'util/locale';
|
||||
import template from 'templates/menu/menu-item.hbs';
|
||||
|
||||
const MenuItemView = Backbone.View.extend({
|
||||
template: require('templates/menu/menu-item.hbs'),
|
||||
class MenuItemView extends View {
|
||||
template = template;
|
||||
|
||||
events: {
|
||||
events = {
|
||||
'mouseover': 'mouseover',
|
||||
'mouseout': 'mouseout',
|
||||
'click .menu__item-option': 'selectOption',
|
||||
|
@ -22,12 +24,13 @@ const MenuItemView = Backbone.View.extend({
|
|||
'drop': 'drop',
|
||||
'dragover .menu__item-drag-top': 'dragoverTop',
|
||||
'dragleave .menu__item-drag-top': 'dragleaveTop'
|
||||
},
|
||||
};
|
||||
|
||||
iconEl: null,
|
||||
itemViews: null,
|
||||
iconEl = null;
|
||||
itemViews = null;
|
||||
|
||||
initialize() {
|
||||
constructor(model, options) {
|
||||
super(model, options);
|
||||
this.itemViews = [];
|
||||
this.listenTo(this.model, 'change:title', this.changeTitle);
|
||||
this.listenTo(this.model, 'change:icon', this.changeIcon);
|
||||
|
@ -39,70 +42,62 @@ const MenuItemView = Backbone.View.extend({
|
|||
this.listenTo(this.model, 'insert', this.insertItem);
|
||||
const shortcut = this.model.get('shortcut');
|
||||
if (shortcut) {
|
||||
KeyHandler.onKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_OPT);
|
||||
this.onKey(shortcut, this.selectItem, KeyHandler.SHORTCUT_OPT);
|
||||
if (shortcut !== Keys.DOM_VK_C) {
|
||||
KeyHandler.onKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_ACTION);
|
||||
this.onKey(shortcut, this.selectItem, KeyHandler.SHORTCUT_ACTION);
|
||||
}
|
||||
}
|
||||
},
|
||||
this.once('remove', () => {
|
||||
this.removeInnerViews();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
this.removeInnerViews();
|
||||
this.renderTemplate(this.model.attributes);
|
||||
super.render(this.model.attributes);
|
||||
this.iconEl = this.$el.find('.menu__item-icon');
|
||||
const items = this.model.get('items');
|
||||
if (items) {
|
||||
items.forEach(function(item) {
|
||||
items.forEach(item => {
|
||||
if (item.get('visible')) {
|
||||
this.insertItem(item);
|
||||
}
|
||||
}, this);
|
||||
});
|
||||
}
|
||||
this.$el.toggleClass('menu__item--collapsed', !this.model.get('expanded'));
|
||||
return this;
|
||||
},
|
||||
}
|
||||
|
||||
insertItem(item) {
|
||||
this.itemViews.push(new MenuItemView({ el: this.$el, model: item }).render());
|
||||
},
|
||||
|
||||
remove() {
|
||||
this.removeInnerViews();
|
||||
const shortcut = this.model.get('shortcut');
|
||||
if (shortcut) {
|
||||
KeyHandler.offKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_OPT);
|
||||
if (shortcut !== Keys.DOM_VK_C) {
|
||||
KeyHandler.offKey(shortcut, this.selectItem, this, KeyHandler.SHORTCUT_ACTION);
|
||||
}
|
||||
}
|
||||
Backbone.View.prototype.remove.apply(this);
|
||||
},
|
||||
const itemView = new MenuItemView(item, { parent: this.el });
|
||||
itemView.render();
|
||||
this.itemViews.push(itemView);
|
||||
}
|
||||
|
||||
removeInnerViews() {
|
||||
this.itemViews.forEach(itemView => itemView.remove());
|
||||
this.itemViews = [];
|
||||
},
|
||||
}
|
||||
|
||||
changeTitle(model, title) {
|
||||
this.$el
|
||||
.find('.menu__item-title')
|
||||
.first()
|
||||
.text(title || '(no title)');
|
||||
},
|
||||
}
|
||||
|
||||
changeIcon(model, icon) {
|
||||
this.iconEl[0].className =
|
||||
'menu__item-icon fa ' + (icon ? 'fa-' + icon : 'menu__item-icon--no-icon');
|
||||
},
|
||||
}
|
||||
|
||||
changeActive(model, active) {
|
||||
this.$el.toggleClass('menu__item--active', active);
|
||||
},
|
||||
}
|
||||
|
||||
changeExpanded(model, expanded) {
|
||||
this.$el.toggleClass('menu__item--collapsed', !expanded);
|
||||
this.model.setExpanded(expanded);
|
||||
},
|
||||
}
|
||||
|
||||
changeCls(model, cls) {
|
||||
const oldCls = model.previousAttributes().cls;
|
||||
|
@ -110,19 +105,19 @@ const MenuItemView = Backbone.View.extend({
|
|||
this.$el.removeClass(oldCls);
|
||||
}
|
||||
this.$el.addClass(cls);
|
||||
},
|
||||
}
|
||||
|
||||
mouseover(e) {
|
||||
if (!e.button) {
|
||||
this.$el.addClass('menu__item--hover');
|
||||
e.stopPropagation();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
mouseout(e) {
|
||||
this.$el.removeClass('menu__item--hover');
|
||||
e.stopPropagation();
|
||||
},
|
||||
}
|
||||
|
||||
selectItem(e) {
|
||||
e.stopPropagation();
|
||||
|
@ -135,7 +130,7 @@ const MenuItemView = Backbone.View.extend({
|
|||
} else {
|
||||
Backbone.trigger('menu-select', { item: this.model });
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
selectOption(e) {
|
||||
const options = this.model.get('options');
|
||||
|
@ -148,14 +143,14 @@ const MenuItemView = Backbone.View.extend({
|
|||
}
|
||||
e.stopImmediatePropagation();
|
||||
e.preventDefault();
|
||||
},
|
||||
}
|
||||
|
||||
expandItem(e) {
|
||||
if (this.model.toggleExpanded) {
|
||||
this.model.toggleExpanded();
|
||||
}
|
||||
e.stopPropagation();
|
||||
},
|
||||
}
|
||||
|
||||
editItem(e) {
|
||||
if (this.model.get('active') && this.model.get('editable')) {
|
||||
|
@ -169,7 +164,7 @@ const MenuItemView = Backbone.View.extend({
|
|||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
emptyTrash(e) {
|
||||
e.stopPropagation();
|
||||
|
@ -181,7 +176,7 @@ const MenuItemView = Backbone.View.extend({
|
|||
Backbone.trigger('empty-trash');
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
dropAllowed(e) {
|
||||
const types = e.originalEvent.dataTransfer.types;
|
||||
|
@ -191,7 +186,7 @@ const MenuItemView = Backbone.View.extend({
|
|||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
dragstart(e) {
|
||||
e.stopPropagation();
|
||||
|
@ -200,7 +195,7 @@ const MenuItemView = Backbone.View.extend({
|
|||
e.originalEvent.dataTransfer.effectAllowed = 'move';
|
||||
DragDropInfo.dragObject = this.model;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
dragover(e) {
|
||||
if (this.model.get('drop') && this.dropAllowed(e)) {
|
||||
|
@ -208,14 +203,14 @@ const MenuItemView = Backbone.View.extend({
|
|||
e.preventDefault();
|
||||
this.$el.addClass('menu__item--drag');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
dragleave(e) {
|
||||
e.stopPropagation();
|
||||
if (this.model.get('drop') && this.dropAllowed(e)) {
|
||||
this.$el.removeClass('menu__item--drag menu__item--drag-top');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
drop(e) {
|
||||
e.stopPropagation();
|
||||
|
@ -233,7 +228,7 @@ const MenuItemView = Backbone.View.extend({
|
|||
}
|
||||
Backbone.trigger('refresh');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
dropTopAllowed(e) {
|
||||
const types = e.originalEvent.dataTransfer.types;
|
||||
|
@ -243,19 +238,19 @@ const MenuItemView = Backbone.View.extend({
|
|||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}
|
||||
|
||||
dragoverTop(e) {
|
||||
if (this.dropTopAllowed(e)) {
|
||||
this.$el.addClass('menu__item--drag-top');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
dragleaveTop(e) {
|
||||
if (this.dropTopAllowed(e)) {
|
||||
this.$el.removeClass('menu__item--drag-top');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { MenuItemView };
|
||||
|
|
|
@ -1,31 +1,36 @@
|
|||
import Backbone from 'backbone';
|
||||
import { View } from 'view-engine/view';
|
||||
import { AppSettingsModel } from 'models/app-settings-model';
|
||||
import { Resizable } from 'view-engine/resizable';
|
||||
import { Scrollable } from 'view-engine/scrollable';
|
||||
import { MenuItemView } from 'views/menu/menu-item-view';
|
||||
import template from 'templates/menu/menu-section.hbs';
|
||||
|
||||
const MenuSectionView = Backbone.View.extend({
|
||||
template: require('templates/menu/menu-section.hbs'),
|
||||
class MenuSectionView extends View {
|
||||
template = template;
|
||||
|
||||
events: {},
|
||||
events = {};
|
||||
|
||||
itemViews: null,
|
||||
itemViews = null;
|
||||
|
||||
minHeight: 55,
|
||||
maxHeight() {
|
||||
return this.$el.parent().height() - 116;
|
||||
},
|
||||
autoHeight: 'auto',
|
||||
minHeight = 55;
|
||||
autoHeigh = 'auto';
|
||||
|
||||
initialize() {
|
||||
constructor(model, options) {
|
||||
super(model, options);
|
||||
this.itemViews = [];
|
||||
this.listenTo(this.model, 'change-items', this.itemsChanged);
|
||||
this.listenTo(this, 'view-resize', this.viewResized);
|
||||
},
|
||||
this.once('remove', () => {
|
||||
if (this.scroll) {
|
||||
this.scroll.dispose();
|
||||
}
|
||||
this.removeInnerViews();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (!this.itemsEl) {
|
||||
this.renderTemplate(this.model.attributes);
|
||||
super.render(this.model.attributes);
|
||||
this.itemsEl = this.model.get('scrollable') ? this.$el.find('.scroller') : this.$el;
|
||||
if (this.model.get('scrollable')) {
|
||||
this.initScroll();
|
||||
|
@ -38,11 +43,11 @@ const MenuSectionView = Backbone.View.extend({
|
|||
} else {
|
||||
this.removeInnerViews();
|
||||
}
|
||||
this.model.get('items').forEach(function(item) {
|
||||
const itemView = new MenuItemView({ el: this.itemsEl, model: item });
|
||||
this.model.get('items').forEach(item => {
|
||||
const itemView = new MenuItemView(item, { parent: this.itemsEl[0] });
|
||||
itemView.render();
|
||||
this.itemViews.push(itemView);
|
||||
}, this);
|
||||
});
|
||||
if (this.model.get('drag')) {
|
||||
const height = AppSettingsModel.instance.get('tagsViewHeight');
|
||||
if (typeof height === 'number') {
|
||||
|
@ -51,36 +56,32 @@ const MenuSectionView = Backbone.View.extend({
|
|||
}
|
||||
}
|
||||
this.pageResized();
|
||||
},
|
||||
}
|
||||
|
||||
remove() {
|
||||
if (this.scroll) {
|
||||
this.scroll.dispose();
|
||||
}
|
||||
this.removeInnerViews();
|
||||
Backbone.View.prototype.remove.apply(this);
|
||||
},
|
||||
maxHeight() {
|
||||
return this.$el.parent().height() - 116;
|
||||
}
|
||||
|
||||
removeInnerViews() {
|
||||
this.itemViews.forEach(itemView => itemView.remove());
|
||||
this.itemViews = [];
|
||||
},
|
||||
}
|
||||
|
||||
itemsChanged() {
|
||||
this.render();
|
||||
},
|
||||
}
|
||||
|
||||
viewResized(size) {
|
||||
this.$el.css('flex', '0 0 ' + (size ? size + 'px' : 'auto'));
|
||||
this.saveViewHeight(size);
|
||||
},
|
||||
}
|
||||
|
||||
saveViewHeight: _.throttle(size => {
|
||||
saveViewHeight = _.throttle(size => {
|
||||
AppSettingsModel.instance.set('tagsViewHeight', size);
|
||||
}, 1000)
|
||||
});
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
_.extend(MenuSectionView.prototype, Resizable);
|
||||
_.extend(MenuSectionView.prototype, Scrollable);
|
||||
Object.assign(MenuSectionView.prototype, Resizable);
|
||||
Object.assign(MenuSectionView.prototype, Scrollable);
|
||||
|
||||
export { MenuSectionView };
|
||||
|
|
|
@ -1,49 +1,50 @@
|
|||
import Backbone from 'backbone';
|
||||
import { View } from 'view-engine/view';
|
||||
import { KeyHandler } from 'comp/browser/key-handler';
|
||||
import { Keys } from 'const/keys';
|
||||
import { AppSettingsModel } from 'models/app-settings-model';
|
||||
import { Resizable } from 'view-engine/resizable';
|
||||
import { DragView } from 'views/drag-view';
|
||||
import { MenuSectionView } from 'views/menu/menu-section-view';
|
||||
import template from 'templates/menu/menu.hbs';
|
||||
|
||||
const MenuView = Backbone.View.extend({
|
||||
template: require('templates/menu/menu.hbs'),
|
||||
class MenuView extends View {
|
||||
parent = '.app__menu';
|
||||
|
||||
events: {},
|
||||
template = template;
|
||||
|
||||
sectionViews: [],
|
||||
events = {};
|
||||
|
||||
minWidth: 130,
|
||||
maxWidth: 300,
|
||||
sectionViews = [];
|
||||
|
||||
initialize() {
|
||||
minWidth = 130;
|
||||
maxWidth = 300;
|
||||
|
||||
constructor(model, options) {
|
||||
super(model, options);
|
||||
this.listenTo(this.model, 'change:sections', this.menuChanged);
|
||||
this.listenTo(this, 'view-resize', this.viewResized);
|
||||
KeyHandler.onKey(
|
||||
this.onKey(
|
||||
Keys.DOM_VK_UP,
|
||||
this.selectPreviousSection,
|
||||
this,
|
||||
KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT
|
||||
);
|
||||
KeyHandler.onKey(
|
||||
this.onKey(
|
||||
Keys.DOM_VK_DOWN,
|
||||
this.selectNextSection,
|
||||
this,
|
||||
KeyHandler.SHORTCUT_ACTION + KeyHandler.SHORTCUT_OPT
|
||||
);
|
||||
},
|
||||
|
||||
remove() {
|
||||
this.sectionViews.forEach(sectionView => sectionView.remove());
|
||||
this.sectionViews = [];
|
||||
Backbone.View.prototype.remove.apply(this);
|
||||
},
|
||||
this.once('remove', () => {
|
||||
this.sectionViews.forEach(sectionView => sectionView.remove());
|
||||
this.sectionViews = [];
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
this.$el.html(this.template());
|
||||
super.render();
|
||||
const sectionsEl = this.$el.find('.menu');
|
||||
this.model.get('sections').forEach(function(section) {
|
||||
const sectionView = new MenuSectionView({ el: sectionsEl, model: section });
|
||||
const sectionView = new MenuSectionView(section, { parent: sectionsEl[0] });
|
||||
sectionView.render();
|
||||
if (section.get('drag')) {
|
||||
const dragEl = $('<div/>')
|
||||
|
@ -60,29 +61,29 @@ const MenuView = Backbone.View.extend({
|
|||
this.$el.width(AppSettingsModel.instance.get('menuViewWidth'));
|
||||
}
|
||||
return this;
|
||||
},
|
||||
}
|
||||
|
||||
menuChanged() {
|
||||
this.render();
|
||||
},
|
||||
}
|
||||
|
||||
viewResized: _.throttle(size => {
|
||||
viewResized = _.throttle(size => {
|
||||
AppSettingsModel.instance.set('menuViewWidth', size);
|
||||
}, 1000),
|
||||
}, 1000);
|
||||
|
||||
switchVisibility(visible) {
|
||||
this.$el.toggleClass('menu-visible', visible);
|
||||
},
|
||||
}
|
||||
|
||||
selectPreviousSection() {
|
||||
Backbone.trigger('select-previous-menu-item');
|
||||
},
|
||||
}
|
||||
|
||||
selectNextSection() {
|
||||
Backbone.trigger('select-next-menu-item');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_.extend(MenuView.prototype, Resizable);
|
||||
Object.assign(MenuView.prototype, Resizable);
|
||||
|
||||
export { MenuView };
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import Backbone from 'backbone';
|
||||
import kdbxweb from 'kdbxweb';
|
||||
import { View } from 'view-engine/view';
|
||||
import { Storage } from 'storage';
|
||||
import { DropboxChooser } from 'comp/app/dropbox-chooser';
|
||||
import { FocusDetector } from 'comp/browser/focus-detector';
|
||||
|
@ -16,13 +17,16 @@ import { Logger } from 'util/logger';
|
|||
import { InputFx } from 'util/ui/input-fx';
|
||||
import { OpenConfigView } from 'views/open-config-view';
|
||||
import { StorageFileListView } from 'views/storage-file-list-view';
|
||||
import template from 'templates/open.hbs';
|
||||
|
||||
const logger = new Logger('open-view');
|
||||
|
||||
const OpenView = Backbone.View.extend({
|
||||
template: require('templates/open.hbs'),
|
||||
class OpenView extends View {
|
||||
parent = '.app__body';
|
||||
|
||||
events: {
|
||||
template = template;
|
||||
|
||||
events = {
|
||||
'change .open__file-ctrl': 'fileSelected',
|
||||
'click .open__icon-open': 'openFile',
|
||||
'click .open__icon-new': 'createNew',
|
||||
|
@ -30,7 +34,7 @@ const OpenView = Backbone.View.extend({
|
|||
'click .open__icon-more': 'toggleMore',
|
||||
'click .open__icon-storage': 'openStorage',
|
||||
'click .open__icon-settings': 'openSettings',
|
||||
'click .open__pass-input[readonly]': 'openFile',
|
||||
'click .open__pass-input': 'passInputClick',
|
||||
'input .open__pass-input': 'inputInput',
|
||||
'keydown .open__pass-input': 'inputKeydown',
|
||||
'keyup .open__pass-input': 'inputKeyup',
|
||||
|
@ -38,39 +42,34 @@ const OpenView = Backbone.View.extend({
|
|||
'click .open__pass-enter-btn': 'openDb',
|
||||
'click .open__settings-key-file': 'openKeyFile',
|
||||
'click .open__last-item': 'openLast',
|
||||
'dragover': 'dragover',
|
||||
'dragleave': 'dragleave',
|
||||
'drop': 'drop'
|
||||
},
|
||||
dragover: 'dragover',
|
||||
dragleave: 'dragleave',
|
||||
drop: 'drop'
|
||||
};
|
||||
|
||||
views: null,
|
||||
params: null,
|
||||
passwordInput: null,
|
||||
busy: false,
|
||||
currentSelectedIndex: -1,
|
||||
params = null;
|
||||
|
||||
initialize() {
|
||||
this.views = {};
|
||||
this.params = {
|
||||
id: null,
|
||||
name: '',
|
||||
storage: null,
|
||||
path: null,
|
||||
keyFileName: null,
|
||||
keyFileData: null,
|
||||
keyFilePath: null,
|
||||
fileData: null,
|
||||
rev: null
|
||||
};
|
||||
passwordInput = null;
|
||||
|
||||
busy = false;
|
||||
|
||||
currentSelectedIndex = -1;
|
||||
|
||||
constructor(model) {
|
||||
super(model);
|
||||
this.resetParams();
|
||||
this.passwordInput = new SecureInput();
|
||||
KeyHandler.onKey(Keys.DOM_VK_Z, this.undoKeyPress, this, KeyHandler.SHORTCUT_ACTION);
|
||||
KeyHandler.onKey(Keys.DOM_VK_TAB, this.tabKeyPress, this);
|
||||
KeyHandler.onKey(Keys.DOM_VK_ENTER, this.enterKeyPress, this);
|
||||
KeyHandler.onKey(Keys.DOM_VK_RETURN, this.enterKeyPress, this);
|
||||
KeyHandler.onKey(Keys.DOM_VK_DOWN, this.moveOpenFileSelectionDown, this);
|
||||
KeyHandler.onKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp, this);
|
||||
this.onKey(Keys.DOM_VK_Z, this.undoKeyPress, KeyHandler.SHORTCUT_ACTION);
|
||||
this.onKey(Keys.DOM_VK_TAB, this.tabKeyPress);
|
||||
this.onKey(Keys.DOM_VK_ENTER, this.enterKeyPress);
|
||||
this.onKey(Keys.DOM_VK_RETURN, this.enterKeyPress);
|
||||
this.onKey(Keys.DOM_VK_DOWN, this.moveOpenFileSelectionDown);
|
||||
this.onKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp);
|
||||
this.listenTo(Backbone, 'main-window-focus', this.windowFocused.bind(this));
|
||||
},
|
||||
this.once('reset', () => {
|
||||
this.passwordInput.reset();
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.dragTimeout) {
|
||||
|
@ -90,7 +89,7 @@ const OpenView = Backbone.View.extend({
|
|||
!this.model.settings.get('canOpen') &&
|
||||
!this.model.settings.get('canCreate') &&
|
||||
!(this.model.settings.get('canOpenDemo') && !this.model.settings.get('demoOpened'));
|
||||
this.renderTemplate({
|
||||
super.render({
|
||||
lastOpenFiles: this.getLastOpenFiles(),
|
||||
canOpenKeyFromDropbox: !Launcher && Storage.dropbox.enabled,
|
||||
demoOpened: this.model.settings.get('demoOpened'),
|
||||
|
@ -106,17 +105,31 @@ const OpenView = Backbone.View.extend({
|
|||
this.inputEl = this.$el.find('.open__pass-input');
|
||||
this.passwordInput.setElement(this.inputEl);
|
||||
return this;
|
||||
},
|
||||
}
|
||||
|
||||
resetParams() {
|
||||
this.params = {
|
||||
id: null,
|
||||
name: '',
|
||||
storage: null,
|
||||
path: null,
|
||||
keyFileName: null,
|
||||
keyFileData: null,
|
||||
keyFilePath: null,
|
||||
fileData: null,
|
||||
rev: null
|
||||
};
|
||||
}
|
||||
|
||||
windowFocused() {
|
||||
this.inputEl.focus();
|
||||
},
|
||||
}
|
||||
|
||||
focusInput(focusOnMobile) {
|
||||
if (FocusDetector.hasFocus() && (focusOnMobile || !Features.isMobile)) {
|
||||
this.inputEl.focus();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getLastOpenFiles() {
|
||||
return this.model.fileInfos.map(f => {
|
||||
|
@ -136,7 +149,7 @@ const OpenView = Backbone.View.extend({
|
|||
iconSvg: storage ? storage.iconSvg : undefined
|
||||
};
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
getDisplayedPath(fileInfo) {
|
||||
const storage = fileInfo.get('storage');
|
||||
|
@ -144,18 +157,7 @@ const OpenView = Backbone.View.extend({
|
|||
return fileInfo.get('path');
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
remove() {
|
||||
this.passwordInput.reset();
|
||||
KeyHandler.offKey(Keys.DOM_VK_Z, this.undoKeyPress, this);
|
||||
KeyHandler.offKey(Keys.DOM_VK_TAB, this.tabKeyPress, this);
|
||||
KeyHandler.offKey(Keys.DOM_VK_ENTER, this.enterKeyPress, this);
|
||||
KeyHandler.offKey(Keys.DOM_VK_RETURN, this.enterKeyPress, this);
|
||||
KeyHandler.offKey(Keys.DOM_VK_DOWN, this.moveOpenFileSelectionDown, this);
|
||||
KeyHandler.offKey(Keys.DOM_VK_UP, this.moveOpenFileSelectionUp, this);
|
||||
Backbone.View.prototype.remove.apply(this);
|
||||
},
|
||||
}
|
||||
|
||||
showLocalFileAlert() {
|
||||
if (this.model.settings.get('skipOpenLocalWarn')) {
|
||||
|
@ -179,7 +181,7 @@ const OpenView = Backbone.View.extend({
|
|||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
fileSelected(e) {
|
||||
const file = e.target.files[0];
|
||||
|
@ -190,7 +192,7 @@ const OpenView = Backbone.View.extend({
|
|||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
processFile(file, complete) {
|
||||
const reader = new FileReader();
|
||||
|
@ -264,7 +266,7 @@ const OpenView = Backbone.View.extend({
|
|||
} else {
|
||||
reader.readAsArrayBuffer(file);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
getOpenFileFormat(fileData) {
|
||||
if (fileData.byteLength < 8) {
|
||||
|
@ -290,7 +292,7 @@ const OpenView = Backbone.View.extend({
|
|||
} else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
displayOpenFile() {
|
||||
this.$el.addClass('open--file');
|
||||
|
@ -298,7 +300,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.inputEl[0].removeAttribute('readonly');
|
||||
this.inputEl[0].setAttribute('placeholder', Locale.openPassFor + ' ' + this.params.name);
|
||||
this.focusInput();
|
||||
},
|
||||
}
|
||||
|
||||
displayOpenKeyFile() {
|
||||
this.$el.toggleClass('open--key-file', !!this.params.keyFileName);
|
||||
|
@ -306,7 +308,7 @@ const OpenView = Backbone.View.extend({
|
|||
.find('.open__settings-key-file-name')
|
||||
.text(this.params.keyFileName || this.params.keyFilePath || Locale.openKeyFile);
|
||||
this.focusInput();
|
||||
},
|
||||
}
|
||||
|
||||
setFile(file, keyFile, fileReadyCallback) {
|
||||
this.reading = 'fileData';
|
||||
|
@ -319,7 +321,13 @@ const OpenView = Backbone.View.extend({
|
|||
fileReadyCallback();
|
||||
}
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
passInputClick(e) {
|
||||
if (e.target.readOnly) {
|
||||
this.openFile();
|
||||
}
|
||||
}
|
||||
|
||||
openFile() {
|
||||
if (this.model.settings.get('canOpen') === false) {
|
||||
|
@ -329,7 +337,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.closeConfig();
|
||||
this.openAny('fileData');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
openKeyFile(e) {
|
||||
if ($(e.target).hasClass('open__settings-key-file-dropbox')) {
|
||||
|
@ -345,7 +353,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.openAny('keyFileData');
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
openKeyFileFromDropbox() {
|
||||
if (!this.busy) {
|
||||
|
@ -358,7 +366,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.displayOpenKeyFile();
|
||||
}).choose();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
openAny(reading, ext) {
|
||||
this.reading = reading;
|
||||
|
@ -380,7 +388,7 @@ const OpenView = Backbone.View.extend({
|
|||
} else {
|
||||
fileInput.click();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
openLast(e) {
|
||||
if (this.busy) {
|
||||
|
@ -414,14 +422,14 @@ const OpenView = Backbone.View.extend({
|
|||
|
||||
const fileInfo = this.model.fileInfos.get(id);
|
||||
this.showOpenFileInfo(fileInfo, true);
|
||||
},
|
||||
}
|
||||
|
||||
removeFile(id) {
|
||||
this.model.removeFileInfo(id);
|
||||
this.$el.find('.open__last-item[data-id="' + id + '"]').remove();
|
||||
this.initialize();
|
||||
this.resetParams();
|
||||
this.render();
|
||||
},
|
||||
}
|
||||
|
||||
inputKeydown(e) {
|
||||
const code = e.keyCode || e.which;
|
||||
|
@ -430,14 +438,14 @@ const OpenView = Backbone.View.extend({
|
|||
} else if (code === Keys.DOM_VK_CAPS_LOCK) {
|
||||
this.toggleCapsLockWarning(false);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
inputKeyup(e) {
|
||||
const code = e.keyCode || e.which;
|
||||
if (code === Keys.DOM_VK_CAPS_LOCK) {
|
||||
this.toggleCapsLockWarning(false);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
inputKeypress(e) {
|
||||
const charCode = e.keyCode || e.which;
|
||||
|
@ -447,11 +455,11 @@ const OpenView = Backbone.View.extend({
|
|||
if (lower !== upper && !e.shiftKey) {
|
||||
this.toggleCapsLockWarning(ch !== lower);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
toggleCapsLockWarning(on) {
|
||||
this.$el.find('.open__pass-warning').toggleClass('invisible', !on);
|
||||
},
|
||||
}
|
||||
|
||||
dragover(e) {
|
||||
if (this.model.settings.get('canOpen') === false) {
|
||||
|
@ -474,7 +482,7 @@ const OpenView = Backbone.View.extend({
|
|||
if (!this.$el.hasClass('open--drag')) {
|
||||
this.$el.addClass('open--drag');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
dragleave() {
|
||||
if (this.model.settings.get('canOpen') === false) {
|
||||
|
@ -486,7 +494,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.dragTimeout = setTimeout(() => {
|
||||
this.$el.removeClass('open--drag');
|
||||
}, 100);
|
||||
},
|
||||
}
|
||||
|
||||
drop(e) {
|
||||
if (this.model.settings.get('canOpen') === false) {
|
||||
|
@ -516,22 +524,22 @@ const OpenView = Backbone.View.extend({
|
|||
this.setFile(xmlFile, null, this.showLocalFileAlert.bind(this));
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
undoKeyPress(e) {
|
||||
e.preventDefault();
|
||||
},
|
||||
}
|
||||
|
||||
tabKeyPress() {
|
||||
this.$el.addClass('open--show-focus');
|
||||
},
|
||||
}
|
||||
|
||||
enterKeyPress(e) {
|
||||
const el = this.$el.find('[tabindex]:focus');
|
||||
if (el.length) {
|
||||
el.trigger('click', e);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
showOpenFileInfo(fileInfo, fileWasClicked) {
|
||||
if (this.busy || !fileInfo) {
|
||||
|
@ -554,7 +562,7 @@ const OpenView = Backbone.View.extend({
|
|||
if (fileWasClicked) {
|
||||
this.focusInput(true);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
showOpenLocalFile(path, keyFilePath) {
|
||||
if (this.busy) {
|
||||
|
@ -574,7 +582,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.params.keyFileData = null;
|
||||
this.displayOpenKeyFile();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
openFileWithFingerprint(fileInfo) {
|
||||
if (!fileInfo.has('fingerprint')) {
|
||||
|
@ -588,29 +596,29 @@ const OpenView = Backbone.View.extend({
|
|||
this.openDb();
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
createDemo() {
|
||||
if (!this.busy) {
|
||||
this.closeConfig();
|
||||
if (!this.model.createDemoFile()) {
|
||||
this.trigger('close');
|
||||
this.emit('close');
|
||||
}
|
||||
if (!this.model.settings.get('demoOpened')) {
|
||||
this.model.settings.set('demoOpened', true);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
createNew() {
|
||||
if (!this.busy) {
|
||||
this.model.createNewFile();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
openDb() {
|
||||
if (this.params.id && this.model.files.get(this.params.id)) {
|
||||
this.trigger('close');
|
||||
this.emit('close');
|
||||
return;
|
||||
}
|
||||
if (this.busy || !this.params.name) {
|
||||
|
@ -623,7 +631,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.afterPaint(
|
||||
this.model.openFile.bind(this.model, this.params, this.openDbComplete.bind(this))
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
openDbComplete(err) {
|
||||
this.busy = false;
|
||||
|
@ -650,9 +658,9 @@ const OpenView = Backbone.View.extend({
|
|||
});
|
||||
}
|
||||
} else {
|
||||
this.trigger('close');
|
||||
this.emit('close');
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
importDbWithXml() {
|
||||
if (this.busy || !this.params.name) {
|
||||
|
@ -670,7 +678,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.openDbComplete(err);
|
||||
})
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
toggleMore() {
|
||||
if (this.busy) {
|
||||
|
@ -678,11 +686,11 @@ const OpenView = Backbone.View.extend({
|
|||
}
|
||||
this.closeConfig();
|
||||
this.$el.find('.open__icons--lower').toggleClass('hide');
|
||||
},
|
||||
}
|
||||
|
||||
openSettings() {
|
||||
Backbone.trigger('toggle-settings');
|
||||
},
|
||||
}
|
||||
|
||||
openStorage(e) {
|
||||
if (this.busy) {
|
||||
|
@ -704,7 +712,7 @@ const OpenView = Backbone.View.extend({
|
|||
} else {
|
||||
Alerts.notImplemented();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
listStorage(storage, config) {
|
||||
if (this.busy) {
|
||||
|
@ -778,7 +786,7 @@ const OpenView = Backbone.View.extend({
|
|||
view: listView
|
||||
});
|
||||
});
|
||||
},
|
||||
}
|
||||
|
||||
openStorageFile(storage, file) {
|
||||
if (this.busy) {
|
||||
|
@ -791,7 +799,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.params.rev = file.rev;
|
||||
this.params.fileData = null;
|
||||
this.displayOpenFile();
|
||||
},
|
||||
}
|
||||
|
||||
showConfig(storage) {
|
||||
if (this.busy) {
|
||||
|
@ -817,7 +825,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.views.openConfig.render();
|
||||
this.$el.find('.open__pass-area').addClass('hide');
|
||||
this.$el.find('.open__icons--lower').addClass('hide');
|
||||
},
|
||||
}
|
||||
|
||||
closeConfig() {
|
||||
if (this.busy) {
|
||||
|
@ -831,7 +839,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.$el.find('.open__pass-area').removeClass('hide');
|
||||
this.$el.find('.open__config').addClass('hide');
|
||||
this.focusInput();
|
||||
},
|
||||
}
|
||||
|
||||
applyConfig(config) {
|
||||
if (this.busy || !config) {
|
||||
|
@ -854,7 +862,7 @@ const OpenView = Backbone.View.extend({
|
|||
} else {
|
||||
storage.stat(path, opts, this.storageStatComplete.bind(this, req));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
storageApplyConfigComplete(req, err) {
|
||||
if (this.storageWaitId !== req.waitId) {
|
||||
|
@ -868,7 +876,7 @@ const OpenView = Backbone.View.extend({
|
|||
} else {
|
||||
this.closeConfig();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
storageStatComplete(req, err, stat) {
|
||||
if (this.storageWaitId !== req.waitId) {
|
||||
|
@ -890,7 +898,7 @@ const OpenView = Backbone.View.extend({
|
|||
this.params.fileData = null;
|
||||
this.displayOpenFile();
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
moveOpenFileSelection(steps) {
|
||||
const lastOpenFiles = this.getLastOpenFiles();
|
||||
|
@ -911,15 +919,15 @@ const OpenView = Backbone.View.extend({
|
|||
if (fileInfo && Launcher && Launcher.fingerprints) {
|
||||
this.openFileWithFingerprint(fileInfo);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
moveOpenFileSelectionDown() {
|
||||
this.moveOpenFileSelection(1);
|
||||
},
|
||||
}
|
||||
|
||||
moveOpenFileSelectionUp() {
|
||||
this.moveOpenFileSelection(-1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { OpenView };
|
||||
|
|
Loading…
Reference in New Issue