diff --git a/packages/app-desktop/gui/Sidebar/Sidebar.tsx b/packages/app-desktop/gui/Sidebar/Sidebar.tsx
index adb613a5a..07cc70a96 100644
--- a/packages/app-desktop/gui/Sidebar/Sidebar.tsx
+++ b/packages/app-desktop/gui/Sidebar/Sidebar.tsx
@@ -152,7 +152,7 @@ const SidebarComponent = (props: Props) => {
// visual alignment is correct for all folders, otherwise the folder tree
// looks messy.
const showFolderIcons = useMemo(() => {
- return !!props.folders.find((f: FolderEntity) => !!f.icon);
+ return Folder.shouldShowFolderIcons(props.folders);
}, [props.folders]);
const getSelectedItem = useCallback(() => {
diff --git a/packages/app-mobile/components/side-menu-content.tsx b/packages/app-mobile/components/side-menu-content.tsx
index 673f89f53..b8123139c 100644
--- a/packages/app-mobile/components/side-menu-content.tsx
+++ b/packages/app-mobile/components/side-menu-content.tsx
@@ -1,5 +1,5 @@
const React = require('react');
-import { useMemo, useEffect } from 'react';
+import { useMemo, useEffect, useCallback } from 'react';
const { Easing, Animated, TouchableOpacity, Text, StyleSheet, ScrollView, View, Alert, Image } = require('react-native');
const { connect } = require('react-redux');
const Icon = require('react-native-vector-icons/Ionicons').default;
@@ -11,6 +11,8 @@ const { themeStyle } = require('./global-style.js');
const shared = require('@joplin/lib/components/shared/side-menu-shared.js');
import { FolderEntity, FolderIcon } from '@joplin/lib/services/database/types';
import { AppState } from '../utils/types';
+import Setting from '@joplin/lib/models/Setting';
+import { reg } from '@joplin/lib/registry';
Icon.loadFont();
@@ -39,6 +41,8 @@ const syncIconRotation = syncIconRotationValue.interpolate({
let syncIconAnimation: any;
const SideMenuContentComponent = (props: Props) => {
+ const alwaysShowFolderIcons = useMemo(() => Folder.shouldShowFolderIcons(props.folders), [props.folders]);
+
const styles_ = useMemo(() => {
const theme = themeStyle(props.themeId);
@@ -215,13 +219,72 @@ const SideMenuContentComponent = (props: Props) => {
});
};
- const synchronize_press = async () => {
- const actionDone = await shared.synchronize_press(this);
+ const performSync = useCallback(async () => {
+ const action = props.syncStarted ? 'cancel' : 'start';
+
+ if (!Setting.value('sync.target')) {
+ props.dispatch({
+ type: 'SIDE_MENU_CLOSE',
+ });
+
+ props.dispatch({
+ type: 'NAV_GO',
+ routeName: 'Config',
+ sectionName: 'sync',
+ });
+
+ return 'init';
+ }
+
+ if (!(await reg.syncTarget().isAuthenticated())) {
+ if (reg.syncTarget().authRouteName()) {
+ props.dispatch({
+ type: 'NAV_GO',
+ routeName: reg.syncTarget().authRouteName(),
+ });
+ return 'auth';
+ }
+
+ reg.logger().error('Not authenticated with sync target - please check your credentials.');
+ return 'error';
+ }
+
+ let sync = null;
+ try {
+ sync = await reg.syncTarget().synchronizer();
+ } catch (error) {
+ reg.logger().error('Could not initialise synchroniser: ');
+ reg.logger().error(error);
+ error.message = `Could not initialise synchroniser: ${error.message}`;
+ props.dispatch({
+ type: 'SYNC_REPORT_UPDATE',
+ report: { errors: [error] },
+ });
+ return 'error';
+ }
+
+ if (action === 'cancel') {
+ void sync.cancel();
+ return 'cancel';
+ } else {
+ void reg.scheduleSync(0);
+ return 'sync';
+ }
+ }, [props.syncStarted, props.dispatch]);
+
+ const synchronize_press = useCallback(async () => {
+ const actionDone = await performSync();
if (actionDone === 'auth') props.dispatch({ type: 'SIDE_MENU_CLOSE' });
- };
+ }, [performSync, props.dispatch]);
const renderFolderIcon = (theme: any, folderIcon: FolderIcon) => {
- if (!folderIcon) return ;
+ if (!folderIcon) {
+ if (alwaysShowFolderIcons) {
+ return ;
+ } else {
+ return null;
+ }
+ }
if (folderIcon.type === 1) { // FolderIconType.Emoji
return {folderIcon.emoji};
@@ -381,8 +444,6 @@ const SideMenuContentComponent = (props: Props) => {
const theme = themeStyle(props.themeId);
- // const showFolderIcons = Folder.shouldShowFolderIcons(props.folders);
-
// HACK: inner height of ScrollView doesn't appear to be calculated correctly when
// using padding. So instead creating blank elements for padding bottom and top.
items.push();
diff --git a/packages/lib/components/shared/side-menu-shared.js b/packages/lib/components/shared/side-menu-shared.js
index 7600db75d..b8961d328 100644
--- a/packages/lib/components/shared/side-menu-shared.js
+++ b/packages/lib/components/shared/side-menu-shared.js
@@ -1,5 +1,4 @@
const Folder = require('../../models/Folder').default;
-const Setting = require('../../models/Setting').default;
const BaseModel = require('../../BaseModel').default;
const shared = {};
@@ -77,59 +76,4 @@ shared.renderTags = function(props, renderItem) {
};
};
-shared.synchronize_press = async function(comp) {
- const { reg } = require('../../registry.js');
-
- const action = comp.props.syncStarted ? 'cancel' : 'start';
-
- if (!Setting.value('sync.target')) {
- comp.props.dispatch({
- type: 'SIDE_MENU_CLOSE',
- });
-
- comp.props.dispatch({
- type: 'NAV_GO',
- routeName: 'Config',
- sectionName: 'sync',
- });
-
- return 'init';
- }
-
- if (!(await reg.syncTarget().isAuthenticated())) {
- if (reg.syncTarget().authRouteName()) {
- comp.props.dispatch({
- type: 'NAV_GO',
- routeName: reg.syncTarget().authRouteName(),
- });
- return 'auth';
- }
-
- reg.logger().error('Not authenticated with sync target - please check your credentials.');
- return 'error';
- }
-
- let sync = null;
- try {
- sync = await reg.syncTarget().synchronizer();
- } catch (error) {
- reg.logger().error('Could not initialise synchroniser: ');
- reg.logger().error(error);
- error.message = `Could not initialise synchroniser: ${error.message}`;
- comp.props.dispatch({
- type: 'SYNC_REPORT_UPDATE',
- report: { errors: [error] },
- });
- return 'error';
- }
-
- if (action === 'cancel') {
- sync.cancel();
- return 'cancel';
- } else {
- reg.scheduleSync(0);
- return 'sync';
- }
-};
-
module.exports = shared;
diff --git a/packages/lib/models/Folder.ts b/packages/lib/models/Folder.ts
index 40f6291de..94eadee97 100644
--- a/packages/lib/models/Folder.ts
+++ b/packages/lib/models/Folder.ts
@@ -782,4 +782,12 @@ export default class Folder extends BaseItem {
};
}
+ public static shouldShowFolderIcons(folders: FolderEntity[]) {
+ // If at least one of the folder has an icon, then we display icons for all
+ // folders (those without one will get the default icon). This is so that
+ // visual alignment is correct for all folders, otherwise the folder tree
+ // looks messy.
+ return !!folders.find(f => !!f.icon);
+ }
+
}