15 lines
8.6 KiB
JavaScript
15 lines
8.6 KiB
JavaScript
const B=window.CITIZEN_BASE;let current=null,activeJob=null;const $=id=>document.getElementById(id);
|
|
async function api(path,opts){const r=await fetch(B+path,opts);if(!r.ok)throw new Error((await r.text()).trim());return r.json()}
|
|
function cls(el,state){el.classList.remove('good','bad','warn');if(state)el.classList.add(state)}
|
|
function txt(id,v,c){const e=$(id);const value=(v===undefined||v===null||v==='')?'—':String(v);e.textContent=value;e.title=value;cls(e,c)}
|
|
function primaryFor(h){if(h==='ready')return['STAR CITIZEN STARTEN','launch'];if(h==='install-game')return['RSI LAUNCHER ÖFFNEN','launch'];if(h==='hardware-blocked')return['SYSTEM-DETAILS','support'];if(h==='system-prepare')return['SYSTEM AUTOMATISCH VORBEREITEN','prepare-system'];if(h==='repair'||h==='launcher-repair')return['AUTOMATISCH REPARIEREN','repair'];return['EINRICHTEN & STARTKLAR MACHEN','setup']}
|
|
function setStep(name,state){const e=document.querySelector(`[data-step="${name}"]`);if(!e)return;e.dataset.state=state}
|
|
function renderSteps(g){setStep('system',g.hardware==='blocked'||g.system?.state==='blocked'?'bad':g.system?.state==='prepare'?'warn':'good');setStep('wine',g.wine_version&&g.powershell_state==='ready'?'good':g.wine_version?'warn':'todo');setStep('launcher',g.launcher_state==='ready'?'good':'todo');setStep('game',g.game_state==='ready'?'good':g.game_state==='partial'?'warn':'todo')}
|
|
function setButtonsBusy(busy){document.querySelectorAll('button[data-action]').forEach(b=>{if(b.dataset.action!=='restart')b.disabled=busy});$('primary').disabled=busy}
|
|
async function refresh(){try{const s=await api('/api/status');current=s;activeJob=s.active_job||null;$('version').textContent='v'+s.version;$('platform').textContent=[s.platform.name,s.platform.desktop].filter(Boolean).join(' · ');$('distro').textContent=s.platform.name;$('session').textContent=s.platform.session||'—';const updateMode=({deb:'APT',rpm:'RPM',arch:'pacman',user:'Benutzer', 'system-managed':'System-Image'})[s.self_update_mode]||s.self_update_mode||'';txt('packageUpdates',s.launcher_auto_update?('automatisch'+(updateMode?' · '+updateMode:'')):((s.self_update_mode==='system-managed'?'über System-Image':'manuell')+(updateMode&&s.self_update_mode!=='system-managed'?' · '+updateMode:'')),s.launcher_auto_update?'good':s.self_update_mode==='system-managed'?'good':'warn');const ub=$('updateBanner');if(s.restart_required){ub.classList.remove('hidden');$('updateText').textContent='Installiert ist '+(s.installed_version||'eine neuere Version')+', dieses Fenster läuft noch mit '+s.version+'.'}else ub.classList.add('hidden');const g=s.game;$('hero').dataset.health=g.health||'setup';let head='READY FOR SETUP',sub='Citizen Launcher übernimmt Wine, DXVK, Prefix und RSI Launcher.';if(g.health==='ready'){head='FLIGHT READY';sub='Star Citizen ist startbereit. Autopilot hält den Gaming-Stack aktuell.'}else if(g.health==='install-game'){head='RSI LAUNCHER READY';sub='Melde dich im RSI Launcher an und installiere Star Citizen am vorgegebenen C:-Pfad.'}else if(g.health==='hardware-blocked'){head='SYSTEM NICHT SPIELBEREIT';sub=g.hardware_reason||g.system?.reason||'Eine Voraussetzung ist noch nicht erfüllt.'}else if(g.health==='system-prepare'){head='SYSTEMVORBEREITUNG';sub='Citizen Launcher kann die benötigten Linux-Limits automatisch setzen.'}else if(g.health==='repair'||g.health==='launcher-repair'){head='REPAIR AVAILABLE';sub='Ein reparierbarer Zustand wurde erkannt. Spieldaten werden nicht gelöscht.'}$('headline').textContent=head;$('subline').textContent=sub;const [label,act]=primaryFor(g.health);$('primary').textContent=label;$('primary').dataset.action=act;renderSteps(g);txt('gpu',g.gpu||'nicht eindeutig erkannt',g.hardware==='blocked'?'bad':'good');txt('vulkan',g.vulkan,g.vulkan==='blocked'?'bad':g.vulkan==='ready'?'good':'warn');txt('memory',`${g.ram_gib} GiB RAM · ${g.combined_gib} GiB gesamt`,g.combined_gib>=48?'good':'warn');txt('disk',(g.system?.storage_free_gib??g.disk_free_gib)+' GiB',((g.system?.storage_free_gib??g.disk_free_gib)>=150||g.game_state==='ready')?'good':'warn');txt('filesystem',g.system?.filesystem||'unbekannt',g.system?.filesystem_ok===false?'bad':'good');txt('wine',g.wine_version||'wird eingerichtet',g.wine_version?'good':'warn');txt('dxvk',g.dxvk_state==='ready'?(g.dxvk_version||'bereit'):g.dxvk_state==='repair'?((g.dxvk_version||'DXVK')+' · Reparatur nötig'):'wird eingerichtet',g.dxvk_state==='ready'?'good':g.dxvk_state==='repair'?'warn':'warn');txt('powershell',g.powershell_state==='ready'?'bereit':g.prefix_state==='ready'?'Reparatur nötig':'wird eingerichtet',g.powershell_state==='ready'?'good':g.prefix_state==='ready'?'warn':'');txt('rsi',g.launcher_state==='ready'?'bereit':'Setup',g.launcher_state==='ready'?'good':'warn');txt('game',g.game_state==='ready'?'LIVE bereit':g.game_state==='partial'?'teilweise vorhanden':'noch nicht installiert',g.game_state==='ready'?'good':g.game_state==='partial'?'warn':'');txt('prefix',g.prefix||'—');txt('autopilot',g.autopilot?'aktiv':'aus',g.autopilot?'good':'warn');$('systemPill').textContent=g.hardware==='blocked'||g.system?.state==='blocked'?'BLOCKED':g.system?.state==='prepare'?'SETUP':'READY';$('systemPill').className='pill '+(g.hardware==='blocked'||g.system?.state==='blocked'?'bad':g.system?.state==='prepare'?'warn':'good');const stackReady=g.launcher_state==='ready'&&g.dxvk_state==='ready'&&g.powershell_state==='ready';$('stackPill').textContent=stackReady?'READY':'SETUP';$('stackPill').className='pill '+(stackReady?'good':'warn');$('autoPill').textContent=g.autopilot?'AUTO':'OFF';$('autoPill').className='pill '+(g.autopilot?'good':'warn');$('raw').textContent=JSON.stringify(s,null,2);setButtonsBusy(!!activeJob);if(activeJob&&$('job').classList.contains('hidden')){showJob('running',friendlyAction(activeJob.action),'Wird ausgeführt …');poll(activeJob.id)}}catch(e){$('headline').textContent='BACKEND ERROR';$('subline').textContent=e.message}}
|
|
function friendlyAction(a){return({setup:'Einrichtung',repair:'Automatische Reparatur',maintain:'Gaming-Stack aktualisieren',doctor:'Wine-Selbsttest',support:'Support-Paket', 'prepare-system':'Systemvorbereitung','choose-prefix':'Installationsordner'})[a]||'Aktion'}
|
|
function showJob(state,title,message,raw=''){const box=$('job');box.classList.remove('hidden','error','done');if(state==='error')box.classList.add('error');if(state==='done')box.classList.add('done');$('jobTitle').textContent=title;$('jobText').textContent=message||'';const spin=box.querySelector('.spinner'),symbol=$('jobSymbol');spin.classList.toggle('hidden',state!=='running');symbol.classList.toggle('hidden',state==='running');symbol.textContent=state==='done'?'✓':'!';const details=$('jobDetails');if(raw&&raw!==message){details.classList.remove('hidden');$('jobRaw').textContent=raw}else{details.classList.add('hidden');$('jobRaw').textContent=''}}
|
|
async function action(name){try{if(name==='restart'){await api('/api/action/restart',{method:'POST'});showJob('done','Launcher wird neu gestartet','Die neue Version wird geöffnet …');return}if(name==='launch'){const r=await api('/api/action/launch',{method:'POST'});if(r.state==='game-running'){showJob('done','Star Citizen läuft bereits','Es wurde keine zweite Instanz gestartet.')}else if(r.state==='launcher-running'){showJob('done','RSI Launcher läuft bereits','Es wurde keine zweite Instanz gestartet.')}else{showJob('done','RSI Launcher gestartet','Der Launcher wurde gestartet.')}return}const j=await api('/api/action/'+name,{method:'POST'});activeJob=j;setButtonsBusy(true);showJob('running',friendlyAction(name),'Wird ausgeführt …');poll(j.id)}catch(e){setButtonsBusy(false);showJob('error','Aktion konnte nicht gestartet werden',e.message,e.message)}}
|
|
async function poll(id){try{const j=await api('/api/job/'+id);if(j.state==='running'){setTimeout(()=>poll(id),900);return}activeJob=null;setButtonsBusy(false);if(j.state==='done'){let m=j.message||'Die Aktion wurde erfolgreich abgeschlossen.';if(j.action==='choose-prefix'&&j.message)m='Installationsort: '+j.message;showJob('done','Abgeschlossen',m)}else showJob('error','Aktion fehlgeschlagen',j.message||'Die Aktion konnte nicht abgeschlossen werden.',j.error||'');await refresh()}catch(e){activeJob=null;setButtonsBusy(false);showJob('error','Statusfehler','Der Aktionsstatus konnte nicht gelesen werden.',e.message)}}
|
|
document.addEventListener('click',e=>{const button=e.target.closest('[data-action],[data-open]');if(!button||button.disabled)return;const a=button.dataset.action;if(a)action(a);const o=button.dataset.open;if(o)api('/api/open/'+o,{method:'POST'}).catch(err=>showJob('error','Öffnen fehlgeschlagen',err.message,err.message))});$('toggle').onclick=()=>$('advanced').classList.toggle('hidden');refresh();setInterval(refresh,10000);
|