mirror of
https://github.com/actualbudget/actual.git
synced 2026-07-24 08:55:09 -05:00
* [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) <noreply@anthropic.com> * [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) <noreply@anthropic.com> * 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) <noreply@anthropic.com> * [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) <noreply@anthropic.com> * [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) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
93 lines
2.7 KiB
TypeScript
93 lines
2.7 KiB
TypeScript
import { send } from '@actual-app/core/platform/client/connection';
|
|
import type { Handlers } from '@actual-app/core/types/handlers';
|
|
import { createSlice } from '@reduxjs/toolkit';
|
|
import type { PayloadAction } from '@reduxjs/toolkit';
|
|
|
|
import { resetApp } from '#app/appSlice';
|
|
import { closeBudget, loadAllFiles } from '#budgetfiles/budgetfilesSlice';
|
|
import { loadGlobalPrefs } from '#prefs/prefsSlice';
|
|
import { createAppAsyncThunk } from '#redux';
|
|
|
|
const sliceName = 'user';
|
|
|
|
export const getUserData = createAppAsyncThunk(
|
|
`${sliceName}/getUserData`,
|
|
async (_, { dispatch }) => {
|
|
const data = await send('subscribe-get-user');
|
|
dispatch(loadUserData({ data }));
|
|
return data;
|
|
},
|
|
);
|
|
|
|
export const loggedIn = createAppAsyncThunk(
|
|
`${sliceName}/loggedIn`,
|
|
async (_, { dispatch }) => {
|
|
await dispatch(getUserData());
|
|
|
|
// We want to be careful about how we call loadAllFiles. It will
|
|
// turn the files state from null into an array, indicating that
|
|
// we've loaded the files at least once. This first attempt at
|
|
// loading files is important - the manager uses files to decide
|
|
// if it should create a new file automatically (if there are no
|
|
// files). If we call it before we have a properly logged in
|
|
// user, later on it could trigger the codepath which
|
|
// automatically creates a file, but we really haven't loaded
|
|
// their files yet.
|
|
//
|
|
// Since the above comment was written, We let in users even if
|
|
// their account is invalid. So we should list all their files
|
|
// regardless. Previously, we kicked users out to a "need payment
|
|
// info" screen and we didn't want to call this.
|
|
void dispatch(loadAllFiles());
|
|
},
|
|
);
|
|
|
|
export const signOut = createAppAsyncThunk(
|
|
`${sliceName}/signOut`,
|
|
async (_, { dispatch }) => {
|
|
await send('subscribe-sign-out');
|
|
|
|
void dispatch(getUserData());
|
|
void dispatch(loadGlobalPrefs());
|
|
void dispatch(closeBudget());
|
|
// Handled in budgetSlice
|
|
// dispatch({ type: constants.SIGN_OUT });
|
|
},
|
|
);
|
|
|
|
type UsersState = {
|
|
data: Awaited<ReturnType<Handlers['subscribe-get-user']>> | null;
|
|
};
|
|
|
|
const initialState: UsersState = {
|
|
data: null,
|
|
};
|
|
|
|
type GetUserDataPayload = {
|
|
data: UsersState['data'];
|
|
};
|
|
|
|
const usersSlice = createSlice({
|
|
name: sliceName,
|
|
initialState,
|
|
reducers: {
|
|
loadUserData(state, action: PayloadAction<GetUserDataPayload>) {
|
|
state.data = action.payload.data;
|
|
},
|
|
},
|
|
extraReducers: builder => {
|
|
builder.addCase(resetApp, state => state || initialState);
|
|
},
|
|
});
|
|
|
|
export const { name, reducer, getInitialState } = usersSlice;
|
|
|
|
export const actions = {
|
|
...usersSlice.actions,
|
|
getUserData,
|
|
loggedIn,
|
|
signOut,
|
|
};
|
|
|
|
export const { loadUserData } = actions;
|