settings import + export
This commit is contained in:
parent
be67f79968
commit
9054016ff2
3 changed files with 91 additions and 5 deletions
18
index.html
18
index.html
|
|
@ -5076,6 +5076,24 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="setting-item">
|
||||||
|
<div class="info">
|
||||||
|
<span class="label">Export All Settings</span>
|
||||||
|
<span class="description"
|
||||||
|
>Export all app settings as JSON</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div style="display: flex; gap: 0.5rem">
|
||||||
|
<button id="export-settings-btn" class="btn-secondary">Export</button>
|
||||||
|
<button id="import-settings-btn" class="btn-secondary">Import</button>
|
||||||
|
<input
|
||||||
|
type="file"
|
||||||
|
id="import-settings-input"
|
||||||
|
style="display: none"
|
||||||
|
accept=".json"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="setting-item">
|
<div class="setting-item">
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<span class="label">ADVANCED: Custom Database/Auth</span>
|
<span class="label">ADVANCED: Custom Database/Auth</span>
|
||||||
|
|
|
||||||
15
js/app.js
15
js/app.js
|
|
@ -2562,12 +2562,27 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||||
const headerAccountImg = document.getElementById('header-account-img');
|
const headerAccountImg = document.getElementById('header-account-img');
|
||||||
const headerAccountIcon = document.getElementById('header-account-icon');
|
const headerAccountIcon = document.getElementById('header-account-icon');
|
||||||
|
|
||||||
|
// Temporarily disable accounts - show popup
|
||||||
|
const isAccountsDisabled = true;
|
||||||
|
|
||||||
if (headerAccountBtn && headerAccountDropdown) {
|
if (headerAccountBtn && headerAccountDropdown) {
|
||||||
|
if (isAccountsDisabled) {
|
||||||
|
headerAccountBtn.style.opacity = '0.5';
|
||||||
|
headerAccountBtn.style.cursor = 'not-allowed';
|
||||||
|
headerAccountBtn.title = 'Accounts temporarily unavailable';
|
||||||
|
headerAccountBtn.addEventListener('click', (e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
alert(
|
||||||
|
"We're moving authentication and data storing systems.\n\nAccounts, profiles, playlists, and community themes will not work during this period (approximately 2 days).\n\nYou will need to re-login after the migration is complete."
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
headerAccountBtn.addEventListener('click', (e) => {
|
headerAccountBtn.addEventListener('click', (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
headerAccountDropdown.classList.toggle('active');
|
headerAccountDropdown.classList.toggle('active');
|
||||||
updateAccountDropdown();
|
updateAccountDropdown();
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('click', (e) => {
|
document.addEventListener('click', (e) => {
|
||||||
if (!headerAccountBtn.contains(e.target) && !headerAccountDropdown.contains(e.target)) {
|
if (!headerAccountBtn.contains(e.target) && !headerAccountDropdown.contains(e.target)) {
|
||||||
|
|
|
||||||
|
|
@ -2750,6 +2750,59 @@ export function initializeSettings(scrobbler, player, api, ui) {
|
||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Export All Settings
|
||||||
|
document.getElementById('export-settings-btn')?.addEventListener('click', () => {
|
||||||
|
const settingsToExport = {};
|
||||||
|
for (let i = 0; i < localStorage.length; i++) {
|
||||||
|
const key = localStorage.key(i);
|
||||||
|
if (key && key.startsWith('monochrome-')) {
|
||||||
|
try {
|
||||||
|
settingsToExport[key] = JSON.parse(localStorage.getItem(key));
|
||||||
|
} catch {
|
||||||
|
settingsToExport[key] = localStorage.getItem(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const blob = new Blob([JSON.stringify(settingsToExport, null, 2)], {
|
||||||
|
type: 'application/json',
|
||||||
|
});
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const a = document.createElement('a');
|
||||||
|
a.href = url;
|
||||||
|
a.download = `monochrome-settings-${new Date().toISOString().split('T')[0]}.json`;
|
||||||
|
a.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Import All Settings
|
||||||
|
const settingsImportInput = document.getElementById('import-settings-input');
|
||||||
|
document.getElementById('import-settings-btn')?.addEventListener('click', () => {
|
||||||
|
settingsImportInput.click();
|
||||||
|
});
|
||||||
|
|
||||||
|
settingsImportInput?.addEventListener('change', async (e) => {
|
||||||
|
const file = e.target.files[0];
|
||||||
|
if (!file) return;
|
||||||
|
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = async (event) => {
|
||||||
|
try {
|
||||||
|
const settingsToImport = JSON.parse(event.target.result);
|
||||||
|
for (const [key, value] of Object.entries(settingsToImport)) {
|
||||||
|
if (key.startsWith('monochrome-')) {
|
||||||
|
localStorage.setItem(key, typeof value === 'string' ? value : JSON.stringify(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
alert('Settings imported successfully! Please reload the app.');
|
||||||
|
window.location.reload();
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Import failed:', err);
|
||||||
|
alert('Failed to import settings. Please check the file format.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
});
|
||||||
|
|
||||||
const customDbBtn = document.getElementById('custom-db-btn');
|
const customDbBtn = document.getElementById('custom-db-btn');
|
||||||
const customDbModal = document.getElementById('custom-db-modal');
|
const customDbModal = document.getElementById('custom-db-modal');
|
||||||
const customPbUrlInput = document.getElementById('custom-pb-url');
|
const customPbUrlInput = document.getElementById('custom-pb-url');
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue