File size: 3,606 Bytes
e229d32
 
 
 
 
 
 
37ab4cc
e229d32
 
 
 
1a9f31a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37ab4cc
1a9f31a
 
 
 
 
 
37ab4cc
1a9f31a
 
 
 
 
 
 
 
 
e229d32
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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||'-';}