Update from Git Manager GUI

This commit is contained in:
2026-03-25 23:07:07 +01:00
parent 89272fb899
commit 2a9812575c
4 changed files with 2624 additions and 1862 deletions

View File

@@ -1,10 +1,13 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
export default function Settings({ onClose }) {
const [githubToken, setGithubToken] = useState('');
const [giteaToken, setGiteaToken] = useState('');
const [giteaURL, setGiteaURL] = useState('');
const [avatarB64, setAvatarB64] = useState(null);
const [savedOk, setSavedOk] = useState(false);
const [avatarUploading, setAvatarUploading] = useState(false);
const fileInputRef = useRef(null);
function normalizeAndValidateGiteaUrl(rawUrl) {
const value = (rawUrl || '').trim();
@@ -36,17 +39,46 @@ export default function Settings({ onClose }) {
setGithubToken(data.githubToken || '');
setGiteaToken(data.giteaToken || '');
setGiteaURL(data.giteaURL || '');
setAvatarB64(data.avatarB64 || null);
}
});
}, []);
function save() {
function handleAvatarFileChange(e) {
const file = e.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = (ev) => setAvatarB64(ev.target.result);
reader.readAsDataURL(file);
}
async function save() {
const checkedUrl = normalizeAndValidateGiteaUrl(giteaURL);
if (!checkedUrl.ok) {
alert(checkedUrl.error);
return;
}
window.electronAPI.saveCredentials({ githubToken, giteaToken, giteaURL: checkedUrl.value });
window.electronAPI.saveCredentials({
githubToken,
giteaToken,
giteaURL: checkedUrl.value,
avatarB64: avatarB64 || null
});
// Avatar automatisch zu Gitea pushen, wenn Token + URL vorhanden
if (avatarB64 && giteaToken && checkedUrl.value) {
setAvatarUploading(true);
const result = await window.electronAPI.updateGiteaAvatar({
token: giteaToken,
url: checkedUrl.value,
imageBase64: avatarB64
});
setAvatarUploading(false);
if (!result.ok) {
console.warn('Avatar-Upload fehlgeschlagen:', result.error);
}
}
setSavedOk(true);
setTimeout(() => setSavedOk(false), 2500);
}
@@ -55,12 +87,28 @@ export default function Settings({ onClose }) {
<div className="modalContent card settings-modal-content">
<div className="settings-header">
<div>
<div className="settings-eyebrow">Konfiguration</div>
<h2> Einstellungen</h2>
<p className="settings-subtitle">
Zugangsdaten für GitHub und Gitea hinterlegen.
</p>
<div className="settings-header-inner">
<div className="settings-avatar-wrap" onClick={() => fileInputRef.current?.click()} title="Profilbild ändern">
{avatarB64
? <img src={avatarB64} alt="Avatar" className="settings-avatar-img" />
: <div className="settings-avatar-placeholder">👤</div>
}
<div className="settings-avatar-overlay"></div>
<input
ref={fileInputRef}
type="file"
accept="image/*"
style={{ display: 'none' }}
onChange={handleAvatarFileChange}
/>
</div>
<div>
<div className="settings-eyebrow">Konfiguration</div>
<h2> Einstellungen</h2>
<p className="settings-subtitle">
Zugangsdaten für GitHub und Gitea hinterlegen.
</p>
</div>
</div>
</div>
@@ -121,9 +169,10 @@ export default function Settings({ onClose }) {
<button
className="accent-btn"
onClick={save}
disabled={avatarUploading}
style={savedOk ? { background: 'var(--success)', borderColor: 'var(--success)' } : {}}
>
{savedOk ? '✅ Gespeichert' : 'Speichern'}
{avatarUploading ? '⏳ Bild wird hochgeladen…' : savedOk ? '✅ Gespeichert' : 'Speichern'}
</button>
{onClose && (
<button className="secondary" onClick={onClose}>Abbrechen</button>