From 10559a68b3ba78f709db0be24fc5bc2778cd28be Mon Sep 17 00:00:00 2001 From: Matiss Janis Aboltins <matiss@mja.lv> Date: Wed, 19 Apr 2023 16:24:58 +0100 Subject: [PATCH] :recycle: (autocomplete) refactor old autocomplete to remove lively dep (#916) --- packages/desktop-client/package.json | 1 - .../components/autocomplete/Autocomplete.js | 84 ++++++++++--------- .../src/hooks/useFeatureFlag.ts | 2 +- upcoming-release-notes/916.md | 6 ++ yarn.lock | 10 --- 5 files changed, 52 insertions(+), 51 deletions(-) create mode 100644 upcoming-release-notes/916.md diff --git a/packages/desktop-client/package.json b/packages/desktop-client/package.json index 06cac92b9..4aced71c8 100644 --- a/packages/desktop-client/package.json +++ b/packages/desktop-client/package.json @@ -6,7 +6,6 @@ "build" ], "devDependencies": { - "@jlongster/lively": "0.0.4", "@juggle/resize-observer": "^3.1.2", "@playwright/test": "^1.29.1", "@reach/listbox": "^0.11.2", diff --git a/packages/desktop-client/src/components/autocomplete/Autocomplete.js b/packages/desktop-client/src/components/autocomplete/Autocomplete.js index fee1ea234..975c9ac4d 100644 --- a/packages/desktop-client/src/components/autocomplete/Autocomplete.js +++ b/packages/desktop-client/src/components/autocomplete/Autocomplete.js @@ -1,13 +1,15 @@ import React, { useState, useRef, useEffect } from 'react'; -import lively from '@jlongster/lively'; import Downshift from 'downshift'; import { css } from 'glamor'; +import usePrevious from '../../hooks/usePrevious'; import Remove from '../../icons/v2/Remove'; import { colors } from '../../style'; import { View, Input, Tooltip, Button } from '../common'; +const inst = {}; + function findItem(strict, suggestions, value) { if (strict) { let idx = suggestions.findIndex(item => item.id === value); @@ -146,13 +148,11 @@ function onInputValueChange( props: { suggestions, onUpdate, - multi, highlightFirst, strict, filterSuggestions = defaultFilterSuggestions, getHighlightedIndex, }, - state: { isOpen }, }, value, changes, @@ -215,7 +215,7 @@ function onInputValueChange( } } -function onStateChange({ props, state, inst }, changes, stateAndHelpers) { +function onStateChange({ props, state }, changes) { if ( props.tableBehavior && changes.type === Downshift.stateChangeTypes.mouseUp @@ -259,7 +259,7 @@ function onStateChange({ props, state, inst }, changes, stateAndHelpers) { } function onSelect( - { props: { onSelect, clearAfterSelect, suggestions }, inst }, + { props: { onSelect, clearAfterSelect, suggestions } }, item, ) { if (onSelect) { @@ -280,10 +280,10 @@ function onSelect( onSelect(getItemId(item)); }, 0); } - return onSelectAfter(suggestions, clearAfterSelect, inst); + return onSelectAfter(suggestions, clearAfterSelect); } -function onSelectAfter(suggestions, clearAfterSelect, inst) { +function onSelectAfter(suggestions, clearAfterSelect) { if (clearAfterSelect) { return { value: '', @@ -291,9 +291,9 @@ function onSelectAfter(suggestions, clearAfterSelect, inst) { highlightedIndex: null, filteredSuggestions: suggestions, }; - } else if (inst.input) { - inst.input.setSelectionRange(0, 10000); } + + return { isOpen: false }; } function onChange({ props: { inputProps } }, e) { @@ -314,16 +314,7 @@ function onKeyDown( shouldSaveFromKey = defaultShouldSaveFromKey, strict, }, - state: { - selectedItem, - filteredSuggestions, - highlightedIndex, - originalItem, - isNulled, - isOpen, - value, - }, - inst, + state: { highlightedIndex, originalItem, isOpen, value }, }, e, ) { @@ -348,7 +339,7 @@ function onKeyDown( // Handle it ourselves e.stopPropagation(); onSelect(value); - return onSelectAfter(suggestions, clearAfterSelect, inst); + return onSelectAfter(suggestions, clearAfterSelect); } else { // No highlighted item, still allow the table to save the item // as `null`, even though we're allowing the table to move @@ -414,7 +405,7 @@ function defaultShouldSaveFromKey(e) { return e.code === 'Enter'; } -function onFocus({ inst, props: { inputProps = {}, openOnFocus = true } }, e) { +function onFocus({ props: { inputProps = {}, openOnFocus = true } }, e) { inputProps.onFocus && inputProps.onFocus(e); if (openOnFocus) { @@ -422,7 +413,7 @@ function onFocus({ inst, props: { inputProps = {}, openOnFocus = true } }, e) { } } -function onBlur({ inst, props, state: { selectedItem } }, e) { +function onBlur({ props, state: { selectedItem } }, e) { let { inputProps = {}, onSelect } = props; e.preventDownshiftDefault = true; @@ -454,26 +445,48 @@ function defaultItemToString(item) { return item ? getItemName(item) : ''; } -function _SingleAutocomplete({ - props: { +function SingleAutocomplete(props) { + const [curState, setState] = React.useState(() => getInitialState({ props })); + const { value, selectedItem, filteredSuggestions, highlightedIndex, isOpen } = + curState; + + const prevProps = usePrevious(props); + React.useEffect(() => { + if (!prevProps) return; + + const newState = componentWillReceiveProps( + { props: prevProps, state: curState }, + props, + ); + + if (newState) { + setState(Object.assign({}, curState, newState)); + } + }, [props, prevProps]); + + const updater = + operation => + (...arg) => { + const newState = Object.assign( + {}, + curState, + operation({ props, state: curState }, ...arg) || {}, + ); + setState(newState); + }; + + const { focused, embedded, containerProps, inputProps, - children, suggestions, tooltipStyle, - onItemClick, - strict, tooltipProps, renderInput = defaultRenderInput, renderItems = defaultRenderItems, itemToString = defaultItemToString, - }, - state: { value, selectedItem, filteredSuggestions, highlightedIndex, isOpen }, - updater, - inst, -}) { + } = props; const filtered = filteredSuggestions || suggestions; return ( @@ -490,10 +503,8 @@ function _SingleAutocomplete({ {({ getInputProps, getItemProps, - getRootProps, isOpen, inputValue, - selectedItem, highlightedIndex, }) => ( // Super annoying but it works best to return a div so we @@ -551,11 +562,6 @@ function _SingleAutocomplete({ ); } -const SingleAutocomplete = lively(_SingleAutocomplete, { - getInitialState, - componentWillReceiveProps, -}); - function MultiItem({ name, onRemove }) { return ( <View diff --git a/packages/desktop-client/src/hooks/useFeatureFlag.ts b/packages/desktop-client/src/hooks/useFeatureFlag.ts index d6e0d17e5..c379d5016 100644 --- a/packages/desktop-client/src/hooks/useFeatureFlag.ts +++ b/packages/desktop-client/src/hooks/useFeatureFlag.ts @@ -1,7 +1,7 @@ import { useSelector } from 'react-redux'; const DEFAULT_FEATURE_FLAG_STATE: Record<string, boolean> = { - newAutocomplete: true, + newAutocomplete: false, syncAccount: false, goalTemplatesEnabled: false, }; diff --git a/upcoming-release-notes/916.md b/upcoming-release-notes/916.md new file mode 100644 index 000000000..f44ac5079 --- /dev/null +++ b/upcoming-release-notes/916.md @@ -0,0 +1,6 @@ +--- +category: Maintenance +authors: [MatissJanis] +--- + +Remove `@jlongster/lively` dependency; refactor old autocomplete to not use it any more; disable new autocomplete diff --git a/yarn.lock b/yarn.lock index 1abbe8c90..1dbedaa88 100644 --- a/yarn.lock +++ b/yarn.lock @@ -55,7 +55,6 @@ __metadata: version: 0.0.0-use.local resolution: "@actual-app/web@workspace:packages/desktop-client" dependencies: - "@jlongster/lively": 0.0.4 "@juggle/resize-observer": ^3.1.2 "@playwright/test": ^1.29.1 "@reach/listbox": ^0.11.2 @@ -2523,15 +2522,6 @@ __metadata: languageName: node linkType: hard -"@jlongster/lively@npm:0.0.4": - version: 0.0.4 - resolution: "@jlongster/lively@npm:0.0.4" - dependencies: - prop-types: ^15.6.0 - checksum: 1984cc66356da110cc7e6496c8b6c9bbfa0f20f94052e5131959a10ee63b2608f90a4e75549a27947c6f2a4ca580eaeb66d3eda5b7ca40b7c055ee76bb573b81 - languageName: node - linkType: hard - "@jlongster/sql.js@npm:^1.6.7": version: 1.6.7 resolution: "@jlongster/sql.js@npm:1.6.7" -- GitLab