React = require 'react/addons' Sheet = require './sheet' Flexbox = require './components/flexbox' RetinaImg = require './components/retina-img' Utils = require './flux/models/utils' _str = require 'underscore.string' _ = require 'underscore' {Actions, ComponentRegistry, WorkspaceStore} = require "nylas-exports" class ToolbarSpacer extends React.Component @displayName: 'ToolbarSpacer' @propTypes: order: React.PropTypes.number render: =>
class WindowTitle extends React.Component @displayName: "WindowTitle" constructor: (@props) -> @state = NylasEnv.getLoadSettings() componentDidMount: -> @unlisten = NylasEnv.onWindowPropsReceived (windowProps) => @setState NylasEnv.getLoadSettings() componentWillUnmount: -> @unlisten?() render: ->
{@state.title}
Category = null FocusedPerspectiveStore = null class ToolbarBack extends React.Component @displayName: 'ToolbarBack' # These stores are only required when this Toolbar is actually needed. # This is because loading these stores has database side effects. constructor: (@props) -> Category ?= require './flux/models/category' FocusedPerspectiveStore ?= require './flux/stores/focused-perspective-store' @state = categoryName: FocusedPerspectiveStore.current()?.name componentDidMount: => @_unsubscriber = FocusedPerspectiveStore.listen => @setState(categoryName: FocusedPerspectiveStore.current()?.name) componentWillUnmount: => @_unsubscriber() if @_unsubscriber render: => if @state.categoryName is Category.AllMailName title = 'All Mail' else if @state.categoryName title = _str.titleize(@state.categoryName) else title = "Back"
{title}
_onClick: => Actions.popSheet() class ToolbarWindowControls extends React.Component @displayName: 'ToolbarWindowControls' constructor: (@props) -> @state = {alt: false} componentDidMount: => if process.platform is 'darwin' window.addEventListener('keydown', @_onAlt) window.addEventListener('keyup', @_onAlt) componentWillUnmount: => if process.platform is 'darwin' window.removeEventListener('keydown', @_onAlt) window.removeEventListener('keyup', @_onAlt) render: =>
_onAlt: (event) => @setState(alt: event.altKey) if @state.alt isnt event.altKey _onMaximize: (event) => if process.platform is 'darwin' and not event.altKey NylasEnv.setFullScreen(!NylasEnv.isFullScreen()) else NylasEnv.maximize() class ToolbarMenuControl extends React.Component @displayName: 'ToolbarMenuControl' render: =>
_openMenu: => applicationMenu = require('remote').getGlobal('application').applicationMenu applicationMenu.menu.popup(NylasEnv.getCurrentWindow()) ComponentRegistry.register ToolbarWindowControls, location: WorkspaceStore.Sheet.Global.Toolbar.Left ComponentRegistry.register ToolbarMenuControl, location: WorkspaceStore.Sheet.Global.Toolbar.Right class Toolbar extends React.Component @displayName: 'Toolbar' @propTypes: data: React.PropTypes.object depth: React.PropTypes.number @childContextTypes: sheetDepth: React.PropTypes.number getChildContext: => sheetDepth: @props.depth constructor: (@props) -> @state = @_getStateFromStores() componentDidMount: => @mounted = true @unlisteners = [] @unlisteners.push WorkspaceStore.listen (event) => @setState(@_getStateFromStores()) @unlisteners.push ComponentRegistry.listen (event) => @setState(@_getStateFromStores()) window.addEventListener("resize", @_onWindowResize) window.requestAnimationFrame => @recomputeLayout() componentWillUnmount: => @mounted = false window.removeEventListener("resize", @_onWindowResize) unlistener() for unlistener in @unlisteners componentWillReceiveProps: (props) => @setState(@_getStateFromStores(props)) componentDidUpdate: => # Wait for other components that are dirty (the actual columns in the sheet) window.requestAnimationFrame => @recomputeLayout() shouldComponentUpdate: (nextProps, nextState) => # This is very important. Because toolbar uses ReactCSSTransitionGroup, # repetitive unnecessary updates can break animations and cause performance issues. not _.isEqual(nextProps, @props) or not _.isEqual(nextState, @state) render: => style = position:'absolute' width:'100%' height:'100%' zIndex: 1 toolbars = @state.columns.map (components, idx) =>
{@_flexboxForComponents(components)}
{toolbars}
_flexboxForComponents: (components) => elements = components.map (component) => {elements} recomputeLayout: => # Yes this really happens - do not remove! return unless @mounted # Find our item containers that are tied to specific columns columnToolbarEls = React.findDOMNode(@).querySelectorAll('[data-column]') # Find the top sheet in the stack sheet = document.querySelectorAll("[name='Sheet']")[@props.depth] return unless sheet # Position item containers so they have the position and width # as their respective columns in the top sheet for columnToolbarEl in columnToolbarEls column = columnToolbarEl.dataset.column columnEl = sheet.querySelector("[data-column='#{column}']") continue unless columnEl columnToolbarEl.style.display = 'inherit' columnToolbarEl.style.left = "#{columnEl.offsetLeft}px" columnToolbarEl.style.width = "#{columnEl.offsetWidth}px" _onWindowResize: => @recomputeLayout() _getStateFromStores: (props) => props ?= @props state = mode: WorkspaceStore.layoutMode() columns: [] # Add items registered to Regions in the current sheet if @props.data?.columns[state.mode]? for loc in @props.data.columns[state.mode] continue if WorkspaceStore.isLocationHidden(loc) entries = ComponentRegistry.findComponentsMatching({location: loc.Toolbar, mode: state.mode}) state.columns.push(entries) # Add left items registered to the Sheet instead of to a Region for loc in [WorkspaceStore.Sheet.Global, @props.data] entries = ComponentRegistry.findComponentsMatching({location: loc.Toolbar.Left, mode: state.mode}) state.columns[0]?.push(entries...) state.columns[0]?.push(ToolbarBack) if @props.depth > 0 # Add right items registered to the Sheet instead of to a Region for loc in [WorkspaceStore.Sheet.Global, @props.data] entries = ComponentRegistry.findComponentsMatching({location: loc.Toolbar.Right, mode: state.mode}) state.columns[state.columns.length - 1]?.push(entries...) if state.mode is "popout" state.columns[0]?.push(WindowTitle) state module.exports = Toolbar