style: auto-fix linting issues

This commit is contained in:
SamidyFR 2026-01-16 15:47:58 +00:00 committed by github-actions[bot]
parent 1cb17680f3
commit 3e212a7e5b
4 changed files with 190 additions and 181 deletions

View file

@ -1493,10 +1493,12 @@
}
</script>
<p style="padding-top: 50px; text-align: center; color: #8b8b93">
We only store music data and a randomized ID to find out which Google/Email account is which.
We only store music data and a randomized ID to find out which Google/Email account is
which.
<br />
All data is anonymous. We do not store anything like emails, usernames, or anything
sensitive. <br />
</p>
</div>
</div>
<div id="page-donate" class="page">

View file

@ -19,22 +19,22 @@ const syncManager = {
if (this._userRecordCache && this._userRecordCache.firebase_id === uid) {
return this._userRecordCache;
}
try {
const record = await this.pb.collection('DB_users').getFirstListItem(
`firebase_id="${uid}"`,
{ f_id: uid }
);
const record = await this.pb.collection('DB_users').getFirstListItem(`firebase_id="${uid}"`, { f_id: uid });
this._userRecordCache = record;
return record;
} catch (error) {
if (error.status === 404) {
try {
const newRecord = await this.pb.collection('DB_users').create({
firebase_id: uid,
library: {},
history: [],
}, { f_id: uid });
const newRecord = await this.pb.collection('DB_users').create(
{
firebase_id: uid,
library: {},
history: [],
},
{ f_id: uid }
);
this._userRecordCache = newRecord;
return newRecord;
} catch (createError) {
@ -95,11 +95,7 @@ const syncManager = {
}
try {
const updated = await this.pb.collection('DB_users').update(
record.id,
{ [field]: data },
{ f_id: uid }
);
const updated = await this.pb.collection('DB_users').update(record.id, { [field]: data }, { f_id: uid });
this._userRecordCache = updated;
} catch (error) {
console.error(`Failed to sync ${field} to PocketBase:`, error);
@ -114,13 +110,13 @@ const syncManager = {
if (!record) return;
let library = record.library || {};
if (typeof library === 'string') {
try {
library = JSON.parse(library);
} catch (e) {
console.error('Library field is not valid JSON', e);
library = {};
library = {};
}
}
@ -255,7 +251,7 @@ const syncManager = {
if (!record) return;
let userPlaylists = record.user_playlists || {};
if (typeof userPlaylists === 'string') {
try {
userPlaylists = JSON.parse(userPlaylists);
@ -272,7 +268,7 @@ const syncManager = {
id: playlist.id,
name: playlist.name,
cover: playlist.cover || null,
tracks: playlist.tracks ? playlist.tracks.map(t => this._minifyItem('track', t)) : [],
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,
@ -286,18 +282,19 @@ const syncManager = {
async getPublicPlaylist(uuid) {
try {
const record = await this.pb.collection(PUBLIC_COLLECTION).getFirstListItem(
`uuid="${uuid}"`,
{ p_id: uuid }
);
const record = await this.pb
.collection(PUBLIC_COLLECTION)
.getFirstListItem(`uuid="${uuid}"`, { p_id: uuid });
let rawCover = record.image || record.cover || record.playlist_cover || '';
let extraData = record.data;
if (typeof extraData === 'string') {
try { extraData = JSON.parse(extraData); } catch(e) {}
try {
extraData = JSON.parse(extraData);
} catch (e) {}
}
if (!rawCover && extraData && typeof extraData === 'object') {
rawCover = extraData.cover || extraData.image || '';
}
@ -309,7 +306,7 @@ const syncManager = {
let images = [];
let tracks = record.tracks || [];
if (typeof tracks === 'string') {
try {
tracks = JSON.parse(tracks);
@ -338,7 +335,6 @@ const syncManager = {
finalTitle = extraData.title || extraData.name;
}
if (!finalTitle) finalTitle = 'Untitled Playlist';
return {
...record,
@ -352,7 +348,7 @@ const syncManager = {
numberOfTracks: tracks.length,
type: 'user-playlist',
isPublic: true,
user: { name: 'Community Playlist' }
user: { name: 'Community Playlist' },
};
} catch (error) {
if (error.status === 404) return null;
@ -379,14 +375,14 @@ const syncManager = {
isPublic: true,
data: {
title: playlist.name,
cover: playlist.cover
}
cover: playlist.cover,
},
};
try {
const existing = await this.pb.collection(PUBLIC_COLLECTION).getList(1, 1, {
filter: `uuid="${playlist.id}"`,
p_id: playlist.id
p_id: playlist.id,
});
if (existing.items.length > 0) {
@ -406,7 +402,7 @@ const syncManager = {
try {
const existing = await this.pb.collection('public_playlists').getList(1, 1, {
filter: `uuid="${uuid}"`,
p_id: uuid
p_id: uuid,
});
if (existing.items && existing.items.length > 0) {
@ -439,24 +435,36 @@ const syncManager = {
if (this._isSyncing) return;
this._isSyncing = true;
try {
const data = await this.getUserData();
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') : [],
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') : [],
user_playlists: data.userPlaylists
? Object.values(data.userPlaylists).filter((p) => p && typeof p === 'object')
: [],
};
await db.importData(convertedData);
await new Promise(resolve => setTimeout(resolve, 300));
await new Promise((resolve) => setTimeout(resolve, 300));
window.dispatchEvent(new CustomEvent('library-changed'));
window.dispatchEvent(new CustomEvent('history-changed'));
window.dispatchEvent(new HashChangeEvent('hashchange'));
@ -477,4 +485,4 @@ if (pb) {
authManager.onAuthStateChanged(syncManager.onAuthStateChanged.bind(syncManager));
}
export { pb, syncManager };
export { pb, syncManager };

261
js/db.js
View file

@ -141,28 +141,28 @@ export class MusicDatabase {
}
}
async getFavorites(type) {
const plural = type === 'mix' ? 'mixes' : `${type}s`;
const storeName = `favorites_${plural}`;
const db = await this.open();
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readonly');
const store = transaction.objectStore(storeName);
const request = store.getAll();
request.onsuccess = () => {
const results = request.result;
results.sort((a, b) => {
const aTime = a.addedAt || 0;
const bTime = b.addedAt || 0;
return bTime - aTime; // Newest first
});
resolve(results);
};
request.onerror = () => reject(request.error);
});
}
async getFavorites(type) {
const plural = type === 'mix' ? 'mixes' : `${type}s`;
const storeName = `favorites_${plural}`;
const db = await this.open();
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readonly');
const store = transaction.objectStore(storeName);
const request = store.getAll();
request.onsuccess = () => {
const results = request.result;
results.sort((a, b) => {
const aTime = a.addedAt || 0;
const bTime = b.addedAt || 0;
return bTime - aTime; // Newest first
});
resolve(results);
};
request.onerror = () => reject(request.error);
});
}
_minifyItem(type, item) {
if (!item) return item;
@ -281,105 +281,102 @@ export class MusicDatabase {
return data;
}
async importData(data, clear = false) {
const db = await this.open();
const importStore = async (storeName, items) => {
if (items === undefined) return false;
let itemsArray = Array.isArray(items) ? items : Object.values(items || {});
console.log(`Importing to ${storeName}: ${itemsArray.length} items`);
if (itemsArray.length === 0) {
if (clear) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
const countReq = store.count();
countReq.onsuccess = () => {
if (countReq.result > 0) {
store.clear();
}
};
transaction.oncomplete = () => {
resolve(countReq.result > 0);
};
transaction.onerror = () => reject(transaction.error);
});
}
return false;
}
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
let hasChanges = false;
// force clear on first sync
console.log(`Clearing ${storeName} to Make Sure Everythings Good`);
store.clear();
hasChanges = true;
itemsArray.forEach((item) => {
if (item.id && typeof item.id === 'string' && !isNaN(item.id)) {
item.id = parseInt(item.id, 10);
}
if (item.album?.id && typeof item.album.id === 'string' && !isNaN(item.album.id)) {
item.album.id = parseInt(item.album.id, 10);
}
if (item.artists) {
item.artists.forEach(artist => {
if (artist.id && typeof artist.id === 'string' && !isNaN(artist.id)) {
artist.id = parseInt(artist.id, 10);
}
});
}
console.log(`${storeName}: Adding item with ID ${item.id || item.uuid || item.timestamp}`);
store.put(item);
});
transaction.oncomplete = () => {
console.log(`${storeName}: Imported ${itemsArray.length} items`);
resolve(true);
};
transaction.onerror = (event) => {
console.error(`${storeName}: Transaction error:`, event.target.error);
reject(transaction.error);
};
});
};
console.log('Starting import with data:', {
tracks: data.favorites_tracks?.length || 0,
albums: data.favorites_albums?.length || 0,
artists: data.favorites_artists?.length || 0,
playlists: data.favorites_playlists?.length || 0,
mixes: data.favorites_mixes?.length || 0,
history: data.history_tracks?.length || 0,
userPlaylists: data.user_playlists?.length || 0,
});
const results = await Promise.all([
importStore('favorites_tracks', data.favorites_tracks),
importStore('favorites_albums', data.favorites_albums),
importStore('favorites_artists', data.favorites_artists),
importStore('favorites_playlists', data.favorites_playlists),
importStore('favorites_mixes', data.favorites_mixes),
importStore('history_tracks', data.history_tracks),
data.user_playlists ? importStore('user_playlists', data.user_playlists) : Promise.resolve(false),
]);
console.log('Import results:', results);
return results.some((r) => r);
}
async importData(data, clear = false) {
const db = await this.open();
const importStore = async (storeName, items) => {
if (items === undefined) return false;
let itemsArray = Array.isArray(items) ? items : Object.values(items || {});
console.log(`Importing to ${storeName}: ${itemsArray.length} items`);
if (itemsArray.length === 0) {
if (clear) {
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
const countReq = store.count();
countReq.onsuccess = () => {
if (countReq.result > 0) {
store.clear();
}
};
transaction.oncomplete = () => {
resolve(countReq.result > 0);
};
transaction.onerror = () => reject(transaction.error);
});
}
return false;
}
return new Promise((resolve, reject) => {
const transaction = db.transaction(storeName, 'readwrite');
const store = transaction.objectStore(storeName);
let hasChanges = false;
// force clear on first sync
console.log(`Clearing ${storeName} to Make Sure Everythings Good`);
store.clear();
hasChanges = true;
itemsArray.forEach((item) => {
if (item.id && typeof item.id === 'string' && !isNaN(item.id)) {
item.id = parseInt(item.id, 10);
}
if (item.album?.id && typeof item.album.id === 'string' && !isNaN(item.album.id)) {
item.album.id = parseInt(item.album.id, 10);
}
if (item.artists) {
item.artists.forEach((artist) => {
if (artist.id && typeof artist.id === 'string' && !isNaN(artist.id)) {
artist.id = parseInt(artist.id, 10);
}
});
}
console.log(`${storeName}: Adding item with ID ${item.id || item.uuid || item.timestamp}`);
store.put(item);
});
transaction.oncomplete = () => {
console.log(`${storeName}: Imported ${itemsArray.length} items`);
resolve(true);
};
transaction.onerror = (event) => {
console.error(`${storeName}: Transaction error:`, event.target.error);
reject(transaction.error);
};
});
};
console.log('Starting import with data:', {
tracks: data.favorites_tracks?.length || 0,
albums: data.favorites_albums?.length || 0,
artists: data.favorites_artists?.length || 0,
playlists: data.favorites_playlists?.length || 0,
mixes: data.favorites_mixes?.length || 0,
history: data.history_tracks?.length || 0,
userPlaylists: data.user_playlists?.length || 0,
});
const results = await Promise.all([
importStore('favorites_tracks', data.favorites_tracks),
importStore('favorites_albums', data.favorites_albums),
importStore('favorites_artists', data.favorites_artists),
importStore('favorites_playlists', data.favorites_playlists),
importStore('favorites_mixes', data.favorites_mixes),
importStore('history_tracks', data.history_tracks),
data.user_playlists ? importStore('user_playlists', data.user_playlists) : Promise.resolve(false),
]);
console.log('Import results:', results);
return results.some((r) => r);
}
_updatePlaylistMetadata(playlist) {
playlist.numberOfTracks = playlist.tracks ? playlist.tracks.length : 0;
@ -402,9 +399,11 @@ export class MusicDatabase {
}
_dispatchPlaylistSync(action, playlist) {
window.dispatchEvent(new CustomEvent('sync-playlist-change', {
detail: { action, playlist }
}));
window.dispatchEvent(
new CustomEvent('sync-playlist-change', {
detail: { action, playlist },
})
);
}
// User Playlists API
@ -418,14 +417,14 @@ export class MusicDatabase {
createdAt: Date.now(),
updatedAt: Date.now(),
numberOfTracks: tracks.length,
images: [] // Initialize images
images: [], // Initialize images
};
this._updatePlaylistMetadata(playlist);
await this.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist));
// TRIGGER SYNC
this._dispatchPlaylistSync('create', playlist);
return playlist;
}
@ -439,9 +438,9 @@ export class MusicDatabase {
playlist.updatedAt = Date.now();
this._updatePlaylistMetadata(playlist);
await this.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist));
this._dispatchPlaylistSync('update', playlist);
return playlist;
}
@ -453,15 +452,15 @@ export class MusicDatabase {
playlist.updatedAt = Date.now();
this._updatePlaylistMetadata(playlist);
await this.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist));
this._dispatchPlaylistSync('update', playlist);
return playlist;
}
async deletePlaylist(playlistId) {
await this.performTransaction('user_playlists', 'readwrite', (store) => store.delete(playlistId));
// TRIGGER SYNC (but for deleting)
this._dispatchPlaylistSync('delete', { id: playlistId });
}
@ -474,9 +473,9 @@ export class MusicDatabase {
playlist.updatedAt = Date.now();
this._updatePlaylistMetadata(playlist);
await this.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist));
this._dispatchPlaylistSync('update', playlist);
return playlist;
}

View file

@ -81,8 +81,8 @@ export function initializeUIInteractions(player, api) {
const likeBtn = container.querySelector('#like-queue-btn');
if (likeBtn) {
likeBtn.addEventListener('click', async () => {
const { db } = await import('./db.js'); // Already imported
const { syncManager } = await import('./accounts/pocketbase.js');
const { db } = await import('./db.js'); // Already imported
const { syncManager } = await import('./accounts/pocketbase.js');
const { showNotification } = await import('./downloads.js');
let addedCount = 0;
@ -107,8 +107,8 @@ export function initializeUIInteractions(player, api) {
const addToPlaylistBtn = container.querySelector('#add-queue-to-playlist-btn');
if (addToPlaylistBtn) {
addToPlaylistBtn.addEventListener('click', async () => {
const { db } = await import('./db.js'); // Already imported
const { syncManager } = await import('./accounts/pocketbase.js');
const { db } = await import('./db.js'); // Already imported
const { syncManager } = await import('./accounts/pocketbase.js');
const { showNotification } = await import('./downloads.js');
const playlists = await db.getPlaylists();