You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-07-06 23:56:13 +02:00
140 lines
4.0 KiB
TypeScript
140 lines
4.0 KiB
TypeScript
import * as React from 'react';
|
|
import { _ } from '@joplin/lib/locale';
|
|
import CommandService from '@joplin/lib/services/CommandService';
|
|
import { Divider } from 'react-native-paper';
|
|
import FloatingActionButton from '../../buttons/FloatingActionButton';
|
|
import { AccessibilityActionEvent, AccessibilityActionInfo, StyleSheet, View } from 'react-native';
|
|
import { AttachFileAction } from '../Note/commands/attachFile';
|
|
import LabelledIconButton from '../../buttons/LabelledIconButton';
|
|
import TextButton, { ButtonSize, ButtonType } from '../../buttons/TextButton';
|
|
import { useCallback, useMemo, useRef } from 'react';
|
|
import Logger from '@joplin/utils/Logger';
|
|
import focusView from '../../../utils/focusView';
|
|
|
|
const logger = Logger.create('NewNoteButton');
|
|
|
|
interface Props {
|
|
|
|
}
|
|
|
|
const makeNewNote = (isTodo: boolean, action?: AttachFileAction) => {
|
|
logger.debug(`New ${isTodo ? 'to-do' : 'note'} with action`, action);
|
|
const body = '';
|
|
return CommandService.instance().execute('newNote', body, isTodo, { attachFileAction: action });
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
buttonRow: {
|
|
flexDirection: 'row',
|
|
flexWrap: 'wrap',
|
|
gap: 2,
|
|
},
|
|
mainButtonRow: {
|
|
flexWrap: 'wrap',
|
|
gap: 12,
|
|
},
|
|
shortcutButton: {
|
|
flexGrow: 1,
|
|
flexShrink: 1,
|
|
flexBasis: 0,
|
|
},
|
|
mainButton: {
|
|
flexShrink: 1,
|
|
flexGrow: 1,
|
|
},
|
|
mainButtonLabel: {
|
|
fontSize: 16,
|
|
fontWeight: 'bold',
|
|
},
|
|
menuContent: {
|
|
gap: 12,
|
|
flexShrink: 1,
|
|
flexGrow: 1,
|
|
flexDirection: 'column',
|
|
},
|
|
});
|
|
|
|
const NewNoteButton: React.FC<Props> = _props => {
|
|
const newNoteRef = useRef<View|null>(null);
|
|
|
|
const renderShortcutButton = (action: AttachFileAction, icon: string, title: string) => {
|
|
return <LabelledIconButton
|
|
onPress={() => makeNewNote(false, action)}
|
|
style={styles.shortcutButton}
|
|
title={title}
|
|
accessibilityHint={_('Creates a new note with an attachment of type %s', title)}
|
|
icon={icon}
|
|
/>;
|
|
};
|
|
|
|
const menuContent = <View style={styles.menuContent}>
|
|
<View style={styles.buttonRow}>
|
|
{renderShortcutButton(AttachFileAction.AttachFile, 'material attachment', _('Attachment'))}
|
|
{renderShortcutButton(AttachFileAction.RecordAudio, 'material microphone', _('Recording'))}
|
|
{renderShortcutButton(AttachFileAction.TakePhoto, 'material camera', _('Camera'))}
|
|
{renderShortcutButton(AttachFileAction.AttachDrawing, 'material draw', _('Drawing'))}
|
|
</View>
|
|
<Divider/>
|
|
<View style={[styles.buttonRow, styles.mainButtonRow]}>
|
|
<TextButton
|
|
icon='checkbox-outline'
|
|
style={styles.mainButton}
|
|
onPress={() => {
|
|
void makeNewNote(true);
|
|
}}
|
|
type={ButtonType.Secondary}
|
|
size={ButtonSize.Larger}
|
|
>{_('New to-do')}</TextButton>
|
|
<TextButton
|
|
touchableRef={newNoteRef}
|
|
icon='file-document-outline'
|
|
style={styles.mainButton}
|
|
onPress={() => {
|
|
void makeNewNote(false);
|
|
}}
|
|
type={ButtonType.Primary}
|
|
size={ButtonSize.Larger}
|
|
>{_('New note')}</TextButton>
|
|
</View>
|
|
</View>;
|
|
|
|
// Android and iOS: Accessibility actions simplify creating new notes and to-dos. These
|
|
// are extra important because the "note with attachment" items are annoyingly first in
|
|
// the focus order (and it doesn't seem possible to change this without adding a new
|
|
// dependency).
|
|
const accessibilityActions = useMemo((): AccessibilityActionInfo[] => {
|
|
return [{
|
|
name: 'new-note',
|
|
label: _('New note'),
|
|
}, {
|
|
name: 'new-to-do',
|
|
label: _('New to-do'),
|
|
}];
|
|
}, []);
|
|
const onAccessibilityAction = useCallback((event: AccessibilityActionEvent) => {
|
|
if (event.nativeEvent.actionName === 'new-note') {
|
|
return makeNewNote(false);
|
|
} else if (event.nativeEvent.actionName === 'new-to-do') {
|
|
return makeNewNote(true);
|
|
}
|
|
return Promise.resolve();
|
|
}, []);
|
|
const onMenuShown = useCallback(() => {
|
|
// Note: May apply only to web:
|
|
focusView('NewNoteButton', newNoteRef.current);
|
|
}, []);
|
|
|
|
return <FloatingActionButton
|
|
mainButton={{
|
|
icon: 'add',
|
|
label: _('Add new'),
|
|
}}
|
|
menuContent={menuContent}
|
|
onMenuShow={onMenuShown}
|
|
accessibilityActions={accessibilityActions}
|
|
onAccessibilityAction={onAccessibilityAction}
|
|
/>;
|
|
};
|
|
|
|
export default NewNoteButton;
|