Skip to content

Commit

Permalink
Fix mobile transaction page amount input (actualbudget#2166)
Browse files Browse the repository at this point in the history
* Request active edit on focus

* Release notes

* Track previous focus state

* use inputRef to focus

* Focus total amount effect

* Run active edit action synchronously

* Revert unneeded changes

* Run cleanup synchronously

* Cleanup

* runAction

* Space
  • Loading branch information
joel-jeremy authored Jan 5, 2024
1 parent e589163 commit d999e46
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
getNumberFormat,
} from 'loot-core/src/shared/util';

import { useMergedRefs } from '../../hooks/useMergedRefs';
import { theme } from '../../style';
import Button from '../common/Button';
import Text from '../common/Text';
Expand All @@ -21,6 +22,7 @@ const AmountInput = memo(function AmountInput({
const [text, setText] = useState('');
const [value, setValue] = useState(0);
const inputRef = useRef();
const mergedInputRef = useMergedRefs(props.inputRef, inputRef);

const getInitialValue = () => Math.abs(props.value);

Expand All @@ -30,10 +32,6 @@ const AmountInput = memo(function AmountInput({
}
}, []);

useEffect(() => {
setEditing(text !== '');
}, [text]);

useEffect(() => {
if (focused) {
focus();
Expand Down Expand Up @@ -72,24 +70,31 @@ const AmountInput = memo(function AmountInput({
return newValue;
};

const onBlur = () => {
const onFocus = e => {
props.onFocus?.(e);
};

const onBlur = e => {
const value = applyText();
props.onUpdate?.(value);
props.onBlur?.(e);
};

const onChangeText = text => {
setEditing(true);
setText(text);
props.onChange?.(text);
};

const input = (
<input
type="text"
ref={inputRef}
ref={mergedInputRef}
value={text}
inputMode="decimal"
autoCapitalize="none"
onChange={e => onChangeText(e.target.value)}
onFocus={onFocus}
onBlur={onBlur}
onKeyUp={onKeyPress}
data-testid="amount-input"
Expand Down Expand Up @@ -131,6 +136,7 @@ export const FocusableAmountInput = memo(function FocusableAmountInput({
focusedStyle,
buttonProps,
onFocus,
onBlur,
...props
}) {
const [isNegative, setIsNegative] = useState(true);
Expand Down Expand Up @@ -166,6 +172,8 @@ export const FocusableAmountInput = memo(function FocusableAmountInput({
<AmountInput
{...props}
value={value}
onFocus={onFocus}
onBlur={onBlur}
onChange={onChange}
onUpdate={onUpdate}
focused={focused}
Expand Down
73 changes: 33 additions & 40 deletions packages/desktop-client/src/hooks/useSingleActiveEditForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,8 @@ import React, {
useContext,
useState,
useRef,
useEffect,
} from 'react';

import usePrevious from './usePrevious';
import useStableCallback from './useStableCallback';

type ActiveEditCleanup = () => void;
type ActiveEditAction = () => void | ActiveEditCleanup;

Expand All @@ -19,7 +15,9 @@ type SingleActiveEditFormContextValue = {
onRequestActiveEdit: (
field: string,
action?: ActiveEditAction,
clearActiveEditDelayMs?: number,
options?: {
clearActiveEditDelayMs?: number;
},
) => void;
onClearActiveEdit: (delayMs?: number) => void;
};
Expand All @@ -38,22 +36,8 @@ export function SingleActiveEditFormProvider({
children,
}: SingleActiveEditFormProviderProps) {
const [editingField, setEditingField] = useState(null);
const prevEditingField = usePrevious(editingField);
const actionRef = useRef<ActiveEditAction>(null);
const cleanupRef = useRef<ActiveEditCleanup | void>(null);

useEffect(() => {
if (prevEditingField != null && prevEditingField !== editingField) {
runCleanup();
} else if (prevEditingField == null && editingField !== null) {
runAction();
}
}, [editingField]);

const runAction = () => {
cleanupRef.current = actionRef.current?.();
};

const runCleanup = () => {
const editCleanup = cleanupRef.current;
if (typeof editCleanup === 'function') {
Expand All @@ -62,31 +46,40 @@ export function SingleActiveEditFormProvider({
cleanupRef.current = null;
};

const runAction = (action: ActiveEditAction) => {
cleanupRef.current = action?.();
};

const onClearActiveEdit = (delayMs?: number) => {
setTimeout(() => setEditingField(null), delayMs);
setTimeout(() => {
runCleanup();
setEditingField(null);
}, delayMs);
};

const onActiveEdit = (field: string, action: ActiveEditAction) => {
runAction(action);
setEditingField(field);
};

const onRequestActiveEdit = useStableCallback(
(
field: string,
action: ActiveEditAction,
options: {
clearActiveEditDelayMs?: number;
},
) => {
if (editingField === field) {
// Already active.
return;
}

if (editingField) {
onClearActiveEdit(options?.clearActiveEditDelayMs);
} else {
actionRef.current = action;
setEditingField(field);
}
const onRequestActiveEdit = (
field: string,
action: ActiveEditAction,
options: {
clearActiveEditDelayMs?: number;
},
);
) => {
if (editingField === field) {
// Already active.
return;
}

if (editingField) {
onClearActiveEdit(options?.clearActiveEditDelayMs);
} else {
onActiveEdit(field, action);
}
};

return (
<SingleActiveEditFormContext.Provider
Expand Down
6 changes: 6 additions & 0 deletions upcoming-release-notes/2166.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [joel-jeremy]
---

Fix mobile transaction page amount input bug on iOS.

0 comments on commit d999e46

Please sign in to comment.