From 8393ccc7f8decebc38ddcb9f2e94851b947e0598 Mon Sep 17 00:00:00 2001 From: Henry Heino <46334387+personalizedrefrigerator@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:15:18 -0700 Subject: [PATCH] Chore: Desktop: Use stronger types in `Sidebar.tsx` (#10305) --- packages/app-desktop/gui/Sidebar/Sidebar.tsx | 119 ++++++++++++------- packages/lib/reducer.ts | 6 +- packages/lib/services/commands/MenuUtils.ts | 4 +- 3 files changed, 82 insertions(+), 47 deletions(-) diff --git a/packages/app-desktop/gui/Sidebar/Sidebar.tsx b/packages/app-desktop/gui/Sidebar/Sidebar.tsx index 9a7255f73..0bbefc01a 100644 --- a/packages/app-desktop/gui/Sidebar/Sidebar.tsx +++ b/packages/app-desktop/gui/Sidebar/Sidebar.tsx @@ -1,5 +1,5 @@ import * as React from 'react'; -import { useEffect, useRef, useCallback, useMemo } from 'react'; +import { useEffect, useRef, useCallback, useMemo, DragEventHandler, MouseEventHandler, RefObject } from 'react'; import { StyledRoot, StyledAddButton, StyledShareIcon, StyledHeader, StyledHeaderIcon, StyledAllNotesIcon, StyledHeaderLabel, StyledListItem, StyledListItemAnchor, StyledExpandLink, StyledNoteCount, StyledSyncReportText, StyledSyncReport, StyledSynchronizeButton, StyledSpanFix } from './styles'; import { ButtonLevel } from '../Button/Button'; import CommandService from '@joplin/lib/services/CommandService'; @@ -19,40 +19,38 @@ import Tag from '@joplin/lib/models/Tag'; import Logger from '@joplin/utils/Logger'; import { FolderEntity, FolderIcon, FolderIconType, TagEntity } from '@joplin/lib/services/database/types'; import stateToWhenClauseContext from '../../services/commands/stateToWhenClauseContext'; -import { store } from '@joplin/lib/reducer'; +import { StateDecryptionWorker, StateResourceFetcher, store } from '@joplin/lib/reducer'; import PerFolderSortOrderService from '../../services/sortOrder/PerFolderSortOrderService'; import { getFolderCallbackUrl, getTagCallbackUrl } from '@joplin/lib/callbackUrlUtils'; import FolderIconBox from '../FolderIconBox'; import onFolderDrop from '@joplin/lib/models/utils/onFolderDrop'; import { RuntimeProps } from './commands/focusElementSideBar'; -const { connect } = require('react-redux'); +import { connect } from 'react-redux'; import { renderFolders, renderTags } from '@joplin/lib/components/shared/side-menu-shared'; import { getTrashFolderIcon, getTrashFolderId } from '@joplin/lib/services/trash'; import { focus } from '@joplin/lib/utils/focusHandler'; import { ThemeStyle, themeStyle } from '@joplin/lib/theme'; -const bridge = require('@electron/remote').require('./bridge').default; +import { Dispatch } from 'redux'; +import bridge from '../../services/bridge'; const Menu = bridge().Menu; const MenuItem = bridge().MenuItem; -const { substrWithEllipsis } = require('@joplin/lib/string-utils'); +import { substrWithEllipsis } from '@joplin/lib/string-utils'; const { ALL_NOTES_FILTER_ID } = require('@joplin/lib/reserved-ids'); -const { clipboard } = require('electron'); +import { clipboard } from 'electron'; const logger = Logger.create('Sidebar'); interface Props { themeId: number; - // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied - dispatch: Function; + dispatch: Dispatch; folders: FolderEntity[]; collapsedFolderIds: string[]; notesParentType: string; selectedFolderId: string; selectedTagId: string; selectedSmartFilterId: string; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - decryptionWorker: any; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - resourceFetcher: any; + decryptionWorker: StateDecryptionWorker; + resourceFetcher: StateResourceFetcher; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied syncReport: any; tags: TagEntity[]; @@ -66,17 +64,30 @@ const commands = [ require('./commands/focusElementSideBar'), ]; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -function ExpandIcon(props: any) { +interface ExpandIconProps { + themeId: number; + isExpanded: boolean; + isVisible: boolean; +} + +function ExpandIcon(props: ExpandIconProps) { const theme = themeStyle(props.themeId); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const style: any = { width: 16, maxWidth: 16, opacity: 0.5, fontSize: Math.round(theme.toolbarIconSize * 0.8), display: 'flex', justifyContent: 'center' }; + const style: React.CSSProperties = { + width: 16, maxWidth: 16, opacity: 0.5, fontSize: Math.round(theme.toolbarIconSize * 0.8), display: 'flex', justifyContent: 'center', + }; if (!props.isVisible) style.visibility = 'hidden'; return ; } -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -function ExpandLink(props: any) { +interface ExpandLinkProps { + themeId: number; + folderId: string; + hasChildren: boolean; + isExpanded: boolean; + onClick: MouseEventHandler; +} + +function ExpandLink(props: ExpandLinkProps) { return props.hasChildren ? ( @@ -100,8 +111,33 @@ const renderFolderIcon = (folderIcon: FolderIcon) => { return
; }; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied -function FolderItem(props: any) { +type ItemDragListener = DragEventHandler; +type ItemContextMenuListener = MouseEventHandler; +type ItemClickListener = MouseEventHandler; + +interface FolderItemProps { + themeId: number; + hasChildren: boolean; + showFolderIcon: boolean; + isExpanded: boolean; + parentId: string; + depth: number; + selected: boolean; + folderId: string; + folderTitle: string; + folderIcon: FolderIcon; + anchorRef: RefObject; + noteCount: number; + onFolderDragStart_: ItemDragListener; + onFolderDragOver_: ItemDragListener; + onFolderDrop_: ItemDragListener; + itemContextMenu: ItemContextMenuListener; + folderItem_click: (folderId: string)=> void; + onFolderToggleClick_: ItemClickListener; + shareId: string; +} + +function FolderItem(props: FolderItemProps) { const { hasChildren, showFolderIcon, isExpanded, parentId, depth, selected, folderId, folderTitle, folderIcon, anchorRef, noteCount, onFolderDragStart_, onFolderDragOver_, onFolderDrop_, itemContextMenu, folderItem_click, onFolderToggleClick_, shareId } = props; const noteCountComp = noteCount ? {noteCount} : null; @@ -147,11 +183,9 @@ const menuUtils = new MenuUtils(CommandService.instance()); const SidebarComponent = (props: Props) => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const folderItemsOrder_ = useRef(); + const folderItemsOrder_ = useRef(); folderItemsOrder_.current = []; - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const tagItemsOrder_ = useRef(); + const tagItemsOrder_ = useRef(); tagItemsOrder_.current = []; const rootRef = useRef(null); @@ -214,8 +248,7 @@ const SidebarComponent = (props: Props) => { getFirstAnchorItemRef, ]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const onFolderDragStart_ = useCallback((event: any) => { + const onFolderDragStart_: ItemDragListener = useCallback(event => { const folderId = event.currentTarget.getAttribute('data-folder-id'); if (!folderId) return; @@ -224,14 +257,12 @@ const SidebarComponent = (props: Props) => { event.dataTransfer.setData('text/x-jop-folder-ids', JSON.stringify([folderId])); }, []); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const onFolderDragOver_ = useCallback((event: any) => { + const onFolderDragOver_: ItemDragListener = useCallback(event => { if (event.dataTransfer.types.indexOf('text/x-jop-note-ids') >= 0) event.preventDefault(); if (event.dataTransfer.types.indexOf('text/x-jop-folder-ids') >= 0) event.preventDefault(); }, []); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const onFolderDrop_ = useCallback(async (event: any) => { + const onFolderDrop_: ItemDragListener = useCallback(async event => { const folderId = event.currentTarget.getAttribute('data-folder-id'); const dt = event.dataTransfer; if (!dt) return; @@ -257,8 +288,7 @@ const SidebarComponent = (props: Props) => { } }, []); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const onTagDrop_ = useCallback(async (event: any) => { + const onTagDrop_: ItemDragListener = useCallback(async event => { const tagId = event.currentTarget.getAttribute('data-tag-id'); const dt = event.dataTransfer; if (!dt) return; @@ -273,8 +303,7 @@ const SidebarComponent = (props: Props) => { } }, []); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const onFolderToggleClick_ = useCallback((event: any) => { + const onFolderToggleClick_: ItemClickListener = useCallback(event => { const folderId = event.currentTarget.getAttribute('data-folder-id'); props.dispatch({ @@ -293,8 +322,7 @@ const SidebarComponent = (props: Props) => { menu.popup({ window: bridge().window() }); }, []); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const itemContextMenu = useCallback(async (event: any) => { + const itemContextMenu: ItemContextMenuListener = useCallback(async event => { const itemId = event.currentTarget.getAttribute('data-id'); if (itemId === Folder.conflictFolderId()) return; @@ -472,8 +500,7 @@ const SidebarComponent = (props: Props) => { }); }, [props.dispatch]); - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const tagItem_click = useCallback((tag: any) => { + const tagItem_click = useCallback((tag: TagEntity|undefined) => { props.dispatch({ type: 'TAG_SELECT', id: tag ? tag.id : null, @@ -625,8 +652,15 @@ const SidebarComponent = (props: Props) => { ); }; - // eslint-disable-next-line @typescript-eslint/ban-types, @typescript-eslint/no-explicit-any -- Old code before rule was applied, Old code before rule was applied - const renderHeader = (key: string, label: string, iconName: string, contextMenuHandler: Function = null, onPlusButtonClick: Function = null, extraProps: any = {}) => { + const renderHeader = ( + key: string, + label: string, + iconName: string, + contextMenuHandler: ItemContextMenuListener|null = null, + onPlusButtonClick: ItemClickListener|null = null, + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied + extraProps: any = {}, + ) => { const headerClick = extraProps.onClick || null; delete extraProps.onClick; const ref = anchorItemRef('headers', key); @@ -637,8 +671,7 @@ const SidebarComponent = (props: Props) => { ref={ref} {...extraProps} onContextMenu={contextMenuHandler} - // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - onClick={(event: any) => { + onClick={(event: MouseEvent) => { // if a custom click event is attached, trigger that. if (headerClick) { headerClick(key, event); @@ -655,7 +688,7 @@ const SidebarComponent = (props: Props) => { }; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied - const onKeyDown = useCallback((event: any) => { + const onKeyDown = useCallback((event: KeyboardEvent) => { const keyCode = event.keyCode; const selectedItem = getSelectedItem(); diff --git a/packages/lib/reducer.ts b/packages/lib/reducer.ts index 738f92339..cd7f632c0 100644 --- a/packages/lib/reducer.ts +++ b/packages/lib/reducer.ts @@ -45,7 +45,7 @@ interface StateClipperServer { port: number; } -interface StateDecryptionWorker { +export interface StateDecryptionWorker { state: string; itemIndex: number; itemCount: number; @@ -55,8 +55,9 @@ interface StateDecryptionWorker { skippedItemCount: number; } -interface StateResourceFetcher { +export interface StateResourceFetcher { toFetchCount: number; + fetchingCount: number; } export interface StateLastDeletion { @@ -187,6 +188,7 @@ export const defaultState: State = { selectedNoteTags: [], resourceFetcher: { toFetchCount: 0, + fetchingCount: 0, }, backwardHistoryNotes: [], forwardHistoryNotes: [], diff --git a/packages/lib/services/commands/MenuUtils.ts b/packages/lib/services/commands/MenuUtils.ts index aa90ba777..88e394638 100644 --- a/packages/lib/services/commands/MenuUtils.ts +++ b/packages/lib/services/commands/MenuUtils.ts @@ -10,10 +10,10 @@ export interface MenuItem { id?: string; label?: string; // eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied - click?: Function; + click?: ()=> void; // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied role?: any; - type?: string; + type?: 'normal'|'separator'|'submenu'; accelerator?: string; checked?: boolean; enabled?: boolean;