feat(ui): add ViewTransition to PlaylistDetail and PlaylistManager views
- PlaylistDetailView: outer slide-down (200ms), spinner fadeout, content slide-up - PlaylistManagerView: outer slide-down (200ms), spinner fadeout, content slide-up - Matches the FavoritesView transition pattern
This commit is contained in:
1 parent
4ce7694290
commit
df17f859e0
2 files changed
+42
-5
No files matched your search
@@ -3,6 +3,7 @@
|
||||
import AlbumMenu from '../AlbumMenu.svelte';
|
||||
import PlaylistCollage from '../PlaylistCollage.svelte';
|
||||
import PlaylistModal from '../PlaylistModal.svelte';
|
||||
import ViewTransition from '../ViewTransition.svelte';
|
||||
import { writeText } from '@tauri-apps/plugin-clipboard-manager';
|
||||
import { invoke } from '@tauri-apps/api/core';
|
||||
import { open } from '@tauri-apps/plugin-dialog';
|
||||
@@ -205,6 +206,7 @@
|
||||
);
|
||||
|
||||
let loading = $state(true);
|
||||
let spinnerFading = $state(false);
|
||||
let error = $state<string | null>(null);
|
||||
let scrollContainer: HTMLDivElement | null = $state(null);
|
||||
|
||||
@@ -499,7 +501,11 @@
|
||||
console.error('Failed to load playlist:', err);
|
||||
error = String(err);
|
||||
} finally {
|
||||
loading = false;
|
||||
spinnerFading = true;
|
||||
setTimeout(() => {
|
||||
loading = false;
|
||||
spinnerFading = false;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1402,6 +1408,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<ViewTransition duration={200} distance={12} direction="down">
|
||||
<div class="playlist-detail" bind:this={scrollContainer}>
|
||||
<!-- Navigation Row -->
|
||||
<div class="nav-row">
|
||||
@@ -1417,7 +1424,7 @@
|
||||
</div>
|
||||
|
||||
{#if loading}
|
||||
<div class="loading">
|
||||
<div class="loading" class:fading={spinnerFading}>
|
||||
<div class="spinner"></div>
|
||||
<p>Loading playlist...</p>
|
||||
</div>
|
||||
@@ -1428,6 +1435,7 @@
|
||||
<button class="retry-btn" onclick={loadPlaylist}>Retry</button>
|
||||
</div>
|
||||
{:else if playlist}
|
||||
<ViewTransition duration={200} distance={12} direction="up">
|
||||
<!-- Playlist Header -->
|
||||
<div class="playlist-header">
|
||||
<!-- Playlist Artwork - Collage or Custom -->
|
||||
@@ -1736,9 +1744,10 @@
|
||||
showReasons={false}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
</ViewTransition>
|
||||
{/if}
|
||||
</div>
|
||||
</ViewTransition>
|
||||
|
||||
<!-- Edit Playlist Modal -->
|
||||
{#if playlist}
|
||||
@@ -1835,6 +1844,15 @@
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.loading {
|
||||
opacity: 1;
|
||||
transition: opacity 200ms ease-out;
|
||||
}
|
||||
|
||||
.loading.fading {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
import { ArrowLeft, Filter, ArrowUpDown, LayoutGrid, List, GripVertical, EyeOff, Eye, BarChart2, Play, Pencil, Search, X, Cloud, CloudOff, Wifi, Heart, Folder, FolderPlus, ChevronRight, ChevronDown, ChevronUp, Trash2, Star, Music, Disc, Library, Info } from 'lucide-svelte';
|
||||
import PlaylistCollage from '../PlaylistCollage.svelte';
|
||||
import PlaylistModal from '../PlaylistModal.svelte';
|
||||
import ViewTransition from '../ViewTransition.svelte';
|
||||
import FolderEditModal from '../FolderEditModal.svelte';
|
||||
import { t } from '$lib/i18n';
|
||||
import {
|
||||
@@ -76,6 +77,7 @@
|
||||
let localTrackCounts = $state<Map<number, number>>(new Map());
|
||||
let pendingPlaylistsMap = $state<Map<number, import('$lib/stores/offlineStore').PendingPlaylist>>(new Map());
|
||||
let loading = $state(true);
|
||||
let spinnerFading = $state(false);
|
||||
|
||||
// Offline state
|
||||
let offlineStatus = $state<OfflineStatus>(getOfflineStatus());
|
||||
@@ -447,7 +449,11 @@
|
||||
} catch (err) {
|
||||
console.error('Failed to load playlists:', err);
|
||||
} finally {
|
||||
loading = false;
|
||||
spinnerFading = true;
|
||||
setTimeout(() => {
|
||||
loading = false;
|
||||
spinnerFading = false;
|
||||
}, 200);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,6 +756,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<ViewTransition duration={200} distance={12} direction="down">
|
||||
<div class="playlist-manager">
|
||||
<!-- Header -->
|
||||
<div class="header">
|
||||
@@ -920,11 +927,12 @@
|
||||
|
||||
<!-- Content -->
|
||||
{#if loading}
|
||||
<div class="loading">
|
||||
<div class="loading" class:fading={spinnerFading}>
|
||||
<div class="spinner"></div>
|
||||
<p>Loading playlists...</p>
|
||||
</div>
|
||||
{:else}
|
||||
<ViewTransition duration={200} distance={12} direction="up">
|
||||
<!-- Folders Section (only at root level) -->
|
||||
{#if !currentFolderId && folders.length > 0}
|
||||
<div class="folders-section">
|
||||
@@ -1288,8 +1296,10 @@
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</ViewTransition>
|
||||
{/if}
|
||||
</div>
|
||||
</ViewTransition>
|
||||
|
||||
<!-- Folder Modal -->
|
||||
<FolderEditModal
|
||||
@@ -1901,6 +1911,15 @@
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.loading {
|
||||
opacity: 1;
|
||||
transition: opacity 200ms ease-out;
|
||||
}
|
||||
|
||||
.loading.fading {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
|
||||
Reference in new issue
Block a user