const React = require('react'); const { StyleSheet } = require('react-native'); const Note = require('@joplin/lib/models/Note').default; const Icon = require('react-native-vector-icons/Ionicons').default; const ReactNativeActionButton = require('react-native-action-button').default; const { connect } = require('react-redux'); const { _ } = require('@joplin/lib/locale'); Icon.loadFont(); const styles = StyleSheet.create({ actionButtonIcon: { fontSize: 20, height: 22, color: 'white', }, itemText: { // fontSize: 14, // Cannot currently set fontsize since the bow surrounding the label has a fixed size }, }); class ActionButtonComponent extends React.Component { constructor() { super(); this.state = { buttonIndex: 0, }; this.renderIconMultiStates = this.renderIconMultiStates.bind(this); this.renderIcon = this.renderIcon.bind(this); } UNSAFE_componentWillReceiveProps(newProps) { if ('buttonIndex' in newProps) { this.setState({ buttonIndex: newProps.buttonIndex }); } } async newNoteNavigate(folderId, isTodo) { const newNote = await Note.save({ parent_id: folderId, is_todo: isTodo ? 1 : 0, }, { provisional: true }); this.props.dispatch({ type: 'NAV_GO', routeName: 'Note', noteId: newNote.id, }); } newTodo_press() { this.newNoteNavigate(this.props.parentFolderId, true); } newNote_press() { this.newNoteNavigate(this.props.parentFolderId, false); } renderIconMultiStates() { const button = this.props.buttons[this.state.buttonIndex]; return ; } renderIcon() { const mainButton = this.props.mainButton ? this.props.mainButton : {}; const iconName = mainButton.icon ?? 'md-add'; // Icons don't have alt text by default. We need to add it: const iconTitle = mainButton.title ?? _('Add new'); // TODO: If the button toggles a sub-menu, state whether the submenu is open // or closed. return ( ); } render() { const buttons = this.props.buttons ? this.props.buttons : []; if (this.props.addFolderNoteButtons) { if (this.props.folders.length) { buttons.push({ title: _('New to-do'), onPress: () => { this.newTodo_press(); }, color: '#9b59b6', icon: 'md-checkbox-outline', }); buttons.push({ title: _('New note'), onPress: () => { this.newNote_press(); }, color: '#9b59b6', icon: 'md-document', }); } } const buttonComps = []; for (let i = 0; i < buttons.length; i++) { const button = buttons[i]; const buttonTitle = button.title ? button.title : ''; const key = `${buttonTitle.replace(/\s/g, '_')}_${button.icon}`; buttonComps.push( // TODO: By default, ReactNativeActionButton also adds a title, which is focusable // by the screen reader. As such, each item currently is double-focusable ); } if (!buttonComps.length && !this.props.mainButton) { return null; } if (this.props.multiStates) { if (!this.props.buttons || !this.props.buttons.length) throw new Error('Multi-state button requires at least one state'); if (this.state.buttonIndex < 0 || this.state.buttonIndex >= this.props.buttons.length) throw new Error(`Button index out of bounds: ${this.state.buttonIndex}/${this.props.buttons.length}`); const button = this.props.buttons[this.state.buttonIndex]; return ( { button.onPress(); }} /> ); } else { return ( {buttonComps} ); } } } const ActionButton = connect(state => { return { folders: state.folders, locale: state.settings.locale, }; })(ActionButtonComponent); module.exports = { ActionButton };