neuronalstarx / src /firebase.js
salomonsky's picture
Upload 10 files
37ab4cc verified
import {initializeApp} from "https://www.gstatic.com/firebasejs/11.6.1/firebase-app.js";
import {getAuth, onAuthStateChanged, signInAnonymously, signOut as fbSignOut} from "https://www.gstatic.com/firebasejs/11.6.1/firebase-auth.js";
import {getFirestore, doc, setDoc, getDoc, serverTimestamp} from "https://www.gstatic.com/firebasejs/11.6.1/firebase-firestore.js";
import {firebaseConfig, appId} from './config.js';
import {autoUsername} from './utils.js';
let app, db, auth, userId=null, username=null, ready=false;
function genId(){ try{ if (crypto && crypto.randomUUID) return crypto.randomUUID(); }catch{} return 'u_'+Math.random().toString(36).slice(2,10)+'_'+Date.now().toString(36); }
let profilesCache={};
async function fetchIP(){try{const r=await fetch('https://api.ipify.org?format=json');if(!r.ok)throw 0;const j=await r.json();return j.ip||'';}catch{return''}}
export async function initFirebase(){
try{
app=initializeApp(firebaseConfig); db=getFirestore(app); auth=getAuth(app);
}catch{
db=undefined; auth=undefined;
}
const ip=await fetchIP(); const last=localStorage.getItem('last_ip')||'';
if(ip&&ip!==last){ localStorage.removeItem('local_username'); localStorage.setItem('last_ip',ip); }
let resolved=false;
function resolveReady(){ if(!resolved){ resolved=true; ready=true; }}
if (auth){
onAuthStateChanged(auth,async u=>{
if(u){ userId=u.uid; const p=await ensureProfile(userId); username=p.username; renderAuthUI(true); resolveReady(); }
else{
try{ await signInAnonymously(auth); }
catch{
userId=localStorage.getItem('local_uid')||genId(); localStorage.setItem('local_uid',userId);
let uname=localStorage.getItem('local_username'); if(!uname){ uname=autoUsername(); localStorage.setItem('local_username',uname); }
username=uname; renderAuthUI(false); resolveReady();
}
}
});
} else {
userId=localStorage.getItem('local_uid')||genId(); localStorage.setItem('local_uid',userId);
let uname=localStorage.getItem('local_username'); if(!uname){ uname=autoUsername(); localStorage.setItem('local_username',uname); }
username=uname; renderAuthUI(false); resolveReady();
}
return new Promise(res=>{
const start=Date.now();
const t=setInterval(()=>{ if(ready){ clearInterval(t); res(); } else if(Date.now()-start>2500){ resolveReady(); clearInterval(t); res(); } }, 50);
});
}
export function getDB(){return db;}
export function getAuthState(){return{userId,username,ready}};
export async function ensureProfile(uid){if(profilesCache[uid])return profilesCache[uid];try{const ref=doc(db,'artifacts',appId,'users',uid,'user_data','profile');const s=await getDoc(ref);if(s.exists()){const p=s.data();profilesCache[uid]=p;return p;}const uname=localStorage.getItem('local_username')||autoUsername();const p={username:uname,createdAt:serverTimestamp()};await setDoc(ref,p);profilesCache[uid]=p;return p;}catch{const uname=localStorage.getItem('local_username')||autoUsername();const p={username:uname};profilesCache[uid]=p;return p;}}
export function getProfile(uid){return profilesCache[uid]||null}
export async function signOut(){try{await fbSignOut(auth);}catch{} localStorage.removeItem('local_username');}
function renderAuthUI(logged){const pill=document.getElementById('statusPill');const lo=document.getElementById('logoutBtn');const ul=document.getElementById('usernameLabel');if(logged){pill.classList.remove('hidden');lo.classList.remove('hidden');}else{pill.classList.remove('hidden');lo.classList.remove('hidden');}ul.textContent=username||'-';}