fix(sidebar): Handle edge cases for sidebar shortcuts

Summary:
- Update menus and shortcuts correclt when accounts change or focused
  accounts change
- Move menu logic into SidebarCommands to remove duplicated logic
- Make `Window` menu also contain checkboxes

Test Plan: - Manual

Reviewers: evan, bengotow

Reviewed By: bengotow

Differential Revision: https://phab.nylas.com/D2534
This commit is contained in:
Juan Tejada 2016-02-05 14:24:07 -08:00
parent 57e7df8356
commit 199150188d
5 changed files with 108 additions and 122 deletions

View file

@ -0,0 +1,87 @@
_ = require 'underscore'
{AccountStore, MenuHelpers} = require 'nylas-exports'
SidebarActions = require './sidebar-actions'
class AccountCommands
@_focusAccounts: (accounts) ->
SidebarActions.focusAccounts(accounts)
NylasEnv.show() unless NylasEnv.isVisible()
@_isSelected: (account, focusedAccounts) =>
if focusedAccounts.length > 1
return account instanceof Array
else
return account?.id is focusedAccounts[0].id
@registerCommands: (accounts) ->
@_commandsDisposable?.dispose()
commands = {}
allKey = "application:select-account-0"
commands[allKey] = @_focusAccounts.bind(@, accounts)
[1..8].forEach (index) =>
account = accounts[index - 1]
return unless account
key = "application:select-account-#{index}"
commands[key] = @_focusAccounts.bind(@, [account])
@_commandsDisposable = NylasEnv.commands.add('body', commands)
@registerMenuItems: (accounts, focusedAccounts) ->
windowMenu = _.find NylasEnv.menu.template, ({label}) ->
MenuHelpers.normalizeLabel(label) is 'Window'
return unless windowMenu
submenu = _.reject windowMenu.submenu, (item) -> item.account
return unless submenu
idx = _.findIndex submenu, ({type}) -> type is 'separator'
return unless idx > 0
template = @menuTemplate(accounts, focusedAccounts)
submenu.splice(idx + 1, 0, template...)
windowMenu.submenu = submenu
NylasEnv.menu.update()
@menuItem: (account, idx, {isSelected, clickHandlers} = {}) =>
item = {
label: account.label ? "All Accounts",
command: "application:select-account-#{idx}",
account: true
}
if isSelected
item.type = 'checkbox'
item.checked = true
if clickHandlers
accounts = if account instanceof Array then account else [account]
item.click = @_focusAccounts.bind(@, accounts)
item.accelerator = "CmdOrCtrl+#{idx + 1}"
return item
@menuTemplate: (accounts, focusedAccounts, {clickHandlers} = {}) =>
template = []
multiAccount = accounts.length > 1
if multiAccount
isSelected = @_isSelected(accounts, focusedAccounts)
template = [
@menuItem(accounts, 0, {isSelected, clickHandlers})
]
template = template.concat accounts.map((account, idx) =>
# If there's only one account, it should be mapped to Cmd+1, not Cmd+2
accIdx = if multiAccount then idx + 1 else idx
isSelected = @_isSelected(account, focusedAccounts)
return @menuItem(account, accIdx, {isSelected, clickHandlers})
)
return template
@register: (accounts, focusedAccounts) ->
@registerCommands(accounts)
@registerMenuItems(accounts, focusedAccounts)
module.exports = AccountCommands

View file

@ -1,15 +1,9 @@
React = require 'react'
crypto = require 'crypto'
classNames = require 'classnames'
{Actions} = require 'nylas-exports'
{RetinaImg} = require 'nylas-component-kit'
SidebarActions = require '../sidebar-actions'
AccountCommands = require '../account-commands'
ItemTypes = {
"Unified"
}
class AccountSwitcher extends React.Component
@displayName: 'AccountSwitcher'
@ -17,71 +11,21 @@ class AccountSwitcher extends React.Component
accounts: React.PropTypes.array.isRequired
focusedAccounts: React.PropTypes.array.isRequired
# Helpers
_makeAccountItem: (account) =>
{id, label, emailAddress, provider} = account
email = emailAddress
iconName = provider
accounts = [account]
return {id, label, email, iconName, accounts}
_makeUnifiedItem: =>
id = ItemTypes.Unified
label = "All Accounts"
email = ""
iconName = 'unified'
accounts = @props.accounts
return {id, label, email, iconName, accounts}
_selectedItem: =>
if @props.focusedAccounts.length > 1
@_makeUnifiedItem()
else
@_makeAccountItem(@props.focusedAccounts[0])
_toggleDropdown: =>
@setState showing: !@state.showing
_makeMenuItem: (item, idx) =>
menuItem = {
label: item.label,
click: @_onSwitchAccount.bind(@, item)
accelerator: "CmdOrCtrl+#{idx}"
}
if @_selectedItem().id is item.id
menuItem.type = 'checkbox'
menuItem.checked = true
return menuItem
_makeMenuTemplate: =>
template = []
items = @props.accounts.map(@_makeAccountItem)
if @props.accounts.length > 1
unifiedItem = @_makeUnifiedItem()
template = [
@_makeMenuItem(unifiedItem, 1)
{type: 'separator'}
]
items.forEach (item, idx) => template.push(@_makeMenuItem(item, idx + 2))
template = AccountCommands.menuTemplate(
@props.accounts,
@props.focusedAccounts,
clickHandlers: true
)
template = template.concat [
{type: 'separator'}
{label: 'Manage Accounts...', click: @_onManageAccounts}
]
return template
# Handlers
_onSwitchAccount: (item) =>
SidebarActions.focusAccounts(item.accounts)
_onManageAccounts: =>
Actions.switchPreferencesTab('Accounts')
Actions.openPreferences()

View file

@ -1,6 +1,5 @@
React = require "react"
AccountSidebar = require "./components/account-sidebar"
SidebarCommands = require "./sidebar-commands"
{ComponentRegistry, WorkspaceStore} = require "nylas-exports"
module.exports =
@ -9,7 +8,6 @@ module.exports =
activate: (@state) ->
ComponentRegistry.register AccountSidebar,
location: WorkspaceStore.Location.RootSidebar
SidebarCommands.register()
deactivate: (@state) ->
ComponentRegistry.unregister(AccountSidebar)

View file

@ -1,57 +0,0 @@
_ = require 'underscore'
{AccountStore, MenuHelpers} = require 'nylas-exports'
SidebarActions = require './sidebar-actions'
class SidebarCommands
@_focusAccounts: (accounts) ->
SidebarActions.focusAccounts(accounts)
NylasEnv.show() unless NylasEnv.isVisible()
@_registerCommands: ->
commands = {}
allKey = "application:select-account-0"
commands[allKey] = @_focusAccounts.bind(@, AccountStore.accounts())
[1..8].forEach (index) =>
account = AccountStore.accounts()[index - 1]
return unless account
key = "application:select-account-#{index}"
commands[key] = @_focusAccounts.bind(@, [account])
NylasEnv.commands.add('body', commands)
@_registerMenuItems: ->
windowMenu = _.find NylasEnv.menu.template, ({label}) ->
MenuHelpers.normalizeLabel(label) is 'Window'
return unless windowMenu
submenu = _.reject windowMenu.submenu, (item) -> item.account
return unless submenu
idx = _.findIndex submenu, ({type}) -> type is 'separator'
return unless idx > 0
menuItems = [{
label: 'All Accounts'
command: "application:select-account-0"
account: true
}]
menuItems = menuItems.concat AccountStore.accounts().map((item, idx) =>
label: item.emailAddress,
command: "application:select-account-#{idx + 1}",
account: true
)
submenu.splice(idx + 1, 0, menuItems...)
windowMenu.submenu = submenu
NylasEnv.menu.update()
@register: ->
@_registerCommands()
@_registerMenuItems()
module.exports = SidebarCommands

View file

@ -10,6 +10,7 @@ _ = require 'underscore'
SidebarSection = require './sidebar-section'
SidebarActions = require './sidebar-actions'
AccountCommands = require './account-commands'
Sections = {
"Standard",
@ -23,6 +24,8 @@ class SidebarStore extends NylasStore
@_sections[Sections.Standard] = {}
@_sections[Sections.User] = []
@_focusedAccounts = @accounts()
@_registerCommands()
@_registerMenuItems()
@_registerListeners()
@_updateSections()
@ -57,13 +60,23 @@ class SidebarStore extends NylasStore
)
return
_registerCommands: (accounts = AccountStore.accounts()) =>
AccountCommands.registerCommands(accounts)
_registerMenuItems: (accounts = AccountStore.accounts()) =>
AccountCommands.registerMenuItems(accounts, @_focusedAccounts)
_onAccountsFocused: (accounts) =>
Actions.focusDefaultMailboxPerspectiveForAccounts(accounts)
@_focusedAccounts = accounts
@_registerMenuItems()
@_updateSections()
_onAccountsChanged: =>
@_focusedAccounts = AccountStore.accounts()
accounts = AccountStore.accounts()
@_focusedAccounts = accounts
@_registerCommands()
@_registerMenuItems()
@_updateSections()
_onFocusedPerspectiveChanged: =>
@ -72,6 +85,7 @@ class SidebarStore extends NylasStore
newIdsNotInCurrent = _.difference(newIds, currentIds).length > 0
if newIdsNotInCurrent
@_focusedAccounts = newIds.map (id) -> AccountStore.accountForId(id)
@_registerMenuItems()
@_updateSections()
_updateSections: =>