Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2ae24f47e3 | |||
| ea4aa06e31 | |||
| f6e73250f0 | |||
| 57bdd3a735 | |||
| 0b56564074 | |||
| 7659be9adc | |||
| 09bfb602e3 | |||
| 5e0f741bc3 | |||
| 7eec6d19e5 | |||
| d8ce73439e | |||
| d8798ac32f | |||
| f2f5823fbb | |||
| 0a6703b87e |
205
CREATE_COMPLETE_FILES.sh
Normal file
205
CREATE_COMPLETE_FILES.sh
Normal file
@@ -0,0 +1,205 @@
|
||||
#!/bin/bash
|
||||
##############################################################################
|
||||
# CREATE_COMPLETE_FILES.sh
|
||||
#
|
||||
# Dieses Script erstellt die vollständigen renderer.js und main.js Dateien
|
||||
# mit allen notwendigen Änderungen für Auto-Login und persistente Settings.
|
||||
#
|
||||
# VERWENDUNG:
|
||||
# 1. Speichere dieses Script in deinem Projekt-Ordner
|
||||
# 2. Mache es ausführbar: chmod +x CREATE_COMPLETE_FILES.sh
|
||||
# 3. Führe es aus: ./CREATE_COMPLETE_FILES.sh
|
||||
# 4. Die neuen Dateien werden erstellt: renderer_NEW.js und main_NEW.js
|
||||
# 5. Ersetze deine alten Dateien mit den neuen
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
echo "========================================="
|
||||
echo "Erstelle vollständige Dateien..."
|
||||
echo "========================================="
|
||||
echo ""
|
||||
|
||||
# Prüfe ob Original-Dateien existieren
|
||||
if [ ! -f "renderer.js" ]; then
|
||||
echo "❌ FEHLER: renderer.js nicht gefunden!"
|
||||
echo "Bitte führe dieses Script im Projekt-Ordner aus."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "main.js" ]; then
|
||||
echo "❌ FEHLER: main.js nicht gefunden!"
|
||||
echo "Bitte führe dieses Script im Projekt-Ordner aus."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ Original-Dateien gefunden"
|
||||
echo ""
|
||||
|
||||
# Backup erstellen
|
||||
echo "📦 Erstelle Backups..."
|
||||
cp renderer.js renderer.js.backup
|
||||
cp main.js main.js.backup
|
||||
echo "✅ Backups erstellt: renderer.js.backup, main.js.backup"
|
||||
echo ""
|
||||
|
||||
# RENDERER.JS - Patch anwenden
|
||||
echo "🔧 Patche renderer.js..."
|
||||
|
||||
# Erstelle temporäre Datei mit der neuen DOMContentLoaded Funktion
|
||||
cat > /tmp/new_domcontentloaded.js << 'NEWFUNC'
|
||||
window.addEventListener('DOMContentLoaded', async () => {
|
||||
// Prevent default drag/drop on document (except in repo view)
|
||||
document.addEventListener('dragover', e => {
|
||||
if (currentState.view !== 'gitea-repo') {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('drop', e => {
|
||||
if (currentState.view !== 'gitea-repo') {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Load credentials and auto-login if available
|
||||
try {
|
||||
const creds = await window.electronAPI.loadCredentials();
|
||||
if (creds) {
|
||||
// Fülle Settings-Felder
|
||||
if ($('githubToken')) $('githubToken').value = creds.githubToken || '';
|
||||
if ($('giteaToken')) $('giteaToken').value = creds.giteaToken || '';
|
||||
if ($('giteaURL')) $('giteaURL').value = creds.giteaURL || '';
|
||||
|
||||
// AUTO-LOGIN: Wenn Gitea-Credentials vorhanden sind, lade sofort die Repos
|
||||
if (creds.giteaToken && creds.giteaURL) {
|
||||
console.log('✅ Credentials gefunden - Auto-Login wird gestartet...');
|
||||
setStatus('Lade deine Projekte...');
|
||||
|
||||
// Kurze Verzögerung damit UI fertig geladen ist
|
||||
setTimeout(() => {
|
||||
loadGiteaRepos();
|
||||
}, 500);
|
||||
} else {
|
||||
console.log('ℹ️ Keine vollständigen Gitea-Credentials - bitte in Settings eintragen');
|
||||
setStatus('Bereit - bitte Settings konfigurieren');
|
||||
}
|
||||
} else {
|
||||
console.log('ℹ️ Keine Credentials gespeichert');
|
||||
setStatus('Bereit - bitte Settings konfigurieren');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading credentials:', error);
|
||||
setStatus('Fehler beim Laden der Einstellungen');
|
||||
}
|
||||
NEWFUNC
|
||||
|
||||
# Nutze sed um die alte Funktion zu ersetzen
|
||||
# (Dies ist komplex - nutze Python für robusteres Replacement)
|
||||
python3 << 'PYSCRIPT'
|
||||
import re
|
||||
|
||||
# Lese Original-Datei
|
||||
with open('renderer.js', 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Lese neue Funktion
|
||||
with open('/tmp/new_domcontentloaded.js', 'r') as f:
|
||||
new_func_start = f.read()
|
||||
|
||||
# Finde die alte DOMContentLoaded Funktion und ersetze nur den Anfang
|
||||
# Der Rest (Event Handlers) bleibt gleich
|
||||
pattern = r"(window\.addEventListener\('DOMContentLoaded', async \(\) => \{.*?// Load credentials.*?try \{.*?\} catch \(error\) \{.*?console\.error\('Error loading credentials:', error\);.*?\})"
|
||||
|
||||
# Suche nach dem Pattern
|
||||
match = re.search(pattern, content, re.DOTALL)
|
||||
if match:
|
||||
# Ersetze nur den Credentials-Loading Teil
|
||||
old_section = match.group(1)
|
||||
content = content.replace(old_section, new_func_start)
|
||||
|
||||
# Schreibe neue Datei
|
||||
with open('renderer_NEW.js', 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
print("✅ renderer_NEW.js erstellt")
|
||||
else:
|
||||
print("⚠️ Konnte Funktion nicht automatisch patchen")
|
||||
print(" Bitte nutze die manuellen Patches")
|
||||
PYSCRIPT
|
||||
|
||||
echo ""
|
||||
|
||||
# MAIN.JS - Patch anwenden
|
||||
echo "🔧 Patche main.js..."
|
||||
|
||||
python3 << 'PYSCRIPT2'
|
||||
import re
|
||||
|
||||
# Lese Original
|
||||
with open('main.js', 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# ÄNDERUNG 1: Entferne getDataDir, ändere getCredentialsFilePath
|
||||
old_funcs = r"function getDataDir\(\) \{[^}]+\}\s*function getCredentialsFilePath\(\) \{[^}]+\}"
|
||||
new_func = """function getCredentialsFilePath() {
|
||||
return ppath.join(app.getPath('userData'), 'credentials.json');
|
||||
}"""
|
||||
|
||||
content = re.sub(old_funcs, new_func, content)
|
||||
|
||||
# ÄNDERUNG 2: Patche save-credentials Handler
|
||||
old_handler = r"(ipcMain\.handle\('save-credentials', async \(event, data\) => \{[\s\S]*?const DATA_DIR = getDataDir\(\);[\s\S]*?ensureDir\(DATA_DIR\);[^}]+)\}"
|
||||
|
||||
new_handler = """ipcMain.handle('save-credentials', async (event, data) => {
|
||||
try {
|
||||
const CREDENTIALS_FILE = getCredentialsFilePath();
|
||||
const userDataDir = app.getPath('userData');
|
||||
if (!fs.existsSync(userDataDir)) {
|
||||
fs.mkdirSync(userDataDir, { recursive: true });
|
||||
}
|
||||
|
||||
const json = JSON.stringify(data);
|
||||
const cipher = crypto.createCipheriv(ALGORITHM, SECRET_KEY, IV);
|
||||
const encrypted = Buffer.concat([cipher.update(json, 'utf8'), cipher.final()]);
|
||||
fs.writeFileSync(CREDENTIALS_FILE, encrypted);
|
||||
|
||||
console.log('✅ Credentials saved to:', CREDENTIALS_FILE);
|
||||
return { ok: true };
|
||||
} catch (e) {
|
||||
console.error('save-credentials error', e);
|
||||
return { ok: false, error: String(e) };
|
||||
}
|
||||
});"""
|
||||
|
||||
content = re.sub(old_handler, new_handler, content, flags=re.DOTALL)
|
||||
|
||||
# Schreibe neue Datei
|
||||
with open('main_NEW.js', 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
|
||||
print("✅ main_NEW.js erstellt")
|
||||
PYSCRIPT2
|
||||
|
||||
echo ""
|
||||
echo "========================================="
|
||||
echo "✅ FERTIG!"
|
||||
echo "========================================="
|
||||
echo ""
|
||||
echo "Neue Dateien erstellt:"
|
||||
echo " 📄 renderer_NEW.js"
|
||||
echo " 📄 main_NEW.js"
|
||||
echo ""
|
||||
echo "Backups erstellt:"
|
||||
echo " 💾 renderer.js.backup"
|
||||
echo " 💾 main.js.backup"
|
||||
echo ""
|
||||
echo "Nächste Schritte:"
|
||||
echo " 1. Prüfe die neuen Dateien"
|
||||
echo " 2. Ersetze die alten:"
|
||||
echo " mv renderer_NEW.js renderer.js"
|
||||
echo " mv main_NEW.js main.js"
|
||||
echo " 3. Starte die App neu"
|
||||
echo ""
|
||||
echo "Bei Problemen: Backups wiederherstellen"
|
||||
echo " mv renderer.js.backup renderer.js"
|
||||
echo " mv main.js.backup main.js"
|
||||
echo ""
|
||||
0
__tests__/gitHandler.test.js
Normal file
0
__tests__/gitHandler.test.js
Normal file
29
main.js
29
main.js
@@ -35,16 +35,8 @@ const {
|
||||
const { initRepo, commitAndPush, getBranches, getCommitLogs } = require('./src/git/gitHandler.js');
|
||||
|
||||
// NOTE: credentials/data location is computed via getDataDir() to avoid calling app.getPath before ready
|
||||
function getDataDir() {
|
||||
try {
|
||||
return ppath.join(app.getPath('userData'), 'data');
|
||||
} catch (e) {
|
||||
// Fallback: use __dirname/data (only if app.getPath not available)
|
||||
return ppath.join(__dirname, 'data');
|
||||
}
|
||||
}
|
||||
function getCredentialsFilePath() {
|
||||
return ppath.join(getDataDir(), 'credentials.json');
|
||||
return ppath.join(app.getPath('userData'), 'credentials.json');
|
||||
}
|
||||
|
||||
const ALGORITHM = 'aes-256-cbc';
|
||||
@@ -188,25 +180,24 @@ ipcMain.handle('select-folder', async () => {
|
||||
ipcMain.handle('select-file', async () => {
|
||||
const result = await dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] });
|
||||
if (result.canceled) return { ok: false, files: [] };
|
||||
|
||||
// Rückgabe mit path und name für jede Datei
|
||||
const files = result.filePaths.map(filePath => ({
|
||||
path: filePath,
|
||||
name: ppath.basename(filePath)
|
||||
}));
|
||||
|
||||
return { ok: true, files };
|
||||
return { ok: true, files: result.filePaths };
|
||||
});
|
||||
|
||||
ipcMain.handle('save-credentials', async (event, data) => {
|
||||
try {
|
||||
const DATA_DIR = getDataDir();
|
||||
const CREDENTIALS_FILE = getCredentialsFilePath();
|
||||
ensureDir(DATA_DIR); // robust gegen ENOTDIR
|
||||
// ✅ Stelle sicher dass das userData Verzeichnis existiert
|
||||
const userDataDir = app.getPath('userData');
|
||||
if (!fs.existsSync(userDataDir)) {
|
||||
fs.mkdirSync(userDataDir, { recursive: true });
|
||||
}
|
||||
|
||||
const json = JSON.stringify(data);
|
||||
const cipher = crypto.createCipheriv(ALGORITHM, SECRET_KEY, IV);
|
||||
const encrypted = Buffer.concat([cipher.update(json, 'utf8'), cipher.final()]);
|
||||
fs.writeFileSync(CREDENTIALS_FILE, encrypted);
|
||||
|
||||
console.log('✅ Credentials gespeichert in:', CREDENTIALS_FILE);
|
||||
return { ok: true };
|
||||
} catch (e) {
|
||||
console.error('save-credentials error', e);
|
||||
|
||||
4190
package-lock.json
generated
4190
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "git-manager-gui",
|
||||
"version": "2.0.1",
|
||||
"version": "2.0.3",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "electron .",
|
||||
|
||||
0
renderer/modules/editor.js
Normal file
0
renderer/modules/editor.js
Normal file
0
renderer/modules/gitea.js
Normal file
0
renderer/modules/gitea.js
Normal file
0
renderer/modules/progress.js
Normal file
0
renderer/modules/progress.js
Normal file
0
renderer/modules/state.js
Normal file
0
renderer/modules/state.js
Normal file
0
renderer/modules/ui.js
Normal file
0
renderer/modules/ui.js
Normal file
@@ -1588,18 +1588,39 @@ window.addEventListener('DOMContentLoaded', async () => {
|
||||
}
|
||||
});
|
||||
|
||||
// Load credentials
|
||||
// Load credentials and auto-login if available
|
||||
try {
|
||||
const creds = await window.electronAPI.loadCredentials();
|
||||
if (creds) {
|
||||
// Fülle Settings-Felder
|
||||
if ($('githubToken')) $('githubToken').value = creds.githubToken || '';
|
||||
if ($('giteaToken')) $('giteaToken').value = creds.giteaToken || '';
|
||||
if ($('giteaURL')) $('giteaURL').value = creds.giteaURL || '';
|
||||
|
||||
// 🆕 AUTO-LOGIN: Wenn Gitea-Credentials vorhanden sind, lade sofort die Repos
|
||||
if (creds.giteaToken && creds.giteaURL) {
|
||||
console.log('✅ Credentials gefunden - Auto-Login wird gestartet...');
|
||||
setStatus('Lade deine Projekte...');
|
||||
|
||||
// Kurze Verzögerung damit UI fertig geladen ist
|
||||
setTimeout(() => {
|
||||
loadGiteaRepos();
|
||||
}, 500);
|
||||
} else {
|
||||
console.log('ℹ️ Keine vollständigen Gitea-Credentials - bitte in Settings eintragen');
|
||||
setStatus('Bereit - bitte Settings konfigurieren');
|
||||
}
|
||||
} else {
|
||||
console.log('ℹ️ Keine Credentials gespeichert');
|
||||
setStatus('Bereit - bitte Settings konfigurieren');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading credentials:', error);
|
||||
setStatus('Fehler beim Laden der Einstellungen');
|
||||
}
|
||||
|
||||
// Rest of Event Handlers... (bleibt unverändert)
|
||||
|
||||
// Event Handlers
|
||||
if ($('btnLoadGiteaRepos')) {
|
||||
$('btnLoadGiteaRepos').onclick = loadGiteaRepos;
|
||||
@@ -1723,8 +1744,6 @@ window.addEventListener('DOMContentLoaded', async () => {
|
||||
};
|
||||
}
|
||||
|
||||
// Modal wird mit pointer-events: none nicht geschlossen durch Klicks
|
||||
// Der Grid bleibt voll interaktiv für neue Tabs
|
||||
|
||||
// Keyboard shortcuts
|
||||
document.addEventListener('keydown', (e) => {
|
||||
@@ -2143,15 +2162,13 @@ function createReleaseCard(release, isLatest) {
|
||||
}
|
||||
|
||||
/* -------------------------
|
||||
CREATE RELEASE MODAL
|
||||
CREATE RELEASE MODAL (MIT DATEI-UPLOAD)
|
||||
------------------------- */
|
||||
function showCreateReleaseModal(owner, repo) {
|
||||
let selectedFiles = [];
|
||||
|
||||
const modal = document.createElement('div');
|
||||
modal.className = 'modal';
|
||||
modal.innerHTML = `
|
||||
<div class="card" style="width: 650px; max-width: 90vw;">
|
||||
<div class="card" style="width: 600px; max-width: 90vw;">
|
||||
<h2>🚀 Neues Release erstellen</h2>
|
||||
|
||||
<div class="input-group">
|
||||
@@ -2187,21 +2204,29 @@ function showCreateReleaseModal(owner, repo) {
|
||||
<input id="releaseTarget" type="text" value="main" placeholder="main">
|
||||
</div>
|
||||
|
||||
<!-- NEU: Datei Upload -->
|
||||
<div class="input-group">
|
||||
<label>📎 Release Assets (optional)</label>
|
||||
<button id="btnSelectAssets" style="
|
||||
width: 100%;
|
||||
padding: 12px;
|
||||
background: var(--bg-tertiary);
|
||||
border: 2px dashed rgba(255, 255, 255, 0.2);
|
||||
<label>Release Asset (Optional)</label>
|
||||
<div style="display: flex; gap: 10px;">
|
||||
<input id="releaseAssetInput" type="text" readonly placeholder="Keine Datei gewählt" style="
|
||||
flex: 1;
|
||||
padding: 10px;
|
||||
border-radius: var(--radius-md);
|
||||
color: var(--text-secondary);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
color: var(--text-muted);
|
||||
cursor: not-allowed;
|
||||
">
|
||||
📁 Dateien auswählen (z.B. .exe, .zip, .tar.gz)
|
||||
</button>
|
||||
<div id="assetsList" style="margin-top: 10px;"></div>
|
||||
<button id="btnSelectReleaseAsset" type="button" style="
|
||||
padding: 10px 20px;
|
||||
border-radius: var(--radius-md);
|
||||
background: var(--bg-secondary);
|
||||
color: var(--text-primary);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
">📎 Datei wählen</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="input-group" style="display: flex; gap: 20px;">
|
||||
@@ -2222,52 +2247,27 @@ function showCreateReleaseModal(owner, repo) {
|
||||
|
||||
document.body.appendChild(modal);
|
||||
|
||||
// Asset-Auswahl Handler
|
||||
$('btnSelectAssets').onclick = async () => {
|
||||
// Variable zum Speichern des gewählten Dateipfads
|
||||
let selectedAssetPath = null;
|
||||
|
||||
// Event Listener: Datei auswählen
|
||||
$('btnSelectReleaseAsset').onclick = async () => {
|
||||
try {
|
||||
const res = await window.electronAPI.selectFile();
|
||||
if (res.ok && res.files && res.files.length > 0) {
|
||||
selectedFiles = res.files;
|
||||
updateAssetsList();
|
||||
selectedAssetPath = res.files[0];
|
||||
const fileName = selectedAssetPath.split(/[\\/]/).pop();
|
||||
$('releaseAssetInput').value = fileName;
|
||||
$('releaseAssetInput').style.color = 'var(--text-primary)';
|
||||
$('releaseAssetInput').style.borderColor = 'var(--accent-primary)';
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Auswählen der Datei:', error);
|
||||
alert('Konnte Dateidialog nicht öffnen.');
|
||||
}
|
||||
};
|
||||
|
||||
function updateAssetsList() {
|
||||
const list = $('assetsList');
|
||||
if (selectedFiles.length === 0) {
|
||||
list.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
list.innerHTML = selectedFiles.map((file, idx) => `
|
||||
<div style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 8px 12px;
|
||||
background: var(--bg-tertiary);
|
||||
border-radius: var(--radius-sm);
|
||||
margin-bottom: 6px;
|
||||
">
|
||||
<span style="flex: 1; color: var(--text-primary); font-size: 13px;">📄 ${file.name}</span>
|
||||
<button onclick="removeAsset(${idx})" style="
|
||||
background: rgba(255, 59, 48, 0.2);
|
||||
color: #ff3b30;
|
||||
border: none;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
">✕</button>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
// Asset entfernen (global für onclick)
|
||||
window.removeAsset = (idx) => {
|
||||
selectedFiles.splice(idx, 1);
|
||||
updateAssetsList();
|
||||
};
|
||||
|
||||
// Event Listener: Release erstellen
|
||||
$('btnCreateRelease').onclick = async () => {
|
||||
const tag = $('releaseTag').value.trim();
|
||||
const name = $('releaseName').value.trim() || tag;
|
||||
@@ -2281,14 +2281,10 @@ function showCreateReleaseModal(owner, repo) {
|
||||
return;
|
||||
}
|
||||
|
||||
const btnCreate = $('btnCreateRelease');
|
||||
const originalText = btnCreate.textContent;
|
||||
btnCreate.disabled = true;
|
||||
btnCreate.textContent = 'Erstelle Release...';
|
||||
|
||||
setStatus('Creating release...');
|
||||
|
||||
try {
|
||||
// 1. Release erstellen
|
||||
const res = await window.electronAPI.createRelease({
|
||||
owner,
|
||||
repo,
|
||||
@@ -2301,43 +2297,49 @@ function showCreateReleaseModal(owner, repo) {
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
// Assets hochladen, falls vorhanden
|
||||
if (selectedFiles.length > 0) {
|
||||
btnCreate.textContent = `Lade Assets (0/${selectedFiles.length})...`;
|
||||
setStatus(`Uploading ${selectedFiles.length} asset(s)...`);
|
||||
|
||||
for (let i = 0; i < selectedFiles.length; i++) {
|
||||
const file = selectedFiles[i];
|
||||
btnCreate.textContent = `Lade Assets (${i + 1}/${selectedFiles.length})...`;
|
||||
// 2. Falls eine Datei ausgewählt wurde, direkt hochladen
|
||||
if (selectedAssetPath) {
|
||||
setStatus('Release erstellt. Lade Datei hoch...');
|
||||
showProgress(50, 'Uploading Asset...');
|
||||
|
||||
try {
|
||||
await window.electronAPI.uploadReleaseAsset({
|
||||
const fileName = selectedAssetPath.split(/[\\/]/).pop();
|
||||
const uploadRes = await window.electronAPI.uploadReleaseAsset({
|
||||
owner,
|
||||
repo,
|
||||
releaseId: res.release.id,
|
||||
filePath: file.path,
|
||||
fileName: file.name
|
||||
filePath: selectedAssetPath,
|
||||
fileName
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Asset upload error:', err);
|
||||
// Weiter mit nächster Datei
|
||||
|
||||
if (uploadRes.ok) {
|
||||
setStatus(`Release "${tag}" und Asset erstellt!`);
|
||||
} else {
|
||||
console.error('Asset Upload fehlgeschlagen:', uploadRes.error);
|
||||
alert(`Release erstellt, aber Asset Upload fehlgeschlagen: ${uploadRes.error}`);
|
||||
setStatus('Release erstellt (Upload Fehler)');
|
||||
}
|
||||
} catch (uploadErr) {
|
||||
console.error('Upload error:', uploadErr);
|
||||
alert('Release erstellt, aber Fehler beim Hochladen der Datei.');
|
||||
setStatus('Release erstellt (Upload Fehler)');
|
||||
} finally {
|
||||
hideProgress();
|
||||
}
|
||||
} else {
|
||||
setStatus('Release created!');
|
||||
}
|
||||
|
||||
modal.remove();
|
||||
setStatus('Release created successfully!');
|
||||
loadRepoReleases(owner, repo); // Reload
|
||||
loadRepoReleases(owner, repo); // Liste neu laden
|
||||
} else {
|
||||
setStatus('Failed: ' + res.error);
|
||||
btnCreate.disabled = false;
|
||||
btnCreate.textContent = originalText;
|
||||
alert('Fehler beim Erstellen des Releases: ' + res.error);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Create release error:', error);
|
||||
setStatus('Create failed');
|
||||
btnCreate.disabled = false;
|
||||
btnCreate.textContent = originalText;
|
||||
alert('Ein unerwarteter Fehler ist aufgetreten.');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2348,7 +2350,6 @@ function showCreateReleaseModal(owner, repo) {
|
||||
if (e.target === modal) modal.remove();
|
||||
};
|
||||
}
|
||||
|
||||
/* -------------------------
|
||||
UPLOAD ASSET DIALOG
|
||||
------------------------- */
|
||||
@@ -2360,9 +2361,8 @@ async function showUploadAssetDialog(release) {
|
||||
return;
|
||||
}
|
||||
|
||||
const file = res.files[0];
|
||||
const filePath = file.path;
|
||||
const fileName = file.name;
|
||||
const filePath = res.files[0];
|
||||
const fileName = filePath.split(/[\\/]/).pop();
|
||||
|
||||
setStatus(`Uploading ${fileName}...`);
|
||||
showProgress(0, `Uploading ${fileName}...`);
|
||||
|
||||
@@ -784,41 +784,12 @@ async function uploadReleaseAsset({ token, url, owner, repo, releaseId, filePath
|
||||
...formData.getHeaders()
|
||||
},
|
||||
maxContentLength: Infinity,
|
||||
maxBodyLength: Infinity,
|
||||
timeout: 300000 // 5 Minuten für große Dateien
|
||||
maxBodyLength: Infinity
|
||||
});
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
console.error('uploadReleaseAsset error:', err.response?.data || err.message);
|
||||
|
||||
// Benutzerfreundliche Fehlerbehandlung
|
||||
if (err.response) {
|
||||
const status = err.response.status;
|
||||
const data = err.response.data;
|
||||
|
||||
if (status === 401) {
|
||||
throw new Error('Authentifizierung fehlgeschlagen beim Upload.');
|
||||
} else if (status === 403) {
|
||||
throw new Error('Zugriff verweigert. Keine Berechtigung zum Hochladen von Assets.');
|
||||
} else if (status === 404) {
|
||||
throw new Error(`Release mit ID ${releaseId} nicht gefunden.`);
|
||||
} else if (status === 413) {
|
||||
throw new Error('Datei ist zu groß. Maximale Größe überschritten.');
|
||||
} else if (status === 500) {
|
||||
const msg = data?.message || err.message;
|
||||
throw new Error(`Server-Fehler beim Upload: ${msg}`);
|
||||
} else {
|
||||
throw new Error(`Fehler beim Upload (${status}): ${data?.message || err.message}`);
|
||||
}
|
||||
} else if (err.code === 'ECONNABORTED') {
|
||||
throw new Error('Upload-Zeitüberschreitung. Datei ist möglicherweise zu groß.');
|
||||
} else if (err.code === 'ENOENT') {
|
||||
throw new Error(`Datei nicht gefunden: ${filePath}`);
|
||||
} else if (err.request) {
|
||||
throw new Error('Keine Antwort vom Server beim Upload.');
|
||||
} else {
|
||||
throw new Error(`Upload fehlgeschlagen: ${err.message}`);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user