const React = require('react'); const { connect } = require('react-redux'); const { reg } = require('lib/registry.js'); const { themeStyle } = require('../theme.js'); const { _ } = require('lib/locale.js'); const { bridge } = require('electron').remote.require('./bridge'); class HeaderComponent extends React.Component { constructor() { super(); this.state = { searchQuery: '', showSearchUsageLink: false, }; this.scheduleSearchChangeEventIid_ = null; this.searchOnQuery_ = null; this.searchElement_ = null; const triggerOnQuery = (query) => { clearTimeout(this.scheduleSearchChangeEventIid_); if (this.searchOnQuery_) this.searchOnQuery_(query); this.scheduleSearchChangeEventIid_ = null; } this.search_onChange = (event) => { this.setState({ searchQuery: event.target.value }); if (this.scheduleSearchChangeEventIid_) clearTimeout(this.scheduleSearchChangeEventIid_); this.scheduleSearchChangeEventIid_ = setTimeout(() => { triggerOnQuery(this.state.searchQuery); }, 500); }; this.search_onClear = (event) => { this.setState({ searchQuery: '' }); triggerOnQuery(''); if (this.searchElement_) this.searchElement_.focus(); } this.search_onFocus = event => { if (this.hideSearchUsageLinkIID_) { clearTimeout(this.hideSearchUsageLinkIID_); this.hideSearchUsageLinkIID_ = null; } this.setState({ showSearchUsageLink: true }); } this.search_onBlur = event => { if (this.hideSearchUsageLinkIID_) return; this.hideSearchUsageLinkIID_ = setTimeout(() => { this.setState({ showSearchUsageLink: false }); }, 5000); } this.searchUsageLink_click = event => { bridge().openExternal('https://joplin.cozic.net/#searching'); } } async componentWillReceiveProps(nextProps) { if (nextProps.windowCommand) { this.doCommand(nextProps.windowCommand); } } componentWillUnmount() { if (this.hideSearchUsageLinkIID_) { clearTimeout(this.hideSearchUsageLinkIID_); this.hideSearchUsageLinkIID_ = null; } } async doCommand(command) { if (!command) return; let commandProcessed = true; if (command.name === 'focus_search' && this.searchElement_) { this.searchElement_.focus(); } else { commandProcessed = false; } if (commandProcessed) { this.props.dispatch({ type: 'WINDOW_COMMAND', name: null, }); } } back_click() { this.props.dispatch({ type: 'NAV_BACK' }); } makeButton(key, style, options) { let icon = null; if (options.iconName) { const iconStyle = { fontSize: Math.round(style.fontSize * 1.4), color: style.color, }; if (options.title) iconStyle.marginRight = 5; if (options.iconRotation) iconStyle.transform = 'rotate(' + options.iconRotation + 'deg)'; icon = } const isEnabled = (!('enabled' in options) || options.enabled); let classes = ['button']; if (!isEnabled) classes.push('disabled'); const finalStyle = Object.assign({}, style, { opacity: isEnabled ? 1 : 0.4, }); return { if (isEnabled) options.onClick() }} > {icon}{options.title ? options.title : ''} } makeSearch(key, style, options, state) { const theme = themeStyle(this.props.theme); const inputStyle = { display: 'flex', flex: 1, paddingLeft: 4, paddingRight: 4, color: style.color, fontSize: style.fontSize, fontFamily: style.fontFamily, backgroundColor: style.searchColor, border: '1px solid', borderColor: style.dividerColor, }; const searchButton = { paddingLeft: 4, paddingRight: 4, paddingTop: 2, paddingBottom: 2, textDecoration: 'none', }; const iconStyle = { display: 'flex', fontSize: Math.round(style.fontSize) * 1.2, color: style.color, }; const containerStyle = { display: 'flex', flexDirection: 'row', alignItems: 'center', }; const iconName = state.searchQuery ? 'fa-times' : 'fa-search'; const icon = if (options.onQuery) this.searchOnQuery_ = options.onQuery; const usageLink = !this.state.showSearchUsageLink ? null : ( {_('Usage')} ); return (
this.searchElement_ = elem} onFocus={this.search_onFocus} onBlur={this.search_onBlur} /> {icon} {usageLink}
); } render() { const style = Object.assign({}, this.props.style); const theme = themeStyle(this.props.theme); const showBackButton = this.props.showBackButton === undefined || this.props.showBackButton === true; style.height = theme.headerHeight; style.display = 'flex'; style.flexDirection = 'row'; style.borderBottom = '1px solid ' + theme.dividerColor; style.boxSizing = 'border-box'; const items = []; const itemStyle = { height: theme.headerHeight, display: 'flex', alignItems: 'center', paddingLeft: theme.headerButtonHPadding, paddingRight: theme.headerButtonHPadding, color: theme.color, searchColor: theme.backgroundColor, dividerColor: theme.dividerColor, textDecoration: 'none', fontFamily: theme.fontFamily, fontSize: theme.fontSize, boxSizing: 'border-box', cursor: 'default', }; if (showBackButton) { items.push(this.makeButton('back', itemStyle, { title: _('Back'), onClick: () => this.back_click(), iconName: 'fa-chevron-left ' })); } if (this.props.items) { for (let i = 0; i < this.props.items.length; i++) { const item = this.props.items[i]; if (item.type === 'search') { items.push(this.makeSearch('item_' + i + '_search', itemStyle, item, this.state)); } else { items.push(this.makeButton('item_' + i + '_' + item.title, itemStyle, item)); } } } return (
{ items }
); } } const mapStateToProps = (state) => { return { theme: state.settings.theme, windowCommand: state.windowCommand, }; }; const Header = connect(mapStateToProps)(HeaderComponent); module.exports = { Header };