[AI] Make the mobile Reconciled toggle work and match the Cleared toggle (#9064)

* [AI] Make the mobile Reconciled toggle work and match the Cleared toggle

The Reconciled toggle in the mobile transaction edit form was rendered as a
disabled `Toggle` with no handler, so a reconciled transaction could not be
unlocked from there. It now opens the existing `unlockReconciled`
confirmation and clears `reconciled` on confirm, matching the desktop table
and the mobile transaction list.

It also used the raw `Toggle` rather than `ToggleField`, which made it
visibly smaller than the Cleared toggle next to it.

Fixes #8453

Co-Authored-By: Claude Opus 5 <[email protected]>

* [AI] Guard the optional onCancel in the reconciled-transaction confirm modal

`onCancel` is optional in the modal's options type, but the Cancel button
called it unconditionally, so cancelling threw a TypeError at the 9 call
sites that omit it — including the new unlock path and the pre-existing
desktop one. The file is `// @ts-strict-ignore`, so the compiler did not
catch it.

Co-Authored-By: Claude Opus 5 <[email protected]>

---------

Co-authored-by: Claude Opus 5 <[email protected]>
This commit is contained in:
youngcw
2026-10-02 20:16:31 +00:00
committed by GitHub
co-authored by Claude Opus 5
parent 954ad61d3c
commit 167bae44f5
3 changed files with 35 additions and 3 deletions
@@ -31,7 +31,6 @@ import {
import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { Toggle } from '@actual-app/components/toggle';
import { View } from '@actual-app/components/view';
import { send } from '@actual-app/core/platform/client/connection';
import { DEFAULT_MAX_DISTANCE_METERS } from '@actual-app/core/shared/constants';
@@ -917,6 +916,29 @@ const TransactionEditInner = memo<TransactionEditInnerProps>(
[onClearActiveEdit, onUpdate],
);
const onUnlockReconciledInner = useCallback(
(serializedTransaction: TransactionEntity) => {
dispatch(
pushModal({
modal: {
name: 'confirm-transaction-edit',
options: {
confirmReason: 'unlockReconciled',
onConfirm: () => {
void onUpdateInner(
serializedTransaction,
'reconciled',
false,
);
},
},
},
}),
);
},
[dispatch, onUpdateInner],
);
const onTotalAmountUpdate = useCallback(
(value: number) => {
if (transaction.amount !== value) {
@@ -1472,7 +1494,11 @@ const TransactionEditInner = memo<TransactionEditInnerProps>(
{transaction.reconciled ? (
<View style={{ alignItems: 'center' }}>
<FieldLabel title={t('Reconciled')} />
<Toggle id="Reconciled" isOn isDisabled />
<ToggleField
id="reconciled"
isOn
onToggle={() => onUnlockReconciledInner(transaction)}
/>
</View>
) : (
<View style={{ alignItems: 'center' }}>
@@ -115,7 +115,7 @@ export function ConfirmTransactionEditModal({
}}
onPress={() => {
state.close();
onCancel();
onCancel?.();
}}
>
<Trans>Cancel</Trans>
@@ -0,0 +1,6 @@
---
category: Bugfix
authors: [youngcw]
---
Make the Reconciled toggle work when editing a transaction on mobile, so a reconciled transaction can be unlocked, and match its size to the Cleared toggle.