FEAT: Moving library

This commit is contained in:
valerio 2026-03-09 21:12:20 +01:00
parent 92732c20c9
commit 132b1ccee7
2 changed files with 130 additions and 4 deletions

View File

@ -1,5 +1,103 @@
<script> <script>
import { join } from '@tauri-apps/api/path';
import { saveSettings, selectDirectory, BASE_LIBRARY_DIR } from '$lib/settings.js';
import { movePath, directoryExists, copyPath } from '$lib/file_utils.js';
import { remove } from '@tauri-apps/plugin-fs';
import { confirm } from '@tauri-apps/plugin-dialog';
import { getInstalledVersions, removeAllDesktopFilesForVersions } from '$lib/library.js';
import Button from '$lib/components/Button.svelte';
let { settings } = $props(); let { settings } = $props();
let changing = $state(false);
let error = $state(null);
async function changeLibraryDirectory() {
changing = true;
error = null;
try {
const newDir = await selectDirectory(settings.libraryDir);
if (!newDir) {
return;
}
if (newDir === settings.libraryDir) {
return;
}
const currentLibraryPath = await join(settings.libraryDir, BASE_LIBRARY_DIR);
const newLibraryPath = await join(newDir, BASE_LIBRARY_DIR);
// Prevent moving library into itself or circular moves
if (
newLibraryPath.startsWith(currentLibraryPath + '/') ||
currentLibraryPath.startsWith(newLibraryPath + '/')
) {
error = 'Cannot move library into itself or a subdirectory of itself';
return;
}
// Check if the current library directory exists and has content
const currentExists = await directoryExists(currentLibraryPath);
const newExists = await directoryExists(newLibraryPath);
let moveLibrary = false;
if (currentExists) {
let message = `Move existing library from\n${currentLibraryPath}\nto\n${newLibraryPath}?`;
if (newExists) {
message = `Library already exists at new location:\n${newLibraryPath}\n\nMoving will replace it. Continue?`;
}
moveLibrary = await confirm(message, {
title: 'Move Library',
kind: 'warning'
});
}
if (moveLibrary) {
// Get current installed versions before moving (to track desktop files)
const currentVersions = await getInstalledVersions();
// Remove .desktop files for all current versions (Linux only)
await removeAllDesktopFilesForVersions(currentVersions);
// If destination exists, remove it first (movePath requires destination not to exist)
if (newExists) {
try {
await remove(newLibraryPath, { recursive: true });
} catch (err) {
error = `Failed to remove existing directory: ${err.message}`;
console.error(error);
return;
}
}
// Move the entire library directory recursively
try {
await movePath(currentLibraryPath, newLibraryPath);
} catch (moveError) {
// If move fails (e.g., cross-device), fallback to copy + delete
console.warn('Move failed, falling back to copy:', moveError);
await copyPath(currentLibraryPath, newLibraryPath);
try {
await remove(currentLibraryPath, { recursive: true });
} catch (deleteError) {
console.warn('Failed to delete original library after copy:', deleteError);
// Continue anyway - library has been copied to new location
}
}
}
// Update settings with the new directory
await saveSettings({ libraryDir: newDir });
// Refresh installed versions to reflect new location (will recreate desktop files if autoCreateShortcuts is enabled)
await getInstalledVersions();
} catch (err) {
error = `Failed to change library directory: ${err.message}`;
console.error(error);
} finally {
changing = false;
}
}
</script> </script>
<div>Settings</div> <div>Settings</div>
@ -8,13 +106,28 @@
<div>Platform: {settings.defaultPlatform}</div> <div>Platform: {settings.defaultPlatform}</div>
<div>Architecture: {settings.defaultArch}</div> <div>Architecture: {settings.defaultArch}</div>
<div>Keep Archives: {settings.keepDownloadedArchives}</div> <div>Keep Archives: {settings.keepDownloadedArchives}</div>
<div>Library: {settings.libraryDir}/Smoothie Library</div> <div>Library: {settings.libraryDir}/{BASE_LIBRARY_DIR}</div>
<Button onclick={changeLibraryDirectory} disabled={changing} color="accent">
{#if changing}
Changing...
{:else}
Change Library Directory
{/if}
</Button>
{#if error}
<div style="color: red; margin-top: 0.5rem;">Error: {error}</div>
{/if}
</div> </div>
<style> <style>
#container { .container {
overflow-y: scroll; overflow-y: scroll;
max-height: 100%; max-height: 100%;
box-sizing: border-box; box-sizing: border-box;
} }
.container :global(.btn) {
margin-top: 1rem;
}
</style> </style>

View File

@ -116,6 +116,21 @@ export async function removeDesktopFile(version) {
} }
} }
/**
* Remove all .desktop files for the given versions (Linux only).
* @param {blenderVersion[]} versions
*/
export async function removeAllDesktopFilesForVersions(versions) {
const currentPlatform = await platform();
if (currentPlatform !== 'linux') {
return;
}
for (const version of versions) {
await removeDesktopFile(version);
}
}
/** /**
* Create a .desktop file for a Blender version (Linux only). * Create a .desktop file for a Blender version (Linux only).
* @param {blenderVersion} version * @param {blenderVersion} version
@ -250,8 +265,6 @@ export async function getInstalledVersions() {
// Filter out non-directory entries // Filter out non-directory entries
for (const entry of entries) { for (const entry of entries) {
if (!entry.isDirectory) { if (!entry.isDirectory) {
const filePath = await join(blenderLibraryPath, entry.name);
//await remove(filePath);
continue; continue;
} }