mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Chore: Refactor: Mobile: Rename CustomButton to IconButton (#10473)
This commit is contained in:
parent
3bf9438a59
commit
b09d6e8568
@ -510,13 +510,13 @@ packages/app-mobile/commands/util/goToNote.js
|
||||
packages/app-mobile/components/ActionButton.js
|
||||
packages/app-mobile/components/BackButtonDialogBox.js
|
||||
packages/app-mobile/components/CameraView.js
|
||||
packages/app-mobile/components/CustomButton.js
|
||||
packages/app-mobile/components/DismissibleDialog.js
|
||||
packages/app-mobile/components/Dropdown.test.js
|
||||
packages/app-mobile/components/Dropdown.js
|
||||
packages/app-mobile/components/ExtendedWebView.js
|
||||
packages/app-mobile/components/FolderPicker.js
|
||||
packages/app-mobile/components/Icon.js
|
||||
packages/app-mobile/components/IconButton.js
|
||||
packages/app-mobile/components/Modal.js
|
||||
packages/app-mobile/components/ModalDialog.js
|
||||
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -489,13 +489,13 @@ packages/app-mobile/commands/util/goToNote.js
|
||||
packages/app-mobile/components/ActionButton.js
|
||||
packages/app-mobile/components/BackButtonDialogBox.js
|
||||
packages/app-mobile/components/CameraView.js
|
||||
packages/app-mobile/components/CustomButton.js
|
||||
packages/app-mobile/components/DismissibleDialog.js
|
||||
packages/app-mobile/components/Dropdown.test.js
|
||||
packages/app-mobile/components/Dropdown.js
|
||||
packages/app-mobile/components/ExtendedWebView.js
|
||||
packages/app-mobile/components/FolderPicker.js
|
||||
packages/app-mobile/components/Icon.js
|
||||
packages/app-mobile/components/IconButton.js
|
||||
packages/app-mobile/components/Modal.js
|
||||
packages/app-mobile/components/ModalDialog.js
|
||||
packages/app-mobile/components/NoteBodyViewer/NoteBodyViewer.js
|
||||
|
@ -4,8 +4,8 @@ import { TextStyle, Text } from 'react-native';
|
||||
|
||||
const FontAwesomeIcon = require('react-native-vector-icons/FontAwesome5').default;
|
||||
const AntIcon = require('react-native-vector-icons/AntDesign').default;
|
||||
const MaterialIcon = require('react-native-vector-icons/MaterialIcons').default;
|
||||
|
||||
const MaterialCommunityIcon = require('react-native-vector-icons/MaterialCommunityIcons').default;
|
||||
const Ionicon = require('react-native-vector-icons/Ionicons').default;
|
||||
|
||||
interface Props {
|
||||
name: string;
|
||||
@ -53,7 +53,9 @@ const Icon: React.FC<Props> = props => {
|
||||
} else if (namePrefix === 'ant') {
|
||||
return <AntIcon name={nameSuffix} {...sharedProps}/>;
|
||||
} else if (namePrefix === 'material') {
|
||||
return <MaterialIcon name={nameSuffix} {...sharedProps}/>;
|
||||
return <MaterialCommunityIcon name={nameSuffix} {...sharedProps}/>;
|
||||
} else if (namePrefix === 'ionicon') {
|
||||
return <Ionicon name={nameSuffix} {...sharedProps}/>;
|
||||
} else if (namePrefix === 'text') {
|
||||
return (
|
||||
<Text
|
||||
|
@ -2,28 +2,28 @@
|
||||
// A button with a long-press action. Long-pressing the button displays a tooltip
|
||||
//
|
||||
|
||||
const React = require('react');
|
||||
import { ReactNode } from 'react';
|
||||
import * as React from 'react';
|
||||
import { themeStyle } from '@joplin/lib/theme';
|
||||
import { Theme } from '@joplin/lib/themes/type';
|
||||
import { useState, useMemo, useCallback, useRef } from 'react';
|
||||
import { View, Text, Pressable, ViewStyle, PressableStateCallbackType, StyleProp, StyleSheet, LayoutChangeEvent, LayoutRectangle, Animated, AccessibilityState, AccessibilityRole } from 'react-native';
|
||||
import { View, Text, Pressable, ViewStyle, StyleSheet, LayoutChangeEvent, LayoutRectangle, Animated, AccessibilityState, AccessibilityRole, TextStyle } from 'react-native';
|
||||
import { Menu, MenuOptions, MenuTrigger, renderers } from 'react-native-popup-menu';
|
||||
import Icon from './Icon';
|
||||
|
||||
type ButtonClickListener = ()=> void;
|
||||
interface ButtonProps {
|
||||
onPress: ButtonClickListener;
|
||||
|
||||
// Accessibility label and text shown in a tooltip
|
||||
description?: string;
|
||||
description: string;
|
||||
|
||||
children: ReactNode;
|
||||
iconName: string;
|
||||
iconStyle: TextStyle;
|
||||
|
||||
themeId: number;
|
||||
|
||||
style?: ViewStyle;
|
||||
pressedStyle?: ViewStyle;
|
||||
contentStyle?: ViewStyle;
|
||||
containerStyle?: ViewStyle;
|
||||
contentWrapperStyle?: ViewStyle;
|
||||
|
||||
// Additional accessibility information. See View.accessibilityHint
|
||||
accessibilityHint?: string;
|
||||
@ -35,7 +35,7 @@ interface ButtonProps {
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const CustomButton = (props: ButtonProps) => {
|
||||
const IconButton = (props: ButtonProps) => {
|
||||
const [tooltipVisible, setTooltipVisible] = useState(false);
|
||||
const [buttonLayout, setButtonLayout] = useState<LayoutRectangle|null>(null);
|
||||
const tooltipStyles = useTooltipStyles(props.themeId);
|
||||
@ -67,19 +67,6 @@ const CustomButton = (props: ButtonProps) => {
|
||||
setTooltipVisible(true);
|
||||
}, []);
|
||||
|
||||
// Select different user-specified styles if selected/unselected.
|
||||
const onStyleChange = useCallback((state: PressableStateCallbackType): StyleProp<ViewStyle> => {
|
||||
let result = { ...props.style };
|
||||
|
||||
if (state.pressed) {
|
||||
result = {
|
||||
...result,
|
||||
...props.pressedStyle,
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}, [props.pressedStyle, props.style]);
|
||||
|
||||
const onButtonLayout = useCallback((event: LayoutChangeEvent) => {
|
||||
const layoutEvt = event.nativeEvent.layout;
|
||||
|
||||
@ -87,7 +74,6 @@ const CustomButton = (props: ButtonProps) => {
|
||||
setButtonLayout({ ...layoutEvt });
|
||||
}, []);
|
||||
|
||||
|
||||
const button = (
|
||||
<Pressable
|
||||
onPress={props.onPress}
|
||||
@ -95,7 +81,7 @@ const CustomButton = (props: ButtonProps) => {
|
||||
onPressIn={onPressIn}
|
||||
onPressOut={onPressOut}
|
||||
|
||||
style={ onStyleChange }
|
||||
style={ props.containerStyle }
|
||||
|
||||
disabled={ props.disabled ?? false }
|
||||
onLayout={ onButtonLayout }
|
||||
@ -107,14 +93,21 @@ const CustomButton = (props: ButtonProps) => {
|
||||
>
|
||||
<Animated.View style={{
|
||||
opacity: fadeAnim,
|
||||
...props.contentStyle,
|
||||
...props.contentWrapperStyle,
|
||||
}}>
|
||||
{ props.children }
|
||||
<Icon
|
||||
name={props.iconName}
|
||||
style={props.iconStyle}
|
||||
accessibilityLabel={null}
|
||||
/>
|
||||
</Animated.View>
|
||||
</Pressable>
|
||||
);
|
||||
|
||||
const tooltip = (
|
||||
const renderTooltip = () => {
|
||||
if (!props.description) return null;
|
||||
|
||||
return (
|
||||
<View
|
||||
// Any information given by the tooltip should also be provided via
|
||||
// [accessibilityLabel]/[accessibilityHint]. As such, we can hide the tooltip
|
||||
@ -159,10 +152,11 @@ const CustomButton = (props: ButtonProps) => {
|
||||
</Menu>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.description ? tooltip : null}
|
||||
{renderTooltip()}
|
||||
{button}
|
||||
</>
|
||||
);
|
||||
@ -187,4 +181,4 @@ const useTooltipStyles = (themeId: number) => {
|
||||
}, [themeId]);
|
||||
};
|
||||
|
||||
export default CustomButton;
|
||||
export default IconButton;
|
@ -14,7 +14,7 @@ interface ToggleOverflowButtonProps {
|
||||
// Button that shows/hides the overflow menu.
|
||||
const ToggleOverflowButton: React.FC<ToggleOverflowButtonProps> = (props: ToggleOverflowButtonProps) => {
|
||||
const spec: ButtonSpec = {
|
||||
icon: 'material more-horiz',
|
||||
icon: 'material dots-horizontal',
|
||||
description:
|
||||
props.overflowVisible ? _('Hide more actions') : _('Show more actions'),
|
||||
active: props.overflowVisible,
|
||||
|
@ -14,9 +14,7 @@ import { Theme } from '@joplin/lib/themes/type';
|
||||
import * as React from 'react';
|
||||
import { ReactNode, useCallback, useState, useEffect } from 'react';
|
||||
import { View, ViewStyle } from 'react-native';
|
||||
import CustomButton from '../../CustomButton';
|
||||
|
||||
const AntIcon = require('react-native-vector-icons/AntDesign').default;
|
||||
import IconButton from '../../IconButton';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
@ -54,10 +52,10 @@ const ToggleSpaceButton = (props: Props) => {
|
||||
height: additionalPositiveSpace,
|
||||
zIndex: -2,
|
||||
}} />
|
||||
<CustomButton
|
||||
<IconButton
|
||||
themeId={props.themeId}
|
||||
description={'Move toolbar to bottom of screen'}
|
||||
style={{
|
||||
containerStyle={{
|
||||
height: additionalPositiveSpace,
|
||||
width: '100%',
|
||||
|
||||
@ -72,11 +70,10 @@ const ToggleSpaceButton = (props: Props) => {
|
||||
alignItems: 'center',
|
||||
}}
|
||||
onPress={onDecreaseSpace}
|
||||
>
|
||||
<AntIcon name='down' style={{
|
||||
color: theme.color,
|
||||
}}/>
|
||||
</CustomButton>
|
||||
|
||||
iconName='material chevron-down'
|
||||
iconStyle={{ color: theme.color }}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
|
@ -2,8 +2,7 @@ import * as React from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { TextStyle, StyleSheet } from 'react-native';
|
||||
import { ButtonSpec, StyleSheetData } from './types';
|
||||
import CustomButton from '../../CustomButton';
|
||||
import Icon from '../../Icon';
|
||||
import IconButton from '../../IconButton';
|
||||
|
||||
export const buttonSize = 54;
|
||||
|
||||
@ -58,16 +57,16 @@ const ToolbarButton = ({ styleSheet, spec, onActionComplete, style }: ToolbarBut
|
||||
}, [disabled, sourceOnPress, onActionComplete]);
|
||||
|
||||
return (
|
||||
<CustomButton
|
||||
style={styles.buttonStyle}
|
||||
<IconButton
|
||||
containerStyle={styles.buttonStyle}
|
||||
themeId={styleSheet.themeId}
|
||||
onPress={onPress}
|
||||
description={ spec.description }
|
||||
accessibilityRole="button"
|
||||
disabled={ disabled }
|
||||
>
|
||||
<Icon name={spec.icon} style={styles.iconStyle} accessibilityLabel={null}/>
|
||||
</CustomButton>
|
||||
|
||||
iconName={spec.icon}
|
||||
iconStyle={styles.iconStyle}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -51,7 +51,7 @@ const useActionButtons = (props: ActionButtonRowProps) => {
|
||||
});
|
||||
|
||||
actionButtons.push({
|
||||
icon: 'material search',
|
||||
icon: 'material magnify',
|
||||
description: (
|
||||
props.searchState.dialogVisible ? _('Close') : _('Find and replace')
|
||||
),
|
||||
@ -63,7 +63,7 @@ const useActionButtons = (props: ActionButtonRowProps) => {
|
||||
});
|
||||
|
||||
actionButtons.push({
|
||||
icon: 'material keyboard-hide',
|
||||
icon: 'material keyboard-close',
|
||||
description: _('Hide keyboard'),
|
||||
disabled: !props.keyboardVisible,
|
||||
visible: props.hasSoftwareKeyboard && Platform.OS === 'ios',
|
||||
|
@ -2,13 +2,12 @@
|
||||
|
||||
const React = require('react');
|
||||
const { useMemo, useState, useEffect } = require('react');
|
||||
const MaterialCommunityIcon = require('react-native-vector-icons/MaterialCommunityIcons').default;
|
||||
|
||||
import { EditorSettings } from './types';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { BackHandler, TextInput, View, Text, StyleSheet, ViewStyle } from 'react-native';
|
||||
import { Theme } from '@joplin/lib/themes/type';
|
||||
import CustomButton from '../CustomButton';
|
||||
import IconButton from '../IconButton';
|
||||
import { SearchState } from '@joplin/editor/types';
|
||||
import { SearchControl } from './types';
|
||||
|
||||
@ -43,14 +42,14 @@ interface ActionButtonProps {
|
||||
|
||||
const ActionButton = (props: ActionButtonProps) => {
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
themeId={props.themeId}
|
||||
style={props.styles.button}
|
||||
containerStyle={props.styles.button}
|
||||
onPress={props.onPress}
|
||||
description={props.title}
|
||||
>
|
||||
<MaterialCommunityIcon name={props.iconName} style={props.styles.buttonText}/>
|
||||
</CustomButton>
|
||||
iconName={`material ${props.iconName}`}
|
||||
iconStyle={props.styles.buttonText}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -68,9 +67,9 @@ const ToggleButton = (props: ToggleButtonProps) => {
|
||||
const active = props.active;
|
||||
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
themeId={props.themeId}
|
||||
style={{
|
||||
containerStyle={{
|
||||
...props.styles.toggleButton,
|
||||
...(active ? props.styles.toggleButtonActive : {}),
|
||||
}}
|
||||
@ -81,11 +80,12 @@ const ToggleButton = (props: ToggleButtonProps) => {
|
||||
}}
|
||||
description={props.title}
|
||||
accessibilityRole='switch'
|
||||
>
|
||||
<MaterialCommunityIcon name={props.iconName} style={
|
||||
|
||||
iconName={`material ${props.iconName}`}
|
||||
iconStyle={
|
||||
active ? props.styles.activeButtonText : props.styles.buttonText
|
||||
}/>
|
||||
</CustomButton>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -15,7 +15,7 @@ const { dialogs } = require('../../utils/dialogs.js');
|
||||
const DialogBox = require('react-native-dialogbox').default;
|
||||
import { FolderEntity } from '@joplin/lib/services/database/types';
|
||||
import { State } from '@joplin/lib/reducer';
|
||||
import CustomButton from '../CustomButton';
|
||||
import IconButton from '../IconButton';
|
||||
import FolderPicker from '../FolderPicker';
|
||||
import { itemIsInTrash } from '@joplin/lib/services/trash';
|
||||
import restoreItems from '@joplin/lib/services/trash/restoreItems';
|
||||
@ -363,26 +363,25 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
|
||||
const renderTopButton = (options: TopButtonOptions) => {
|
||||
if (!options.visible) return null;
|
||||
|
||||
const icon = <Icon name={options.iconName} style={this.styles().topIcon} />;
|
||||
const viewStyle = options.disabled ? this.styles().iconButtonDisabled : this.styles().iconButton;
|
||||
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
onPress={options.onPress}
|
||||
style={{ padding: 0 }}
|
||||
containerStyle={{ padding: 0 }}
|
||||
contentWrapperStyle={viewStyle}
|
||||
themeId={themeId}
|
||||
disabled={!!options.disabled}
|
||||
description={options.description}
|
||||
contentStyle={viewStyle}
|
||||
>
|
||||
{icon}
|
||||
</CustomButton>
|
||||
iconName={options.iconName}
|
||||
iconStyle={this.styles().topIcon}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const renderUndoButton = () => {
|
||||
return renderTopButton({
|
||||
iconName: 'arrow-undo-circle-sharp',
|
||||
iconName: 'ionicon arrow-undo-circle-sharp',
|
||||
description: _('Undo'),
|
||||
onPress: this.props.onUndoButtonPress,
|
||||
visible: this.props.showUndoButton,
|
||||
@ -392,7 +391,7 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
|
||||
|
||||
const renderRedoButton = () => {
|
||||
return renderTopButton({
|
||||
iconName: 'arrow-redo-circle-sharp',
|
||||
iconName: 'ionicon arrow-redo-circle-sharp',
|
||||
description: _('Redo'),
|
||||
onPress: this.props.onRedoButtonPress,
|
||||
visible: this.props.showRedoButton,
|
||||
@ -402,30 +401,32 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
function selectAllButton(styles: any, onPress: OnPressCallback) {
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
onPress={onPress}
|
||||
|
||||
themeId={themeId}
|
||||
description={_('Select all')}
|
||||
contentStyle={styles.iconButton}
|
||||
>
|
||||
<Icon name="checkmark-circle-outline" style={styles.topIcon} />
|
||||
</CustomButton>
|
||||
contentWrapperStyle={styles.iconButton}
|
||||
|
||||
iconName="ionicon checkmark-circle-outline"
|
||||
iconStyle={styles.topIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
function searchButton(styles: any, onPress: OnPressCallback) {
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
onPress={onPress}
|
||||
|
||||
description={_('Search')}
|
||||
themeId={themeId}
|
||||
contentStyle={styles.iconButton}
|
||||
>
|
||||
<Icon name="search" style={styles.topIcon} />
|
||||
</CustomButton>
|
||||
contentWrapperStyle={styles.iconButton}
|
||||
|
||||
iconName='ionicon search'
|
||||
iconStyle={styles.topIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
@ -438,21 +439,22 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
|
||||
if (allVisiblePanels.length === 0) return null;
|
||||
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
onPress={onPress}
|
||||
description={_('Plugin panels')}
|
||||
themeId={themeId}
|
||||
contentStyle={styles.iconButton}
|
||||
>
|
||||
<Icon name="extension-puzzle" style={styles.topIcon} />
|
||||
</CustomButton>
|
||||
contentWrapperStyle={styles.iconButton}
|
||||
|
||||
iconName="ionicon extension-puzzle"
|
||||
iconStyle={styles.topIcon}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
function deleteButton(styles: any, onPress: OnPressCallback, disabled: boolean) {
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
|
||||
@ -461,17 +463,18 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
|
||||
accessibilityHint={
|
||||
disabled ? null : _('Delete selected notes')
|
||||
}
|
||||
contentStyle={disabled ? styles.iconButtonDisabled : styles.iconButton}
|
||||
>
|
||||
<Icon name="trash" style={styles.topIcon} />
|
||||
</CustomButton>
|
||||
contentWrapperStyle={disabled ? styles.iconButtonDisabled : styles.iconButton}
|
||||
|
||||
iconName='ionicon trash'
|
||||
iconStyle={styles.topIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
function restoreButton(styles: any, onPress: OnPressCallback, disabled: boolean) {
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
|
||||
@ -480,17 +483,18 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
|
||||
accessibilityHint={
|
||||
disabled ? null : _('Restore')
|
||||
}
|
||||
contentStyle={disabled ? styles.iconButtonDisabled : styles.iconButton}
|
||||
>
|
||||
<Icon name="reload-circle" style={styles.topIcon} />
|
||||
</CustomButton>
|
||||
contentWrapperStyle={disabled ? styles.iconButtonDisabled : styles.iconButton}
|
||||
|
||||
iconName='ionicon reload-circle'
|
||||
iconStyle={styles.topIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
function duplicateButton(styles: any, onPress: OnPressCallback, disabled: boolean) {
|
||||
return (
|
||||
<CustomButton
|
||||
<IconButton
|
||||
onPress={onPress}
|
||||
disabled={disabled}
|
||||
|
||||
@ -499,10 +503,10 @@ class ScreenHeaderComponent extends PureComponent<ScreenHeaderProps, ScreenHeade
|
||||
accessibilityHint={
|
||||
disabled ? null : _('Duplicate selected notes')
|
||||
}
|
||||
contentStyle={disabled ? styles.iconButtonDisabled : styles.iconButton}
|
||||
>
|
||||
<Icon name="copy" style={styles.topIcon} />
|
||||
</CustomButton>
|
||||
contentWrapperStyle={disabled ? styles.iconButtonDisabled : styles.iconButton}
|
||||
iconName='ionicon copy'
|
||||
iconStyle={styles.topIcon}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -108,3 +108,4 @@ libasound
|
||||
libatk
|
||||
ENOTFOUND
|
||||
Scaleway
|
||||
Ionicon
|
||||
|
Loading…
Reference in New Issue
Block a user