FEAT: Custom dialog and popup
FEAT: Set as Default and Delete
This commit is contained in:
parent
b9b6bd1490
commit
3a9f5566b2
324
src/lib/components/Dialog.svelte
Normal file
324
src/lib/components/Dialog.svelte
Normal file
@ -0,0 +1,324 @@
|
|||||||
|
<script module>
|
||||||
|
// Store for managing dialog state
|
||||||
|
export let dialogStore = $state({
|
||||||
|
open: false,
|
||||||
|
title: 'Dialog',
|
||||||
|
message: '',
|
||||||
|
buttons: ['OK', 'Cancel'],
|
||||||
|
type: 'confirm',
|
||||||
|
resolve: null
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a dialog and return a promise that resolves with the clicked button text
|
||||||
|
* @param {Object} options
|
||||||
|
* @param {string} [options.title='Dialog']
|
||||||
|
* @param {string} [options.message='']
|
||||||
|
* @param {string[]} [options.buttons=['OK', 'Cancel']]
|
||||||
|
* @param {'confirm'|'warning'|'error'|'info'} [options.type='confirm']
|
||||||
|
* @returns {Promise<string|null>} Button text or null if dismissed
|
||||||
|
*/
|
||||||
|
export function show(options = {}) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
// Close any existing dialog
|
||||||
|
if (dialogStore.resolve) {
|
||||||
|
dialogStore.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialogStore.open = true;
|
||||||
|
dialogStore.title = options.title || 'Dialog';
|
||||||
|
dialogStore.message = options.message || '';
|
||||||
|
dialogStore.buttons = options.buttons || ['OK', 'Cancel'];
|
||||||
|
dialogStore.type = options.type || 'confirm';
|
||||||
|
dialogStore.resolve = resolve;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the current dialog with a result
|
||||||
|
* @param {string|null} result
|
||||||
|
*/
|
||||||
|
export function closeDialog(result = null) {
|
||||||
|
if (dialogStore.resolve) {
|
||||||
|
dialogStore.resolve(result);
|
||||||
|
}
|
||||||
|
dialogStore.open = false;
|
||||||
|
dialogStore.resolve = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convenience methods for common dialog types
|
||||||
|
export const dialogs = {
|
||||||
|
/** Show a confirmation dialog */
|
||||||
|
confirm: (message, title = 'Confirm') =>
|
||||||
|
show({ title, message, buttons: ['Confirm', 'Cancel'], type: 'confirm' }).then(
|
||||||
|
(result) => result === 'Confirm'
|
||||||
|
),
|
||||||
|
|
||||||
|
/** Show a warning dialog */
|
||||||
|
warning: (message, title = 'Warning') =>
|
||||||
|
show({ title, message, buttons: ['Continue', 'Cancel'], type: 'warning' }).then(
|
||||||
|
(result) => result === 'Continue'
|
||||||
|
),
|
||||||
|
|
||||||
|
/** Show an error dialog */
|
||||||
|
error: (message, title = 'Error') =>
|
||||||
|
show({ title, message, buttons: ['OK'], type: 'error' }).then(() => {}),
|
||||||
|
|
||||||
|
/** Show an info dialog */
|
||||||
|
info: (message, title = 'Information') =>
|
||||||
|
show({ title, message, buttons: ['OK'], type: 'info' }).then(() => {})
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { onMount, onDestroy } from 'svelte';
|
||||||
|
import { fly, fade } from 'svelte/transition';
|
||||||
|
import Button from '$lib/components/Button.svelte';
|
||||||
|
|
||||||
|
// Props for declarative usage
|
||||||
|
let {
|
||||||
|
open = false,
|
||||||
|
title = 'Dialog',
|
||||||
|
message = '',
|
||||||
|
buttons = ['OK', 'Cancel'],
|
||||||
|
type = 'confirm',
|
||||||
|
onresult = null // callback function
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
// Determine if we're using imperative mode (via store)
|
||||||
|
let usingStore = $state(false);
|
||||||
|
let dialogRef = $state(null);
|
||||||
|
|
||||||
|
// Module store is accessible via module exports
|
||||||
|
// dialogStore and closeDialog are defined in module script
|
||||||
|
|
||||||
|
// Computed state based on mode
|
||||||
|
const currentOpen = $derived(usingStore ? dialogStore.open : open);
|
||||||
|
const currentTitle = $derived(usingStore ? dialogStore.title : title);
|
||||||
|
const currentMessage = $derived(usingStore ? dialogStore.message : message);
|
||||||
|
const currentButtons = $derived(usingStore ? dialogStore.buttons : buttons);
|
||||||
|
const currentType = $derived(usingStore ? dialogStore.type : type);
|
||||||
|
|
||||||
|
// Switch to store mode when store dialog opens
|
||||||
|
$effect(() => {
|
||||||
|
if (dialogStore.open && !open) {
|
||||||
|
usingStore = true;
|
||||||
|
} else if (!dialogStore.open && usingStore) {
|
||||||
|
// Delay reset to allow animations
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!dialogStore.open) {
|
||||||
|
usingStore = false;
|
||||||
|
}
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function handleButtonClick(button) {
|
||||||
|
if (usingStore) {
|
||||||
|
closeDialog(button);
|
||||||
|
} else {
|
||||||
|
open = false;
|
||||||
|
// Call result callback for declarative usage
|
||||||
|
onresult?.(button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleClose() {
|
||||||
|
if (usingStore) {
|
||||||
|
closeDialog(null);
|
||||||
|
} else {
|
||||||
|
open = false;
|
||||||
|
onresult?.(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleKeydown(event) {
|
||||||
|
if (event.key === 'Escape') {
|
||||||
|
event.preventDefault();
|
||||||
|
handleClose();
|
||||||
|
} else if (event.key === 'Enter' && currentButtons.length > 0) {
|
||||||
|
// Enter triggers the first button
|
||||||
|
handleButtonClick(currentButtons[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBackdropClick(event) {
|
||||||
|
if (event.target === event.currentTarget) {
|
||||||
|
handleClose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manage keyboard listeners
|
||||||
|
onMount(() => {
|
||||||
|
if (currentOpen) {
|
||||||
|
document.addEventListener('keydown', handleKeydown);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
document.removeEventListener('keydown', handleKeydown);
|
||||||
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (currentOpen) {
|
||||||
|
document.addEventListener('keydown', handleKeydown);
|
||||||
|
// Focus dialog for keyboard navigation
|
||||||
|
setTimeout(() => {
|
||||||
|
if (dialogRef) {
|
||||||
|
dialogRef.focus();
|
||||||
|
}
|
||||||
|
}, 10);
|
||||||
|
} else {
|
||||||
|
document.removeEventListener('keydown', handleKeydown);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Helper to determine button style based on text and dialog type
|
||||||
|
function getButtonStyle(buttonText) {
|
||||||
|
const lower = buttonText.toLowerCase();
|
||||||
|
if (lower.includes('cancel') || lower.includes('no') || lower.includes('dismiss')) {
|
||||||
|
return 'black';
|
||||||
|
}
|
||||||
|
if (currentType === 'warning' || currentType === 'error' || currentType === 'info') {
|
||||||
|
if (
|
||||||
|
lower.includes('ok') ||
|
||||||
|
lower.includes('yes') ||
|
||||||
|
lower.includes('confirm') ||
|
||||||
|
lower.includes('continue')
|
||||||
|
) {
|
||||||
|
return 'accent';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (currentType === 'confirm') {
|
||||||
|
if (lower.includes('ok') || lower.includes('yes') || lower.includes('confirm')) {
|
||||||
|
return 'accent';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 'black';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if currentOpen}
|
||||||
|
<div
|
||||||
|
class="dialog-backdrop"
|
||||||
|
in:fade={{ duration: 150 }}
|
||||||
|
out:fade={{ duration: 150 }}
|
||||||
|
onclick={handleBackdropClick}
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="dialog-container"
|
||||||
|
in:fly={{ duration: 200, y: 20 }}
|
||||||
|
out:fade={{ duration: 150 }}
|
||||||
|
bind:this={dialogRef}
|
||||||
|
tabindex="-1"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="dialog-title"
|
||||||
|
aria-describedby="dialog-message"
|
||||||
|
>
|
||||||
|
<div class="dialog-header">
|
||||||
|
<h3 id="dialog-title" class="dialog-title">{currentTitle}</h3>
|
||||||
|
<div class="dialog-type-indicator {currentType}"></div>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-content">
|
||||||
|
<p id="dialog-message" class="dialog-content-text">{currentMessage}</p>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-actions">
|
||||||
|
{#each currentButtons as button (button)}
|
||||||
|
<Button style={getButtonStyle(button)} onclick={() => handleButtonClick(button)}>
|
||||||
|
{button}
|
||||||
|
</Button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.dialog-backdrop {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
background-color: rgba(0, 0, 0, 0.5);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-container {
|
||||||
|
background-color: var(--light);
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
min-width: 300px;
|
||||||
|
max-width: 500px;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
outline: none;
|
||||||
|
border: 2px solid var(--);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 1rem;
|
||||||
|
padding-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-title {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--black);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-type-indicator {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-type-indicator.confirm {
|
||||||
|
background-color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-type-indicator.warning {
|
||||||
|
background-color: var(--warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-type-indicator.error {
|
||||||
|
background-color: var(--error);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-type-indicator.info {
|
||||||
|
background-color: var(--warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-content {
|
||||||
|
flex: 1;
|
||||||
|
color: var(--black);
|
||||||
|
line-height: 1.5;
|
||||||
|
max-height: 50vh;
|
||||||
|
overflow-y: auto;
|
||||||
|
padding: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-content p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialog-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 0.75rem;
|
||||||
|
padding-top: 0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
38
src/lib/components/Popup.svelte
Normal file
38
src/lib/components/Popup.svelte
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<script>
|
||||||
|
import { fade, fly } from 'svelte/transition';
|
||||||
|
|
||||||
|
let { content = '', type = 'confirm' } = $props();
|
||||||
|
let open = $state(false);
|
||||||
|
|
||||||
|
export function pop(resetTimeout = 0) {
|
||||||
|
open = true;
|
||||||
|
if (resetTimeout > 0) {
|
||||||
|
setTimeout(() => {
|
||||||
|
open = false;
|
||||||
|
}, resetTimeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if open}
|
||||||
|
<div in:fly={{ duration: 200, y: 100 }} out:fade class="popup {type}">
|
||||||
|
<div class="popup-content">
|
||||||
|
<p>{content}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.popup {
|
||||||
|
position: fixed;
|
||||||
|
width: 20rem;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 2rem;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
border-radius: 0.1rem;
|
||||||
|
}
|
||||||
|
.confirm {
|
||||||
|
background-color: var(--light-accent);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -3,6 +3,7 @@
|
|||||||
import Progress from '$lib/components/Progress.svelte';
|
import Progress from '$lib/components/Progress.svelte';
|
||||||
import { downloadBlenderVersion } from '$lib/download.js';
|
import { downloadBlenderVersion } from '$lib/download.js';
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
|
import Popup from '$lib/components/Popup.svelte';
|
||||||
|
|
||||||
let { release, installedVersions = [], downloadTasks } = $props();
|
let { release, installedVersions = [], downloadTasks } = $props();
|
||||||
let linkIndex = $state(0);
|
let linkIndex = $state(0);
|
||||||
@ -10,6 +11,13 @@
|
|||||||
|
|
||||||
let installed = $derived(installedVersions.some((v) => v.version === selectedLink.version));
|
let installed = $derived(installedVersions.some((v) => v.version === selectedLink.version));
|
||||||
|
|
||||||
|
async function handleDownload() {
|
||||||
|
let result = await downloadBlenderVersion(selectedLink);
|
||||||
|
if (result.success) {
|
||||||
|
popup?.pop(2000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let percent = $derived(
|
let percent = $derived(
|
||||||
downloadTasks.find((task) => task.version === selectedLink.version)?.percent ?? 0
|
downloadTasks.find((task) => task.version === selectedLink.version)?.percent ?? 0
|
||||||
);
|
);
|
||||||
@ -18,8 +26,11 @@
|
|||||||
onMount(() => {
|
onMount(() => {
|
||||||
linkIndex = release.links.length - 1;
|
linkIndex = release.links.length - 1;
|
||||||
});
|
});
|
||||||
|
let popup = $state();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Popup bind:this={popup} content={'Blender ' + selectedLink.version + ' has been installed'}
|
||||||
|
></Popup>
|
||||||
<div class="download" class:full-width={downloading || installed}>
|
<div class="download" class:full-width={downloading || installed}>
|
||||||
<div class="selectVersion {downloading}">
|
<div class="selectVersion {downloading}">
|
||||||
<select class:disabled={downloading && !installed} bind:value={linkIndex}>
|
<select class:disabled={downloading && !installed} bind:value={linkIndex}>
|
||||||
@ -37,8 +48,11 @@
|
|||||||
disabled={installed}
|
disabled={installed}
|
||||||
color={downloading ? 'accent' : 'black'}
|
color={downloading ? 'accent' : 'black'}
|
||||||
onclick={() => {
|
onclick={() => {
|
||||||
downloadBlenderVersion(selectedLink);
|
if (downloading) {
|
||||||
downloading = !downloading;
|
return;
|
||||||
|
}
|
||||||
|
downloading = true;
|
||||||
|
handleDownload();
|
||||||
}}>{installed ? 'Installed' : downloading ? 'Cancel' : 'Download'}</Button
|
}}>{installed ? 'Installed' : downloading ? 'Cancel' : 'Download'}</Button
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -6,6 +6,7 @@
|
|||||||
import { confirm } from '@tauri-apps/plugin-dialog';
|
import { confirm } from '@tauri-apps/plugin-dialog';
|
||||||
import { getInstalledVersions, removeAllDesktopFilesForVersions } from '$lib/library.js';
|
import { getInstalledVersions, removeAllDesktopFilesForVersions } from '$lib/library.js';
|
||||||
import Button from '$lib/components/Button.svelte';
|
import Button from '$lib/components/Button.svelte';
|
||||||
|
import { show } from '$lib/components/Dialog.svelte';
|
||||||
|
|
||||||
let { settings } = $props();
|
let { settings } = $props();
|
||||||
let changing = $state(false);
|
let changing = $state(false);
|
||||||
@ -41,16 +42,19 @@
|
|||||||
const newExists = await directoryExists(newLibraryPath);
|
const newExists = await directoryExists(newLibraryPath);
|
||||||
|
|
||||||
let moveLibrary = false;
|
let moveLibrary = false;
|
||||||
|
|
||||||
if (currentExists) {
|
if (currentExists) {
|
||||||
let message = `Move existing library from\n${currentLibraryPath}\nto\n${newLibraryPath}?`;
|
let message = `Move existing library from\n${currentLibraryPath}\nto\n${newLibraryPath}?`;
|
||||||
if (newExists) {
|
if (newExists) {
|
||||||
message = `Library already exists at new location:\n${newLibraryPath}\n\nMoving will replace it. Continue?`;
|
message = `Library already exists at new location:\n${newLibraryPath}\n\nMoving will replace it. Continue?`;
|
||||||
}
|
}
|
||||||
moveLibrary = await confirm(message, {
|
|
||||||
title: 'Move Library',
|
const prompt = await show({
|
||||||
kind: 'warning'
|
title: 'Move library ',
|
||||||
|
message: message,
|
||||||
|
buttons: ['Cancel', 'Continue'],
|
||||||
|
type: 'info'
|
||||||
});
|
});
|
||||||
|
moveLibrary = prompt === 'Continue';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (moveLibrary) {
|
if (moveLibrary) {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import Popup from '$lib/components/Popup.svelte';
|
||||||
import {
|
import {
|
||||||
deleteVersion,
|
deleteVersion,
|
||||||
launchBlenderVersion,
|
launchBlenderVersion,
|
||||||
@ -7,9 +8,39 @@
|
|||||||
} from '$lib/library';
|
} from '$lib/library';
|
||||||
import Button from '$lib/components/Button.svelte';
|
import Button from '$lib/components/Button.svelte';
|
||||||
import Menu from '$lib/components/Menu.svelte';
|
import Menu from '$lib/components/Menu.svelte';
|
||||||
|
import { show } from '$lib/components/Dialog.svelte';
|
||||||
|
|
||||||
let { version } = $props();
|
let { version } = $props();
|
||||||
|
let popup = $state();
|
||||||
|
|
||||||
|
async function handleDelete() {
|
||||||
|
const prompt = await show({
|
||||||
|
title: 'Delete',
|
||||||
|
message: `This will remove Blender ${version.version} and all associated files from your system.`,
|
||||||
|
buttons: ['Cancel', 'Continue'],
|
||||||
|
type: 'warning'
|
||||||
|
});
|
||||||
|
if (prompt == 'Continue') {
|
||||||
|
deleteVersion(version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleDefault() {
|
||||||
|
const prompt = await show({
|
||||||
|
title: 'Set as Default',
|
||||||
|
message: `This will make Blender ${version.version} the default version on your system.`,
|
||||||
|
buttons: ['Cancel', 'Continue'],
|
||||||
|
type: 'info'
|
||||||
|
});
|
||||||
|
if (prompt == 'Continue') {
|
||||||
|
popup.pop(1500);
|
||||||
|
registerVersion(version);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Popup bind:this={popup} content="Version {version.version} is now the default on your system"
|
||||||
|
></Popup>
|
||||||
<div id="card">
|
<div id="card">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
{version.version}
|
{version.version}
|
||||||
@ -34,24 +65,18 @@
|
|||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
onclick={() => deleteVersion(version) && close()}
|
onclick={async () => {
|
||||||
onkeydown={(e) =>
|
await handleDelete();
|
||||||
(e.key === 'Enter' || e.key === ' ') && deleteVersion(version) && close()}
|
close();
|
||||||
>Delete</button
|
}}>Delete</button
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="menu-item"
|
class="menu-item"
|
||||||
onclick={close}
|
onclick={async () => {
|
||||||
onkeydown={(e) => (e.key === 'Enter' || e.key === ' ') && close()}>Option 2</button
|
await handleDefault();
|
||||||
>
|
close();
|
||||||
<button
|
}}>Default</button
|
||||||
type="button"
|
|
||||||
class="menu-item"
|
|
||||||
onclick={() => registerVersion(version) && close()}
|
|
||||||
onkeydown={(e) =>
|
|
||||||
(e.key === 'Enter' || e.key === ' ') && registerVersion(version) && close()}
|
|
||||||
>Default</button
|
|
||||||
>
|
>
|
||||||
{/snippet}
|
{/snippet}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|||||||
@ -219,14 +219,6 @@ export async function toggleFavourite(version) {
|
|||||||
*/
|
*/
|
||||||
export async function deleteVersion(version) {
|
export async function deleteVersion(version) {
|
||||||
try {
|
try {
|
||||||
const confirmation = await confirm(
|
|
||||||
`This will remove the blender ${version.version} from your system. Are you sure?`,
|
|
||||||
{
|
|
||||||
title: 'Delete',
|
|
||||||
kind: 'warning'
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!confirmation) return;
|
|
||||||
// Remove the version directory from disk
|
// Remove the version directory from disk
|
||||||
await removeVersion(version);
|
await removeVersion(version);
|
||||||
updateDownloadProgress(version.version, { loaded: 0, total: 0, percent: 0 });
|
updateDownloadProgress(version.version, { loaded: 0, total: 0, percent: 0 });
|
||||||
|
|||||||
@ -9,6 +9,8 @@
|
|||||||
import Library from '$lib/components/Library.svelte';
|
import Library from '$lib/components/Library.svelte';
|
||||||
import Download from '$lib/components/Download.svelte';
|
import Download from '$lib/components/Download.svelte';
|
||||||
import Settings from '$lib/components/Settings.svelte';
|
import Settings from '$lib/components/Settings.svelte';
|
||||||
|
import Popup from '$lib/components/Popup.svelte';
|
||||||
|
import Dialog from '$lib/components/Dialog.svelte';
|
||||||
|
|
||||||
let fadeInSettings = { duration: 100 };
|
let fadeInSettings = { duration: 100 };
|
||||||
let fadeOutSettings = { duration: 100, delay: fadeInSettings.duration };
|
let fadeOutSettings = { duration: 100, delay: fadeInSettings.duration };
|
||||||
@ -61,6 +63,9 @@
|
|||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<Popup content="Are you sure you want to delete this file?" type="confirm" />
|
||||||
|
<Dialog />
|
||||||
|
|
||||||
<div id="main">
|
<div id="main">
|
||||||
{#if initialized}
|
{#if initialized}
|
||||||
<div class="tablist" role="tablist">
|
<div class="tablist" role="tablist">
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user