feat(release): add cross-platform packaging

Add target-aware engine provisioning, platform package configs, and CI/release verification for macOS arm64, Windows x64, and Linux AppImage.
This commit is contained in:
NimBold
2026-06-23 21:26:51 +03:30
parent 0e3118ec2c
commit f603b74a99
41 changed files with 1889 additions and 382 deletions
+23 -1
View File
@@ -74,6 +74,7 @@ export interface SettingsState {
baseDownloadFolder: string;
categorySubfolders: Record<string, string>;
categoryDirectoryOverrides: Record<string, string>;
approvedDownloadRoots: string[];
maxConcurrentDownloads: number;
globalSpeedLimit: string;
isSidebarVisible: boolean;
@@ -108,6 +109,7 @@ export interface SettingsState {
setTheme: (theme: Theme) => void;
setBaseDownloadFolder: (path: string) => void;
approveDownloadRoot: (path: string) => Promise<string>;
setMaxConcurrentDownloads: (count: number) => void;
setGlobalSpeedLimit: (limit: string) => void;
setActiveView: (view: ActiveView) => void;
@@ -178,6 +180,7 @@ export const useSettingsStore = create<SettingsState>()(
baseDownloadFolder: '~/Downloads',
categorySubfolders: { ...DEFAULT_CATEGORY_SUBFOLDERS },
categoryDirectoryOverrides: {},
approvedDownloadRoots: [],
maxConcurrentDownloads: 3,
globalSpeedLimit: '',
activeView: 'downloads',
@@ -224,6 +227,15 @@ export const useSettingsStore = create<SettingsState>()(
info('Settings updated: baseDownloadFolder');
set({ baseDownloadFolder: path });
},
approveDownloadRoot: async (path) => {
const approvedPath = await invoke('approve_download_root', { path });
set(state => ({
approvedDownloadRoots: state.approvedDownloadRoots.includes(approvedPath)
? state.approvedDownloadRoots
: [...state.approvedDownloadRoots, approvedPath]
}));
return approvedPath;
},
setMaxConcurrentDownloads: (max) => {
info('Settings updated: maxConcurrentDownloads');
set({ maxConcurrentDownloads: max });
@@ -299,6 +311,9 @@ export const useSettingsStore = create<SettingsState>()(
hydratePairingToken: async () => {
const result = await invoke('hydrate_extension_pairing_token');
set({ extensionPairingToken: result.token });
if (!result.persistent && result.error) {
throw new Error(`Session-only browser pairing token: ${result.error}`);
}
return result.tokenChanged;
},
setAutoCheckUpdates: (autoCheckUpdates) => set({ autoCheckUpdates }),
@@ -330,7 +345,10 @@ export const useSettingsStore = create<SettingsState>()(
: [DEFAULT_SCHEDULER_QUEUE_ID]
}
: persisted.scheduler,
siteLogins: Array.isArray(persisted.siteLogins) ? persisted.siteLogins : []
siteLogins: Array.isArray(persisted.siteLogins) ? persisted.siteLogins : [],
approvedDownloadRoots: Array.isArray(persisted.approvedDownloadRoots)
? persisted.approvedDownloadRoots
: []
} as SettingsState;
},
partialize: (state): PersistedSettings => ({
@@ -338,6 +356,7 @@ export const useSettingsStore = create<SettingsState>()(
baseDownloadFolder: state.baseDownloadFolder,
categorySubfolders: state.categorySubfolders,
categoryDirectoryOverrides: state.categoryDirectoryOverrides,
approvedDownloadRoots: state.approvedDownloadRoots,
maxConcurrentDownloads: state.maxConcurrentDownloads,
globalSpeedLimit: state.globalSpeedLimit,
isSidebarVisible: state.isSidebarVisible,
@@ -376,6 +395,9 @@ export const useSettingsStore = create<SettingsState>()(
...currentState,
...persisted,
...locations,
approvedDownloadRoots: Array.isArray(persisted.approvedDownloadRoots)
? persisted.approvedDownloadRoots
: currentState.approvedDownloadRoots,
scheduler: {
...currentState.scheduler,
...persisted.scheduler,