diff --git a/dev/Common/Constants.js b/dev/Common/Constants.js index b1afef8ad..6eac0fc8b 100644 --- a/dev/Common/Constants.js +++ b/dev/Common/Constants.js @@ -38,7 +38,7 @@ Consts.Defaults.SearchAjaxTimeout = 120000; * @const * @type {number} */ -Consts.Defaults.SendMessageAjaxTimeout = 200000; +Consts.Defaults.SendMessageAjaxTimeout = 300000; /** * @const diff --git a/dev/Common/Enums.js b/dev/Common/Enums.js index 7fc7ed718..5707ff3a3 100644 --- a/dev/Common/Enums.js +++ b/dev/Common/Enums.js @@ -35,11 +35,13 @@ Enums.KeyState = { 'None': 'none', 'ContactList': 'contact-list', 'MessageList': 'message-list', + 'FolderList': 'folder-list', 'MessageView': 'message-view', 'Compose': 'compose', 'Settings': 'settings', 'Menu': 'menu', 'PopupComposeOpenPGP': 'compose-open-pgp', + 'PopupKeyboardShortcutsHelp': 'popup-keyboard-shortcuts-help', 'PopupAsk': 'popup-ask' }; diff --git a/dev/Common/Globals.js b/dev/Common/Globals.js index e6eca73a6..bc7ea2fa4 100644 --- a/dev/Common/Globals.js +++ b/dev/Common/Globals.js @@ -13,7 +13,7 @@ Globals.momentTrigger = ko.observable(true); /** * @type {?} */ -Globals.dropdownVisibility = ko.observable(false); +Globals.dropdownVisibility = ko.observable(false).extend({'rateLimit': 0}); /** * @type {?} diff --git a/dev/Common/Knockout.js b/dev/Common/Knockout.js index 0954888ca..d78a7a197 100644 --- a/dev/Common/Knockout.js +++ b/dev/Common/Knockout.js @@ -5,22 +5,33 @@ ko.bindingHandlers.tooltip = { if (!Globals.bMobileDevice) { var - sClass = $(oElement).data('tooltip-class') || '', - sPlacement = $(oElement).data('tooltip-placement') || 'top' + $oEl = $(oElement), + sClass = $oEl.data('tooltip-class') || '', + sPlacement = $oEl.data('tooltip-placement') || 'top' ; - $(oElement).tooltip({ + $oEl.tooltip({ 'delay': { 'show': 500, 'hide': 100 }, 'html': true, + 'container': 'body', 'placement': sPlacement, 'trigger': 'hover', 'title': function () { - return '' + + return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : '' + Utils.i18n(ko.utils.unwrapObservable(fValueAccessor())) + ''; } + }).click(function () { + $oEl.tooltip('hide'); + }); + + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + $oEl.tooltip('hide'); + } }); } } @@ -29,51 +40,39 @@ ko.bindingHandlers.tooltip = { ko.bindingHandlers.tooltip2 = { 'init': function (oElement, fValueAccessor) { var - sClass = $(oElement).data('tooltip-class') || '', - sPlacement = $(oElement).data('tooltip-placement') || 'top' + $oEl = $(oElement), + sClass = $oEl.data('tooltip-class') || '', + sPlacement = $oEl.data('tooltip-placement') || 'top' ; - $(oElement).tooltip({ + + $oEl.tooltip({ 'delay': { 'show': 500, 'hide': 100 }, 'html': true, + 'container': 'body', 'placement': sPlacement, 'title': function () { - return '' + fValueAccessor()() + ''; + return $oEl.is('.disabled') || Globals.dropdownVisibility() ? '' : + '' + fValueAccessor()() + ''; + } + }).click(function () { + $oEl.tooltip('hide'); + }); + + Globals.dropdownVisibility.subscribe(function (bValue) { + if (bValue) + { + $oEl.tooltip('hide'); } }); } }; -ko.__detectDropdownVisibility = _.debounce(function ($el) { - Globals.dropdownVisibility(!!$el.hasClass('open')); -}, 50); - -ko.bindingHandlers.dropdownOpenStatus = { +ko.bindingHandlers.registrateBootstrapDropdown = { 'init': function (oElement) { - var $el = $(oElement); - - $el.find('.dropdown-toggle').click(function () { - ko.__detectDropdownVisibility($el); - }); - -// $el.on('.dropdown-menu .menuitem', 'click', function () { -// $el.removeClass('open'); -// ko.__detectDropdownVisibility($el); -// }); - -// $el.on('.dropdown-menu .menuitem', 'keydown', function (oEvent) { -// if (oEvent && Enums.EventKeyCode.Esc === oEvent.keyCode) -// { -// $el.removeClass('open'); -// ko.__detectDropdownVisibility($el); -// } -// }); - - $html.on('click.dropdown.data-api', function () { - ko.__detectDropdownVisibility($el); - }); + BootstrapDropdowns.push($(oElement)); } }; @@ -85,7 +84,7 @@ ko.bindingHandlers.openDropdownTrigger = { if (!$el.hasClass('open')) { $el.find('.dropdown-toggle').dropdown('toggle'); - ko.__detectDropdownVisibility($el); + Utils.detectDropdownVisibility(); } fValueAccessor()(false); @@ -184,13 +183,16 @@ ko.bindingHandlers.clickOnTrue = { ko.bindingHandlers.modal = { 'init': function (oElement, fValueAccessor) { - $(oElement).toggleClass('fade', !Globals.bMobileDevice) .modal({ + + $(oElement).toggleClass('fade', !Globals.bMobileDevice).modal({ 'keyboard': false, 'show': ko.utils.unwrapObservable(fValueAccessor()) - }).on('hidden', function () { - fValueAccessor()(false); - }).on('shown', function () { + }) + .on('shown', function () { Utils.windowResize(); + }) + .find('.close').click(function () { + fValueAccessor()(false); }); }, 'update': function (oElement, fValueAccessor) { diff --git a/dev/Common/Selector.js b/dev/Common/Selector.js index 619214e69..df13b9587 100644 --- a/dev/Common/Selector.js +++ b/dev/Common/Selector.js @@ -108,10 +108,8 @@ function Selector(oKoList, oKoSelectedItem, this.sItemFocusedSelector = sItemFocusedSelector; this.sLastUid = ''; - this.oCallbacks = {}; - - this.bUseKeyboard = true; this.bAutoSelect = true; + this.oCallbacks = {}; this.emptyFunction = function () {}; @@ -320,7 +318,6 @@ Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeySco }) ; -// TODO key('enter', sKeyScope, function () { if (self.focusedItem()) { @@ -379,11 +376,6 @@ Selector.prototype.init = function (oContentVisible, oContentScrollable, sKeySco } }; -Selector.prototype.useKeyboard = function (bValue) -{ - this.bUseKeyboard = !!bValue; -}; - Selector.prototype.autoSelect = function (bValue) { this.bAutoSelect = !!bValue; diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index 2d287d4ac..694fbfc26 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -1736,7 +1736,7 @@ Utils.disableKeyFilter = function () if (window.key) { key.filter = function () { - return true; + return RL.data().useKeyboardShortcuts(); }; } }; @@ -1746,15 +1746,27 @@ Utils.restoreKeyFilter = function () if (window.key) { key.filter = function (event) { - var - element = event.target || event.srcElement, - tagName = element ? element.tagName : '' - ; - tagName = tagName.toUpperCase(); - return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || - (element && tagName === 'DIV' && 'editorHtmlArea' === element.className && element.contentEditable) - ); + if (RL.data().useKeyboardShortcuts()) + { + var + element = event.target || event.srcElement, + tagName = element ? element.tagName : '' + ; + + tagName = tagName.toUpperCase(); + return !(tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA' || + (element && tagName === 'DIV' && 'editorHtmlArea' === element.className && element.contentEditable) + ); + } + + return false; }; } }; + +Utils.detectDropdownVisibility = _.debounce(function () { + Globals.dropdownVisibility(!!_.find(BootstrapDropdowns, function (oItem) { + return oItem.hasClass('open'); + })); +}, 50); \ No newline at end of file diff --git a/dev/Common/_Begin.js b/dev/Common/_Begin.js index 7ec597282..c55cd7aac 100644 --- a/dev/Common/_Begin.js +++ b/dev/Common/_Begin.js @@ -46,6 +46,11 @@ var 'settings-disabled': [] }, + /** + * @type {Array} + */ + BootstrapDropdowns = [], + /** * @type {*} */ diff --git a/dev/Common/_End.js b/dev/Common/_End.js index bb235fb9e..efe4a28b2 100644 --- a/dev/Common/_End.js +++ b/dev/Common/_End.js @@ -7,6 +7,10 @@ $window.unload(function () { Globals.bUnload = true; }); +$html.on('click.dropdown.data-api', function () { + Utils.detectDropdownVisibility(); +}); + // export window['rl'] = window['rl'] || {}; window['rl']['addHook'] = Plugins.addHook; diff --git a/dev/Knoin/AbstractViewModel.js b/dev/Knoin/AbstractViewModel.js index ecfc45eb8..5288e32cd 100644 --- a/dev/Knoin/AbstractViewModel.js +++ b/dev/Knoin/AbstractViewModel.js @@ -16,11 +16,8 @@ function KnoinAbstractViewModel(sPosition, sTemplate) this.viewModelName = ''; this.viewModelVisibility = ko.observable(false); - if ('Popups' === this.sPosition) - { - this.modalVisibility = ko.observable(false); - } - + this.modalVisibility = ko.observable(false).extend({'rateLimit': 0}); + this.viewModelDom = null; } diff --git a/dev/Knoin/Knoin.js b/dev/Knoin/Knoin.js index 7ed2eff08..e7ae6f297 100644 --- a/dev/Knoin/Knoin.js +++ b/dev/Knoin/Knoin.js @@ -100,6 +100,32 @@ Knoin.prototype.buildViewModel = function (ViewModelClass, oScreen) oViewModel.cancelCommand = oViewModel.closeCommand = Utils.createCommand(oViewModel, function () { kn.hideScreenPopup(ViewModelClass); }); + + oViewModel.modalVisibility.subscribe(function (bValue) { + + var self = this; + if (bValue) + { + this.viewModelDom.show(); + this.storeAndSetKeyScope(); + + RL.popupVisibilityNames.push(this.viewModelName); + + Utils.delegateRun(this, 'onFocus', [], 500); + } + else + { + Utils.delegateRun(this, 'onHide'); + this.restoreKeyScope(); + + RL.popupVisibilityNames.remove(this.viewModelName); + + _.delay(function () { + self.viewModelDom.hide(); + }, 300); + } + + }, oViewModel); } Plugins.runHook('view-model-pre-build', [ViewModelClass.__name, oViewModel, oViewModelDom]); @@ -142,16 +168,7 @@ Knoin.prototype.hideScreenPopup = function (ViewModelClassToHide) if (ViewModelClassToHide && ViewModelClassToHide.__vm && ViewModelClassToHide.__dom) { ViewModelClassToHide.__vm.modalVisibility(false); - Utils.delegateRun(ViewModelClassToHide.__vm, 'onHide'); - ViewModelClassToHide.__vm.restoreKeyScope(); - - RL.popupVisibilityNames.remove(ViewModelClassToHide.__name); - Plugins.runHook('view-model-on-hide', [ViewModelClassToHide.__name, ViewModelClassToHide.__vm]); - - _.delay(function () { - ViewModelClassToHide.__dom.hide(); - }, 300); } }; @@ -167,17 +184,9 @@ Knoin.prototype.showScreenPopup = function (ViewModelClassToShow, aParameters) if (ViewModelClassToShow.__vm && ViewModelClassToShow.__dom) { - ViewModelClassToShow.__dom.show(); ViewModelClassToShow.__vm.modalVisibility(true); - Utils.delegateRun(ViewModelClassToShow.__vm, 'onShow', aParameters || []); - ViewModelClassToShow.__vm.storeAndSetKeyScope(); - - RL.popupVisibilityNames.push(ViewModelClassToShow.__name); - Plugins.runHook('view-model-on-show', [ViewModelClassToShow.__name, ViewModelClassToShow.__vm, aParameters || []]); - - Utils.delegateRun(ViewModelClassToShow.__vm, 'onFocus', [], 500); } } }; diff --git a/dev/Storages/AbstractData.js b/dev/Storages/AbstractData.js index 0a617d7d9..78cfe5f22 100644 --- a/dev/Storages/AbstractData.js +++ b/dev/Storages/AbstractData.js @@ -5,6 +5,8 @@ */ function AbstractData() { + this.useKeyboardShortcuts = ko.observable(true); + this.keyScopeReal = ko.observable(Enums.KeyState.All); this.keyScopeFake = ko.observable(Enums.KeyState.All); @@ -33,13 +35,12 @@ function AbstractData() } } -// window.console.log(sValue + '/' + this.keyScopeFake()); this.keyScopeReal(sValue); } }); this.keyScopeReal.subscribe(function (sValue) { - window.console.log(sValue); +// window.console.log(sValue); key.setScope(sValue); }); diff --git a/dev/Storages/WebMailData.js b/dev/Storages/WebMailData.js index dde1815f8..6647655c3 100644 --- a/dev/Storages/WebMailData.js +++ b/dev/Storages/WebMailData.js @@ -85,6 +85,7 @@ function WebMailDataStorage() // folders this.namespace = ''; this.folderList = ko.observableArray([]); + this.folderList.focused = ko.observable(false); this.foldersListError = ko.observable(''); @@ -279,6 +280,7 @@ function WebMailDataStorage() this.message.focused.subscribe(function (bValue) { if (bValue) { + RL.data().folderList.focused(false); RL.data().keyScope(Enums.KeyState.MessageView); } else if (Enums.KeyState.MessageView === RL.data().keyScope()) @@ -287,6 +289,17 @@ function WebMailDataStorage() } }); + this.folderList.focused.subscribe(function (bValue) { + if (bValue) + { + RL.data().keyScope(Enums.KeyState.FolderList); + } + else if (Enums.KeyState.FolderList === RL.data().keyScope()) + { + RL.data().keyScope(Enums.KeyState.MessageList); + } + }); + this.messageLoading.subscribe(function (bValue) { this.messageLoadingThrottle(bValue); }, this); @@ -363,8 +376,6 @@ function WebMailDataStorage() }, this); // other - this.useKeyboardShortcuts = ko.observable(true); - this.allowOpenPGP = ko.observable(false); this.openpgpkeys = ko.observableArray([]); this.openpgpKeyring = null; diff --git a/dev/Styles/@Main.less b/dev/Styles/@Main.less index d503d6288..208ff7502 100644 --- a/dev/Styles/@Main.less +++ b/dev/Styles/@Main.less @@ -23,6 +23,12 @@ @import "../../vendors/bootstrap/less/button-groups.less"; @import "../../vendors/bootstrap/less/alerts.less"; +@import "../../vendors/bootstrap/less/navs.less"; +@import "../../vendors/bootstrap/less/navbar.less"; +@import "../../vendors/bootstrap/less/breadcrumbs.less"; +// @import "../../vendors/bootstrap/less/pagination.less"; +// @import "../../vendors/bootstrap/less/pager.less"; + @import "../../vendors/bootstrap/less/modals.less"; @import "../../vendors/bootstrap/less/tooltip.less"; @import "../../vendors/bootstrap/less/popovers.less"; diff --git a/dev/Styles/Compose.less b/dev/Styles/Compose.less index ac98ad59a..c36380329 100644 --- a/dev/Styles/Compose.less +++ b/dev/Styles/Compose.less @@ -54,13 +54,22 @@ color: #333; .e-identity { + + color: #333; + text-decoration: none; font-weight: bold; + &:hover { + color: #333; + text-decoration: none; + } + &.multiply { cursor: pointer; border-bottom: 1px dashed #555; } } + .e-row { line-height: 30px; } diff --git a/dev/Styles/FolderList.less b/dev/Styles/FolderList.less index fc0c7fcec..d91abdc59 100644 --- a/dev/Styles/FolderList.less +++ b/dev/Styles/FolderList.less @@ -4,6 +4,9 @@ .b-folders { + &.focused .b-content { + } + .b-toolbar { position: absolute; top: 0; @@ -75,10 +78,14 @@ color: #000; cursor: pointer; - &:hover, &.selected, &.droppableHover { + &:hover, &.selected, &.focused, &.droppableHover { background-color: #555; color: #fff; } + &.focused { + background-color: #888; + color: #fff; + } } &.system { diff --git a/dev/Styles/Shortcuts.less b/dev/Styles/Shortcuts.less index db63404cb..1b5429659 100644 --- a/dev/Styles/Shortcuts.less +++ b/dev/Styles/Shortcuts.less @@ -1,10 +1,8 @@ .popups { .b-shortcuts-content { - &.modal { - width: 1025px; + width: 700px; } - .modal-header { background-color: #fff; } diff --git a/dev/Styles/_BootstrapFix.less b/dev/Styles/_BootstrapFix.less index ffa935df8..f6f710a6b 100644 --- a/dev/Styles/_BootstrapFix.less +++ b/dev/Styles/_BootstrapFix.less @@ -115,6 +115,8 @@ html.rgba.textshadow { .tooltip { font-size: 14px; + z-index: 2000 !important; + &.in { .opacity(100); } @@ -203,6 +205,10 @@ select { color: #b94a48; } +.nav-tabs > li > a { + color: #555; +} + html.no-rgba .modal { border-width: 0px !important; } diff --git a/dev/ViewModels/AbstractSystemDropDownViewModel.js b/dev/ViewModels/AbstractSystemDropDownViewModel.js index 841a072f2..0b5b389c5 100644 --- a/dev/ViewModels/AbstractSystemDropDownViewModel.js +++ b/dev/ViewModels/AbstractSystemDropDownViewModel.js @@ -75,7 +75,7 @@ AbstractSystemDropDownViewModel.prototype.onBuild = function () { var self = this; key('`', [Enums.KeyState.MessageList, Enums.KeyState.MessageView, Enums.KeyState.Settings], function () { - if (RL.data().useKeyboardShortcuts() && !RL.popupVisibility() && !Globals.dropdownVisibility() && self.viewModelVisibility()) + if (self.viewModelVisibility()) { self.accountMenuDropdownTrigger(true); } diff --git a/dev/ViewModels/MailBoxFolderListViewModel.js b/dev/ViewModels/MailBoxFolderListViewModel.js index 2859b0feb..b09461145 100644 --- a/dev/ViewModels/MailBoxFolderListViewModel.js +++ b/dev/ViewModels/MailBoxFolderListViewModel.js @@ -7,11 +7,14 @@ function MailBoxFolderListViewModel() { KnoinAbstractViewModel.call(this, 'Left', 'MailFolderList'); + + var oData = RL.data(); - this.folderList = RL.data().folderList; - this.folderListSystem = RL.data().folderListSystem; - this.foldersChanging = RL.data().foldersChanging; - + this.messageList = oData.messageList; + this.folderList = oData.folderList; + this.folderListSystem = oData.folderListSystem; + this.foldersChanging = oData.foldersChanging; + this.iDropOverTimer = 0; this.allowContacts = !!RL.settingsGet('ContactsIsAllowed'); @@ -23,16 +26,12 @@ Utils.extendAsViewModel('MailBoxFolderListViewModel', MailBoxFolderListViewModel MailBoxFolderListViewModel.prototype.onBuild = function (oDom) { + var self = this; + oDom - .on('click', '.b-folders .b-content', function () { - if (RL.data().useKeyboardShortcuts() && RL.data().message.focused()) - { - RL.data().message.focused(false); - } - }) .on('click', '.b-folders .e-item .e-link .e-collapsed-sign', function (oEvent) { - var + var oFolder = ko.dataFor(this), bCollapsed = false ; @@ -72,6 +71,61 @@ MailBoxFolderListViewModel.prototype.onBuild = function (oDom) } }) ; + + key('up, down', Enums.KeyState.FolderList, function (event, handler) { + + var + iIndex = -1, + iKeyCode = handler && 'up' === handler.shortcut ? 38 : 40, + $items = $('.b-folders .e-item .e-link:not(.hidden):visible', oDom) + ; + + if (event && $items.length) + { + iIndex = $items.index($items.filter('.focused')); + if (-1 < iIndex) + { + $items.eq(iIndex).removeClass('focused'); + } + + if (iKeyCode === 38 && iIndex > 0) + { + iIndex--; + } + else if (iKeyCode === 40 && iIndex < $items.length - 1) + { + iIndex++; + } + + $items.eq(iIndex).addClass('focused'); + } + + return false; + }); + + key('enter', Enums.KeyState.FolderList, function () { + var $items = $('.b-folders .e-item .e-link:not(.hidden).focused', oDom); + if ($items.length && $items[0]) + { + self.folderList.focused(false); + $items.click(); + } + + return false; + }); + + key('esc, tab, shift+tab', Enums.KeyState.FolderList, function () { + self.folderList.focused(false); + return false; + }); + + self.folderList.focused.subscribe(function (bValue) { + $('.b-folders .e-item .e-link.focused', oDom).removeClass('focused'); + if (bValue) + { + $('.b-folders .e-item .e-link.selected', oDom).addClass('focused'); + } + }); }; MailBoxFolderListViewModel.prototype.messagesDropOver = function (oFolder) diff --git a/dev/ViewModels/MailBoxMessageListViewModel.js b/dev/ViewModels/MailBoxMessageListViewModel.js index a0768b62d..57dfc2d45 100644 --- a/dev/ViewModels/MailBoxMessageListViewModel.js +++ b/dev/ViewModels/MailBoxMessageListViewModel.js @@ -18,6 +18,7 @@ function MailBoxMessageListViewModel() this.message = oData.message; this.messageList = oData.messageList; + this.folderList = oData.folderList; this.currentMessage = oData.currentMessage; this.isMessageSelected = oData.isMessageSelected; this.messageListSearch = oData.messageListSearch; @@ -207,7 +208,6 @@ function MailBoxMessageListViewModel() return oMessage ? oMessage.generateUid() : ''; }); -// this.selector.autoSelect(false); oData.layout.subscribe(function (mValue) { this.selector.autoSelect(Enums.Layout.NoPreview !== mValue); }, this); @@ -618,7 +618,7 @@ MailBoxMessageListViewModel.prototype.onBuild = function (oDom) oDom .on('click', '.messageList .b-message-list-wrapper', function () { - if (oData.useKeyboardShortcuts() && self.message.focused()) + if (self.message.focused()) { self.message.focused(false); } @@ -657,30 +657,28 @@ MailBoxMessageListViewModel.prototype.onBuild = function (oDom) MailBoxMessageListViewModel.prototype.initShortcuts = function () { - var - self = this, - oData = RL.data() - ; + var self = this; // disable print key('ctrl+p, command+p', Enums.KeyState.MessageList, function () { - if (oData.useKeyboardShortcuts()) - { - return false; - } + return false; }); + // TODO // more toggle +// key('', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { +// self.moreDropdownTrigger(true); +// return false; +// }); + + // archive (zip) key('z', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - self.moreDropdownTrigger(true); - return false; - } + self.archiveCommand(); + return false; }); - + // delete key('delete, shift+delete', Enums.KeyState.MessageList, function (event, handler) { - if (oData.useKeyboardShortcuts() && event) + if (event) { if (0 < RL.data().messageListCheckedOrSelected().length) { @@ -700,92 +698,60 @@ MailBoxMessageListViewModel.prototype.initShortcuts = function () // check all key('ctrl+a, command+a', Enums.KeyState.MessageList, function () { - if (oData.useKeyboardShortcuts()) - { - self.checkAll(!(self.checkAll() && !self.isIncompleteChecked())); - return false; - } + self.checkAll(!(self.checkAll() && !self.isIncompleteChecked())); + return false; }); // write/compose (open compose popup) key('w,c', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - kn.showScreenPopup(PopupsComposeViewModel); - return false; - } + kn.showScreenPopup(PopupsComposeViewModel); + return false; }); // important - star/flag messages key('i', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - self.flagMessagesFast(); - return false; - } + self.flagMessagesFast(); + return false; }); // move key('m', Enums.KeyState.MessageList, function () { - if (oData.useKeyboardShortcuts()) - { - self.moveDropdownTrigger(true); - return false; - } + self.moveDropdownTrigger(true); + return false; }); // read key('q', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - self.seenMessagesFast(true); - return false; - } + self.seenMessagesFast(true); + return false; }); // unread key('u', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - self.seenMessagesFast(false); - return false; - } + self.seenMessagesFast(false); + return false; }); // shortcuts help key('shift+/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - kn.showScreenPopup(PopupsKeyboardShortcutsHelpViewModel); - return false; - } + kn.showScreenPopup(PopupsKeyboardShortcutsHelpViewModel); + return false; }); key('shift+f', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - self.multyForwardCommand(); - return false; - } + self.multyForwardCommand(); + return false; }); // search input focus key('/', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - if (self.message()) - { - self.message.focused(false); - } - - self.inputMessageListSearchFocus(true); - return false; - } + self.inputMessageListSearchFocus(true); + return false; }); // cancel search key('esc', Enums.KeyState.MessageList, function () { - if (oData.useKeyboardShortcuts() && '' !== self.messageListSearchDesc()) + if ('' !== self.messageListSearchDesc()) { self.cancelSearch(); return false; @@ -793,32 +759,27 @@ MailBoxMessageListViewModel.prototype.initShortcuts = function () }); // change focused state - key('tab, shift+tab', Enums.KeyState.MessageList, function () { - if (oData.useKeyboardShortcuts()) + key('tab, shift+tab', Enums.KeyState.MessageList, function (event, handler) { + if (event && handler && 'shift+tab' === handler.shortcut) { - if (self.message()) - { - self.message.focused(true); - } - - return false; + self.folderList.focused(true); } + else if (self.message()) + { + self.message.focused(true); + } + + return false; }); + // TODO key('ctrl+left, command+left', Enums.KeyState.MessageView, function () { - if (oData.useKeyboardShortcuts()) - { - // TODO - return false; - } + return false; }); + // TODO key('ctrl+right, command+right', Enums.KeyState.MessageView, function () { - if (oData.useKeyboardShortcuts()) - { - // TODO - return false; - } + return false; }); }; diff --git a/dev/ViewModels/MailBoxMessageViewViewModel.js b/dev/ViewModels/MailBoxMessageViewViewModel.js index d3191c5d3..199f2b023 100644 --- a/dev/ViewModels/MailBoxMessageViewViewModel.js +++ b/dev/ViewModels/MailBoxMessageViewViewModel.js @@ -386,7 +386,7 @@ MailBoxMessageViewViewModel.prototype.onBuild = function (oDom) */ MailBoxMessageViewViewModel.prototype.escShortcuts = function () { - if (this.viewModelVisibility() && RL.data().useKeyboardShortcuts() && this.message()) + if (this.viewModelVisibility() && this.message()) { if (this.fullScreenMode()) { @@ -417,24 +417,19 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function () // fullscreen key('enter', Enums.KeyState.MessageView, function () { - if (oData.useKeyboardShortcuts()) - { - self.toggleFullScreen(); - return false; - } + self.toggleFullScreen(); + return false; }); - key('x', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts()) - { - self.moreDropdownTrigger(true); - return false; - } - }); + // TODO // more toggle +// key('', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { +// self.moreDropdownTrigger(true); +// return false; +// }); // reply key('r', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts() && oData.message()) + if (oData.message()) { self.replyCommand(); return false; @@ -443,7 +438,7 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function () // replaAll key('a', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts() && oData.message()) + if (oData.message()) { self.replyAllCommand(); return false; @@ -452,7 +447,7 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function () // forward key('f', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts() && oData.message()) + if (oData.message()) { self.forwardCommand(); return false; @@ -461,7 +456,7 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function () // message information // key('i', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { -// if (oData.useKeyboardShortcuts()) +// if (oData.message()) // { // self.showFullInfo(!self.showFullInfo()); // return false; @@ -470,7 +465,7 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function () // toggle message blockquotes key('b', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (oData.useKeyboardShortcuts() && oData.message() && oData.message().body) + if (oData.message() && oData.message().body) { Utils.toggleMessageBlockquote(oData.message().body); return false; @@ -478,37 +473,28 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function () }); key('ctrl+left, command+left, ctrl+up, command+up', Enums.KeyState.MessageView, function () { - if (oData.useKeyboardShortcuts()) - { - self.goUpCommand(); - return false; - } + self.goUpCommand(); + return false; }); key('ctrl+right, command+right, ctrl+down, command+down', Enums.KeyState.MessageView, function () { - if (oData.useKeyboardShortcuts()) - { - self.goDownCommand(); - return false; - } + self.goDownCommand(); + return false; }); // print key('ctrl+p, command+p', Enums.KeyState.MessageView, function () { - if (oData.useKeyboardShortcuts()) + if (self.message()) { - if (self.message()) - { - self.message().printMessage(); - } - - return false; + self.message().printMessage(); } + + return false; }); // delete key('delete, shift+delete', Enums.KeyState.MessageView, function (event, handler) { - if (oData.useKeyboardShortcuts() && event) + if (event) { if (handler && 'shift+delete' === handler.shortcut) { @@ -525,15 +511,12 @@ MailBoxMessageViewViewModel.prototype.initShortcuts = function () // change focused state key('tab, shift+tab', Enums.KeyState.MessageView, function () { - if (oData.useKeyboardShortcuts()) + if (!self.fullScreenMode() && self.message()) { - if (!self.fullScreenMode() && self.message()) - { - self.message.focused(false); - } - - return false; + self.message.focused(false); } + + return false; }); }; diff --git a/dev/ViewModels/PopupsAskViewModel.js b/dev/ViewModels/PopupsAskViewModel.js index a2b9f3f67..dd3d7aed7 100644 --- a/dev/ViewModels/PopupsAskViewModel.js +++ b/dev/ViewModels/PopupsAskViewModel.js @@ -21,8 +21,6 @@ function PopupsAskViewModel() this.bDisabeCloseOnEsc = true; this.sDefaultKeyScope = Enums.KeyState.PopupAsk; - this.sKeyScope = Enums.KeyState.MessageList; - Knoin.constructorEnd(this); } @@ -94,7 +92,7 @@ PopupsAskViewModel.prototype.onFocus = function () PopupsAskViewModel.prototype.onBuild = function () { - key('tab, right, left', Enums.KeyState.PopupAsk, _.bind(function () { + key('tab, shift+tab, right, left', Enums.KeyState.PopupAsk, _.bind(function () { if (this.yesFocus()) { this.noFocus(true); diff --git a/dev/ViewModels/PopupsComposeViewModel.js b/dev/ViewModels/PopupsComposeViewModel.js index 759124f96..268f1415d 100644 --- a/dev/ViewModels/PopupsComposeViewModel.js +++ b/dev/ViewModels/PopupsComposeViewModel.js @@ -31,6 +31,8 @@ function PopupsComposeViewModel() this.resizer = ko.observable(false).extend({'throttle': 50}); + this.identitiesDropdownTrigger = ko.observable(false); + this.to = ko.observable(''); this.to.focusTrigger = ko.observable(false); this.cc = ko.observable(''); @@ -915,43 +917,33 @@ PopupsComposeViewModel.prototype.tryToClosePopup = function () }]); }; -PopupsComposeViewModel.prototype.useShortcuts = function () -{ - return RL.data().useKeyboardShortcuts(); -}; - PopupsComposeViewModel.prototype.onBuild = function () { this.initUploader(); var self = this, - oData = RL.data(), oScript = null ; + key('ctrl+q, command+q', Enums.KeyState.Compose, function () { + self.identitiesDropdownTrigger(true); + return false; + }); + key('ctrl+s, command+s', Enums.KeyState.Compose, function () { - if (oData.useKeyboardShortcuts()) - { - self.saveCommand(); - return false; - } + self.saveCommand(); + return false; }); key('ctrl+enter, command+enter', Enums.KeyState.Compose, function () { - if (oData.useKeyboardShortcuts()) - { - self.sendCommand(); - return false; - } + self.sendCommand(); + return false; }); key('esc', Enums.KeyState.Compose, function () { - if (oData.useKeyboardShortcuts()) - { - self.tryToClosePopup(); - return false; - } + self.tryToClosePopup(); + return false; }); $window.on('resize', function () { diff --git a/dev/ViewModels/PopupsContactsViewModel.js b/dev/ViewModels/PopupsContactsViewModel.js index 40c747fc4..b46049486 100644 --- a/dev/ViewModels/PopupsContactsViewModel.js +++ b/dev/ViewModels/PopupsContactsViewModel.js @@ -582,11 +582,8 @@ PopupsContactsViewModel.prototype.onBuild = function (oDom) var self = this; key('delete', Enums.KeyState.ContactList, function () { - if (RL.data().useKeyboardShortcuts()) - { - self.deleteCommand(); - return false; - } + self.deleteCommand(); + return false; }); oDom diff --git a/dev/ViewModels/PopupsKeyboardShortcutsHelpViewModel.js b/dev/ViewModels/PopupsKeyboardShortcutsHelpViewModel.js index f1dfea80c..8f75fe9e4 100644 --- a/dev/ViewModels/PopupsKeyboardShortcutsHelpViewModel.js +++ b/dev/ViewModels/PopupsKeyboardShortcutsHelpViewModel.js @@ -8,7 +8,39 @@ function PopupsKeyboardShortcutsHelpViewModel() { KnoinAbstractViewModel.call(this, 'Popups', 'PopupsKeyboardShortcutsHelp'); + this.sDefaultKeyScope = Enums.KeyState.PopupKeyboardShortcutsHelp; + Knoin.constructorEnd(this); } Utils.extendAsViewModel('PopupsKeyboardShortcutsHelpViewModel', PopupsKeyboardShortcutsHelpViewModel); + +PopupsKeyboardShortcutsHelpViewModel.prototype.onBuild = function (oDom) +{ + key('tab, shift+tab', Enums.KeyState.PopupKeyboardShortcutsHelp, _.bind(function (event, handler) { + if (event && handler) + { + var + $tabs = oDom.find('.nav.nav-tabs > li'), + bNext = handler && 'tab' === handler.shortcut, + iIndex = $tabs.index($tabs.filter('.active')) + ; + + if (!bNext && iIndex > 0) + { + iIndex--; + } + else if (bNext && iIndex < $tabs.length - 1) + { + iIndex++; + } + else + { + iIndex = bNext ? 0 : $tabs.length - 1; + } + + $tabs.eq(iIndex).find('a[data-toggle="tab"]').tab('show'); + return false; + } + }, this)); +}; diff --git a/dev/ViewModels/SettingsPaneViewModel.js b/dev/ViewModels/SettingsPaneViewModel.js index 2eb2df876..b6d5ee08c 100644 --- a/dev/ViewModels/SettingsPaneViewModel.js +++ b/dev/ViewModels/SettingsPaneViewModel.js @@ -17,10 +17,7 @@ SettingsPaneViewModel.prototype.onBuild = function () { var self = this; key('esc', Enums.KeyState.Settings, function () { - if (RL.data().useKeyboardShortcuts()) - { - self.backToMailBoxClick(); - } + self.backToMailBoxClick(); }); }; diff --git a/rainloop/v/0.0.0/app/templates/Themes/custom-values-dark.less b/rainloop/v/0.0.0/app/templates/Themes/custom-values-dark.less index 243ea9842..5a2921373 100644 --- a/rainloop/v/0.0.0/app/templates/Themes/custom-values-dark.less +++ b/rainloop/v/0.0.0/app/templates/Themes/custom-values-dark.less @@ -29,6 +29,9 @@ @folders-selected-color: #fff; @folders-selected-background-color: #2b333d; @folders-selected-rgba-background-color: rgba(0,0,0,0.5); +@folders-focused-color: #fff; +@folders-focused-background-color: #2b333d; +@folders-focused-rgba-background-color: rgba(0,0,0,0.7); @folders-hover-color: #fff; @folders-hover-background-color: #2b333d; @folders-hover-rgba-background-color: rgba(0,0,0,0.5); diff --git a/rainloop/v/0.0.0/app/templates/Themes/custom-values-light.less b/rainloop/v/0.0.0/app/templates/Themes/custom-values-light.less index fc90b675a..64ce868bb 100644 --- a/rainloop/v/0.0.0/app/templates/Themes/custom-values-light.less +++ b/rainloop/v/0.0.0/app/templates/Themes/custom-values-light.less @@ -28,6 +28,9 @@ @folders-selected-color: #eee; @folders-selected-background-color: #757575; @folders-selected-rgba-background-color: rgba(0,0,0,0.5); +@folders-focused-color: #eee; +@folders-focused-background-color: #757575; +@folders-focused-rgba-background-color: rgba(0,0,0,0.7); @folders-hover-color: #eee; @folders-hover-background-color: #757575; @folders-hover-rgba-background-color: rgba(0,0,0,0.5); diff --git a/rainloop/v/0.0.0/app/templates/Themes/template.less b/rainloop/v/0.0.0/app/templates/Themes/template.less index 4ac9d62d2..49e340e07 100644 --- a/rainloop/v/0.0.0/app/templates/Themes/template.less +++ b/rainloop/v/0.0.0/app/templates/Themes/template.less @@ -130,6 +130,11 @@ .thm-rgba-background-color(@folders-selected-background-color, @folders-selected-rgba-background-color); } + &.selectable.focused { + color: @folders-focused-color !important; + .thm-rgba-background-color(@folders-focused-background-color, @folders-focused-rgba-background-color); + } + &.selectable.droppableHover { color: @folders-drop-color !important; .thm-rgba-background-color(@folders-drop-background-color, @folders-drop-rgba-background-color); diff --git a/rainloop/v/0.0.0/app/templates/Themes/values.less b/rainloop/v/0.0.0/app/templates/Themes/values.less index 05ba5c5ec..5c887916e 100644 --- a/rainloop/v/0.0.0/app/templates/Themes/values.less +++ b/rainloop/v/0.0.0/app/templates/Themes/values.less @@ -33,6 +33,9 @@ @folders-selected-color: #eee; @folders-selected-background-color: #333; @folders-selected-rgba-background-color: false; +@folders-focused-color: #eee; +@folders-focused-background-color: #333; +@folders-focused-rgba-background-color: false; @folders-hover-color: #eee; @folders-hover-background-color: #333; @folders-hover-rgba-background-color: false; diff --git a/rainloop/v/0.0.0/app/templates/Views/MailFolderList.html b/rainloop/v/0.0.0/app/templates/Views/MailFolderList.html index 11ee5c30d..e59920c92 100644 --- a/rainloop/v/0.0.0/app/templates/Views/MailFolderList.html +++ b/rainloop/v/0.0.0/app/templates/Views/MailFolderList.html @@ -1,4 +1,4 @@ -
+
 
-