[AI] Migrate desktop-client to subpath imports (#7446)

* [AI] Migrate desktop-client to subpath imports

Replace the `@desktop-client/*` path alias with Node.js subpath
imports (`#*`) across packages/desktop-client:

- Declare the full `imports` map in packages/desktop-client/package.json
  (bare index entries, root-level files, and per-subdirectory wildcards
  with explicit extension overrides where `.ts` and `.tsx` mix).
- Update all source files to import from `#...` specifiers.
- Drop the `@desktop-client` group from .oxfmtrc.json.
- Enable `actual/prefer-subpath-imports` for desktop-client in
  .oxlintrc.json so future code keeps using the subpath form.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* [AI] Drop legacy desktop-client aliases

Remove the `@desktop-client/*` and `loot-core/*` path aliases from
vite.config.ts and tsconfig.json now that every desktop-client source
file imports via subpath imports / `@actual-app/core`.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* Release notes

* [AI] Use electron-renderer condition for renderer-only exports

Desktop-client's Vite build used the `electron` resolve condition, which
overlapped with loot-core exports where `electron` means the Node/main
variant (e.g. `shared/platform.electron.ts` using `os`,
`platform/server/asyncStorage/index.electron.ts` using `fs`). Once the
`loot-core` Vite alias was removed, the renderer bundle started pulling
those Node variants and crashed at runtime with
`It.default.platform is not a function` inside `platform.electron.ts`.

Introduce a distinct `electron-renderer` condition used only by
desktop-client's Vite config, and rename the `electron` key to
`electron-renderer` on the sole loot-core export whose `electron` branch
is the Electron renderer variant (`#/./platform/client/connection`, the
IPC `global.Actual.ipcConnect` file). Every other `electron`-conditioned
export keeps its Node semantics and is still matched by loot-core's own
`vite.desktop.config.ts` (`conditions: ['electron']`).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* [AI] Drop .electron.* extensions from loot-core desktop resolver

Now that every Node/main variant is selected via the `electron` subpath
import condition in `packages/loot-core/package.json`, Vite's
`resolveExtensions` list no longer needs the `.electron.js`,
`.electron.ts`, `.electron.tsx` entries. Remove them to keep resolution
explicit and avoid implicit extension picking.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

* [AI] Align desktop-client TS resolution with Vite

- Set `customConditions: ["electron-renderer"]` in
  `packages/desktop-client/tsconfig.json` so TypeScript resolves
  conditional imports (notably `@actual-app/core/platform/client/connection`)
  to the same file Vite picks at runtime. Today the surfaces happen to
  match because both variants import from a shared `index-types.ts`,
  but the alignment prevents a latent drift bug.
- Fix typo in the release note (`Standartise` -> `Standardise`).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
Matiss Janis Aboltins
2026-04-10 17:03:45 +00:00
committed by GitHub
co-authored by Claude Opus 4.6
parent c2c6d49afa
commit d8317c44b7
581 changed files with 3778 additions and 4401 deletions
+1 -11
View File
@@ -9,24 +9,14 @@
"react",
"builtin",
"external",
"loot-core",
["parent", "subpath"],
"sibling",
"index",
"desktop-client"
"index"
],
"customGroups": [
{
"groupName": "react",
"elementNamePattern": ["react", "react-dom/*", "react-*"]
},
{
"groupName": "loot-core",
"elementNamePattern": ["loot-core/**", "@actual-app/core/**"]
},
{
"groupName": "desktop-client",
"elementNamePattern": ["@desktop-client/**"]
}
],
"newlinesBetween": true
+4 -1
View File
@@ -397,7 +397,10 @@
}
},
{
"files": ["packages/loot-core/src/**/*.{ts,tsx}"],
"files": [
"packages/loot-core/src/**/*.{ts,tsx}",
"packages/desktop-client/src/**/*.{ts,tsx}"
],
"rules": {
"actual/prefer-subpath-imports": "error"
}
+1 -2
View File
@@ -1,9 +1,8 @@
import * as fs from 'fs/promises';
import * as path from 'path';
import { vi } from 'vitest';
import type { RuleEntity } from '@actual-app/core/types/models';
import { vi } from 'vitest';
import * as api from './index';
@@ -1,8 +1,10 @@
import * as monthUtils from '@actual-app/core/shared/months';
import {
amountToCurrency,
currencyToAmount,
} from '@actual-app/core/shared/util';
import type { Page } from '@playwright/test';
import * as monthUtils from 'loot-core/shared/months';
import { amountToCurrency, currencyToAmount } from 'loot-core/shared/util';
import { expect, test } from './fixtures';
import { ConfigurationPage } from './page-models/configuration-page';
import type { MobileBudgetPage } from './page-models/mobile-budget-page';
+85
View File
@@ -5,6 +5,91 @@
"files": [
"build"
],
"imports": {
"#browser-preload": {
"electron": "./src/browser-preload.js",
"default": "./src/browser-preload.browser.js"
},
"#accounts": "./src/accounts/index.ts",
"#budget": "./src/budget/index.ts",
"#payees": "./src/payees/index.ts",
"#queries": "./src/queries/index.ts",
"#redux": "./src/redux/index.ts",
"#reports": "./src/reports/index.ts",
"#spreadsheet": "./src/spreadsheet/index.ts",
"#style": "./src/style/index.ts",
"#tags": "./src/tags/index.ts",
"#transactions": "./src/transactions/index.ts",
"#undo": "./src/undo/index.ts",
"#global-events": "./src/global-events.ts",
"#gocardless": "./src/gocardless.ts",
"#i18n": "./src/i18n.ts",
"#mocks": "./src/mocks.tsx",
"#polyfills": "./src/polyfills.ts",
"#components/forms": "./src/components/forms/index.tsx",
"#components/banksync/useBankSyncAccountSettings": "./src/components/banksync/useBankSyncAccountSettings.ts",
"#components/budget/goals/actions": "./src/components/budget/goals/actions.ts",
"#components/budget/goals/constants": "./src/components/budget/goals/constants.ts",
"#components/budget/goals/reducer": "./src/components/budget/goals/reducer.ts",
"#components/budget/goals/useBudgetAutomationCategories": "./src/components/budget/goals/useBudgetAutomationCategories.ts",
"#components/budget/util": "./src/components/budget/util.ts",
"#components/codemirror/autocompleteTabAccept": "./src/components/codemirror/autocompleteTabAccept.ts",
"#components/mobile/utils": "./src/components/mobile/utils.ts",
"#components/reports/chart-theme": "./src/components/reports/chart-theme.ts",
"#components/reports/constants": "./src/components/reports/constants.ts",
"#components/reports/disabledList": "./src/components/reports/disabledList.ts",
"#components/reports/getCustomTick": "./src/components/reports/getCustomTick.ts",
"#components/reports/getLiveRange": "./src/components/reports/getLiveRange.ts",
"#components/reports/graphs/showActivity": "./src/components/reports/graphs/showActivity.ts",
"#components/reports/numberFormatter": "./src/components/reports/numberFormatter.ts",
"#components/reports/ReportOptions": "./src/components/reports/ReportOptions.ts",
"#components/reports/reportRanges": "./src/components/reports/reportRanges.ts",
"#components/reports/setSessionReport": "./src/components/reports/setSessionReport.ts",
"#components/reports/spreadsheets/cash-flow-spreadsheet": "./src/components/reports/spreadsheets/cash-flow-spreadsheet.tsx",
"#components/reports/spreadsheets/*": "./src/components/reports/spreadsheets/*.ts",
"#components/reports/useDashboardWidgetCopyMenu": "./src/components/reports/useDashboardWidgetCopyMenu.ts",
"#components/reports/useReport": "./src/components/reports/useReport.ts",
"#components/reports/util": "./src/components/reports/util.ts",
"#components/schedules/schedule-edit-utils": "./src/components/schedules/schedule-edit-utils.ts",
"#components/util/accountValidation": "./src/components/util/accountValidation.ts",
"#components/util/countries": "./src/components/util/countries.ts",
"#components/util/localeToCountry": "./src/components/util/localeToCountry.ts",
"#components/*": "./src/components/*.tsx",
"#hooks/useCachedSchedules": "./src/hooks/useCachedSchedules.tsx",
"#hooks/useDisplayPayee": "./src/hooks/useDisplayPayee.tsx",
"#hooks/useDragDrop": "./src/hooks/useDragDrop.tsx",
"#hooks/useProperFocus": "./src/hooks/useProperFocus.tsx",
"#hooks/useScrollListener": "./src/hooks/useScrollListener.tsx",
"#hooks/useSelected": "./src/hooks/useSelected.tsx",
"#hooks/useSheetName": "./src/hooks/useSheetName.tsx",
"#hooks/useSingleActiveEditForm": "./src/hooks/useSingleActiveEditForm.tsx",
"#hooks/useSplitsExpanded": "./src/hooks/useSplitsExpanded.tsx",
"#hooks/useSpreadsheet": "./src/hooks/useSpreadsheet.tsx",
"#hooks/*": "./src/hooks/*.ts",
"#auth/AuthProvider": "./src/auth/AuthProvider.tsx",
"#auth/ProtectedRoute": "./src/auth/ProtectedRoute.tsx",
"#auth/*": "./src/auth/*.ts",
"#style/theme": "./src/style/theme.tsx",
"#style/*": "./src/style/*.ts",
"#notes/*": "./src/notes/*.tsx",
"#accounts/*": "./src/accounts/*.ts",
"#app/*": "./src/app/*.ts",
"#budget/*": "./src/budget/*.ts",
"#budgetfiles/*": "./src/budgetfiles/*.ts",
"#modals/*": "./src/modals/*.ts",
"#notifications/*": "./src/notifications/*.ts",
"#payees/*": "./src/payees/*.ts",
"#prefs/*": "./src/prefs/*.ts",
"#queries/*": "./src/queries/*.ts",
"#redux/*": "./src/redux/*.ts",
"#reports/*": "./src/reports/*.ts",
"#spreadsheet/*": "./src/spreadsheet/*.ts",
"#tags/*": "./src/tags/*.ts",
"#transactions/*": "./src/transactions/*.ts",
"#undo/*": "./src/undo/*.ts",
"#users/*": "./src/users/*.ts",
"#util/*": "./src/util/*.ts"
},
"scripts": {
"start": "cross-env PORT=3001 vite",
"start:browser": "cross-env ./bin/watch-browser",
@@ -1,11 +1,10 @@
import { groupById } from '@actual-app/core/shared/util';
import type { AccountEntity } from '@actual-app/core/types/models';
import { createSlice } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit';
import memoizeOne from 'memoize-one';
import { groupById } from 'loot-core/shared/util';
import type { AccountEntity } from 'loot-core/types/models';
import { resetApp } from '@desktop-client/app/appSlice';
import { resetApp } from '#app/appSlice';
const sliceName = 'account';
@@ -1,11 +1,7 @@
import { useTranslation } from 'react-i18next';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import type { QueryClient, QueryKey } from '@tanstack/react-query';
import { v4 as uuidv4 } from 'uuid';
import { send } from 'loot-core/platform/client/connection';
import type { SyncResponseWithErrors } from 'loot-core/server/accounts/app';
import { send } from '@actual-app/core/platform/client/connection';
import type { SyncResponseWithErrors } from '@actual-app/core/server/accounts/app';
import type {
AccountEntity,
CategoryEntity,
@@ -13,7 +9,18 @@ import type {
SyncServerPluggyAiAccount,
SyncServerSimpleFinAccount,
TransactionEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import type { QueryClient, QueryKey } from '@tanstack/react-query';
import { v4 as uuidv4 } from 'uuid';
import { sync } from '#app/appSlice';
import { useAccounts } from '#hooks/useAccounts';
import { addNotification } from '#notifications/notificationsSlice';
import { payeeQueries } from '#payees';
import { useDispatch, useStore } from '#redux';
import type { AppDispatch } from '#redux/store';
import { setNewTransactions } from '#transactions/transactionsSlice';
import {
markAccountFailed,
@@ -23,14 +30,6 @@ import {
} from './accountsSlice';
import { accountQueries } from './queries';
import { sync } from '@desktop-client/app/appSlice';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { payeeQueries } from '@desktop-client/payees';
import { useDispatch, useStore } from '@desktop-client/redux';
import type { AppDispatch } from '@desktop-client/redux/store';
import { setNewTransactions } from '@desktop-client/transactions/transactionsSlice';
const invalidateQueries = (queryClient: QueryClient, queryKey?: QueryKey) => {
void queryClient.invalidateQueries({
queryKey: queryKey ?? accountQueries.lists(),
@@ -1,8 +1,7 @@
import { send } from '@actual-app/core/platform/client/connection';
import type { AccountEntity } from '@actual-app/core/types/models';
import { queryOptions } from '@tanstack/react-query';
import { send } from 'loot-core/platform/client/connection';
import type { AccountEntity } from 'loot-core/types/models';
function selectActive(accounts: AccountEntity[]) {
return accounts.filter(account => !account.closed);
}
+7 -8
View File
@@ -1,14 +1,13 @@
import { send } from '@actual-app/core/platform/client/connection';
import { getUploadError } from '@actual-app/core/shared/errors';
import type { AtLeastOne } from '@actual-app/core/types/util';
import { createAction, createSlice } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit';
import { send } from 'loot-core/platform/client/connection';
import { getUploadError } from 'loot-core/shared/errors';
import type { AtLeastOne } from 'loot-core/types/util';
import { pushModal } from '@desktop-client/modals/modalsSlice';
import { loadPrefs } from '@desktop-client/prefs/prefsSlice';
import { createAppAsyncThunk } from '@desktop-client/redux';
import { getIsOutdated, getLatestVersion } from '@desktop-client/util/versions';
import { pushModal } from '#modals/modalsSlice';
import { loadPrefs } from '#prefs/prefsSlice';
import { createAppAsyncThunk } from '#redux';
import { getIsOutdated, getLatestVersion } from '#util/versions';
const sliceName = 'app';
@@ -1,10 +1,10 @@
import React, { createContext, useContext } from 'react';
import type { ReactNode } from 'react';
import type { Permissions } from './types';
import { useServerURL } from '#components/ServerContext';
import { useSelector } from '#redux';
import { useServerURL } from '@desktop-client/components/ServerContext';
import { useSelector } from '@desktop-client/redux';
import type { Permissions } from './types';
type AuthContextType = {
hasPermission: (permission?: Permissions) => boolean;
@@ -3,15 +3,14 @@ import type { ReactElement } from 'react';
import { Trans } from 'react-i18next';
import { View } from '@actual-app/components/view';
import type { RemoteFile, SyncedLocalFile } from '@actual-app/core/types/file';
import type { RemoteFile, SyncedLocalFile } from 'loot-core/types/file';
import { useMetadataPref } from '#hooks/useMetadataPref';
import { useSelector } from '#redux';
import { useAuth } from './AuthProvider';
import type { Permissions } from './types';
import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref';
import { useSelector } from '@desktop-client/redux';
type ProtectedRouteProps = {
permission: Permissions;
element: ReactElement;
@@ -1,8 +1,7 @@
import * as Platform from '@actual-app/core/shared/platform';
import { initBackend as initSQLBackend } from 'absurd-sql/dist/indexeddb-main-thread';
import { registerSW } from 'virtual:pwa-register';
import * as Platform from 'loot-core/shared/platform';
// oxlint-disable-next-line typescript-paths/absolute-parent-import
import packageJson from '../package.json';
+10 -11
View File
@@ -1,24 +1,23 @@
import { useTranslation } from 'react-i18next';
import { send } from '@actual-app/core/platform/client/connection';
import type { IntegerAmount } from '@actual-app/core/shared/util';
import type {
CategoryEntity,
CategoryGroupEntity,
} from '@actual-app/core/types/models';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import type { QueryClient, QueryKey } from '@tanstack/react-query';
import type { TFunction } from 'i18next';
import { v4 as uuidv4 } from 'uuid';
import { send } from 'loot-core/platform/client/connection';
import type { IntegerAmount } from 'loot-core/shared/util';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
import { pushModal } from '#modals/modalsSlice';
import { addNotification } from '#notifications/notificationsSlice';
import { useDispatch } from '#redux';
import type { AppDispatch } from '#redux/store';
import { categoryQueries } from './queries';
import { pushModal } from '@desktop-client/modals/modalsSlice';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { useDispatch } from '@desktop-client/redux';
import type { AppDispatch } from '@desktop-client/redux/store';
function invalidateQueries(queryClient: QueryClient, queryKey?: QueryKey) {
void queryClient.invalidateQueries({
queryKey: queryKey ?? categoryQueries.lists(),
@@ -1,11 +1,10 @@
import { queryOptions } from '@tanstack/react-query';
import i18n from 'i18next';
import { send } from 'loot-core/platform/client/connection';
import { send } from '@actual-app/core/platform/client/connection';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { queryOptions } from '@tanstack/react-query';
import i18n from 'i18next';
type CategoryViews = {
grouped: CategoryGroupEntity[];
@@ -1,19 +1,18 @@
import { send } from '@actual-app/core/platform/client/connection';
import type { RemoteFile } from '@actual-app/core/server/cloud-storage';
import { getDownloadError, getSyncError } from '@actual-app/core/shared/errors';
import type { Budget } from '@actual-app/core/types/budget';
import type { File } from '@actual-app/core/types/file';
import type { Handlers } from '@actual-app/core/types/handlers';
import { createSlice } from '@reduxjs/toolkit';
import type { PayloadAction } from '@reduxjs/toolkit';
import { t } from 'i18next';
import { send } from 'loot-core/platform/client/connection';
import type { RemoteFile } from 'loot-core/server/cloud-storage';
import { getDownloadError, getSyncError } from 'loot-core/shared/errors';
import type { Budget } from 'loot-core/types/budget';
import type { File } from 'loot-core/types/file';
import type { Handlers } from 'loot-core/types/handlers';
import { resetApp, setAppState } from '@desktop-client/app/appSlice';
import { closeModal, pushModal } from '@desktop-client/modals/modalsSlice';
import { loadGlobalPrefs, loadPrefs } from '@desktop-client/prefs/prefsSlice';
import { createAppAsyncThunk } from '@desktop-client/redux';
import { signOut } from '@desktop-client/users/usersSlice';
import { resetApp, setAppState } from '#app/appSlice';
import { closeModal, pushModal } from '#modals/modalsSlice';
import { loadGlobalPrefs, loadPrefs } from '#prefs/prefsSlice';
import { createAppAsyncThunk } from '#redux';
import { signOut } from '#users/usersSlice';
const sliceName = 'budgetfiles';
+23 -27
View File
@@ -9,12 +9,32 @@ import { BrowserRouter } from 'react-router';
import { styles } from '@actual-app/components/styles';
import { View } from '@actual-app/components/view';
import { useQueryClient } from '@tanstack/react-query';
import {
init as initConnection,
send,
} from 'loot-core/platform/client/connection';
} from '@actual-app/core/platform/client/connection';
import { useQueryClient } from '@tanstack/react-query';
import { setAppState, sync } from '#app/appSlice';
import { closeBudget, loadBudget } from '#budgetfiles/budgetfilesSlice';
import { handleGlobalEvents } from '#global-events';
import { useIsTestEnv } from '#hooks/useIsTestEnv';
import { useMetadataPref } from '#hooks/useMetadataPref';
import { useOnVisible } from '#hooks/useOnVisible';
import { SpreadsheetProvider } from '#hooks/useSpreadsheet';
import { setI18NextLanguage } from '#i18n';
import { addNotification } from '#notifications/notificationsSlice';
import { installPolyfills } from '#polyfills';
import { loadGlobalPrefs } from '#prefs/prefsSlice';
import { useDispatch, useSelector, useStore } from '#redux';
import {
CustomThemeStyle,
hasHiddenScrollbars,
ThemeStyle,
useTheme,
} from '#style';
import { signOut } from '#users/usersSlice';
import { ExposeNavigate } from '#util/router-tools';
import { AppBackground } from './AppBackground';
import { BudgetMonthCountProvider } from './budget/BudgetMonthCountContext';
@@ -26,30 +46,6 @@ import { Modals } from './Modals';
import { SidebarProvider } from './sidebar/SidebarProvider';
import { UpdateNotification } from './UpdateNotification';
import { setAppState, sync } from '@desktop-client/app/appSlice';
import {
closeBudget,
loadBudget,
} from '@desktop-client/budgetfiles/budgetfilesSlice';
import { handleGlobalEvents } from '@desktop-client/global-events';
import { useIsTestEnv } from '@desktop-client/hooks/useIsTestEnv';
import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref';
import { useOnVisible } from '@desktop-client/hooks/useOnVisible';
import { SpreadsheetProvider } from '@desktop-client/hooks/useSpreadsheet';
import { setI18NextLanguage } from '@desktop-client/i18n';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { installPolyfills } from '@desktop-client/polyfills';
import { loadGlobalPrefs } from '@desktop-client/prefs/prefsSlice';
import { useDispatch, useSelector, useStore } from '@desktop-client/redux';
import {
CustomThemeStyle,
hasHiddenScrollbars,
ThemeStyle,
useTheme,
} from '@desktop-client/style';
import { signOut } from '@desktop-client/users/usersSlice';
import { ExposeNavigate } from '@desktop-client/util/router-tools';
function AppInner() {
const [budgetId] = useMetadataPref('id');
const [cloudFileId] = useMetadataPref('cloudFileId');
@@ -7,9 +7,9 @@ import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { css } from '@emotion/css';
import { Background } from './Background';
import { useSelector } from '#redux';
import { useSelector } from '@desktop-client/redux';
import { Background } from './Background';
type AppBackgroundProps = {
isLoading?: boolean;
@@ -7,9 +7,9 @@ import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { AnimatedRefresh } from './AnimatedRefresh';
import { useSelector } from '#redux';
import { useSelector } from '@desktop-client/redux';
import { AnimatedRefresh } from './AnimatedRefresh';
export function BankSyncStatus() {
const accountsSyncing = useSelector(state => state.account.accountsSyncing);
@@ -22,25 +22,21 @@ import { View } from '@actual-app/components/view';
import { css } from '@emotion/css';
import { Command } from 'cmdk';
import { CellValue, CellValueText } from './spreadsheet/CellValue';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
import { useDashboardPages } from '@desktop-client/hooks/useDashboardPages';
import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref';
import { useModalState } from '@desktop-client/hooks/useModalState';
import { useNavigate } from '@desktop-client/hooks/useNavigate';
import { useReports } from '@desktop-client/hooks/useReports';
import type {
Binding,
SheetFields,
SheetNames,
} from '@desktop-client/spreadsheet';
import { useAccounts } from '#hooks/useAccounts';
import { useDashboardPages } from '#hooks/useDashboardPages';
import { useMetadataPref } from '#hooks/useMetadataPref';
import { useModalState } from '#hooks/useModalState';
import { useNavigate } from '#hooks/useNavigate';
import { useReports } from '#hooks/useReports';
import type { Binding, SheetFields, SheetNames } from '#spreadsheet';
import {
accountBalance,
allAccountBalance,
offBudgetAccountBalance,
onBudgetAccountBalance,
} from '@desktop-client/spreadsheet/bindings';
} from '#spreadsheet/bindings';
import { CellValue, CellValueText } from './spreadsheet/CellValue';
type SearchableItem = {
id: string;
@@ -8,15 +8,14 @@ import { Paragraph } from '@actual-app/components/paragraph';
import { SpaceBetween } from '@actual-app/components/space-between';
import { Text } from '@actual-app/components/text';
import { View } from '@actual-app/components/view';
import { LazyLoadFailedError } from '@actual-app/core/shared/errors';
import { LazyLoadFailedError } from 'loot-core/shared/errors';
import { useModalState } from '#hooks/useModalState';
import { Link } from './common/Link';
import { Modal, ModalHeader } from './common/Modal';
import { Checkbox } from './forms';
import { useModalState } from '@desktop-client/hooks/useModalState';
type AppError = Error & {
type?: string;
IDBFailure?: boolean;
@@ -6,8 +6,19 @@ import { Navigate, Route, Routes, useHref, useLocation } from 'react-router';
import { useResponsive } from '@actual-app/components/hooks/useResponsive';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import * as undo from '@actual-app/core/platform/client/undo';
import * as undo from 'loot-core/platform/client/undo';
import { getLatestAppVersion, sync } from '#app/appSlice';
import { ProtectedRoute } from '#auth/ProtectedRoute';
import { Permissions } from '#auth/types';
import { useAccounts } from '#hooks/useAccounts';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { useLocalPref } from '#hooks/useLocalPref';
import { useMetaThemeColor } from '#hooks/useMetaThemeColor';
import { useNavigate } from '#hooks/useNavigate';
import { ScrollProvider } from '#hooks/useScrollListener';
import { addNotification } from '#notifications/notificationsSlice';
import { useDispatch, useSelector } from '#redux';
import { UserAccessPage } from './admin/UserAccess/UserAccessPage';
import { BankSyncStatus } from './BankSyncStatus';
@@ -27,18 +38,6 @@ import { FloatableSidebar } from './sidebar';
import { ManageTagsPage } from './tags/ManageTagsPage';
import { Titlebar } from './Titlebar';
import { getLatestAppVersion, sync } from '@desktop-client/app/appSlice';
import { ProtectedRoute } from '@desktop-client/auth/ProtectedRoute';
import { Permissions } from '@desktop-client/auth/types';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
import { useLocalPref } from '@desktop-client/hooks/useLocalPref';
import { useMetaThemeColor } from '@desktop-client/hooks/useMetaThemeColor';
import { useNavigate } from '@desktop-client/hooks/useNavigate';
import { ScrollProvider } from '@desktop-client/hooks/useScrollListener';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { useDispatch, useSelector } from '@desktop-client/redux';
function NarrowNotSupported({
redirectTo = '/budget',
children,
@@ -1,8 +1,8 @@
import { useEffect } from 'react';
import * as Platform from 'loot-core/shared/platform';
import * as Platform from '@actual-app/core/shared/platform';
import { useNavigate } from '@desktop-client/hooks/useNavigate';
import { useNavigate } from '#hooks/useNavigate';
export function GlobalKeys() {
const navigate = useNavigate();
@@ -10,9 +10,9 @@ import { Popover } from '@actual-app/components/popover';
import { SpaceBetween } from '@actual-app/components/space-between';
import { useToggle } from 'usehooks-ts';
import { useFeatureFlag } from '@desktop-client/hooks/useFeatureFlag';
import { pushModal } from '@desktop-client/modals/modalsSlice';
import { useDispatch } from '@desktop-client/redux';
import { useFeatureFlag } from '#hooks/useFeatureFlag';
import { pushModal } from '#modals/modalsSlice';
import { useDispatch } from '#redux';
const getPageDocs = (page: string) => {
switch (page) {
@@ -10,22 +10,21 @@ import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { listen } from '@actual-app/core/platform/client/connection';
import type { RemoteFile, SyncedLocalFile } from '@actual-app/core/types/file';
import type { TransObjectLiteral } from '@actual-app/core/types/util';
import { listen } from 'loot-core/platform/client/connection';
import type { RemoteFile, SyncedLocalFile } from 'loot-core/types/file';
import type { TransObjectLiteral } from 'loot-core/types/util';
import { useAuth } from '#auth/AuthProvider';
import { Permissions } from '#auth/types';
import { closeBudget } from '#budgetfiles/budgetfilesSlice';
import { useMetadataPref } from '#hooks/useMetadataPref';
import { useNavigate } from '#hooks/useNavigate';
import { useDispatch, useSelector } from '#redux';
import { getUserData, signOut } from '#users/usersSlice';
import { PrivacyFilter } from './PrivacyFilter';
import { useMultiuserEnabled, useServerURL } from './ServerContext';
import { useAuth } from '@desktop-client/auth/AuthProvider';
import { Permissions } from '@desktop-client/auth/types';
import { closeBudget } from '@desktop-client/budgetfiles/budgetfilesSlice';
import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref';
import { useNavigate } from '@desktop-client/hooks/useNavigate';
import { useDispatch, useSelector } from '@desktop-client/redux';
import { getUserData, signOut } from '@desktop-client/users/usersSlice';
type LoggedInUserProps = {
hideIfNoServer?: boolean;
style?: CSSProperties;
@@ -9,18 +9,25 @@ import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { send } from 'loot-core/platform/client/connection';
import * as undo from 'loot-core/platform/client/undo';
import { getNormalisedString } from 'loot-core/shared/normalisation';
import { q } from 'loot-core/shared/query';
import { friendlyOp, mapField } from 'loot-core/shared/rules';
import { describeSchedule } from 'loot-core/shared/schedules';
import { send } from '@actual-app/core/platform/client/connection';
import * as undo from '@actual-app/core/platform/client/undo';
import { getNormalisedString } from '@actual-app/core/shared/normalisation';
import { q } from '@actual-app/core/shared/query';
import { friendlyOp, mapField } from '@actual-app/core/shared/rules';
import { describeSchedule } from '@actual-app/core/shared/schedules';
import type {
NewRuleEntity,
RuleEntity,
ScheduleEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { useAccounts } from '#hooks/useAccounts';
import { useCategories } from '#hooks/useCategories';
import { usePayees } from '#hooks/usePayees';
import { useSchedules } from '#hooks/useSchedules';
import { SelectedProvider, useSelected } from '#hooks/useSelected';
import { pushModal } from '#modals/modalsSlice';
import { useDispatch } from '#redux';
import { InfiniteScrollWrapper } from './common/InfiniteScrollWrapper';
import { Link } from './common/Link';
@@ -28,17 +35,6 @@ import { Search } from './common/Search';
import { RulesHeader } from './rules/RulesHeader';
import { RulesList } from './rules/RulesList';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
import { useCategories } from '@desktop-client/hooks/useCategories';
import { usePayees } from '@desktop-client/hooks/usePayees';
import { useSchedules } from '@desktop-client/hooks/useSchedules';
import {
SelectedProvider,
useSelected,
} from '@desktop-client/hooks/useSelected';
import { pushModal } from '@desktop-client/modals/modalsSlice';
import { useDispatch } from '@desktop-client/redux';
export type FilterData = {
payees?: Array<{ id: string; name: string }>;
categories?: Array<{ id: string; name: string }>;
@@ -2,8 +2,14 @@
import React, { Fragment, useEffect, useEffectEvent } from 'react';
import { useLocation } from 'react-router';
import { send } from 'loot-core/platform/client/connection';
import * as monthUtils from 'loot-core/shared/months';
import { send } from '@actual-app/core/platform/client/connection';
import * as monthUtils from '@actual-app/core/shared/months';
import { useMetadataPref } from '#hooks/useMetadataPref';
import { useModalState } from '#hooks/useModalState';
import { SheetNameProvider } from '#hooks/useSheetName';
import { closeModal } from '#modals/modalsSlice';
import { useDispatch } from '#redux';
import { EditSyncAccount } from './banksync/EditSyncAccount';
import { AccountAutocompleteModal } from './modals/AccountAutocompleteModal';
@@ -79,12 +85,6 @@ import { ScheduleEditModal } from './schedules/ScheduleEditModal';
import { ScheduleLink } from './schedules/ScheduleLink';
import { UpcomingLength } from './schedules/UpcomingLength';
import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref';
import { useModalState } from '@desktop-client/hooks/useModalState';
import { SheetNameProvider } from '@desktop-client/hooks/useSheetName';
import { closeModal } from '@desktop-client/modals/modalsSlice';
import { useDispatch } from '@desktop-client/redux';
export function Modals() {
const location = useLocation();
const dispatch = useDispatch();
@@ -14,7 +14,7 @@ import {
markdownBaseStyles,
remarkBreaks,
sequentialNewlinesPlugin,
} from '@desktop-client/util/markdown';
} from '#util/markdown';
const remarkPlugins = [sequentialNewlinesPlugin, remarkGfm, remarkBreaks];
@@ -9,14 +9,13 @@ import type { CSSProperties } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { Tooltip } from '@actual-app/components/tooltip';
import { View } from '@actual-app/components/view';
import { send } from '@actual-app/core/platform/client/connection';
import { css, cx } from '@emotion/css';
import { send } from 'loot-core/platform/client/connection';
import { useNotes } from '#hooks/useNotes';
import { Notes } from './Notes';
import { useNotes } from '@desktop-client/hooks/useNotes';
type NotesButtonProps = {
id: string;
width?: number;
@@ -15,13 +15,13 @@ import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { css } from '@emotion/css';
import { removeNotification } from '#notifications/notificationsSlice';
import type { NotificationWithId } from '#notifications/notificationsSlice';
import { useDispatch, useSelector } from '#redux';
import { Link } from './common/Link';
import { MODAL_Z_INDEX } from './common/Modal';
import { removeNotification } from '@desktop-client/notifications/notificationsSlice';
import type { NotificationWithId } from '@desktop-client/notifications/notificationsSlice';
import { useDispatch, useSelector } from '@desktop-client/redux';
// Notification stacking configuration
const MAX_VISIBLE_NOTIFICATIONS = 3; // Maximum number of notifications visible in the stack
const SCALE_MULTIPLIER = 0.05; // Scale reduction per stacked notification
@@ -6,7 +6,7 @@ import { useResponsive } from '@actual-app/components/hooks/useResponsive';
import { View } from '@actual-app/components/view';
import { css } from '@emotion/css';
import { usePrivacyMode } from '@desktop-client/hooks/usePrivacyMode';
import { usePrivacyMode } from '#hooks/usePrivacyMode';
type ConditionalPrivacyFilterProps = {
children: ReactNode;
@@ -7,14 +7,13 @@ import React, {
} from 'react';
import type { ReactNode } from 'react';
import { send } from '@actual-app/core/platform/client/connection';
import type { Handlers } from '@actual-app/core/types/handlers';
import { t } from 'i18next';
import { send } from 'loot-core/platform/client/connection';
import type { Handlers } from 'loot-core/types/handlers';
import { useOnVisible } from '@desktop-client/hooks/useOnVisible';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { useDispatch } from '@desktop-client/redux';
import { useOnVisible } from '#hooks/useOnVisible';
import { addNotification } from '#notifications/notificationsSlice';
import { useDispatch } from '#redux';
type LoginMethod = {
method: string;
@@ -11,10 +11,9 @@ import {
} from '@actual-app/components/icons/v2';
import { Menu } from '@actual-app/components/menu';
import { Popover } from '@actual-app/components/popover';
import type { Theme } from '@actual-app/core/types/prefs';
import type { Theme } from 'loot-core/types/prefs';
import { themeOptions, useTheme } from '@desktop-client/style';
import { themeOptions, useTheme } from '#style';
type ThemeSelectorProps = {
style?: CSSProperties;
@@ -18,11 +18,20 @@ import type { CSSProperties } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { listen } from '@actual-app/core/platform/client/connection';
import { isDevelopmentEnvironment } from '@actual-app/core/shared/environment';
import * as Platform from '@actual-app/core/shared/platform';
import { css } from '@emotion/css';
import { listen } from 'loot-core/platform/client/connection';
import { isDevelopmentEnvironment } from 'loot-core/shared/environment';
import * as Platform from 'loot-core/shared/platform';
import { sync } from '#app/appSlice';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { useIsTestEnv } from '#hooks/useIsTestEnv';
import { useMetadataPref } from '#hooks/useMetadataPref';
import { useNavigate } from '#hooks/useNavigate';
import { useSheetValue } from '#hooks/useSheetValue';
import { useSyncedPref } from '#hooks/useSyncedPref';
import { useDispatch } from '#redux';
import * as bindings from '#spreadsheet/bindings';
import { AccountSyncCheck } from './accounts/AccountSyncCheck';
import { AnimatedRefresh } from './AnimatedRefresh';
@@ -34,16 +43,6 @@ import { useServerURL } from './ServerContext';
import { useSidebar } from './sidebar/SidebarProvider';
import { ThemeSelector } from './ThemeSelector';
import { sync } from '@desktop-client/app/appSlice';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
import { useIsTestEnv } from '@desktop-client/hooks/useIsTestEnv';
import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref';
import { useNavigate } from '@desktop-client/hooks/useNavigate';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import { useSyncedPref } from '@desktop-client/hooks/useSyncedPref';
import { useDispatch } from '@desktop-client/redux';
import * as bindings from '@desktop-client/spreadsheet/bindings';
function UncategorizedButton() {
const count: number | null = useSheetValue(bindings.uncategorizedCount());
if (count === null || count <= 0) {
@@ -7,10 +7,10 @@ import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { Link } from './common/Link';
import { setAppState, updateApp } from '#app/appSlice';
import { useDispatch, useSelector } from '#redux';
import { setAppState, updateApp } from '@desktop-client/app/appSlice';
import { useDispatch, useSelector } from '@desktop-client/redux';
import { Link } from './common/Link';
export function UpdateNotification() {
const { t } = useTranslation();
@@ -6,17 +6,12 @@ import { Navigate, useLocation, useParams } from 'react-router';
import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { t } from 'i18next';
import debounce from 'lodash/debounce';
import isEqual from 'lodash/isEqual';
import { v4 as uuidv4 } from 'uuid';
import { listen, send } from 'loot-core/platform/client/connection';
import * as undo from 'loot-core/platform/client/undo';
import type { UndoState } from 'loot-core/server/undo';
import { currentDay } from 'loot-core/shared/months';
import { q } from 'loot-core/shared/query';
import type { Query } from 'loot-core/shared/query';
import { listen, send } from '@actual-app/core/platform/client/connection';
import * as undo from '@actual-app/core/platform/client/undo';
import type { UndoState } from '@actual-app/core/server/undo';
import { currentDay } from '@actual-app/core/shared/months';
import { q } from '@actual-app/core/shared/query';
import type { Query } from '@actual-app/core/shared/query';
import {
makeAsNonChildTransactions,
makeChild,
@@ -24,9 +19,9 @@ import {
ungroupTransaction,
ungroupTransactions,
updateTransaction,
} from 'loot-core/shared/transactions';
import { applyChanges } from 'loot-core/shared/util';
import type { IntegerAmount } from 'loot-core/shared/util';
} from '@actual-app/core/shared/transactions';
import { applyChanges } from '@actual-app/core/shared/util';
import type { IntegerAmount } from '@actual-app/core/shared/util';
import type {
AccountEntity,
CategoryGroupEntity,
@@ -36,55 +31,59 @@ import type {
RuleConditionEntity,
TransactionEntity,
TransactionFilterEntity,
} from 'loot-core/types/models';
import { AccountEmptyMessage } from './AccountEmptyMessage';
import { AccountHeader } from './Header';
} from '@actual-app/core/types/models';
import { t } from 'i18next';
import debounce from 'lodash/debounce';
import isEqual from 'lodash/isEqual';
import { v4 as uuidv4 } from 'uuid';
import {
useReopenAccountMutation,
useSyncAndDownloadMutation,
useUnlinkAccountMutation,
useUpdateAccountMutation,
} from '@desktop-client/accounts';
import { markAccountRead } from '@desktop-client/accounts/accountsSlice';
import type { SavedFilter } from '@desktop-client/components/filters/SavedFilterMenuButton';
import { TransactionList } from '@desktop-client/components/transactions/TransactionList';
import { validateAccountName } from '@desktop-client/components/util/accountValidation';
import { useAccountPreviewTransactions } from '@desktop-client/hooks/useAccountPreviewTransactions';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
import { SchedulesProvider } from '@desktop-client/hooks/useCachedSchedules';
import { useCategories } from '@desktop-client/hooks/useCategories';
import { useDateFormat } from '@desktop-client/hooks/useDateFormat';
import { useFailedAccounts } from '@desktop-client/hooks/useFailedAccounts';
import { useLocalPref } from '@desktop-client/hooks/useLocalPref';
import { usePayees } from '@desktop-client/hooks/usePayees';
import { getSchedulesQuery } from '@desktop-client/hooks/useSchedules';
import { SelectedProviderWithItems } from '@desktop-client/hooks/useSelected';
import type { Actions } from '@desktop-client/hooks/useSelected';
} from '#accounts';
import { markAccountRead } from '#accounts/accountsSlice';
import type { SavedFilter } from '#components/filters/SavedFilterMenuButton';
import { TransactionList } from '#components/transactions/TransactionList';
import { validateAccountName } from '#components/util/accountValidation';
import { useAccountPreviewTransactions } from '#hooks/useAccountPreviewTransactions';
import { useAccounts } from '#hooks/useAccounts';
import { SchedulesProvider } from '#hooks/useCachedSchedules';
import { useCategories } from '#hooks/useCategories';
import { useDateFormat } from '#hooks/useDateFormat';
import { useFailedAccounts } from '#hooks/useFailedAccounts';
import { useLocalPref } from '#hooks/useLocalPref';
import { usePayees } from '#hooks/usePayees';
import { getSchedulesQuery } from '#hooks/useSchedules';
import { SelectedProviderWithItems } from '#hooks/useSelected';
import type { Actions } from '#hooks/useSelected';
import {
SplitsExpandedProvider,
useSplitsExpanded,
} from '@desktop-client/hooks/useSplitsExpanded';
import { useSyncedPref } from '@desktop-client/hooks/useSyncedPref';
import { useTransactionBatchActions } from '@desktop-client/hooks/useTransactionBatchActions';
import { useTransactionFilters } from '@desktop-client/hooks/useTransactionFilters';
import { calculateRunningBalancesBottomUp } from '@desktop-client/hooks/useTransactions';
} from '#hooks/useSplitsExpanded';
import { useSyncedPref } from '#hooks/useSyncedPref';
import { useTransactionBatchActions } from '#hooks/useTransactionBatchActions';
import { useTransactionFilters } from '#hooks/useTransactionFilters';
import { calculateRunningBalancesBottomUp } from '#hooks/useTransactions';
import {
openAccountCloseModal,
pushModal,
replaceModal,
} from '@desktop-client/modals/modalsSlice';
import type { ConfirmTransactionEditReason } from '@desktop-client/modals/modalsSlice';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { useCreatePayeeMutation } from '@desktop-client/payees';
import * as queries from '@desktop-client/queries';
import { aqlQuery } from '@desktop-client/queries/aqlQuery';
import { pagedQuery } from '@desktop-client/queries/pagedQuery';
import type { PagedQuery } from '@desktop-client/queries/pagedQuery';
import { useDispatch, useSelector } from '@desktop-client/redux';
import type { AppDispatch } from '@desktop-client/redux/store';
import { updateNewTransactions } from '@desktop-client/transactions/transactionsSlice';
} from '#modals/modalsSlice';
import type { ConfirmTransactionEditReason } from '#modals/modalsSlice';
import { addNotification } from '#notifications/notificationsSlice';
import { useCreatePayeeMutation } from '#payees';
import * as queries from '#queries';
import { aqlQuery } from '#queries/aqlQuery';
import { pagedQuery } from '#queries/pagedQuery';
import type { PagedQuery } from '#queries/pagedQuery';
import { useDispatch, useSelector } from '#redux';
import type { AppDispatch } from '#redux/store';
import { updateNewTransactions } from '#transactions/transactionsSlice';
import { AccountEmptyMessage } from './AccountEmptyMessage';
import { AccountHeader } from './Header';
type ConditionEntity = Partial<RuleConditionEntity> | TransactionFilterEntity;
@@ -7,15 +7,14 @@ import { SvgExclamationOutline } from '@actual-app/components/icons/v1';
import { Popover } from '@actual-app/components/popover';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type { AccountEntity } from '@actual-app/core/types/models';
import type { AccountEntity } from 'loot-core/types/models';
import { useUnlinkAccountMutation } from '@desktop-client/accounts';
import { Link } from '@desktop-client/components/common/Link';
import { authorizeBank } from '@desktop-client/gocardless';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
import { useFailedAccounts } from '@desktop-client/hooks/useFailedAccounts';
import { useDispatch } from '@desktop-client/redux';
import { useUnlinkAccountMutation } from '#accounts';
import { Link } from '#components/common/Link';
import { authorizeBank } from '#gocardless';
import { useAccounts } from '#hooks/useAccounts';
import { useFailedAccounts } from '#hooks/useFailedAccounts';
import { useDispatch } from '#redux';
function useErrorMessage() {
const { t } = useTranslation();
@@ -1,25 +1,24 @@
import React from 'react';
import type { ScheduleEntity } from '@actual-app/core/types/models';
import { render, screen } from '@testing-library/react';
import type { ScheduleEntity } from 'loot-core/types/models';
import { useCachedSchedules } from '#hooks/useCachedSchedules';
import { useSelectedItems } from '#hooks/useSelected';
import { useSheetValue } from '#hooks/useSheetValue';
import { TestProviders } from '#mocks';
import { SelectedBalance } from './Balance';
import { useCachedSchedules } from '@desktop-client/hooks/useCachedSchedules';
import { useSelectedItems } from '@desktop-client/hooks/useSelected';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import { TestProviders } from '@desktop-client/mocks';
vi.mock('@desktop-client/hooks/useSelected', () => ({
vi.mock('#hooks/useSelected', () => ({
useSelectedItems: vi.fn(),
}));
vi.mock('@desktop-client/hooks/useSheetValue', () => ({
vi.mock('#hooks/useSheetValue', () => ({
useSheetValue: vi.fn(),
}));
vi.mock('@desktop-client/hooks/useCachedSchedules', () => ({
vi.mock('#hooks/useCachedSchedules', () => ({
useCachedSchedules: vi.fn(),
}));
@@ -7,25 +7,21 @@ import { SvgArrowButtonRight1 } from '@actual-app/components/icons/v2';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { q } from '@actual-app/core/shared/query';
import type { Query } from '@actual-app/core/shared/query';
import { getScheduledAmount } from '@actual-app/core/shared/schedules';
import { isPreviewId } from '@actual-app/core/shared/transactions';
import type { AccountEntity } from '@actual-app/core/types/models';
import { useHover } from 'usehooks-ts';
import { q } from 'loot-core/shared/query';
import type { Query } from 'loot-core/shared/query';
import { getScheduledAmount } from 'loot-core/shared/schedules';
import { isPreviewId } from 'loot-core/shared/transactions';
import type { AccountEntity } from 'loot-core/types/models';
import { FinancialText } from '@desktop-client/components/FinancialText';
import { PrivacyFilter } from '@desktop-client/components/PrivacyFilter';
import {
CellValue,
CellValueText,
} from '@desktop-client/components/spreadsheet/CellValue';
import { useCachedSchedules } from '@desktop-client/hooks/useCachedSchedules';
import { useFormat } from '@desktop-client/hooks/useFormat';
import { useSelectedItems } from '@desktop-client/hooks/useSelected';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import type { Binding } from '@desktop-client/spreadsheet';
import { FinancialText } from '#components/FinancialText';
import { PrivacyFilter } from '#components/PrivacyFilter';
import { CellValue, CellValueText } from '#components/spreadsheet/CellValue';
import { useCachedSchedules } from '#hooks/useCachedSchedules';
import { useFormat } from '#hooks/useFormat';
import { useSelectedItems } from '#hooks/useSelected';
import { useSheetValue } from '#hooks/useSheetValue';
import type { Binding } from '#spreadsheet';
type DetailedBalanceProps = {
name: string;
@@ -7,18 +7,17 @@ import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import * as monthUtils from '@actual-app/core/shared/months';
import { integerToCurrency } from '@actual-app/core/shared/util';
import { eachMonthOfInterval, format, subMonths } from 'date-fns';
import { Area, AreaChart, Tooltip as RechartsTooltip, YAxis } from 'recharts';
import * as monthUtils from 'loot-core/shared/months';
import { integerToCurrency } from 'loot-core/shared/util';
import { PrivacyFilter } from '@desktop-client/components/PrivacyFilter';
import { useRechartsAnimation } from '@desktop-client/components/reports/chart-theme';
import { LoadingIndicator } from '@desktop-client/components/reports/LoadingIndicator';
import { useLocale } from '@desktop-client/hooks/useLocale';
import * as query from '@desktop-client/queries';
import { liveQuery } from '@desktop-client/queries/liveQuery';
import { PrivacyFilter } from '#components/PrivacyFilter';
import { useRechartsAnimation } from '#components/reports/chart-theme';
import { LoadingIndicator } from '#components/reports/LoadingIndicator';
import { useLocale } from '#hooks/useLocale';
import * as query from '#queries';
import { liveQuery } from '#queries/liveQuery';
const LABEL_WIDTH = 70;
@@ -26,35 +26,34 @@ import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { Tooltip } from '@actual-app/components/tooltip';
import { View } from '@actual-app/components/view';
import { format as formatDate } from 'date-fns';
import { tsToRelativeTime } from 'loot-core/shared/util';
import { tsToRelativeTime } from '@actual-app/core/shared/util';
import type {
AccountEntity,
RuleConditionEntity,
TransactionEntity,
TransactionFilterEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { format as formatDate } from 'date-fns';
import { AnimatedRefresh } from '#components/AnimatedRefresh';
import { Search } from '#components/common/Search';
import { FilterButton } from '#components/filters/FiltersMenu';
import { FiltersStack } from '#components/filters/FiltersStack';
import type { SavedFilter } from '#components/filters/SavedFilterMenuButton';
import { NotesButton } from '#components/NotesButton';
import { SelectedTransactionsButton } from '#components/transactions/SelectedTransactionsButton';
import { useDateFormat } from '#hooks/useDateFormat';
import { useLocale } from '#hooks/useLocale';
import { useLocalPref } from '#hooks/useLocalPref';
import { useSplitsExpanded } from '#hooks/useSplitsExpanded';
import { useSyncedPref } from '#hooks/useSyncedPref';
import { useSyncServerStatus } from '#hooks/useSyncServerStatus';
import type { TableRef } from './Account';
import { Balances } from './Balance';
import { BalanceHistoryGraph } from './BalanceHistoryGraph';
import { ReconcileMenu, ReconcilingMessage } from './Reconcile';
import { AnimatedRefresh } from '@desktop-client/components/AnimatedRefresh';
import { Search } from '@desktop-client/components/common/Search';
import { FilterButton } from '@desktop-client/components/filters/FiltersMenu';
import { FiltersStack } from '@desktop-client/components/filters/FiltersStack';
import type { SavedFilter } from '@desktop-client/components/filters/SavedFilterMenuButton';
import { NotesButton } from '@desktop-client/components/NotesButton';
import { SelectedTransactionsButton } from '@desktop-client/components/transactions/SelectedTransactionsButton';
import { useDateFormat } from '@desktop-client/hooks/useDateFormat';
import { useLocale } from '@desktop-client/hooks/useLocale';
import { useLocalPref } from '@desktop-client/hooks/useLocalPref';
import { useSplitsExpanded } from '@desktop-client/hooks/useSplitsExpanded';
import { useSyncedPref } from '@desktop-client/hooks/useSyncedPref';
import { useSyncServerStatus } from '@desktop-client/hooks/useSyncServerStatus';
type AccountHeaderProps = {
tableRef: TableRef;
isNameEditable: boolean;
@@ -1,18 +1,17 @@
import React from 'react';
import { generateAccount } from '@actual-app/core/mocks';
import { q } from '@actual-app/core/shared/query';
import type { AccountEntity } from '@actual-app/core/types/models';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { generateAccount } from 'loot-core/mocks';
import { q } from 'loot-core/shared/query';
import type { AccountEntity } from 'loot-core/types/models';
import { useSheetValue } from '#hooks/useSheetValue';
import { TestProviders } from '#mocks';
import { ReconcileMenu, ReconcilingMessage } from './Reconcile';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import { TestProviders } from '@desktop-client/mocks';
vi.mock('@desktop-client/hooks/useSheetValue', () => ({
vi.mock('#hooks/useSheetValue', () => ({
useSheetValue: vi.fn(),
}));
@@ -11,19 +11,18 @@ import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type { Query } from '@actual-app/core/shared/query';
import { tsToRelativeTime } from '@actual-app/core/shared/util';
import type { AccountEntity } from '@actual-app/core/types/models';
import type { TransObjectLiteral } from '@actual-app/core/types/util';
import { format as formatDate } from 'date-fns';
import { t } from 'i18next';
import type { Query } from 'loot-core/shared/query';
import { tsToRelativeTime } from 'loot-core/shared/util';
import type { AccountEntity } from 'loot-core/types/models';
import type { TransObjectLiteral } from 'loot-core/types/util';
import { useDateFormat } from '@desktop-client/hooks/useDateFormat';
import { useFormat } from '@desktop-client/hooks/useFormat';
import { useLocale } from '@desktop-client/hooks/useLocale';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import * as bindings from '@desktop-client/spreadsheet/bindings';
import { useDateFormat } from '#hooks/useDateFormat';
import { useFormat } from '#hooks/useFormat';
import { useLocale } from '#hooks/useLocale';
import { useSheetValue } from '#hooks/useSheetValue';
import * as bindings from '#spreadsheet/bindings';
type ReconcilingMessageProps = {
balanceQuery: { name: `balance-query-${string}`; query: Query };
@@ -10,23 +10,25 @@ import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { send } from '@actual-app/core/platform/client/connection';
import * as undo from '@actual-app/core/platform/client/undo';
import type { Handlers } from '@actual-app/core/types/handlers';
import type {
UserAccessEntity,
UserAvailable,
} from '@actual-app/core/types/models';
import { send } from 'loot-core/platform/client/connection';
import * as undo from 'loot-core/platform/client/undo';
import type { Handlers } from 'loot-core/types/handlers';
import type { UserAccessEntity, UserAvailable } from 'loot-core/types/models';
import { InfiniteScrollWrapper } from '#components/common/InfiniteScrollWrapper';
import { Link } from '#components/common/Link';
import { Search } from '#components/common/Search';
import { useMetadataPref } from '#hooks/useMetadataPref';
import { pushModal } from '#modals/modalsSlice';
import { addNotification } from '#notifications/notificationsSlice';
import { useDispatch } from '#redux';
import { UserAccessHeader } from './UserAccessHeader';
import { UserAccessRow } from './UserAccessRow';
import { InfiniteScrollWrapper } from '@desktop-client/components/common/InfiniteScrollWrapper';
import { Link } from '@desktop-client/components/common/Link';
import { Search } from '@desktop-client/components/common/Search';
import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref';
import { pushModal } from '@desktop-client/modals/modalsSlice';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { useDispatch } from '@desktop-client/redux';
type ManageUserAccessContentProps = {
isModal: boolean;
};
@@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Cell, TableHeader } from '@desktop-client/components/table';
import { Cell, TableHeader } from '#components/table';
export function UserAccessHeader() {
const { t } = useTranslation();
@@ -1,9 +1,9 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { UserAccess } from './UserAccess';
import { Page } from '#components/Page';
import { Page } from '@desktop-client/components/Page';
import { UserAccess } from './UserAccess';
export function UserAccessPage() {
const { t } = useTranslation();
@@ -4,17 +4,16 @@ import { useTranslation } from 'react-i18next';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { send } from '@actual-app/core/platform/client/connection';
import { getUserAccessErrors } from '@actual-app/core/shared/errors';
import type { UserAvailable } from '@actual-app/core/types/models';
import { send } from 'loot-core/platform/client/connection';
import { getUserAccessErrors } from 'loot-core/shared/errors';
import type { UserAvailable } from 'loot-core/types/models';
import { Checkbox } from '@desktop-client/components/forms';
import { Cell, Row } from '@desktop-client/components/table';
import { useMetadataPref } from '@desktop-client/hooks/useMetadataPref';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { useDispatch } from '@desktop-client/redux';
import { signOut } from '@desktop-client/users/usersSlice';
import { Checkbox } from '#components/forms';
import { Cell, Row } from '#components/table';
import { useMetadataPref } from '#hooks/useMetadataPref';
import { addNotification } from '#notifications/notificationsSlice';
import { useDispatch } from '#redux';
import { signOut } from '#users/usersSlice';
type UserAccessProps = {
access: UserAvailable;
@@ -9,26 +9,22 @@ import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { send } from '@actual-app/core/platform/client/connection';
import * as undo from '@actual-app/core/platform/client/undo';
import type { NewUserEntity, UserEntity } from '@actual-app/core/types/models';
import { send } from 'loot-core/platform/client/connection';
import * as undo from 'loot-core/platform/client/undo';
import type { NewUserEntity, UserEntity } from 'loot-core/types/models';
import { InfiniteScrollWrapper } from '#components/common/InfiniteScrollWrapper';
import { Link } from '#components/common/Link';
import { Search } from '#components/common/Search';
import { SelectedProvider, useSelected } from '#hooks/useSelected';
import { pushModal } from '#modals/modalsSlice';
import { addNotification } from '#notifications/notificationsSlice';
import { useDispatch } from '#redux';
import { signOut } from '#users/usersSlice';
import { UserDirectoryHeader } from './UserDirectoryHeader';
import { UserDirectoryRow } from './UserDirectoryRow';
import { InfiniteScrollWrapper } from '@desktop-client/components/common/InfiniteScrollWrapper';
import { Link } from '@desktop-client/components/common/Link';
import { Search } from '@desktop-client/components/common/Search';
import {
SelectedProvider,
useSelected,
} from '@desktop-client/hooks/useSelected';
import { pushModal } from '@desktop-client/modals/modalsSlice';
import { addNotification } from '@desktop-client/notifications/notificationsSlice';
import { useDispatch } from '@desktop-client/redux';
import { signOut } from '@desktop-client/users/usersSlice';
type ManageUserDirectoryContentProps = {
isModal: boolean;
};
@@ -1,15 +1,8 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import {
Cell,
SelectCell,
TableHeader,
} from '@desktop-client/components/table';
import {
useSelectedDispatch,
useSelectedItems,
} from '@desktop-client/hooks/useSelected';
import { Cell, SelectCell, TableHeader } from '#components/table';
import { useSelectedDispatch, useSelectedItems } from '#hooks/useSelected';
export function UserDirectoryHeader() {
const { t } = useTranslation();
@@ -5,10 +5,10 @@ import { Trans, useTranslation } from 'react-i18next';
import { Button } from '@actual-app/components/button';
import { View } from '@actual-app/components/view';
import { UserDirectory } from './UserDirectory';
import { Page } from '#components/Page';
import { useNavigate } from '#hooks/useNavigate';
import { Page } from '@desktop-client/components/Page';
import { useNavigate } from '@desktop-client/hooks/useNavigate';
import { UserDirectory } from './UserDirectory';
export function UserDirectoryPage({
bottomContent,
@@ -5,13 +5,12 @@ import { Trans } from 'react-i18next';
import { Button } from '@actual-app/components/button';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { PossibleRoles } from '@actual-app/core/shared/user';
import type { UserEntity } from '@actual-app/core/types/models';
import { PossibleRoles } from 'loot-core/shared/user';
import type { UserEntity } from 'loot-core/types/models';
import { Checkbox } from '@desktop-client/components/forms';
import { Cell, Row, SelectCell } from '@desktop-client/components/table';
import { useSelectedDispatch } from '@desktop-client/hooks/useSelected';
import { Checkbox } from '#components/forms';
import { Cell, Row, SelectCell } from '#components/table';
import { useSelectedDispatch } from '#hooks/useSelected';
type UserDirectoryProps = {
user: UserEntity;
@@ -13,15 +13,14 @@ import { styles } from '@actual-app/components/styles';
import { TextOneLine } from '@actual-app/components/text-one-line';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type { AccountEntity } from '@actual-app/core/types/models';
import { css, cx } from '@emotion/css';
import type { AccountEntity } from 'loot-core/types/models';
import { useAccounts } from '#hooks/useAccounts';
import { Autocomplete } from './Autocomplete';
import { ItemHeader } from './ItemHeader';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
type AccountAutocompleteItem = AccountEntity;
type AccountListProps = {
@@ -15,13 +15,12 @@ import { Popover } from '@actual-app/components/popover';
import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { View, viewStyles } from '@actual-app/components/view';
import { getNormalisedString } from '@actual-app/core/shared/normalisation';
import { css, cx } from '@emotion/css';
import Downshift from 'downshift';
import type { StateChangeTypes } from 'downshift';
import { getNormalisedString } from 'loot-core/shared/normalisation';
import { useProperFocus } from '@desktop-client/hooks/useProperFocus';
import { useProperFocus } from '#hooks/useProperFocus';
type CommonAutocompleteProps<T extends AutocompleteItem> = {
focused?: boolean;
@@ -17,30 +17,26 @@ import { Text } from '@actual-app/components/text';
import { TextOneLine } from '@actual-app/components/text-one-line';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { css, cx } from '@emotion/css';
import { getNormalisedString } from 'loot-core/shared/normalisation';
import { integerToCurrency } from 'loot-core/shared/util';
import { getNormalisedString } from '@actual-app/core/shared/normalisation';
import { integerToCurrency } from '@actual-app/core/shared/util';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { css, cx } from '@emotion/css';
import { useEnvelopeSheetValue } from '#components/budget/envelope/EnvelopeBudgetComponents';
import { makeAmountFullStyle } from '#components/budget/util';
import { FinancialText } from '#components/FinancialText';
import { useCategories } from '#hooks/useCategories';
import { useSheetValue } from '#hooks/useSheetValue';
import { useSyncedPref } from '#hooks/useSyncedPref';
import { envelopeBudget, trackingBudget } from '#spreadsheet/bindings';
import { Autocomplete, defaultFilterSuggestion } from './Autocomplete';
import { rankAutocompleteMatch } from './autocompleteRanking';
import { ItemHeader } from './ItemHeader';
import { useEnvelopeSheetValue } from '@desktop-client/components/budget/envelope/EnvelopeBudgetComponents';
import { makeAmountFullStyle } from '@desktop-client/components/budget/util';
import { FinancialText } from '@desktop-client/components/FinancialText';
import { useCategories } from '@desktop-client/hooks/useCategories';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import { useSyncedPref } from '@desktop-client/hooks/useSyncedPref';
import {
envelopeBudget,
trackingBudget,
} from '@desktop-client/spreadsheet/bindings';
type CategoryAutocompleteItem = Omit<CategoryEntity, 'group'> & {
group?: CategoryGroupEntity;
};
@@ -13,14 +13,13 @@ import { styles } from '@actual-app/components/styles';
import { TextOneLine } from '@actual-app/components/text-one-line';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type { CategoryGroupEntity } from '@actual-app/core/types/models';
import { css, cx } from '@emotion/css';
import type { CategoryGroupEntity } from 'loot-core/types/models';
import { useCategories } from '#hooks/useCategories';
import { Autocomplete } from './Autocomplete';
import { useCategories } from '@desktop-client/hooks/useCategories';
type CategoryGroupAutocompleteItem = CategoryGroupEntity;
type CategoryGroupListProps = {
@@ -1,13 +1,13 @@
import React from 'react';
import type { ComponentProps } from 'react';
import type { TransactionFilterEntity } from 'loot-core/types/models';
import type { TransactionFilterEntity } from '@actual-app/core/types/models';
import { useTransactionFilters } from '#hooks/useTransactionFilters';
import { Autocomplete } from './Autocomplete';
import { FilterList } from './FilterList';
import { useTransactionFilters } from '@desktop-client/hooks/useTransactionFilters';
export function FilterAutocomplete({
embedded,
...props
@@ -1,24 +1,23 @@
import { generateAccount } from '@actual-app/core/mocks';
import type {
AccountEntity,
NearbyPayeeEntity,
PayeeEntity,
} from '@actual-app/core/types/models';
import type { UseQueryResult } from '@tanstack/react-query';
import { render, screen } from '@testing-library/react';
import type { Screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { vi } from 'vitest';
import { generateAccount } from 'loot-core/mocks';
import type {
AccountEntity,
NearbyPayeeEntity,
PayeeEntity,
} from 'loot-core/types/models';
import { AuthProvider } from '#auth/AuthProvider';
import { useNearbyPayees } from '#hooks/useNearbyPayees';
import { createTestQueryClient, TestProviders } from '#mocks';
import { payeeQueries } from '#payees';
import { PayeeAutocomplete } from './PayeeAutocomplete';
import type { PayeeAutocompleteProps } from './PayeeAutocomplete';
import { AuthProvider } from '@desktop-client/auth/AuthProvider';
import { useNearbyPayees } from '@desktop-client/hooks/useNearbyPayees';
import { createTestQueryClient, TestProviders } from '@desktop-client/mocks';
import { payeeQueries } from '@desktop-client/payees';
const PAYEE_SELECTOR = '[data-testid][role=option]';
const PAYEE_SECTION_SELECTOR = '[data-testid$="-item-group"]';
const ALL_PAYEE_ITEMS_SELECTOR = '[data-testid$="-payee-item"]';
@@ -108,7 +107,7 @@ async function clickAutocomplete(autocomplete: HTMLElement) {
await waitForAutocomplete();
}
vi.mock('@desktop-client/hooks/useNearbyPayees', () => ({
vi.mock('#hooks/useNearbyPayees', () => ({
useNearbyPayees: vi.fn(),
}));
@@ -22,15 +22,24 @@ import { styles } from '@actual-app/components/styles';
import { TextOneLine } from '@actual-app/components/text-one-line';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { css, cx } from '@emotion/css';
import { formatDistance } from 'loot-core/shared/location-utils';
import { getNormalisedString } from 'loot-core/shared/normalisation';
import { formatDistance } from '@actual-app/core/shared/location-utils';
import { getNormalisedString } from '@actual-app/core/shared/normalisation';
import type {
AccountEntity,
NearbyPayeeEntity,
PayeeEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { css, cx } from '@emotion/css';
import { useAccounts } from '#hooks/useAccounts';
import { useCommonPayees } from '#hooks/useCommonPayees';
import { useNearbyPayees } from '#hooks/useNearbyPayees';
import { usePayees } from '#hooks/usePayees';
import {
getActivePayees,
useCreatePayeeMutation,
useDeletePayeeLocationMutation,
} from '#payees';
import {
Autocomplete,
@@ -40,16 +49,6 @@ import {
import { rankAutocompleteMatch } from './autocompleteRanking';
import { ItemHeader } from './ItemHeader';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
import { useCommonPayees } from '@desktop-client/hooks/useCommonPayees';
import { useNearbyPayees } from '@desktop-client/hooks/useNearbyPayees';
import { usePayees } from '@desktop-client/hooks/usePayees';
import {
getActivePayees,
useCreatePayeeMutation,
useDeletePayeeLocationMutation,
} from '@desktop-client/payees';
type PayeeAutocompleteItem = PayeeEntity &
PayeeItemType & {
nearbyLocationId?: string;
@@ -1,13 +1,13 @@
import React from 'react';
import type { ComponentProps } from 'react';
import type { CustomReportEntity } from 'loot-core/types/models';
import type { CustomReportEntity } from '@actual-app/core/types/models';
import { useReports } from '#hooks/useReports';
import { Autocomplete } from './Autocomplete';
import { ReportList } from './ReportList';
import { useReports } from '@desktop-client/hooks/useReports';
type ReportAutocompleteProps = {
embedded?: boolean;
} & ComponentProps<typeof Autocomplete<CustomReportEntity>>;
@@ -1,4 +1,4 @@
import { getNormalisedString } from 'loot-core/shared/normalisation';
import { getNormalisedString } from '@actual-app/core/shared/normalisation';
/**
* Returns a numeric rank for how well `name` matches `input`.
@@ -5,13 +5,12 @@ import { Button } from '@actual-app/components/button';
import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { Tooltip } from '@actual-app/components/tooltip';
import { tsToRelativeTime } from '@actual-app/core/shared/util';
import type { AccountEntity } from '@actual-app/core/types/models';
import { format as formatDate } from 'date-fns';
import type { Locale } from 'date-fns';
import { tsToRelativeTime } from 'loot-core/shared/util';
import type { AccountEntity } from 'loot-core/types/models';
import { Cell, Row } from '@desktop-client/components/table';
import { Cell, Row } from '#components/table';
type AccountRowProps = {
account: AccountEntity;
@@ -1,7 +1,7 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Cell, TableHeader } from '@desktop-client/components/table';
import { Cell, TableHeader } from '#components/table';
type AccountsHeaderProps = {
unlinked: boolean;
@@ -1,13 +1,12 @@
import React from 'react';
import { View } from '@actual-app/components/view';
import type { AccountEntity } from '@actual-app/core/types/models';
import type { AccountEntity } from 'loot-core/types/models';
import { useLocale } from '#hooks/useLocale';
import { AccountRow } from './AccountRow';
import { useLocale } from '@desktop-client/hooks/useLocale';
type AccountsListProps = {
accounts: AccountEntity[];
hoveredAccount?: string | null;
@@ -9,8 +9,8 @@ import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { Tooltip } from '@actual-app/components/tooltip';
import { LabeledCheckbox } from '@desktop-client/components/forms/LabeledCheckbox';
import { ToggleField } from '@desktop-client/components/mobile/MobileForms';
import { LabeledCheckbox } from '#components/forms/LabeledCheckbox';
import { ToggleField } from '#components/mobile/MobileForms';
type CheckboxOptionProps = {
id: string;
@@ -6,22 +6,17 @@ import { SpaceBetween } from '@actual-app/components/space-between';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type { AccountEntity } from '@actual-app/core/types/models';
import type { AccountEntity } from 'loot-core/types/models';
import { useUnlinkAccountMutation } from '#accounts';
import { Modal, ModalCloseButton, ModalHeader } from '#components/common/Modal';
import { pushModal } from '#modals/modalsSlice';
import { useDispatch } from '#redux';
import { BankSyncCheckboxOptions } from './BankSyncCheckboxOptions';
import { FieldMapping } from './FieldMapping';
import { useBankSyncAccountSettings } from './useBankSyncAccountSettings';
import { useUnlinkAccountMutation } from '@desktop-client/accounts';
import {
Modal,
ModalCloseButton,
ModalHeader,
} from '@desktop-client/components/common/Modal';
import { pushModal } from '@desktop-client/modals/modalsSlice';
import { useDispatch } from '@desktop-client/redux';
export type TransactionDirection = 'payment' | 'deposit';
type MappableActualFields = 'date' | 'payee' | 'notes';
@@ -9,13 +9,13 @@ import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { Cell, Row, TableHeader } from '#components/table';
import type {
MappableFieldWithExample,
TransactionDirection,
} from './EditSyncAccount';
import { Cell, Row, TableHeader } from '@desktop-client/components/table';
const useTransactionDirectionOptions = () => {
const { t } = useTranslation();
@@ -5,19 +5,21 @@ import { useResponsive } from '@actual-app/components/hooks/useResponsive';
import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { View } from '@actual-app/components/view';
import type {
AccountEntity,
BankSyncProviders,
} from '@actual-app/core/types/models';
import type { AccountEntity, BankSyncProviders } from 'loot-core/types/models';
import { MOBILE_NAV_HEIGHT } from '#components/mobile/MobileNavTabs';
import { Page } from '#components/Page';
import { useAccounts } from '#hooks/useAccounts';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { pushModal } from '#modals/modalsSlice';
import { useDispatch } from '#redux';
import { AccountsHeader } from './AccountsHeader';
import { AccountsList } from './AccountsList';
import { MOBILE_NAV_HEIGHT } from '@desktop-client/components/mobile/MobileNavTabs';
import { Page } from '@desktop-client/components/Page';
import { useAccounts } from '@desktop-client/hooks/useAccounts';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
import { pushModal } from '@desktop-client/modals/modalsSlice';
import { useDispatch } from '@desktop-client/redux';
type SyncProviders = BankSyncProviders | 'unlinked';
const useSyncSourceReadable = () => {
@@ -4,9 +4,12 @@ import {
defaultMappings,
mappingsFromString,
mappingsToString,
} from 'loot-core/server/util/custom-sync-mapping';
import type { Mappings } from 'loot-core/server/util/custom-sync-mapping';
import { q } from 'loot-core/shared/query';
} from '@actual-app/core/server/util/custom-sync-mapping';
import type { Mappings } from '@actual-app/core/server/util/custom-sync-mapping';
import { q } from '@actual-app/core/shared/query';
import { useSyncedPref } from '#hooks/useSyncedPref';
import { useTransactions } from '#hooks/useTransactions';
import { getFields } from './EditSyncAccount';
import type {
@@ -14,9 +17,6 @@ import type {
TransactionDirection,
} from './EditSyncAccount';
import { useSyncedPref } from '@desktop-client/hooks/useSyncedPref';
import { useTransactions } from '@desktop-client/hooks/useTransactions';
export function useBankSyncAccountSettings(accountId: string) {
const [savedMappings = mappingsToString(defaultMappings), setSavedMappings] =
useSyncedPref(`custom-sync-mappings-${accountId}`);
@@ -13,21 +13,17 @@ import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { Tooltip } from '@actual-app/components/tooltip';
import { View } from '@actual-app/components/view';
import type { TransObjectLiteral } from '@actual-app/core/types/util';
import { css } from '@emotion/css';
import type { TransObjectLiteral } from 'loot-core/types/util';
import { CellValue, CellValueText } from '#components/spreadsheet/CellValue';
import { useFeatureFlag } from '#hooks/useFeatureFlag';
import { useFormat } from '#hooks/useFormat';
import { useSheetValue } from '#hooks/useSheetValue';
import type { Binding } from '#spreadsheet';
import { makeBalanceAmountStyle } from './util';
import {
CellValue,
CellValueText,
} from '@desktop-client/components/spreadsheet/CellValue';
import { useFeatureFlag } from '@desktop-client/hooks/useFeatureFlag';
import { useFormat } from '@desktop-client/hooks/useFormat';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import type { Binding } from '@desktop-client/spreadsheet';
type CarryoverIndicatorProps = {
style?: CSSProperties;
};
@@ -3,11 +3,15 @@ import React, { memo, useMemo, useState } from 'react';
import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { DropHighlightPosContext } from '#components/sort';
import type { DragState, OnDropCallback } from '#components/sort';
import { Row } from '#components/table';
import { useLocalPref } from '#hooks/useLocalPref';
import { ExpenseCategory } from './ExpenseCategory';
import { ExpenseGroup } from './ExpenseGroup';
@@ -18,14 +22,6 @@ import { SidebarCategory } from './SidebarCategory';
import { SidebarGroup } from './SidebarGroup';
import { separateGroups } from './util';
import { DropHighlightPosContext } from '@desktop-client/components/sort';
import type {
DragState,
OnDropCallback,
} from '@desktop-client/components/sort';
import { Row } from '@desktop-client/components/table';
import { useLocalPref } from '@desktop-client/hooks/useLocalPref';
type BudgetItem =
| { type: 'new-group' }
| { type: 'new-category' }
@@ -4,11 +4,11 @@ import type { ComponentProps } from 'react';
import { View } from '@actual-app/components/view';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { MonthPicker } from './MonthPicker';
import { getScrollbarWidth } from './util';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
type BudgetPageHeaderProps = {
startMonth: string;
onMonthSelect: (month: string) => void;
@@ -9,16 +9,15 @@ import React, {
import { animated, useSpring } from 'react-spring';
import { View, viewStyles } from '@actual-app/components/view';
import { addMonths, subMonths } from '@actual-app/core/shared/months';
import { css } from '@emotion/css';
import { addMonths, subMonths } from 'loot-core/shared/months';
import { useResizeObserver } from '#hooks/useResizeObserver';
import { MonthsContext } from './MonthsContext';
import { useBudgetComponents } from '.';
import { useResizeObserver } from '@desktop-client/hooks/useResizeObserver';
export function BudgetSummaries() {
const { months } = useContext(MonthsContext);
const [firstMonth] = months;
@@ -4,12 +4,17 @@ import type { KeyboardEvent } from 'react';
import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { q } from 'loot-core/shared/query';
import { q } from '@actual-app/core/shared/query';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import type { DropPosition } from '#components/sort';
import { SchedulesProvider } from '#hooks/useCachedSchedules';
import { useCategories } from '#hooks/useCategories';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { useLocalPref } from '#hooks/useLocalPref';
import { BudgetCategories } from './BudgetCategories';
import { BudgetSummaries } from './BudgetSummaries';
@@ -23,12 +28,6 @@ import {
separateGroups,
} from './util';
import type { DropPosition } from '@desktop-client/components/sort';
import { SchedulesProvider } from '@desktop-client/hooks/useCachedSchedules';
import { useCategories } from '@desktop-client/hooks/useCategories';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
import { useLocalPref } from '@desktop-client/hooks/useLocalPref';
type BudgetTableProps = {
type: string;
prewarmStartMonth: string;
@@ -14,13 +14,13 @@ import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { RenderMonths } from './RenderMonths';
import { getScrollbarWidth } from './util';
import { useBudgetComponents } from '.';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
type BudgetTotalsProps = {
toggleHiddenCategories: () => void;
expandAllCategories: () => void;
@@ -5,15 +5,14 @@ import { useHotkeys } from 'react-hotkeys-hook';
import { AutoSizer } from 'react-virtualized-auto-sizer';
import { View } from '@actual-app/components/view';
import * as monthUtils from '@actual-app/core/shared/months';
import * as monthUtils from 'loot-core/shared/months';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { useBudgetMonthCount } from './BudgetMonthCountContext';
import { BudgetPageHeader } from './BudgetPageHeader';
import { BudgetTable } from './BudgetTable';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
function getNumPossibleMonths(width: number, categoryWidth: number) {
const estimatedTableWidth = width - categoryWidth;
@@ -4,30 +4,25 @@ import type { ComponentProps } from 'react';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { DropHighlight, useDraggable, useDroppable } from '#components/sort';
import type {
DragState,
OnDragChangeCallback,
OnDropCallback,
} from '#components/sort';
import { Row } from '#components/table';
import { useDragRef } from '#hooks/useDragRef';
import { RenderMonths } from './RenderMonths';
import { SidebarCategory } from './SidebarCategory';
import { useBudgetComponents } from '.';
import {
DropHighlight,
useDraggable,
useDroppable,
} from '@desktop-client/components/sort';
import type {
DragState,
OnDragChangeCallback,
OnDropCallback,
} from '@desktop-client/components/sort';
import { Row } from '@desktop-client/components/table';
import { useDragRef } from '@desktop-client/hooks/useDragRef';
type ExpenseCategoryProps = {
cat: CategoryEntity;
categoryGroup?: CategoryGroupEntity;
@@ -4,30 +4,25 @@ import type { ComponentProps } from 'react';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { DropHighlight, useDraggable, useDroppable } from '#components/sort';
import type {
DragState,
OnDragChangeCallback,
OnDropCallback,
} from '#components/sort';
import { Row, ROW_HEIGHT } from '#components/table';
import { useDragRef } from '#hooks/useDragRef';
import { RenderMonths } from './RenderMonths';
import { SidebarGroup } from './SidebarGroup';
import { useBudgetComponents } from '.';
import {
DropHighlight,
useDraggable,
useDroppable,
} from '@desktop-client/components/sort';
import type {
DragState,
OnDragChangeCallback,
OnDropCallback,
} from '@desktop-client/components/sort';
import { Row, ROW_HEIGHT } from '@desktop-client/components/table';
import { useDragRef } from '@desktop-client/hooks/useDragRef';
type ExpenseGroupProps = {
group: ComponentProps<typeof SidebarGroup>['group'];
collapsed: boolean;
@@ -2,25 +2,18 @@
import React from 'react';
import type { ComponentProps } from 'react';
import type { CategoryEntity } from 'loot-core/types/models';
import type { CategoryEntity } from '@actual-app/core/types/models';
import { DropHighlight, useDraggable, useDroppable } from '#components/sort';
import type { OnDragChangeCallback, OnDropCallback } from '#components/sort';
import { Row } from '#components/table';
import { useDragRef } from '#hooks/useDragRef';
import { RenderMonths } from './RenderMonths';
import { SidebarCategory } from './SidebarCategory';
import { useBudgetComponents } from '.';
import {
DropHighlight,
useDraggable,
useDroppable,
} from '@desktop-client/components/sort';
import type {
OnDragChangeCallback,
OnDropCallback,
} from '@desktop-client/components/sort';
import { Row } from '@desktop-client/components/table';
import { useDragRef } from '@desktop-client/hooks/useDragRef';
type IncomeCategoryProps = {
cat: CategoryEntity;
isLast?: boolean;
@@ -2,16 +2,15 @@
import React from 'react';
import { theme } from '@actual-app/components/theme';
import type { CategoryGroupEntity } from '@actual-app/core/types/models';
import type { CategoryGroupEntity } from 'loot-core/types/models';
import { Row } from '#components/table';
import { RenderMonths } from './RenderMonths';
import { SidebarGroup } from './SidebarGroup';
import { useBudgetComponents } from '.';
import { Row } from '@desktop-client/components/table';
type IncomeGroupProps = {
group: CategoryGroupEntity;
editingCell: { id: CategoryGroupEntity['id']; cell: string } | null;
@@ -4,12 +4,12 @@ import { Trans } from 'react-i18next';
import { Button } from '@actual-app/components/button';
import { View } from '@actual-app/components/view';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { RenderMonths } from './RenderMonths';
import { useBudgetComponents } from '.';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
type IncomeHeaderProps = {
onShowNewGroup: () => void;
};
@@ -11,15 +11,14 @@ import { SvgCalendar } from '@actual-app/components/icons/v2';
import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import * as monthUtils from '@actual-app/core/shared/months';
import * as monthUtils from 'loot-core/shared/months';
import { Link } from '#components/common/Link';
import { useLocale } from '#hooks/useLocale';
import { useResizeObserver } from '#hooks/useResizeObserver';
import type { MonthBounds } from './MonthsContext';
import { Link } from '@desktop-client/components/common/Link';
import { useLocale } from '@desktop-client/hooks/useLocale';
import { useResizeObserver } from '@desktop-client/hooks/useResizeObserver';
type MonthPickerProps = {
startMonth: string;
numDisplayed: number;
@@ -2,7 +2,7 @@
import React, { createContext } from 'react';
import type { ReactNode } from 'react';
import * as monthUtils from 'loot-core/shared/months';
import * as monthUtils from '@actual-app/core/shared/months';
export type MonthBounds = {
start: string;
@@ -3,13 +3,12 @@ import type { CSSProperties, ReactNode } from 'react';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import * as monthUtils from '@actual-app/core/shared/months';
import * as monthUtils from 'loot-core/shared/months';
import { SheetNameProvider } from '#hooks/useSheetName';
import { MonthsContext } from './MonthsContext';
import { SheetNameProvider } from '@desktop-client/hooks/useSheetName';
type RenderMonthsProps = {
children: ReactNode | (({ month }: { month: string }) => ReactNode);
style?: CSSProperties;
@@ -10,18 +10,17 @@ import { Popover } from '@actual-app/components/popover';
import { TextOneLine } from '@actual-app/components/text-one-line';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { InputCell } from '#components/table';
import { useContextMenu } from '#hooks/useContextMenu';
import { useGlobalPref } from '#hooks/useGlobalPref';
import { SidebarCategoryButtons } from './SidebarCategoryButtons';
import { InputCell } from '@desktop-client/components/table';
import { useContextMenu } from '@desktop-client/hooks/useContextMenu';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
type SidebarCategoryProps = {
innerRef: Ref<HTMLDivElement>;
category: CategoryEntity;
@@ -1,14 +1,13 @@
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import type { CategoryEntity } from '@actual-app/core/types/models/category';
import type { CategoryEntity } from 'loot-core/types/models/category';
import { NotesButton } from '#components/NotesButton';
import { useFeatureFlag } from '#hooks/useFeatureFlag';
import { useNotes } from '#hooks/useNotes';
import { CategoryAutomationButton } from './goals/CategoryAutomationButton';
import { NotesButton } from '@desktop-client/components/NotesButton';
import { useFeatureFlag } from '@desktop-client/hooks/useFeatureFlag';
import { useNotes } from '@desktop-client/hooks/useNotes';
type SidebarCategoryButtonsProps = {
category: CategoryEntity;
dragging: boolean;
@@ -12,18 +12,17 @@ import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { Tooltip } from '@actual-app/components/tooltip';
import { View } from '@actual-app/components/view';
import { css, cx } from '@emotion/css';
import type {
CategoryEntity,
CategoryGroupEntity,
} from 'loot-core/types/models';
} from '@actual-app/core/types/models';
import { css, cx } from '@emotion/css';
import { NotesButton } from '@desktop-client/components/NotesButton';
import { InputCell } from '@desktop-client/components/table';
import { useContextMenu } from '@desktop-client/hooks/useContextMenu';
import { useFeatureFlag } from '@desktop-client/hooks/useFeatureFlag';
import { useGlobalPref } from '@desktop-client/hooks/useGlobalPref';
import { NotesButton } from '#components/NotesButton';
import { InputCell } from '#components/table';
import { useContextMenu } from '#hooks/useContextMenu';
import { useFeatureFlag } from '#hooks/useFeatureFlag';
import { useGlobalPref } from '#hooks/useGlobalPref';
type SidebarGroupProps = {
group: CategoryGroupEntity;
@@ -4,9 +4,9 @@ import { useTranslation } from 'react-i18next';
import { Menu } from '@actual-app/components/menu';
import { useEnvelopeSheetValue } from './EnvelopeBudgetComponents';
import { envelopeBudget } from '#spreadsheet/bindings';
import { envelopeBudget } from '@desktop-client/spreadsheet/bindings';
import { useEnvelopeSheetValue } from './EnvelopeBudgetComponents';
type BalanceMenuProps = Omit<
ComponentPropsWithoutRef<typeof Menu>,
@@ -1,13 +1,13 @@
import React, { useCallback, useRef, useState } from 'react';
import { useFormat } from '#hooks/useFormat';
import { envelopeBudget } from '#spreadsheet/bindings';
import { BalanceMenu } from './BalanceMenu';
import { CoverMenu } from './CoverMenu';
import { useEnvelopeSheetValue } from './EnvelopeBudgetComponents';
import { TransferMenu } from './TransferMenu';
import { useFormat } from '@desktop-client/hooks/useFormat';
import { envelopeBudget } from '@desktop-client/spreadsheet/bindings';
type BalanceMovementMenuProps = {
categoryId: string;
month: string;
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
import { Menu } from '@actual-app/components/menu';
import { useFeatureFlag } from '@desktop-client/hooks/useFeatureFlag';
import { useFeatureFlag } from '#hooks/useFeatureFlag';
type BudgetMenuProps = Omit<
ComponentPropsWithoutRef<typeof Menu>,
@@ -6,18 +6,20 @@ import { Button } from '@actual-app/components/button';
import { Input } from '@actual-app/components/input';
import { styles } from '@actual-app/components/styles';
import { View } from '@actual-app/components/view';
import { evalArithmetic } from '@actual-app/core/shared/arithmetic';
import {
amountToInteger,
integerToCurrency,
} from '@actual-app/core/shared/util';
import type { IntegerAmount } from '@actual-app/core/shared/util';
import type { CategoryEntity } from '@actual-app/core/types/models';
import { evalArithmetic } from 'loot-core/shared/arithmetic';
import { amountToInteger, integerToCurrency } from 'loot-core/shared/util';
import type { IntegerAmount } from 'loot-core/shared/util';
import type { CategoryEntity } from 'loot-core/types/models';
import { CategoryAutocomplete } from '@desktop-client/components/autocomplete/CategoryAutocomplete';
import { CategoryAutocomplete } from '#components/autocomplete/CategoryAutocomplete';
import {
addToBeBudgetedGroup,
removeCategoriesFromGroups,
} from '@desktop-client/components/budget/util';
import { useCategories } from '@desktop-client/hooks/useCategories';
} from '#components/budget/util';
import { useCategories } from '#hooks/useCategories';
type CoverMenuProps = {
showToBeBudgeted?: boolean;
@@ -13,35 +13,30 @@ import { styles } from '@actual-app/components/styles';
import { Text } from '@actual-app/components/text';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import * as monthUtils from '@actual-app/core/shared/months';
import { css } from '@emotion/css';
import * as monthUtils from 'loot-core/shared/months';
import { BalanceWithCarryover } from '#components/budget/BalanceWithCarryover';
import { makeAmountGrey } from '#components/budget/util';
import { NotesButton } from '#components/NotesButton';
import { CellValue, CellValueText } from '#components/spreadsheet/CellValue';
import { Field, Row, SheetCell } from '#components/table';
import type { SheetCellProps } from '#components/table';
import { useCategoryScheduleGoalTemplateIndicator } from '#hooks/useCategoryScheduleGoalTemplateIndicator';
import { useContextMenu } from '#hooks/useContextMenu';
import { useFormat } from '#hooks/useFormat';
import { useNavigate } from '#hooks/useNavigate';
import { useSheetName } from '#hooks/useSheetName';
import { useSheetValue } from '#hooks/useSheetValue';
import { useUndo } from '#hooks/useUndo';
import type { Binding, SheetFields } from '#spreadsheet';
import { envelopeBudget } from '#spreadsheet/bindings';
import type { CategoryGroupMonthProps, CategoryMonthProps } from '..';
import { BalanceMovementMenu } from './BalanceMovementMenu';
import { BudgetMenu } from './BudgetMenu';
import { IncomeMenu } from './IncomeMenu';
import { BalanceWithCarryover } from '@desktop-client/components/budget/BalanceWithCarryover';
import { makeAmountGrey } from '@desktop-client/components/budget/util';
import { NotesButton } from '@desktop-client/components/NotesButton';
import {
CellValue,
CellValueText,
} from '@desktop-client/components/spreadsheet/CellValue';
import { Field, Row, SheetCell } from '@desktop-client/components/table';
import type { SheetCellProps } from '@desktop-client/components/table';
import { useCategoryScheduleGoalTemplateIndicator } from '@desktop-client/hooks/useCategoryScheduleGoalTemplateIndicator';
import { useContextMenu } from '@desktop-client/hooks/useContextMenu';
import { useFormat } from '@desktop-client/hooks/useFormat';
import { useNavigate } from '@desktop-client/hooks/useNavigate';
import { useSheetName } from '@desktop-client/hooks/useSheetName';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import { useUndo } from '@desktop-client/hooks/useUndo';
import type { Binding, SheetFields } from '@desktop-client/spreadsheet';
import { envelopeBudget } from '@desktop-client/spreadsheet/bindings';
export function useEnvelopeSheetName<
FieldName extends SheetFields<'envelope-budget'>,
>(binding: Binding<'envelope-budget', FieldName>) {
@@ -1,7 +1,7 @@
import React, { createContext, useContext } from 'react';
import type { ReactNode } from 'react';
import * as monthUtils from 'loot-core/shared/months';
import * as monthUtils from '@actual-app/core/shared/months';
type EnvelopeBudgetContextDefinition = {
summaryCollapsed: boolean;
@@ -5,11 +5,10 @@ import { Trans } from 'react-i18next';
import { Button } from '@actual-app/components/button';
import { InitialFocus } from '@actual-app/components/initial-focus';
import { View } from '@actual-app/components/view';
import type { IntegerAmount } from '@actual-app/core/shared/util';
import type { IntegerAmount } from 'loot-core/shared/util';
import { FinancialInput } from '@desktop-client/components/util/FinancialInput';
import { useSheetValue } from '@desktop-client/hooks/useSheetValue';
import { FinancialInput } from '#components/util/FinancialInput';
import { useSheetValue } from '#hooks/useSheetValue';
type HoldMenuProps = {
onSubmit: (amount: number) => void;
@@ -1,13 +1,12 @@
import { useTranslation } from 'react-i18next';
import { Menu } from '@actual-app/components/menu';
import type { CategoryEntity } from '@actual-app/core/types/models';
import type { CategoryEntity } from 'loot-core/types/models';
import { envelopeBudget } from '#spreadsheet/bindings';
import { useEnvelopeSheetValue } from './EnvelopeBudgetComponents';
import { envelopeBudget } from '@desktop-client/spreadsheet/bindings';
type IncomeMenuProps = {
categoryId: string;
month: string;
@@ -5,17 +5,16 @@ import { Trans } from 'react-i18next';
import { Button } from '@actual-app/components/button';
import { InitialFocus } from '@actual-app/components/initial-focus';
import { View } from '@actual-app/components/view';
import type { IntegerAmount } from '@actual-app/core/shared/util';
import type { CategoryEntity } from '@actual-app/core/types/models';
import type { IntegerAmount } from 'loot-core/shared/util';
import type { CategoryEntity } from 'loot-core/types/models';
import { CategoryAutocomplete } from '@desktop-client/components/autocomplete/CategoryAutocomplete';
import { CategoryAutocomplete } from '#components/autocomplete/CategoryAutocomplete';
import {
addToBeBudgetedGroup,
removeCategoriesFromGroups,
} from '@desktop-client/components/budget/util';
import { FinancialInput } from '@desktop-client/components/util/FinancialInput';
import { useCategories } from '@desktop-client/hooks/useCategories';
} from '#components/budget/util';
import { FinancialInput } from '#components/util/FinancialInput';
import { useCategories } from '#hooks/useCategories';
type TransferMenuProps = {
categoryId?: CategoryEntity['id'];
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next';
import { Menu } from '@actual-app/components/menu';
import { useFeatureFlag } from '@desktop-client/hooks/useFeatureFlag';
import { useFeatureFlag } from '#hooks/useFeatureFlag';
type BudgetMonthMenuProps = Omit<
ComponentPropsWithoutRef<typeof Menu>,
@@ -11,20 +11,19 @@ import { Popover } from '@actual-app/components/popover';
import { styles } from '@actual-app/components/styles';
import { theme } from '@actual-app/components/theme';
import { View } from '@actual-app/components/view';
import * as monthUtils from '@actual-app/core/shared/months';
import { css } from '@emotion/css';
import * as monthUtils from 'loot-core/shared/months';
import { useEnvelopeBudget } from '#components/budget/envelope/EnvelopeBudgetContext';
import { NotesButton } from '#components/NotesButton';
import { useLocale } from '#hooks/useLocale';
import { SheetNameProvider } from '#hooks/useSheetName';
import { useUndo } from '#hooks/useUndo';
import { BudgetMonthMenu } from './BudgetMonthMenu';
import { ToBudget } from './ToBudget';
import { TotalsList } from './TotalsList';
import { useEnvelopeBudget } from '@desktop-client/components/budget/envelope/EnvelopeBudgetContext';
import { NotesButton } from '@desktop-client/components/NotesButton';
import { useLocale } from '@desktop-client/hooks/useLocale';
import { SheetNameProvider } from '@desktop-client/hooks/useSheetName';
import { useUndo } from '@desktop-client/hooks/useUndo';
type BudgetSummaryProps = {
month: string;
};
@@ -4,17 +4,17 @@ import type { CSSProperties } from 'react';
import { Popover } from '@actual-app/components/popover';
import { View } from '@actual-app/components/view';
import { CoverMenu } from '#components/budget/envelope/CoverMenu';
import { useEnvelopeSheetValue } from '#components/budget/envelope/EnvelopeBudgetComponents';
import { HoldMenu } from '#components/budget/envelope/HoldMenu';
import { TransferMenu } from '#components/budget/envelope/TransferMenu';
import { useContextMenu } from '#hooks/useContextMenu';
import { useFormat } from '#hooks/useFormat';
import { envelopeBudget } from '#spreadsheet/bindings';
import { ToBudgetAmount } from './ToBudgetAmount';
import { ToBudgetMenu } from './ToBudgetMenu';
import { CoverMenu } from '@desktop-client/components/budget/envelope/CoverMenu';
import { useEnvelopeSheetValue } from '@desktop-client/components/budget/envelope/EnvelopeBudgetComponents';
import { HoldMenu } from '@desktop-client/components/budget/envelope/HoldMenu';
import { TransferMenu } from '@desktop-client/components/budget/envelope/TransferMenu';
import { useContextMenu } from '@desktop-client/hooks/useContextMenu';
import { useFormat } from '@desktop-client/hooks/useFormat';
import { envelopeBudget } from '@desktop-client/spreadsheet/bindings';
type ToBudgetProps = {
month: string;
onBudgetAction: (month: string, action: string, arg?: unknown) => void;
@@ -9,16 +9,16 @@ import { Tooltip } from '@actual-app/components/tooltip';
import { View } from '@actual-app/components/view';
import { css } from '@emotion/css';
import { TotalsList } from './TotalsList';
import {
useEnvelopeSheetName,
useEnvelopeSheetValue,
} from '@desktop-client/components/budget/envelope/EnvelopeBudgetComponents';
import { FinancialText } from '@desktop-client/components/FinancialText';
import { PrivacyFilter } from '@desktop-client/components/PrivacyFilter';
import { useFormat } from '@desktop-client/hooks/useFormat';
import { envelopeBudget } from '@desktop-client/spreadsheet/bindings';
} from '#components/budget/envelope/EnvelopeBudgetComponents';
import { FinancialText } from '#components/FinancialText';
import { PrivacyFilter } from '#components/PrivacyFilter';
import { useFormat } from '#hooks/useFormat';
import { envelopeBudget } from '#spreadsheet/bindings';
import { TotalsList } from './TotalsList';
type ToBudgetAmountProps = {
prevMonthName: string;
@@ -4,8 +4,8 @@ import { useTranslation } from 'react-i18next';
import { Menu } from '@actual-app/components/menu';
import { useEnvelopeSheetValue } from '@desktop-client/components/budget/envelope/EnvelopeBudgetComponents';
import { envelopeBudget } from '@desktop-client/spreadsheet/bindings';
import { useEnvelopeSheetValue } from '#components/budget/envelope/EnvelopeBudgetComponents';
import { envelopeBudget } from '#spreadsheet/bindings';
type ToBudgetMenuProps = Omit<
ComponentPropsWithoutRef<typeof Menu>,
@@ -8,11 +8,11 @@ import { styles } from '@actual-app/components/styles';
import { Tooltip } from '@actual-app/components/tooltip';
import { View } from '@actual-app/components/view';
import { EnvelopeCellValue } from '@desktop-client/components/budget/envelope/EnvelopeBudgetComponents';
import { CellValueText } from '@desktop-client/components/spreadsheet/CellValue';
import { useFormat } from '@desktop-client/hooks/useFormat';
import type { FormatType } from '@desktop-client/hooks/useFormat';
import { envelopeBudget } from '@desktop-client/spreadsheet/bindings';
import { EnvelopeCellValue } from '#components/budget/envelope/EnvelopeBudgetComponents';
import { CellValueText } from '#components/spreadsheet/CellValue';
import { useFormat } from '#hooks/useFormat';
import type { FormatType } from '#hooks/useFormat';
import { envelopeBudget } from '#spreadsheet/bindings';
/**
* Creates a formatter that displays values with explicit +/- signs.

Some files were not shown because too many files have changed in this diff Show More