Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile: Implement plugin screen redesign #10465

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
7d043b3
Refactor: Rename CustomButton -> IconButton
personalizedrefrigerator May 14, 2024
6c9f8cb
Make card and button styles closer to the original design
personalizedrefrigerator May 16, 2024
5e946c3
Make plugin screen styles (but not yet layout) closer to the Figma
personalizedrefrigerator May 17, 2024
cc7aa45
Make chip styles closer to desktop
personalizedrefrigerator May 17, 2024
7aa2395
Fix TextButton spacing when showing loading animation
personalizedrefrigerator May 17, 2024
8411b2d
Fix padding when buttons have an icon
personalizedrefrigerator May 17, 2024
8002ce1
Start restyling the about modal
personalizedrefrigerator May 17, 2024
e8afcc4
Restyle and add enable button to info modal
personalizedrefrigerator May 18, 2024
6d5d994
Add delete button to info modal, minor refactoring
personalizedrefrigerator May 20, 2024
f2ab7d8
Revert to unstyled RN Paper widgets in most cases
personalizedrefrigerator May 20, 2024
99b3dea
WIP
personalizedrefrigerator May 21, 2024
9b2f48f
Plugin info modal: Mostly functional
personalizedrefrigerator May 23, 2024
006e07c
Fix dialog size in landscape mode
personalizedrefrigerator May 23, 2024
6279841
Change style of "report an issue" to better match design
personalizedrefrigerator May 23, 2024
00d285f
Restyle "install from file
personalizedrefrigerator May 23, 2024
c77be22
Slightly decrease size of plugin chips
personalizedrefrigerator May 23, 2024
4f35657
Fix error chip, adjust global styles to simplify changes
personalizedrefrigerator May 23, 2024
cca5ebc
Adjust chip and card title styles
personalizedrefrigerator May 23, 2024
d5d3a62
Ignore auto-generated file
personalizedrefrigerator May 23, 2024
ac5b9c6
Add a disabled chip
personalizedrefrigerator May 23, 2024
360a3b8
Refactor plugin search to re-use the install handler created in
personalizedrefrigerator May 23, 2024
77a6784
Add search results text
personalizedrefrigerator May 23, 2024
c364690
Fix test compilation (running still failing)
personalizedrefrigerator May 24, 2024
81fb684
Fix several tests (many still broken)
personalizedrefrigerator May 24, 2024
e7bfe06
Try to reduce number of warnings during testing
personalizedrefrigerator May 24, 2024
4639da8
Fix tests
personalizedrefrigerator May 24, 2024
75a3e93
Adjust loading indicator
personalizedrefrigerator May 24, 2024
8d95787
Wrap installed and search sections in different accordion groups
personalizedrefrigerator May 24, 2024
d4799f3
Use correct singular/plural description for installed plugins accordi…
personalizedrefrigerator May 24, 2024
dda04ed
Search: Use data from installed plugins, when available
personalizedrefrigerator May 24, 2024
91cbaa3
Fix desktop build
personalizedrefrigerator May 24, 2024
4fdb5f7
Adjust modal styles
personalizedrefrigerator May 24, 2024
106d453
Simplify primary button default colors
personalizedrefrigerator May 24, 2024
56ffd13
Fix failing test
personalizedrefrigerator May 24, 2024
a9622c4
Fix linter errors
personalizedrefrigerator May 24, 2024
53ca1e4
Merge remote-tracking branch 'upstream/dev' into pr/mobile/implement-…
personalizedrefrigerator May 25, 2024
c598a28
Merge remote-tracking branch 'upstream/dev' into pr/mobile/implement-…
personalizedrefrigerator May 27, 2024
9cbaa77
Remove extra styles from Modal.tsx
personalizedrefrigerator May 27, 2024
735c5e5
Better handle showing an info modal for an uninstalled plugin
personalizedrefrigerator May 27, 2024
04dcb5a
Fix TouchableRipple animation on Android
personalizedrefrigerator May 27, 2024
e424daf
Improve commenting, file names
personalizedrefrigerator May 27, 2024
fb86547
Limit the maximum dialog size
personalizedrefrigerator May 27, 2024
836a9e6
Hide accordion description when searching through settings
personalizedrefrigerator May 27, 2024
ab2cc8b
Refactoring: Props/naming
personalizedrefrigerator May 29, 2024
cd87512
Fix type name
personalizedrefrigerator May 29, 2024
e992cce
Add test for the "enabled" toggle
personalizedrefrigerator May 29, 2024
eb981ac
Fix version number doesn't update in modal
personalizedrefrigerator Jun 3, 2024
d0804b5
Increase findByRole timeout for CI
personalizedrefrigerator Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,8 @@ packages/app-mobile/components/base-screen.js
packages/app-mobile/components/biometrics/BiometricPopup.js
packages/app-mobile/components/biometrics/biometricAuthenticate.js
packages/app-mobile/components/biometrics/sensorInfo.js
packages/app-mobile/components/buttons/TextButton.js
packages/app-mobile/components/buttons/index.js
packages/app-mobile/components/getResponsiveValue.test.js
packages/app-mobile/components/getResponsiveValue.js
packages/app-mobile/components/global-style.js
Expand All @@ -608,19 +610,28 @@ packages/app-mobile/components/screens/ConfigScreen/SettingsButton.js
packages/app-mobile/components/screens/ConfigScreen/SettingsToggle.js
packages/app-mobile/components/screens/ConfigScreen/configScreenStyles.js
packages/app-mobile/components/screens/ConfigScreen/plugins/EnablePluginSupportPage.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/ActionButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginInfoButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/InstalledPluginBox.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginChips.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginTitle.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/StyledChip.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/index.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginInfoModal.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.installed.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.search.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginToggle.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginUploadButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/SearchPlugins.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/SearchPlugins.js
packages/app-mobile/components/screens/ConfigScreen/plugins/buttons/ActionButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/buttons/InstallButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/WrappedPluginStates.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/mockRepositoryApiConstructor.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/newRepoApi.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/pluginServiceSetup.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/openWebsiteForPlugin.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/usePluginCallbacks.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/usePluginItem.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useRepoApi.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useUpdateState.js
packages/app-mobile/components/screens/ConfigScreen/types.js
packages/app-mobile/components/screens/JoplinCloudLoginScreen.js
packages/app-mobile/components/screens/LogScreen.js
Expand Down
21 changes: 16 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,8 @@ packages/app-mobile/components/base-screen.js
packages/app-mobile/components/biometrics/BiometricPopup.js
packages/app-mobile/components/biometrics/biometricAuthenticate.js
packages/app-mobile/components/biometrics/sensorInfo.js
packages/app-mobile/components/buttons/TextButton.js
packages/app-mobile/components/buttons/index.js
packages/app-mobile/components/getResponsiveValue.test.js
packages/app-mobile/components/getResponsiveValue.js
packages/app-mobile/components/global-style.js
Expand All @@ -587,19 +589,28 @@ packages/app-mobile/components/screens/ConfigScreen/SettingsButton.js
packages/app-mobile/components/screens/ConfigScreen/SettingsToggle.js
packages/app-mobile/components/screens/ConfigScreen/configScreenStyles.js
packages/app-mobile/components/screens/ConfigScreen/plugins/EnablePluginSupportPage.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/ActionButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginInfoButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/InstalledPluginBox.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginChips.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/PluginTitle.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/StyledChip.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginBox/index.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginInfoModal.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.installed.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.search.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginStates.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginToggle.js
packages/app-mobile/components/screens/ConfigScreen/plugins/PluginUploadButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/SearchPlugins.test.js
packages/app-mobile/components/screens/ConfigScreen/plugins/SearchPlugins.js
packages/app-mobile/components/screens/ConfigScreen/plugins/buttons/ActionButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/buttons/InstallButton.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/WrappedPluginStates.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/mockRepositoryApiConstructor.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/newRepoApi.js
packages/app-mobile/components/screens/ConfigScreen/plugins/testUtils/pluginServiceSetup.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/openWebsiteForPlugin.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/usePluginCallbacks.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/usePluginItem.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useRepoApi.js
packages/app-mobile/components/screens/ConfigScreen/plugins/utils/useUpdateState.js
packages/app-mobile/components/screens/ConfigScreen/types.js
packages/app-mobile/components/screens/JoplinCloudLoginScreen.js
packages/app-mobile/components/screens/LogScreen.js
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ interface Props {
function manifestToItem(manifest: PluginManifest): PluginItem {
return {
manifest: manifest,
installed: true,
enabled: true,
deleted: false,
devMode: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ function usePluginItems(plugins: Plugins, settings: PluginSettings): PluginItem[

output.push({
manifest: plugin.manifest,
installed: true,
enabled: setting.enabled,
deleted: setting.deleted,
devMode: plugin.devMode,
Expand Down
24 changes: 19 additions & 5 deletions packages/app-mobile/components/DismissibleDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,32 @@ import { themeStyle } from './global-style';
import Modal from './Modal';
import { _ } from '@joplin/lib/locale';

export enum DialogSize {
Small = 'small',

// Ideal for panels and dialogs that should be fullscreen even on large devices
Large = 'large',
}

interface Props {
themeId: number;
visible: boolean;
onDismiss: ()=> void;
containerStyle?: ViewStyle;
children: React.ReactNode;

size: DialogSize;
}

const useStyles = (themeId: number, containerStyle: ViewStyle) => {
const useStyles = (themeId: number, containerStyle: ViewStyle, size: DialogSize) => {
const windowSize = useWindowDimensions();

return useMemo(() => {
const theme = themeStyle(themeId);

const maxWidth = size === DialogSize.Large ? Infinity : 500;
const maxHeight = size === DialogSize.Large ? Infinity : 700;

return StyleSheet.create({
webView: {
backgroundColor: 'transparent',
Expand All @@ -38,8 +50,10 @@ const useStyles = (themeId: number, containerStyle: ViewStyle) => {
borderRadius: 12,
padding: 10,

height: windowSize.height * 0.9,
width: windowSize.width * 0.97,
// Use Math.min with width and height -- the maxWidth and maxHeight style
// properties don't seem to limit the size for this.
height: Math.min(maxHeight, windowSize.height * 0.9),
width: Math.min(maxWidth, windowSize.width * 0.97),
flexShrink: 1,

// Center
Expand All @@ -56,11 +70,11 @@ const useStyles = (themeId: number, containerStyle: ViewStyle) => {
flexGrow: 1,
},
});
}, [themeId, windowSize.width, windowSize.height, containerStyle]);
}, [themeId, windowSize.width, windowSize.height, containerStyle, size]);
};

const DismissibleDialog: React.FC<Props> = props => {
const styles = useStyles(props.themeId, props.containerStyle);
const styles = useStyles(props.themeId, props.containerStyle, props.size);

const closeButton = (
<View style={styles.closeButtonContainer}>
Expand Down
81 changes: 81 additions & 0 deletions packages/app-mobile/components/buttons/TextButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as React from 'react';
import { ReactNode, useMemo } from 'react';
import { themeStyle } from '../global-style';
import { Button, ButtonProps } from 'react-native-paper';
import { connect } from 'react-redux';
import { AppState } from '../../utils/types';

export enum ButtonType {
Primary,
Secondary,
Delete,
Link,
}

interface Props extends Omit<ButtonProps, 'item'|'onPress'|'children'> {
themeId: number;
type: ButtonType;
onPress: ()=> void;
children: ReactNode;
}

export type TextButtonProps = Omit<Props, 'themeId'>;

const useStyles = ({ themeId }: Props) => {
return useMemo(() => {
const theme = themeStyle(themeId);

const themeOverride = {
secondaryButton: {
colors: {
primary: theme.color4,
outline: theme.color4,
},
},
deleteButton: {
colors: {
primary: theme.destructiveColor,
outline: theme.destructiveColor,
},
},
primaryButton: { },
};

return { themeOverride };
}, [themeId]);
};

const TextButton: React.FC<Props> = props => {
const { themeOverride } = useStyles(props);

let mode: ButtonProps['mode'];
let theme: ButtonProps['theme'];

if (props.type === ButtonType.Primary) {
theme = themeOverride.primaryButton;
mode = 'contained';
} else if (props.type === ButtonType.Secondary) {
theme = themeOverride.secondaryButton;
mode = 'outlined';
} else if (props.type === ButtonType.Delete) {
theme = themeOverride.deleteButton;
mode = 'outlined';
} else if (props.type === ButtonType.Link) {
theme = themeOverride.secondaryButton;
mode = 'text';
} else {
const exhaustivenessCheck: never = props.type;
return exhaustivenessCheck;
}

return <Button
{...props}
theme={theme}
mode={mode}
onPress={props.onPress}
>{props.children}</Button>;
};

export default connect((state: AppState) => {
return { themeId: state.settings.theme };
})(TextButton);
14 changes: 14 additions & 0 deletions packages/app-mobile/components/buttons/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import * as React from 'react';
import TextButton, { ButtonType, TextButtonProps } from './TextButton';

type Props = Omit<TextButtonProps, 'type'>;

const makeTextButtonComponent = (type: ButtonType) => {
return (props: Props) => {
return <TextButton {...props} type={type} />;
};
};

export const PrimaryButton = makeTextButtonComponent(ButtonType.Primary);
export const SecondaryButton = makeTextButtonComponent(ButtonType.Secondary);
export const LinkButton = makeTextButtonComponent(ButtonType.Link);
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { Platform, Linking, View, Switch, ScrollView, Text, TouchableOpacity, Alert, PermissionsAndroid, Dimensions, AccessibilityInfo } from 'react-native';
import Setting, { AppType, SettingItem, SettingMetadataSection } from '@joplin/lib/models/Setting';
import Setting, { AppType, SettingMetadataSection } from '@joplin/lib/models/Setting';
import NavService from '@joplin/lib/services/NavService';
import SearchEngine from '@joplin/lib/services/search/SearchEngine';
import checkPermissions from '../../../utils/checkPermissions';
Expand All @@ -26,7 +26,7 @@ import ExportProfileButton, { exportProfileButtonTitle } from './NoteExportSecti
import SettingComponent from './SettingComponent';
import ExportDebugReportButton, { exportDebugReportTitle } from './NoteExportSection/ExportDebugReportButton';
import SectionSelector from './SectionSelector';
import { Button, TextInput } from 'react-native-paper';
import { TextInput, List } from 'react-native-paper';
import PluginService, { PluginSettings } from '@joplin/lib/services/plugins/PluginService';
import PluginStates, { getSearchText as getPluginStatesSearchText } from './plugins/PluginStates';
import PluginUploadButton, { canInstallPluginsFromFile, buttonLabel as pluginUploadButtonSearchText } from './plugins/PluginUploadButton';
Expand Down Expand Up @@ -390,7 +390,7 @@ class ConfigScreenComponent extends BaseScreenComponent<ConfigScreenProps, Confi
const addSettingComponent = (
component: ReactElement,
relatedText: string|string[],
settingMetadata?: SettingItem,
settingMetadata?: { advanced?: boolean },
) => {
const hiddenBySearch = this.state.searching && !matchesSearchQuery(relatedText);
if (component && !hiddenBySearch) {
Expand Down Expand Up @@ -504,8 +504,10 @@ class ConfigScreenComponent extends BaseScreenComponent<ConfigScreenProps, Confi
key='plugins-install-from-file'
pluginSettings={settings[pluginStatesKey]}
updatePluginStates={updatePluginStates}
styles={this.styles()}
/>,
pluginUploadButtonSearchText(),
{ advanced: true },
);
}
} else {
Expand Down Expand Up @@ -672,19 +674,15 @@ class ConfigScreenComponent extends BaseScreenComponent<ConfigScreenProps, Confi
const renderAdvancedSettings = () => {
if (!advancedSettingComps.length) return null;

const toggleAdvancedLabel = this.state.showAdvancedSettings ? _('Hide Advanced Settings') : _('Show Advanced Settings');
const toggleAdvancedLabel = _('Advanced settings');
return (
<>
<Button
style={{ marginBottom: 20 }}
icon={this.state.showAdvancedSettings ? 'menu-down' : 'menu-right'}
onPress={() => this.setState({ showAdvancedSettings: !this.state.showAdvancedSettings })}
>
<Text>{toggleAdvancedLabel}</Text>
</Button>

<List.Accordion
title={toggleAdvancedLabel}
expanded={this.state.showAdvancedSettings}
onPress={() => this.setState({ showAdvancedSettings: !this.state.showAdvancedSettings })}
>
{this.state.showAdvancedSettings ? advancedSettingComps : null}
</>
</List.Accordion>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { themeStyle } from '../../../global-style';
import * as React from 'react';
import { useMemo } from 'react';
import { Linking, View, StyleSheet, ViewStyle, TextStyle } from 'react-native';
import { Button, Card, Divider, Icon, List, Text } from 'react-native-paper';
import { Card, Divider, Icon, List, Text } from 'react-native-paper';
import { LinkButton, PrimaryButton } from '../../../buttons';

interface Props {
themeId: number;
Expand Down Expand Up @@ -50,26 +51,13 @@ const useStyles = (themeId: number) => {
marginBottom: 0,
},
actionButton: {
borderRadius: 10,
marginLeft: theme.marginLeft * 2,
marginRight: theme.marginRight * 2,
marginBottom: theme.margin,
},
});

const themeOverride = {
secondaryButton: {
colors: {
primary: theme.color4,
outline: theme.color4,
},
},
primaryButton: {
colors: {
primary: theme.color4,
onPrimary: theme.backgroundColor4,
},
},
card: {
colors: {
outline: theme.codeBorderColor,
Expand Down Expand Up @@ -127,8 +115,8 @@ const EnablePluginSupportPage: React.FC<Props> = props => {
{renderCard('source-branch-check', _('Open Source'), _('Most plugins have source code available for review on the plugin website.'))}
{renderCard('flag-remove', _('Report system'), _('We have a system for reporting and removing problematic plugins.'))}
<View>
<Button style={styles.actionButton} theme={themeOverride.secondaryButton} onPress={onLearnMorePress}>{_('Learn more')}</Button>
<Button style={styles.actionButton} theme={themeOverride.primaryButton} mode='contained' onPress={props.onEnablePluginSupport}>{_('Enable plugin support')}</Button>
<LinkButton style={styles.actionButton} onPress={onLearnMorePress}>{_('Learn more')}</LinkButton>
<PrimaryButton style={styles.actionButton} onPress={props.onEnablePluginSupport}>{_('Enable plugin support')}</PrimaryButton>
</View>
</View>
);
Expand Down
Loading
Loading