Skip to content

Commit

Permalink
Merge branch 'master' into budget-nohidden
Browse files Browse the repository at this point in the history
  • Loading branch information
psybers authored Mar 4, 2025
2 parents e13993a + c17cd28 commit a23d1d3
Show file tree
Hide file tree
Showing 402 changed files with 1,537 additions and 1,340 deletions.
6 changes: 5 additions & 1 deletion .github/actions/bump-package-versions
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
#!/bin/bash
set -euo pipefail

version="${1#v}"
if [ "$#" -gt 0 ]; then
version="${1#v}"
else
version=""
fi

files_to_bump=(
packages/api/package.json
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/docker-edge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ env:
IMAGES: |
actualbudget/actual-server
ghcr.io/actualbudget/actual-server
ghcr.io/actualbudget/actual
# Creates the following tags:
# - actual-server:edge
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/docker-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ env:
IMAGES: |
actualbudget/actual-server
ghcr.io/actualbudget/actual-server
ghcr.io/actualbudget/actual
# Creates the following tags:
# - actual-server:latest (see docker/metadata-action flavor inputs, below)
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,6 @@ bundle.mobile.js.map

# build output
package.tgz

# Fly.io configuration
fly.toml
1 change: 1 addition & 0 deletions bin/package-browser
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ if ! [ -d packages/desktop-client/locale ]; then
git clone https://github.com/actualbudget/translations packages/desktop-client/locale
fi
pushd packages/desktop-client/locale > /dev/null
git checkout .
git pull
popd > /dev/null
packages/desktop-client/bin/remove-untranslated-languages
Expand Down
1 change: 1 addition & 0 deletions bin/package-electron
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ if ! [ -d packages/desktop-client/locale ]; then
git clone https://github.com/actualbudget/translations packages/desktop-client/locale
fi
pushd packages/desktop-client/locale > /dev/null
git checkout .
git pull
popd > /dev/null
packages/desktop-client/bin/remove-untranslated-languages
Expand Down
1 change: 0 additions & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,6 @@ export default [
'packages/desktop-client/src/components/select/DateSelect.tsx',
'packages/desktop-client/src/components/sidebar/Tools.tsx',
'packages/desktop-client/src/components/sort.tsx',
'packages/desktop-client/src/components/spreadsheet/useSheetValue.ts',
],

rules: {
Expand Down
2 changes: 1 addition & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@actual-app/api",
"version": "25.2.1",
"version": "25.3.1",
"license": "MIT",
"description": "An API for Actual",
"engines": {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/desktop-client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@actual-app/web",
"version": "25.2.1",
"version": "25.3.1",
"license": "MIT",
"files": [
"build"
Expand Down
36 changes: 29 additions & 7 deletions packages/desktop-client/src/browser-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,28 @@ const importScriptsWithRetry = async (script, { maxRetries = 5 } = {}) => {
}
};

const RECONNECT_INTERVAL_MS = 200;
const MAX_RECONNECT_ATTEMPTS = 500;
let reconnectAttempts = 0;

const postMessageWithRetry = message => {
const reconnectToClientInterval = setInterval(() => {
self.postMessage(message);

reconnectAttempts++;
if (reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
clearInterval(reconnectToClientInterval);
}
}, RECONNECT_INTERVAL_MS);

return reconnectToClientInterval;
};

let appInitFailureInterval;
self.addEventListener('message', async event => {
try {
const msg = event.data;
if (!hasInitialized) {
const msg = event.data;

if (msg.type === 'init') {
hasInitialized = true;
const isDev = !!msg.isDev;
Expand All @@ -51,10 +68,11 @@ self.addEventListener('message', async event => {
!self.SharedArrayBuffer &&
!msg.isSharedArrayBufferOverrideEnabled
) {
self.postMessage({
appInitFailureInterval = postMessageWithRetry({
type: 'app-init-failure',
SharedArrayBufferMissing: true,
});

return;
}

Expand All @@ -65,19 +83,23 @@ self.addEventListener('message', async event => {

backend.initApp(isDev, self).catch(err => {
console.log(err);
const msg = {
appInitFailureInterval = postMessageWithRetry({
type: 'app-init-failure',
IDBFailure: err.message.includes('indexeddb-failure'),
};
self.postMessage(msg);
});

throw err;
});
}
}

if (msg.name === '__app-init-failure-acknowledged') {
// Clear the interval if the client has acknowledged the failure, otherwise keep retrying
clearInterval(appInitFailureInterval);
}
} catch (error) {
console.log('Failed initializing backend:', error);
self.postMessage({
appInitFailureInterval = postMessageWithRetry({
type: 'app-init-failure',
BackendInitFailure: true,
});
Expand Down
15 changes: 8 additions & 7 deletions packages/desktop-client/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ import { View } from '@actual-app/components/view';

import {
addNotification,
closeBudget,
loadBudget,
loadGlobalPrefs,
signOut,
} from 'loot-core/client/actions';
import { setAppState, sync } from 'loot-core/client/app/appSlice';
import { closeBudget, loadBudget } from 'loot-core/client/budgets/budgetsSlice';
import * as Platform from 'loot-core/client/platform';
import { SpreadsheetProvider } from 'loot-core/client/SpreadsheetProvider';
import { init as initConnection, send } from 'loot-core/platform/client/fetch';
Expand Down Expand Up @@ -53,6 +52,10 @@ function AppInner() {
const dispatch = useDispatch();
const userData = useSelector(state => state.user.data);

useEffect(() => {
setI18NextLanguage(null);
}, []);

useEffect(() => {
const maybeUpdate = async <T,>(cb?: () => T): Promise<T> => {
if (global.Actual.isUpdateReadyForDownload()) {
Expand All @@ -67,8 +70,6 @@ function AppInner() {
};

async function init() {
setI18NextLanguage(null);

const socketName = await maybeUpdate(() =>
global.Actual.getServerSocket(),
);
Expand Down Expand Up @@ -98,7 +99,7 @@ function AppInner() {
);
const budgetId = await send('get-last-opened-backup');
if (budgetId) {
await dispatch(loadBudget(budgetId));
await dispatch(loadBudget({ id: budgetId }));

// Check to see if this file has been remotely deleted (but
// don't block on this in case they are offline or something)
Expand Down Expand Up @@ -126,9 +127,9 @@ function AppInner() {
}

initAll().catch(showErrorBoundary);
// Removed cloudFileId from dependencies to prevent hard crash when closing budget in Electron
// Removed cloudFileId & t from dependencies to prevent hard crash when closing budget in Electron
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dispatch, showErrorBoundary, t]);
}, [dispatch, showErrorBoundary]);

useEffect(() => {
global.Actual.updateAppMenu(budgetId);
Expand Down
3 changes: 2 additions & 1 deletion packages/desktop-client/src/components/LoggedInUser.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { View } from '@actual-app/components/view';

import { closeBudget, getUserData, signOut } from 'loot-core/client/actions';
import { getUserData, signOut } from 'loot-core/client/actions';
import { closeBudget } from 'loot-core/client/budgets/budgetsSlice';
import { listen } from 'loot-core/platform/client/fetch';
import { type RemoteFile, type SyncedLocalFile } from 'loot-core/types/file';
import { type TransObjectLiteral } from 'loot-core/types/util';
Expand Down
14 changes: 14 additions & 0 deletions packages/desktop-client/src/components/accounts/Account.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,13 @@ class AccountInternal extends PureComponent<

onDoneReconciling = async () => {
const { accountId } = this.props;
const account = this.props.accounts.find(
account => account.id === accountId,
);
if (!account) {
throw new Error(`Account with ID ${accountId} not found.`);
}

const { reconcileAmount } = this.state;

const { data } = await runQuery(
Expand All @@ -1034,6 +1041,13 @@ class AccountInternal extends PureComponent<
await this.lockTransactions();
}

const lastReconciled = new Date().getTime().toString();
this.props.dispatch(
updateAccount({
account: { ...account, last_reconciled: lastReconciled },
}),
);

this.setState({
reconcileAmount: null,
showCleared: this.state.prevShowCleared,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ function useErrorMessage() {
case 'RATE_LIMIT_EXCEEDED':
return t('Rate limit exceeded for this item. Please try again later.');

case 'TIMED_OUT':
return t('The request timed out. Please try again later.');

case 'INVALID_ACCESS_TOKEN':
return t(
'Your SimpleFIN Access Token is no longer valid. Please reset and generate a new token.',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ export function Balances({
}}
/>
</Button>

{showExtraBalances && <MoreBalances balanceQuery={balanceQuery} />}

{selectedItems.size > 0 && (
Expand Down
29 changes: 24 additions & 5 deletions packages/desktop-client/src/components/accounts/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@ import { Menu } from '@actual-app/components/menu';
import { Popover } from '@actual-app/components/popover';
import { Stack } from '@actual-app/components/stack';
import { styles } from '@actual-app/components/styles';
import { Tooltip } from '@actual-app/components/tooltip';
import { View } from '@actual-app/components/view';

import { tsToRelativeTime } from 'loot-core/shared/util';
import {
type AccountEntity,
type RuleConditionEntity,
type TransactionEntity,
type TransactionFilterEntity,
} from 'loot-core/types/models';

import { useGlobalPref } from '../../hooks/useGlobalPref';
import { useLocalPref } from '../../hooks/useLocalPref';
import { useSplitsExpanded } from '../../hooks/useSplitsExpanded';
import { useSyncServerStatus } from '../../hooks/useSyncServerStatus';
Expand Down Expand Up @@ -185,6 +188,8 @@ export function AccountHeader({
onMakeAsNonSplitTransactions,
}: AccountHeaderProps) {
const { t } = useTranslation();
const [language] = useGlobalPref('language');

const [menuOpen, setMenuOpen] = useState(false);
const [reconcileOpen, setReconcileOpen] = useState(false);
const searchInput = useRef<HTMLInputElement>(null);
Expand Down Expand Up @@ -374,19 +379,33 @@ export function AccountHeader({
onMakeAsNonSplitTransactions={onMakeAsNonSplitTransactions}
/>
)}
<View style={{ flex: '0 0 auto' }}>
<View style={{ flex: '0 0 auto', marginLeft: 10 }}>
{account && (
<>
<Tooltip
style={{
...styles.tooltip,
marginBottom: 10,
}}
content={
account?.last_reconciled
? `${t('Reconciled')} ${tsToRelativeTime(account.last_reconciled, language || 'en-US')}`
: t('Not yet reconciled')
}
placement="top"
triggerProps={{
isDisabled: reconcileOpen,
}}
>
<Button
ref={reconcileRef}
variant="bare"
aria-label={t('Reconcile')}
style={{ padding: 6, marginLeft: 10 }}
style={{ padding: 6 }}
onPress={() => {
setReconcileOpen(true);
}}
>
<View title={t('Reconcile')}>
<View>
<SvgLockClosed width={14} height={14} />
</View>
</Button>
Expand All @@ -403,7 +422,7 @@ export function AccountHeader({
onReconcile={onReconcile}
/>
</Popover>
</>
</Tooltip>
)}
</View>
<Button
Expand Down
17 changes: 6 additions & 11 deletions packages/desktop-client/src/components/banksync/AccountRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,13 @@ import { Trans } from 'react-i18next';

import { Button } from '@actual-app/components/button';

import { format } from 'loot-core/src/shared/months';
import { tsToRelativeTime } from 'loot-core/shared/util';
import { type AccountEntity } from 'loot-core/src/types/models';

import { useDateFormat } from '../../hooks/useDateFormat';
import { useGlobalPref } from '../../hooks/useGlobalPref';
import { theme } from '../../style';
import { Row, Cell } from '../table';

const tsToString = (ts: string | null, dateFormat: string) => {
if (!ts) return 'Unknown';

const parsed = new Date(parseInt(ts, 10));
return `${format(parsed, dateFormat)} ${format(parsed, 'HH:mm:ss')}`;
};

type AccountRowProps = {
account: AccountEntity;
hovered: boolean;
Expand All @@ -28,9 +21,11 @@ export const AccountRow = memo(
({ account, hovered, onHover, onAction }: AccountRowProps) => {
const backgroundFocus = hovered;

const dateFormat = useDateFormat() || 'MM/dd/yyyy';
const [language = 'en-US'] = useGlobalPref('language');

const lastSync = tsToString(account.last_sync, dateFormat);
const lastSync = tsToRelativeTime(account.last_sync, language, {
capitalize: true,
});

return (
<Row
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ export function AccountsList({
}

return (
<View>
<View
style={{
minHeight: 'initial',
}}
>
{accounts.map(account => {
const hovered = hoveredAccount === account.id;

Expand Down
2 changes: 1 addition & 1 deletion packages/desktop-client/src/components/banksync/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export function BankSync() {
)}
{Object.entries(groupedAccounts).map(([syncProvider, accounts]) => {
return (
<View key={syncProvider}>
<View key={syncProvider} style={{ minHeight: 'initial' }}>
{Object.keys(groupedAccounts).length > 1 && (
<Text
style={{ fontWeight: 500, fontSize: 20, margin: '.5em 0' }}
Expand Down
Loading

0 comments on commit a23d1d3

Please sign in to comment.