import { LazyStore } from '@tauri-apps/plugin-store'; import { writable, get } from 'svelte/store'; import { platform, arch } from '@tauri-apps/plugin-os'; import { appDataDir } from '@tauri-apps/api/path'; import { ensureLibraryStructure, selectDirectory } from './file_utils.js'; // Define the settings structure /** @typedef {Object} Settings * @property {string} [libraryDir] - Path to library directory * @property {string} [defaultPlatform] - Default platform ('auto', 'windows', 'linux', 'macos') * @property {string} [defaultArch] - Default architecture ('x86_64', 'arm64', etc.) * @property {string} [theme] - Theme ('light', 'dark') * @property {boolean} [autoCreateShortcuts] - should smoothie create a shortcut to newly installed blender versions * @property {boolean} [keepDownloadedArchives] - Whether to keep downloaded archives after extraction */ // Settings lazy store const settingsStore = new LazyStore('settings.json'); export const currentSettings = writable(/** @type {Settings} */ ({})); export const BASE_LIBRARY_DIR = 'smoothie-library'; let DEFAULT_SETTINGS = null; export async function initSettings() { const detectedPlatform = await detectPlatform(); const detectedArch = await detectArch(); const defaultLibraryDir = await appDataDir(); DEFAULT_SETTINGS = { libraryDir: defaultLibraryDir, // Will be filled with default library directory defaultPlatform: detectedPlatform, //Automatic defaultArch: detectedArch, keepDownloadedArchives: false, autoCreateShortcuts: true, theme: 'light' // }; } /** * Get the current settings, filling with defaults if missing. * @returns {Promise} */ export async function getSettings() { if (DEFAULT_SETTINGS === null) { await initSettings(); } try { // Get all stored values const storeEntries = await settingsStore.entries(); // Store empty, load defaults if (storeEntries.length === 0) { await resetSettings(); } //load settings object and patch with defaults for missing fields const settings = Object.fromEntries(storeEntries); const filledSettings = { ...DEFAULT_SETTINGS, ...settings }; currentSettings.set(filledSettings); await ensureLibraryStructure(filledSettings.libraryDir); return filledSettings; } catch (error) { console.error('Error loading settings:', error); currentSettings.set(DEFAULT_SETTINGS); return DEFAULT_SETTINGS; } } /** * @typedef {Partial} PartialSettings */ export async function saveSettings(newSettings) { try { for (const [key, value] of Object.entries(newSettings)) { await settingsStore.set(key, value); } if (newSettings.libraryDir) { //if new library dir check it await ensureLibraryStructure(newSettings.libraryDir); } await settingsStore.save(); let completeSettings = { ...get(currentSettings), ...newSettings }; currentSettings.set(completeSettings); } catch (error) { console.error('Error saving settings:', error); throw error; } } /** * Clear store and reset all settings to defaults. * @returns {Promise} */ export async function resetSettings() { try { await settingsStore.clear(); await saveSettings(DEFAULT_SETTINGS); return DEFAULT_SETTINGS; } catch (error) { console.error('Error resetting settings:', error); throw error; } } /** * Detect the current platform, mapping to our supported values. * @returns {Promise} 'windows', 'linux', or 'macos' */ async function detectPlatform() { try { const currentPlatform = platform(); // Map from OS plugin values to our settings values (desktop only) const platformMap = { linux: 'linux', windows: 'windows', darwin: 'macos', macos: 'macos' }; // Only desktop platforms are supported if (currentPlatform in platformMap) { return currentPlatform; } console.warn(`Platform "${currentPlatform}" is not supported, defaulting to linux`); return 'linux'; } catch (error) { console.error('Error detecting platform:', error); return 'linux'; // fallback } } /** * Detect the current platform, mapping to our supported values. * @returns {Promise} 'windows', 'linux', or 'macos' */ async function detectArch() { try { const currentArch = arch(); const archmap = { x86_64: 'x64', arm: 'arm64', aarch64: 'arm64' }; if (currentArch in archmap) { return currentArch; } console.warn(`Architecture "${currentArch}" is not supported, defaulting to x64`); return 'x64'; } catch (error) { console.error('Error detecting platform:', error); return 'linux'; // fallback } } export { selectDirectory };