diff --git a/js/accounts/pocketbase.js b/js/accounts/pocketbase.js
index e826406..4571ce9 100644
--- a/js/accounts/pocketbase.js
+++ b/js/accounts/pocketbase.js
@@ -393,29 +393,85 @@ const syncManager = {
this._isSyncing = true;
try {
- const data = await this.getUserData();
+ const cloudData = await this.getUserData();
+
+ if (cloudData) {
+ const localData = {
+ tracks: (await db.getAll('favorites_tracks')) || [],
+ albums: (await db.getAll('favorites_albums')) || [],
+ artists: (await db.getAll('favorites_artists')) || [],
+ playlists: (await db.getAll('favorites_playlists')) || [],
+ mixes: (await db.getAll('favorites_mixes')) || [],
+ history: (await db.getAll('history_tracks')) || [],
+ userPlaylists: (await db.getAll('user_playlists')) || [],
+ };
+
+ let { library, history, userPlaylists } = cloudData;
+ let needsUpdate = false;
+
+ if (!library) library = {};
+ if (!library.tracks) library.tracks = {};
+ if (!library.albums) library.albums = {};
+ if (!library.artists) library.artists = {};
+ if (!library.playlists) library.playlists = {};
+ if (!library.mixes) library.mixes = {};
+ if (!userPlaylists) userPlaylists = {};
+ if (!history) history = [];
+
+ const mergeItem = (collection, item, type) => {
+ const id = type === 'playlist' ? item.uuid || item.id : item.id;
+ if (!collection[id]) {
+ collection[id] = this._minifyItem(type, item);
+ needsUpdate = true;
+ }
+ };
+
+ localData.tracks.forEach((item) => mergeItem(library.tracks, item, 'track'));
+ localData.albums.forEach((item) => mergeItem(library.albums, item, 'album'));
+ localData.artists.forEach((item) => mergeItem(library.artists, item, 'artist'));
+ localData.playlists.forEach((item) => mergeItem(library.playlists, item, 'playlist'));
+ localData.mixes.forEach((item) => mergeItem(library.mixes, item, 'mix'));
+
+ localData.userPlaylists.forEach((playlist) => {
+ if (!userPlaylists[playlist.id]) {
+ userPlaylists[playlist.id] = {
+ id: playlist.id,
+ name: playlist.name,
+ cover: playlist.cover || null,
+ tracks: playlist.tracks
+ ? playlist.tracks.map((t) => this._minifyItem('track', t))
+ : [],
+ createdAt: playlist.createdAt || Date.now(),
+ updatedAt: playlist.updatedAt || Date.now(),
+ numberOfTracks: playlist.tracks ? playlist.tracks.length : 0,
+ images: playlist.images || [],
+ isPublic: playlist.isPublic || false,
+ };
+ needsUpdate = true;
+ }
+ });
+
+ if (history.length === 0 && localData.history.length > 0) {
+ history = localData.history;
+ needsUpdate = true;
+ }
+
+ if (needsUpdate) {
+ await this._updateUserJSON(user.uid, 'library', library);
+ await this._updateUserJSON(user.uid, 'user_playlists', userPlaylists);
+ await this._updateUserJSON(user.uid, 'history', history);
+ }
- if (data) {
const convertedData = {
- favorites_tracks: data.library.tracks
- ? Object.values(data.library.tracks).filter((t) => t && typeof t === 'object')
- : [],
- favorites_albums: data.library.albums
- ? Object.values(data.library.albums).filter((a) => a && typeof a === 'object')
- : [],
- favorites_artists: data.library.artists
- ? Object.values(data.library.artists).filter((a) => a && typeof a === 'object')
- : [],
- favorites_playlists: data.library.playlists
- ? Object.values(data.library.playlists).filter((p) => p && typeof p === 'object')
- : [],
- favorites_mixes: data.library.mixes
- ? Object.values(data.library.mixes).filter((m) => m && typeof m === 'object')
- : [],
- history_tracks: data.history || [],
- user_playlists: data.userPlaylists
- ? Object.values(data.userPlaylists).filter((p) => p && typeof p === 'object')
- : [],
+ favorites_tracks: Object.values(library.tracks).filter((t) => t && typeof t === 'object'),
+ favorites_albums: Object.values(library.albums).filter((a) => a && typeof a === 'object'),
+ favorites_artists: Object.values(library.artists).filter((a) => a && typeof a === 'object'),
+ favorites_playlists: Object.values(library.playlists).filter(
+ (p) => p && typeof p === 'object'
+ ),
+ favorites_mixes: Object.values(library.mixes).filter((m) => m && typeof m === 'object'),
+ history_tracks: history,
+ user_playlists: Object.values(userPlaylists).filter((p) => p && typeof p === 'object'),
};
await db.importData(convertedData);
diff --git a/public/assets/installdesk.svg b/public/assets/installdesk.svg
new file mode 100644
index 0000000..698b830
--- /dev/null
+++ b/public/assets/installdesk.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/styles.css b/styles.css
index ab7191e..21b7df3 100644
--- a/styles.css
+++ b/styles.css
@@ -321,6 +321,16 @@ kbd {
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
+.sidebar-content {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+}
+
+.sidebar-nav.main {
+ flex: 1;
+}
+
.main-content {
grid-area: main;
overflow-y: auto;