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); + } + }