235 lines
8.8 KiB
JavaScript
235 lines
8.8 KiB
JavaScript
// js/firebase/config.js
|
|
import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js";
|
|
import { getAuth, GoogleAuthProvider } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js";
|
|
import { getDatabase } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-database.js";
|
|
|
|
let app = null;
|
|
let auth = null;
|
|
let database = null;
|
|
let provider = null;
|
|
|
|
const STORAGE_KEY = 'monochrome-firebase-config';
|
|
|
|
const DEFAULT_CONFIG = {
|
|
apiKey: "AIzaSyDPU-unAjuLtQJt4IkGS5faG50UCF7lYyA",
|
|
authDomain: "monochrome-database.firebaseapp.com",
|
|
projectId: "monochrome-database",
|
|
storageBucket: "monochrome-database.firebasestorage.app",
|
|
messagingSenderId: "895657412760",
|
|
appId: "1:895657412760:web:e81c5044c7f4e9b799e8ed"
|
|
};
|
|
|
|
function getStoredConfig() {
|
|
try {
|
|
const stored = localStorage.getItem(STORAGE_KEY);
|
|
return stored ? JSON.parse(stored) : null;
|
|
} catch (e) {
|
|
console.warn('Failed to parse Firebase config from storage', e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Attempt to initialize on load
|
|
const storedConfig = getStoredConfig();
|
|
const config = storedConfig || DEFAULT_CONFIG;
|
|
|
|
if (config) {
|
|
try {
|
|
app = initializeApp(config);
|
|
auth = getAuth(app);
|
|
database = getDatabase(app);
|
|
provider = new GoogleAuthProvider();
|
|
console.log("Firebase initialized from " + (storedConfig ? "saved" : "default") + " config");
|
|
} catch (error) {
|
|
console.error("Error initializing Firebase:", error);
|
|
}
|
|
} else {
|
|
console.log("No Firebase config found.");
|
|
}
|
|
|
|
export function saveFirebaseConfig(configObj) {
|
|
if (!configObj) return;
|
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(configObj));
|
|
}
|
|
|
|
export function clearFirebaseConfig() {
|
|
localStorage.removeItem(STORAGE_KEY);
|
|
}
|
|
|
|
/**
|
|
* Generates a shareable URL containing the encoded configuration.
|
|
* @param {Object} config - The Firebase configuration object.
|
|
* @returns {string} The full URL with the config hash.
|
|
*/
|
|
export function generateShareLink(config) {
|
|
if (!config) return null;
|
|
try {
|
|
const json = JSON.stringify(config);
|
|
// Base64 encode (safe for URL hash)
|
|
const encoded = btoa(json);
|
|
const url = new URL(window.location.href);
|
|
url.hash = `#setup_firebase=${encoded}`;
|
|
return url.toString();
|
|
} catch (e) {
|
|
console.error('Failed to generate share link:', e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks the current URL for a shared configuration.
|
|
* If found, prompts the user to import it.
|
|
* @returns {boolean} True if a config was handled/processed.
|
|
*/
|
|
export function checkAndImportConfig() {
|
|
const hash = window.location.hash;
|
|
if (!hash.startsWith('#setup_firebase=')) return false;
|
|
|
|
const encoded = hash.split('#setup_firebase=')[1];
|
|
if (!encoded) return false;
|
|
|
|
try {
|
|
const json = atob(encoded);
|
|
const config = JSON.parse(json);
|
|
|
|
// Validate basic structure
|
|
if (!config.apiKey || !config.authDomain) {
|
|
alert('The shared configuration link appears to be invalid.');
|
|
return false;
|
|
}
|
|
|
|
if (confirm('A Firebase configuration was detected in the link. Do you want to import it and enable Sync?')) {
|
|
saveFirebaseConfig(config);
|
|
// Clean URL
|
|
window.history.replaceState(null, null, window.location.pathname);
|
|
alert('Configuration imported successfully! The app will now reload.');
|
|
window.location.reload();
|
|
return true;
|
|
} else {
|
|
// User rejected, clean URL anyway to avoid re-prompting
|
|
window.history.replaceState(null, null, window.location.pathname + '#settings');
|
|
}
|
|
} catch (e) {
|
|
console.error('Failed to parse shared config:', e);
|
|
alert('Failed to read configuration from link. The link might be corrupted.');
|
|
}
|
|
return false;
|
|
}
|
|
|
|
export function initializeFirebaseSettingsUI() {
|
|
// Check for shared config in URL first
|
|
checkAndImportConfig();
|
|
|
|
const firebaseConfigInput = document.getElementById('firebase-config-input');
|
|
const saveFirebaseConfigBtn = document.getElementById('save-firebase-config-btn');
|
|
const clearFirebaseConfigBtn = document.getElementById('clear-firebase-config-btn');
|
|
const shareFirebaseConfigBtn = document.getElementById('share-firebase-config-btn');
|
|
const toggleFirebaseConfigBtn = document.getElementById('toggle-firebase-config-btn');
|
|
const customFirebaseConfigContainer = document.getElementById('custom-firebase-config-container');
|
|
|
|
// Toggle Button Logic
|
|
if (toggleFirebaseConfigBtn && customFirebaseConfigContainer) {
|
|
toggleFirebaseConfigBtn.addEventListener('click', () => {
|
|
const isVisible = customFirebaseConfigContainer.classList.contains('visible');
|
|
if (isVisible) {
|
|
customFirebaseConfigContainer.classList.remove('visible');
|
|
toggleFirebaseConfigBtn.textContent = 'Advanced: Custom Configuration';
|
|
} else {
|
|
customFirebaseConfigContainer.classList.add('visible');
|
|
toggleFirebaseConfigBtn.textContent = 'Hide Custom Configuration';
|
|
}
|
|
});
|
|
}
|
|
|
|
// Populate current config
|
|
if (firebaseConfigInput) {
|
|
const currentConfig = localStorage.getItem(STORAGE_KEY);
|
|
if (currentConfig) {
|
|
try {
|
|
firebaseConfigInput.value = JSON.stringify(JSON.parse(currentConfig), null, 2);
|
|
// If custom config exists, show the container
|
|
if (customFirebaseConfigContainer && toggleFirebaseConfigBtn) {
|
|
customFirebaseConfigContainer.classList.add('visible');
|
|
toggleFirebaseConfigBtn.textContent = 'Hide Custom Configuration';
|
|
}
|
|
} catch (e) {
|
|
firebaseConfigInput.value = currentConfig;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Share Button
|
|
if (shareFirebaseConfigBtn) {
|
|
shareFirebaseConfigBtn.addEventListener('click', () => {
|
|
const currentConfigStr = localStorage.getItem(STORAGE_KEY);
|
|
if (!currentConfigStr) {
|
|
alert('No configuration saved to share.');
|
|
return;
|
|
}
|
|
try {
|
|
const config = JSON.parse(currentConfigStr);
|
|
const link = generateShareLink(config);
|
|
if (link) {
|
|
navigator.clipboard.writeText(link).then(() => {
|
|
alert('Magic Link copied to clipboard! Send it to your other device.');
|
|
}).catch(err => {
|
|
console.error('Clipboard error:', err);
|
|
prompt('Copy this link:', link);
|
|
});
|
|
}
|
|
} catch (e) {
|
|
alert('Invalid configuration found.');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Save Button
|
|
if (saveFirebaseConfigBtn) {
|
|
saveFirebaseConfigBtn.addEventListener('click', () => {
|
|
const inputVal = firebaseConfigInput.value.trim();
|
|
if (!inputVal) {
|
|
alert('Please enter a valid configuration.');
|
|
return;
|
|
}
|
|
|
|
try {
|
|
let cleaned = inputVal;
|
|
// Remove variable declaration if present (e.g., "const firebaseConfig = ")
|
|
if (cleaned.includes('=')) {
|
|
cleaned = cleaned.substring(cleaned.indexOf('=') + 1);
|
|
}
|
|
// Remove trailing semicolon
|
|
cleaned = cleaned.trim();
|
|
if (cleaned.endsWith(';')) {
|
|
cleaned = cleaned.slice(0, -1);
|
|
}
|
|
|
|
// Convert JS Object format to JSON format
|
|
const jsonReady = cleaned
|
|
.replace(/([{,]\s*)([a-zA-Z0-9_]+)\s*:/g, '$1"$2":') // Wrap keys in double quotes
|
|
.replace(/:\s*'([^']*)'/g, ': "$1"') // Replace single-quoted values with double quotes
|
|
.replace(/,\s*([}\]])/g, '$1'); // Remove trailing commas
|
|
|
|
const config = JSON.parse(jsonReady);
|
|
saveFirebaseConfig(config);
|
|
alert('Configuration saved. Reloading...');
|
|
window.location.reload();
|
|
} catch (error) {
|
|
console.error('Invalid Config:', error);
|
|
alert('Could not parse configuration. Please ensure it looks like a valid JSON or JS object.');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Clear Button
|
|
if (clearFirebaseConfigBtn) {
|
|
clearFirebaseConfigBtn.addEventListener('click', () => {
|
|
if (confirm('Are you sure you want to remove the custom configuration? The app will revert to the shared default database.')) {
|
|
clearFirebaseConfig();
|
|
window.location.reload();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
export { app, auth, database, provider };
|