diff --git a/android/build.gradle.kts b/android/build.gradle.kts index ee4a899..a4cd58a 100644 --- a/android/build.gradle.kts +++ b/android/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("com.android.application") version "8.3.2" apply false + id("com.android.application") version "8.13.2" apply false id("org.jetbrains.kotlin.android") version "2.0.0" apply false id("org.jetbrains.kotlin.plugin.compose") version "2.0.0" apply false id("org.jetbrains.kotlin.plugin.serialization") version "2.0.0" apply false diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index a80b22c..37f853b 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/web/themes/default/app.js b/web/themes/default/app.js index 6723a6c..41329dd 100644 --- a/web/themes/default/app.js +++ b/web/themes/default/app.js @@ -392,6 +392,16 @@ function applyLang(){ setText('file-ready-btn',T.file_ready_btn); setText('file-slots-btn',T.file_slots_btn); setText('file-cancel-btn',T.file_cancel_btn); + // Elements not yet covered by setText above + var settingsBtn=document.getElementById('settings-btn'); + if(settingsBtn)settingsBtn.title=T.settings_btn_tooltip||T.settings_title||'Einstellungen'; + var snpEl=document.getElementById('s-printer-name'); + if(snpEl)snpEl.placeholder=T.settings_printer_name_placeholder||'z.B. Kobra X Links'; + var sdidEl=document.getElementById('s-device-id'); + if(sdidEl)sdidEl.placeholder=T.settings_device_id_placeholder||'32 Hex-Zeichen'; + setText('d-fan-off',T.label_off||'Aus'); + setText('skip-confirm',T.skip_confirm_btn||'Überspringen'); + setText('ams-no-data',T.ams_no_data||'Keine AMS-Daten empfangen'); // GCode-Browser-Karten: Texte sind via innerHTML eingebacken, // bei Sprachwechsel komplett neu rendern. if(typeof renderStore==='function' && typeof storeFiles!=='undefined'){ @@ -1029,7 +1039,7 @@ function refreshUserProfileList(){ return '
' +'★ '+label+'' +'' + +'style="background:none;border:none;color:var(--err);cursor:pointer;font-size:14px" title="'+tr('btn_delete','Löschen')+'">🗑' +'
'; }).join(''); }).catch(function(){}); @@ -1066,7 +1076,7 @@ function refreshImportDialogList(){ return '
' +'★ '+label+'' +'' + +'style="background:none;border:none;color:var(--err);cursor:pointer;font-size:14px" title="'+tr('btn_delete','Löschen')+'">🗑' +'
'; }).join(''); }).catch(function(){}); @@ -1103,7 +1113,7 @@ function doProfileImportUpload(files){ _one(idx+1); }) .catch(function(e){ - status.textContent='Fehler: '+e; + status.textContent=tr('log_error','Fehler:')+' '+e; status.style.color='var(--err)'; }); } @@ -1245,7 +1255,7 @@ function startReadyFile(){ if(btn){btn.disabled=false;setText('file-ready-btn',T.file_ready_btn);} }) .catch(function(e){ - clog(tr('log_error')+' '+e,'msg-err'); + clog(tr('log_error','Fehler:')+' '+e,'msg-err'); if(btn){btn.disabled=false;setText('file-ready-btn',T.file_ready_btn);} }); } @@ -1330,7 +1340,7 @@ function saveSlotEdit(){ if(typeof applyState==='function') applyState(); if(typeof poll==='function') poll(); }) - .catch(function(e){clog('Fehler: '+e,'msg-err');}); + .catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err');}); } document.addEventListener('DOMContentLoaded',function(){ document.getElementById('s-printer-ip').addEventListener('input',function(){ @@ -1377,7 +1387,7 @@ function saveSettings(){ },4000); }).catch(function(e){ btn.disabled=false;setText('btn-save-settings',T.settings_save); - clog('Settings-Fehler: '+e,'msg-err'); + clog(T.settings_title+' '+tr('log_error','Fehler:')+' '+e,'msg-err'); }); } function checkUpdate(){ @@ -1450,8 +1460,8 @@ var pollTimer; // ── Print actions ── function printAction(a){ - post('/printer/print/'+a,{}).then(function(){clog('Druck: '+a,'msg-ok');poll()}) - .catch(function(e){clog('Fehler: '+e,'msg-err')}); + post('/printer/print/'+a,{}).then(function(){clog(tr('log_print_action','Druck:')+' '+a,'msg-ok');poll()}) + .catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err')}); } function togglePauseResume(){ // Druckt → pause; Pausiert → resume. Status kommt aus dem zuletzt gepollten @@ -1490,50 +1500,50 @@ function move(axis,dir,dist){ // axis: 0=X,1=Y,2=Z → printer axis codes: 1=X,2=Y,3=Z var axisMap={0:1,1:2,2:3}; post('/api/axis',{axis:axisMap[axis],move_type:1,distance:dir*dist}) - .then(function(){clog('Achse '+(axis===0?'X':axis===1?'Y':'Z')+' '+(dir>0?'+':'')+dir*dist+'mm','msg-ok')}) - .catch(function(e){clog('Achse-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('log_axis','Achse')+' '+(axis===0?'X':axis===1?'Y':'Z')+' '+(dir>0?'+':'')+dir*dist+'mm','msg-ok')}) + .catch(function(e){clog(tr('log_axis','Achse')+'-'+tr('log_error','Fehler:')+' '+e,'msg-err')}); } function homeAll(){ post('/api/axis',{axis:5,move_type:2,distance:0}) - .then(function(){clog('Home All','msg-ok')}) - .catch(function(e){clog('Home-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('log_home_all','Home All'),'msg-ok')}) + .catch(function(e){clog(tr('log_home_all','Home All')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')}); } function homeXY(){ post('/api/axis',{axis:4,move_type:2,distance:0}) - .then(function(){clog('Home XY','msg-ok')}) - .catch(function(e){clog('Home-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('btn_home_xy','Home XY'),'msg-ok')}) + .catch(function(e){clog(tr('btn_home_xy','Home XY')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')}); } function homeZ(){ post('/api/axis',{axis:3,move_type:2,distance:0}) - .then(function(){clog('Home Z','msg-ok')}) - .catch(function(e){clog('Home-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('btn_home_z','Home Z'),'msg-ok')}) + .catch(function(e){clog(tr('btn_home_z','Home Z')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')}); } function disableMotors(){ post('/api/axis',{action:'turnOff'}) - .then(function(){clog('Motors Off','msg-ok')}) - .catch(function(e){clog('Motors-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('btn_disable_motors','Motors Off'),'msg-ok')}) + .catch(function(e){clog(tr('btn_disable_motors','Motors Off')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')}); } // ── Temperature ── function setNozzle(){ var v=parseFloat(document.getElementById('p-nozzle-inp').value||0); post('/api/temperature',{nozzle:v,bed:S.bed_target}) - .then(function(){clog('Nozzle → '+v+'°C','msg-ok')}) - .catch(function(e){clog('Temp-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('log_nozzle','Nozzle → ')+v+'°C','msg-ok')}) + .catch(function(e){clog(tr('label_nozzle','Düse')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')}); } function setBed(){ var v=parseFloat(document.getElementById('p-bed-inp').value||0); post('/api/temperature',{nozzle:S.nozzle_target,bed:v}) - .then(function(){clog(T.label_bed+' → '+v+'°C','msg-ok')}) - .catch(function(e){clog('Temp-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('log_bed','Bett → ')+v+'°C','msg-ok')}) + .catch(function(e){clog(tr('label_bed','Bett')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')}); } // ── Light ── function setLight(){ var on=document.getElementById('d-light-toggle').checked; post('/api/light',{on:on,brightness:80}) - .then(function(){clog('Licht '+(on?'an, '+br+'%':'aus'),'msg-ok')}) - .catch(function(e){clog('Licht-Fehler: '+e,'msg-err')}); + .then(function(){clog(on?tr('log_light_on','Licht an'):tr('log_light_off','Licht aus'),'msg-ok')}) + .catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err')}); } // ── Print Speed ── @@ -1544,7 +1554,7 @@ function setSpeed(mode){ if(b) b.classList.toggle('spd-active',m===mode); }); post('/api/speed',{mode:mode}) - .catch(function(e){clog('Speed-Fehler: '+e,'msg-err')}); + .catch(function(e){clog(tr('label_speed','Geschwindigkeit')+' '+tr('log_error','Fehler:')+' '+e,'msg-err')}); } // ── Fan ── @@ -1552,15 +1562,15 @@ function setFan(){ var v=parseInt(document.getElementById('d-fan').value); document.getElementById('d-fan-val').textContent=v; post('/api/fan',{speed:v}) - .then(function(){clog('Lüfter → '+v+'%','msg-ok')}) - .catch(function(e){clog('Lüfter-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('log_fan','Lüfter → ')+v+'%','msg-ok')}) + .catch(function(e){clog(tr('log_fan','Lüfter → ')+tr('log_error','Fehler:')+' '+e,'msg-err')}); } function quickFan(v){ document.getElementById('d-fan').value=v; document.getElementById('d-fan-val').textContent=v; post('/api/fan',{speed:v}) - .then(function(){clog('Lüfter → '+v+'%','msg-ok')}) - .catch(function(e){clog('Lüfter-Fehler: '+e,'msg-err')}); + .then(function(){clog(tr('log_fan','Lüfter → ')+v+'%','msg-ok')}) + .catch(function(e){clog(tr('log_fan','Lüfter → ')+tr('log_error','Fehler:')+' '+e,'msg-err')}); } // ── AMS ── @@ -1575,7 +1585,7 @@ function amsFeed(type,slotIndex){ } return post('/api/ams/feed',{slot_index:globalIdx,type:type}) .then(function(){clog((type===1?T.lbl_feed:T.lbl_unload)+' Slot '+(globalIdx+1),'msg-ok')}) - .catch(function(e){clog('AMS-Fehler: '+e,'msg-err');throw e;}); + .catch(function(e){clog('AMS '+tr('log_error','Fehler:')+' '+e,'msg-err');throw e;}); } // ── Camera ── @@ -1593,7 +1603,7 @@ function camStart(){ ph.style.display='flex'; camOn=false; document.getElementById('cam-toggle-btn').textContent=tr('btn_cam_start'); - clog(tr('log_error')+' '+tr('cam_stream_unavailable'),'msg-err'); + clog(tr('log_error','Fehler:')+' '+tr('cam_stream_unavailable'),'msg-err'); }; img.src='/api/camera/stream?t='+Date.now(); camOn=true; @@ -1607,7 +1617,7 @@ function camStart(){ }).catch(function(e){ sp.style.display='none'; ph.style.display='flex'; - clog(tr('log_error')+' '+e,'msg-err'); + clog(tr('log_error','Fehler:')+' '+e,'msg-err'); }); } @@ -1636,7 +1646,7 @@ function aceDryStart(aceId){ clog('ACE '+(aceId+1)+' - '+tr('ace_dry_dryer')+': '+tr('ace_dry_start')+' ('+t+'°C, '+d+' min)','msg-ok'); poll(); }) - .catch(function(e){clog('ACE-Fehler: '+e,'msg-err');}); + .catch(function(e){clog('ACE '+tr('log_error','Fehler:')+' '+e,'msg-err');}); } var _aceAutoFeedPending={}; @@ -1840,7 +1850,7 @@ function saveAceDryPresetAndRestart(){ }).catch(function(e){ btn.disabled=false; btn.textContent=tr('ace_dry_dialog_save_restart'); - clog('ACE-Preset Fehler: '+e,'msg-err'); + clog('ACE preset '+tr('log_error','Fehler:')+' '+e,'msg-err'); }); } @@ -1878,14 +1888,14 @@ function aceDryStop(aceId){ clog('ACE '+(aceId+1)+' - '+tr('ace_dry_dryer')+': '+tr('ace_dry_stop'),'msg-ok'); poll(); }) - .catch(function(e){clog('ACE-Fehler: '+e,'msg-err');}); + .catch(function(e){clog('ACE '+tr('log_error','Fehler:')+' '+e,'msg-err');}); } function loadStore(){ fetch(_apiUrl('/kx/files')).then(function(r){return r.json()}).then(function(d){ storeFiles=d.result||[]; renderStore(); - }).catch(function(e){clog('Store-Fehler: '+e,'msg-err')}); + }).catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err')}); } function uploadGcode(file){ @@ -1917,7 +1927,7 @@ function uploadGcode(file){ if(status){ status.textContent=T.store_upload_error.replace('{error}',e.message); status.className='upload-status-err'; } if(label) label.style.display=''; if(zone) zone.style.pointerEvents=''; - clog('Upload-Fehler: '+e,'msg-err'); + clog(tr('log_error','Fehler:')+' '+e,'msg-err'); }); } @@ -2074,7 +2084,7 @@ function clearWebUploadWarningFlag(fileId, onDone){ loadStore(); }) .catch(function(e){ - clog('Verifizierungs-Fehler: '+e,'msg-err'); + clog(tr('log_error','Fehler:')+' '+e,'msg-err'); }); } @@ -2140,7 +2150,7 @@ function confirmStoreWebVerify(){ }) .catch(function(e){ if(status){status.textContent='✗ '+e.message;} - clog('Verifizierungs-Fehler: '+e,'msg-err'); + clog(tr('log_error','Fehler:')+' '+e,'msg-err'); }); } @@ -2387,7 +2397,7 @@ function confirmFilamentPrint(){ if(btn){btn.disabled=false;setText('file-ready-btn',T.file_ready_btn);} }) .catch(function(e){ - clog(tr('log_error')+' '+e,'msg-err'); + clog(tr('log_error','Fehler:')+' '+e,'msg-err'); if(btn){btn.disabled=false;setText('file-ready-btn',T.file_ready_btn);} }); } else { @@ -2397,9 +2407,9 @@ function confirmFilamentPrint(){ headers:{'Content-Type':'application/json'}, body:JSON.stringify({file_id:_storeFileId,filament_assignments:assignments,excluded_objects:excludedObjects}) }).then(function(r){return r.json()}).then(function(d){ - if(d.result==='ok'){clog('Druckstart: '+_storeFilename,'msg-ok');showPanel('dashboard');} - else{clog('Druckfehler: '+(d.error||'?'),'msg-err');} - }).catch(function(e){clog('Druckfehler: '+e,'msg-err');}); + if(d.result==='ok'){clog(tr('log_print_start','Druckstart:')+' '+_storeFilename,'msg-ok');showPanel('dashboard');} + else{clog(tr('log_error','Fehler:')+' '+(d.error||'?'),'msg-err');} + }).catch(function(e){clog(tr('log_error','Fehler:')+' '+e,'msg-err');}); } } @@ -2553,7 +2563,7 @@ function confirmSkip(){ fetch(_apiUrl('/kx/skip'),{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({names:names})}) .then(function(r){return r.json().then(function(j){return {ok:r.ok,j:j};});}) .then(function(res){ - if(!res.ok){st.textContent=(res.j&&res.j.error)||'Fehler';st.style.color='var(--err)';btn.disabled=false;return;} + if(!res.ok){st.textContent=(res.j&&res.j.error)||tr('log_error','Fehler:');st.style.color='var(--err)';btn.disabled=false;return;} st.textContent=tr('skip_success');st.style.color='var(--ok)'; // Dialog offen lassen + neu laden damit der "übersprungen"-Status erscheint setTimeout(function(){ _refreshSkipDialog(); btn.disabled=false; st.textContent=''; }, 1500); @@ -2565,7 +2575,7 @@ function storeDelete(fileId){ if(!confirm(T.store_delete_confirm)) return; fetch(_apiUrl('/kx/files/'+fileId),{method:'DELETE'}).then(function(r){ if(r.ok){loadStore();} - else{clog('Löschen fehlgeschlagen','msg-err');} + else{clog(tr('log_delete_failed','Löschen fehlgeschlagen'),'msg-err');} }); } @@ -2599,7 +2609,7 @@ function confirmAddPrinter(){ body:JSON.stringify({printer_ip:ip,name:name})}) .then(function(r){return r.json().then(function(j){return {ok:r.ok,j:j};});}) .then(function(res){ - if(!res.ok){st.textContent=(res.j&&res.j.error)||'Fehler';st.style.color='var(--err)';btn.disabled=false;return;} + if(!res.ok){st.textContent=(res.j&&res.j.error)||tr('log_error','Fehler:');st.style.color='var(--err)';btn.disabled=false;return;} st.textContent=T.apd_success;st.style.color='var(--ok)'; setTimeout(function(){location.reload();},2500); }) @@ -2610,7 +2620,7 @@ function removePrinter(id,name){ fetch('/kx/printers/'+encodeURIComponent(id),{method:'DELETE'}) .then(function(r){return r.json().then(function(j){return {ok:r.ok,j:j};});}) .then(function(res){ - if(!res.ok){alert((res.j&&res.j.error)||'Fehler');return;} + if(!res.ok){alert((res.j&&res.j.error)||tr('log_error','Fehler:'));return;} setTimeout(function(){location.href='/printer1';},2000); }) .catch(function(e){alert(''+e);}); @@ -2679,6 +2689,6 @@ function loadPrinterTab(){ }).join(''); }); }).catch(function(e){ - if(grid)grid.innerHTML='
Fehler: '+e+'
'; + if(grid)grid.innerHTML='
'+tr('log_error','Fehler:')+' '+e+'
'; }); } diff --git a/web/themes/default/index.html b/web/themes/default/index.html index 1c3c2ed..59d6ea1 100644 --- a/web/themes/default/index.html +++ b/web/themes/default/index.html @@ -424,7 +424,7 @@ 0
- + diff --git a/web/translations/de.json b/web/translations/de.json index 6e6fac1..8573e4a 100644 --- a/web/translations/de.json +++ b/web/translations/de.json @@ -261,5 +261,13 @@ "settings_notif_min_unit": "Min.", "settings_notif_layers_unit": "Layer", "settings_notif_zero_off": "(0 = aus)", - "settings_notif_send_image": "Bild" + "settings_notif_send_image": "Bild", + "settings_btn_tooltip": "Einstellungen", + "settings_printer_name_placeholder": "z.B. Kobra X Links", + "settings_device_id_placeholder": "32 Hex-Zeichen", + "skip_confirm_btn": "Überspringen", + "btn_delete": "Löschen", + "log_print_start": "Druckstart:", + "log_print_action": "Druck:", + "log_delete_failed": "Löschen fehlgeschlagen" } diff --git a/web/translations/en.json b/web/translations/en.json index decf3ea..7ca5e39 100644 --- a/web/translations/en.json +++ b/web/translations/en.json @@ -261,5 +261,13 @@ "settings_notif_min_unit": "min", "settings_notif_layers_unit": "layers", "settings_notif_zero_off": "(0 = off)", - "settings_notif_send_image": "Image" + "settings_notif_send_image": "Image", + "settings_btn_tooltip": "Settings", + "settings_printer_name_placeholder": "e.g. Kobra X Left", + "settings_device_id_placeholder": "32 hex characters", + "skip_confirm_btn": "Skip", + "btn_delete": "Delete", + "log_print_start": "Print start:", + "log_print_action": "Print:", + "log_delete_failed": "Delete failed" } diff --git a/web/translations/es.json b/web/translations/es.json index b6177b1..04b6416 100644 --- a/web/translations/es.json +++ b/web/translations/es.json @@ -261,5 +261,13 @@ "settings_notif_min_unit": "min", "settings_notif_layers_unit": "capas", "settings_notif_zero_off": "(0 = off)", - "settings_notif_send_image": "Imagen" + "settings_notif_send_image": "Imagen", + "settings_btn_tooltip": "Configuración", + "settings_printer_name_placeholder": "p. ej. Kobra X Izquierda", + "settings_device_id_placeholder": "32 caracteres hexadecimales", + "skip_confirm_btn": "Omitir", + "btn_delete": "Eliminar", + "log_print_start": "Inicio de impresión:", + "log_print_action": "Imprimir:", + "log_delete_failed": "Error al eliminar" } diff --git a/web/translations/zh-cn.json b/web/translations/zh-cn.json index e0a7f80..935041b 100644 --- a/web/translations/zh-cn.json +++ b/web/translations/zh-cn.json @@ -261,5 +261,13 @@ "settings_notif_min_unit": "分钟", "settings_notif_layers_unit": "层", "settings_notif_zero_off": "(0 = 关闭)", - "settings_notif_send_image": "图片" + "settings_notif_send_image": "图片", + "settings_btn_tooltip": "设置", + "settings_printer_name_placeholder": "例如 Kobra X 左侧", + "settings_device_id_placeholder": "32位十六进制字符", + "skip_confirm_btn": "跳过", + "btn_delete": "删除", + "log_print_start": "开始打印:", + "log_print_action": "打印:", + "log_delete_failed": "删除失败" }