2019-07-29 15:43:53 +02:00
const React = require ( 'react' ) ;
2019-07-29 15:58:33 +02:00
const { StyleSheet } = require ( 'react-native' ) ;
2021-01-22 19:41:11 +02:00
const Note = require ( '@joplin/lib/models/Note' ) . default ;
2018-03-09 22:59:12 +02:00
const Icon = require ( 'react-native-vector-icons/Ionicons' ) . default ;
const ReactNativeActionButton = require ( 'react-native-action-button' ) . default ;
const { connect } = require ( 'react-redux' ) ;
2020-11-07 17:59:37 +02:00
const { _ } = require ( '@joplin/lib/locale' ) ;
2017-05-16 23:05:53 +02:00
2020-02-09 16:51:12 +02:00
Icon . loadFont ( ) ;
2017-05-16 23:05:53 +02:00
const styles = StyleSheet . create ( {
actionButtonIcon : {
fontSize : 20 ,
height : 22 ,
2018-03-09 22:59:12 +02:00
color : 'white' ,
2017-05-16 23:05:53 +02:00
} ,
2017-07-30 23:04:26 +02:00
itemText : {
// fontSize: 14, // Cannot currently set fontsize since the bow surrounding the label has a fixed size
2019-07-29 15:43:53 +02:00
} ,
2017-05-16 23:05:53 +02:00
} ) ;
class ActionButtonComponent extends React . Component {
2017-07-14 01:35:37 +02:00
constructor ( ) {
super ( ) ;
this . state = {
2017-07-15 20:21:39 +02:00
buttonIndex : 0 ,
2017-07-14 01:35:37 +02:00
} ;
2020-10-16 17:26:19 +02:00
this . renderIconMultiStates = this . renderIconMultiStates . bind ( this ) ;
this . renderIcon = this . renderIcon . bind ( this ) ;
2017-07-14 01:35:37 +02:00
}
2018-04-30 18:38:19 +02:00
UNSAFE _componentWillReceiveProps ( newProps ) {
2018-03-09 22:59:12 +02:00
if ( 'buttonIndex' in newProps ) {
2017-07-15 20:21:39 +02:00
this . setState ( { buttonIndex : newProps . buttonIndex } ) ;
2017-07-15 01:12:32 +02:00
}
}
2020-03-06 20:49:30 +02:00
async newNoteNavigate ( folderId , isTodo ) {
const newNote = await Note . save ( {
parent _id : folderId ,
is _todo : isTodo ? 1 : 0 ,
} , { provisional : true } ) ;
2017-05-24 22:51:50 +02:00
this . props . dispatch ( {
2018-03-09 22:59:12 +02:00
type : 'NAV_GO' ,
routeName : 'Note' ,
2020-03-06 20:49:30 +02:00
noteId : newNote . id ,
2017-05-24 22:51:50 +02:00
} ) ;
}
2020-03-06 20:49:30 +02:00
newTodo _press ( ) {
this . newNoteNavigate ( this . props . parentFolderId , true ) ;
}
2017-05-16 23:05:53 +02:00
newNote _press ( ) {
2020-03-06 20:49:30 +02:00
this . newNoteNavigate ( this . props . parentFolderId , false ) ;
2017-05-16 23:05:53 +02:00
}
2020-10-16 17:26:19 +02:00
renderIconMultiStates ( ) {
const button = this . props . buttons [ this . state . buttonIndex ] ;
2022-06-26 19:23:41 +02:00
return < Icon
name = { button . icon }
style = { styles . actionButtonIcon }
accessibilityLabel = { button . title }
/ > ;
2020-10-16 17:26:19 +02:00
}
renderIcon ( ) {
const mainButton = this . props . mainButton ? this . props . mainButton : { } ;
2022-06-26 19:23:41 +02:00
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 (
< Icon
name = { iconName }
style = { styles . actionButtonIcon }
accessibilityLabel = { iconTitle }
/ >
) ;
2020-10-16 17:26:19 +02:00
}
2017-05-16 23:05:53 +02:00
render ( ) {
2020-03-14 01:46:14 +02:00
const buttons = this . props . buttons ? this . props . buttons : [ ] ;
2017-05-24 22:51:50 +02:00
2017-07-14 01:35:37 +02:00
if ( this . props . addFolderNoteButtons ) {
if ( this . props . folders . length ) {
buttons . push ( {
2018-03-09 22:59:12 +02:00
title : _ ( 'New to-do' ) ,
2019-07-29 15:43:53 +02:00
onPress : ( ) => {
this . newTodo _press ( ) ;
} ,
2018-03-09 22:59:12 +02:00
color : '#9b59b6' ,
icon : 'md-checkbox-outline' ,
2017-07-14 01:35:37 +02:00
} ) ;
buttons . push ( {
2018-03-09 22:59:12 +02:00
title : _ ( 'New note' ) ,
2019-07-29 15:43:53 +02:00
onPress : ( ) => {
this . newNote _press ( ) ;
} ,
2018-03-09 22:59:12 +02:00
color : '#9b59b6' ,
icon : 'md-document' ,
2017-07-14 01:35:37 +02:00
} ) ;
}
}
2017-05-24 22:51:50 +02:00
2020-03-14 01:46:14 +02:00
const buttonComps = [ ] ;
2017-07-14 01:35:37 +02:00
for ( let i = 0 ; i < buttons . length ; i ++ ) {
2020-03-14 01:46:14 +02:00
const button = buttons [ i ] ;
const buttonTitle = button . title ? button . title : '' ;
const key = ` ${ buttonTitle . replace ( /\s/g , '_' ) } _ ${ button . icon } ` ;
2017-07-14 01:35:37 +02:00
buttonComps . push (
2022-06-26 19:23:41 +02:00
// TODO: By default, ReactNativeActionButton also adds a title, which is focusable
// by the screen reader. As such, each item currently is double-focusable
2017-07-14 01:35:37 +02:00
< ReactNativeActionButton . Item key = { key } buttonColor = { button . color } title = { buttonTitle } onPress = { button . onPress } >
2022-06-26 19:23:41 +02:00
< Icon
name = { button . icon }
style = { styles . actionButtonIcon }
accessibilityLabel = { buttonTitle }
/ >
2017-05-16 23:05:53 +02:00
< / R e a c t N a t i v e A c t i o n B u t t o n . I t e m >
2017-07-09 00:57:09 +02:00
) ;
}
2017-05-24 22:51:50 +02:00
2017-07-14 01:35:37 +02:00
if ( ! buttonComps . length && ! this . props . mainButton ) {
2020-09-07 18:42:16 +02:00
return null ;
2017-07-14 01:35:37 +02:00
}
2017-07-15 20:21:39 +02:00
if ( this . props . multiStates ) {
2018-03-09 22:59:12 +02:00
if ( ! this . props . buttons || ! this . props . buttons . length ) throw new Error ( 'Multi-state button requires at least one state' ) ;
2019-09-19 23:51:18 +02:00
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 } ` ) ;
2020-03-14 01:46:14 +02:00
const button = this . props . buttons [ this . state . buttonIndex ] ;
2017-07-14 01:35:37 +02:00
return (
< ReactNativeActionButton
2020-10-16 17:26:19 +02:00
renderIcon = { this . renderIconMultiStates }
2017-07-14 01:35:37 +02:00
buttonColor = "rgba(231,76,60,1)"
2019-07-29 15:43:53 +02:00
onPress = { ( ) => {
button . onPress ( ) ;
} }
2017-07-14 01:35:37 +02:00
/ >
) ;
} else {
return (
2020-10-16 17:26:19 +02:00
< ReactNativeActionButton textStyle = { styles . itemText } renderIcon = { this . renderIcon } buttonColor = "rgba(231,76,60,1)" onPress = { function ( ) { } } >
2019-07-29 15:43:53 +02:00
{ buttonComps }
2017-07-14 01:35:37 +02:00
< / R e a c t N a t i v e A c t i o n B u t t o n >
) ;
}
2017-05-16 23:05:53 +02:00
}
}
2020-05-21 10:14:33 +02:00
const ActionButton = connect ( state => {
2019-07-29 15:43:53 +02:00
return {
folders : state . folders ,
locale : state . settings . locale ,
} ;
} ) ( ActionButtonComponent ) ;
2017-05-16 23:05:53 +02:00
2019-07-29 15:43:53 +02:00
module . exports = { ActionButton } ;