1
0

auto-git:

[change] renderer.js
This commit is contained in:
2025-06-01 12:03:56 +02:00
parent 0e5b175202
commit a4fe460719

View File

@@ -31,7 +31,7 @@ window.addEventListener('DOMContentLoaded', async () => {
} }
}); });
// Readme-Button // Readme-Button nur einmal binden
readmeBtn.addEventListener('click', async () => { readmeBtn.addEventListener('click', async () => {
const selected = await window.electronAPI.getSelected(); const selected = await window.electronAPI.getSelected();
if (!selected) return alert('No folder selected!'); if (!selected) return alert('No folder selected!');
@@ -48,7 +48,6 @@ window.addEventListener('DOMContentLoaded', async () => {
readmeBtn.textContent = hasReadme ? 'Update README' : 'Generate README'; readmeBtn.textContent = hasReadme ? 'Update README' : 'Generate README';
}); });
// Drag and Drop // Drag and Drop
document.body.addEventListener('dragover', e => { document.body.addEventListener('dragover', e => {
e.preventDefault(); e.preventDefault();
@@ -59,10 +58,8 @@ window.addEventListener('DOMContentLoaded', async () => {
e.preventDefault(); e.preventDefault();
const files = [...e.dataTransfer.files]; const files = [...e.dataTransfer.files];
if (!files.length) return; if (!files.length) return;
// Prüfe, ob Ordner:
for (let f of files) { for (let f of files) {
// f ist File, hat .path und .type, aber bei Folders oft type="" (leerer String) if (f.type === "") {
if (f.type === "" /* = Ordner (bei DnD) */) {
await window.electronAPI.addFolderByPath(f.path); await window.electronAPI.addFolderByPath(f.path);
await renderSidebar(); await renderSidebar();
const sel = await window.electronAPI.getSelected(); const sel = await window.electronAPI.getSelected();
@@ -72,7 +69,6 @@ window.addEventListener('DOMContentLoaded', async () => {
}); });
// Farben für Sky-Mode // Farben für Sky-Mode
const DAY_COLOR = [173, 216, 230]; const DAY_COLOR = [173, 216, 230];
const NIGHT_COLOR = [0, 0, 50]; const NIGHT_COLOR = [0, 0, 50];
@@ -105,7 +101,7 @@ window.addEventListener('DOMContentLoaded', async () => {
skyIntervalId = setInterval(updateBackground, 60_000); skyIntervalId = setInterval(updateBackground, 60_000);
function updateAllTextColors() { setTextColor('sky'); } function updateAllTextColors() { setTextColor('sky'); }
updateAllTextColors(); updateAllTextColors();
titleIntervalId = setInterval(updateAllTextColors, 60_000); // damit sich die Farbe nachts/tags ändert titleIntervalId = setInterval(updateAllTextColors, 60_000);
} else { } else {
panel.style.backgroundColor = ''; panel.style.backgroundColor = '';
setTextColor('default'); setTextColor('default');
@@ -118,47 +114,37 @@ window.addEventListener('DOMContentLoaded', async () => {
function setTextColor(mode) { function setTextColor(mode) {
// Default: Schwarz
let textColor = '#111'; let textColor = '#111';
if (mode === 'sky') { if (mode === 'sky') {
const hour = new Date().getHours(); const hour = new Date().getHours();
// Sky-Mode: Tagsüber schwarz, nachts weiß
textColor = (hour >= 18 || hour < 6) ? '#fff' : '#111'; textColor = (hour >= 18 || hour < 6) ? '#fff' : '#111';
} }
titleEl.style.color = textColor; titleEl.style.color = textColor;
treeviewEl.style.color = textColor; treeviewEl.style.color = textColor;
titleArrow.style.color = textColor; titleArrow.style.color = textColor;
// Auch die Pagination einfärben:
paginationEl.style.color = textColor; paginationEl.style.color = textColor;
// Falls Treeview geöffnet und HTML gerendert: auch alle Spans darin einfärben
if (treeviewEl.querySelectorAll) { if (treeviewEl.querySelectorAll) {
treeviewEl.querySelectorAll('.tree-file, .tree-dir').forEach(el => el.style.color = textColor); treeviewEl.querySelectorAll('.tree-file, .tree-dir').forEach(el => el.style.color = textColor);
} }
} }
function basename(fullPath) { function basename(fullPath) {
return fullPath.replace(/.*[\\/]/, ''); return fullPath.replace(/.*[\\/]/, '');
} }
// Utility für FolderObj-Suche per Path
async function getFolderObjByPath(path) { async function getFolderObjByPath(path) {
const folders = await window.electronAPI.getFolders(); const folders = await window.electronAPI.getFolders();
return folders.find(f => f.path === path) || null; return folders.find(f => f.path === path) || null;
} }
async function renderSidebar() { async function renderSidebar() {
const folders = await window.electronAPI.getFolders(); const folders = await window.electronAPI.getFolders();
//console.log("Renderer-Folders:", folders);
const selected = await window.electronAPI.getSelected(); const selected = await window.electronAPI.getSelected();
folderList.innerHTML = ''; folderList.innerHTML = '';
folders.forEach(folderObj => { for (const folderObj of folders) {
const folder = folderObj.path; const folder = folderObj.path;
const isMonitoring = folderObj.monitoring; const isMonitoring = folderObj.monitoring;
const li = document.createElement('li'); const li = document.createElement('li');
@@ -169,10 +155,8 @@ folders.forEach(folderObj => {
folderObj.needsRelocation ? 'needs-relocation' : '' folderObj.needsRelocation ? 'needs-relocation' : ''
].join(' '); ].join(' ');
// beide Buttons schon im Template unter „right“
li.innerHTML = ` li.innerHTML = `
<div class="flex items-center space-x-2 overflow-hidden"> <div class="flex items-center space-x-2 overflow-hidden">
<!-- links: Icon + Name -->
<svg xmlns="http://www.w3.org/2000/svg" <svg xmlns="http://www.w3.org/2000/svg"
class="h-5 w-5 flex-shrink-0" class="h-5 w-5 flex-shrink-0"
fill="none" viewBox="0 0 24 24" stroke="currentColor"> fill="none" viewBox="0 0 24 24" stroke="currentColor">
@@ -209,44 +193,35 @@ folders.forEach(folderObj => {
</div> </div>
`; `;
// jetzt Listener setzen
// relocate missing folder // relocate missing folder
li.addEventListener('click', async e => { li.addEventListener('click', async e => {
if (e.target.closest('.pause-play-btn, .remove-btn')) return; if (e.target.closest('.pause-play-btn, .remove-btn')) return;
// Nur wenn Folder fehlt
if (folderObj.needsRelocation) { if (folderObj.needsRelocation) {
// 1. Ordner wählen
const paths = await window.electronAPI.pickFolder(); const paths = await window.electronAPI.pickFolder();
const newPath = paths && paths[0]; const newPath = paths && paths[0];
if (!newPath) return; if (!newPath) return;
// 2. Prüfen ob Git-Repo
const isGit = await window.electronAPI.isGitRepo(newPath); const isGit = await window.electronAPI.isGitRepo(newPath);
if (!isGit) { if (!isGit) {
alert('Das ist kein gültiges Git-Repository.'); alert('Das ist kein gültiges Git-Repository.');
return; return;
} }
// 3. Hash-Vergleich
const lastKnownHash = folderObj.lastHeadHash; const lastKnownHash = folderObj.lastHeadHash;
if (!lastKnownHash) { if (!lastKnownHash) {
alert('Kein gespeicherter Hash Vergleich nicht möglich.'); alert('Kein gespeicherter Hash Vergleich nicht möglich.');
return; return;
} }
const isMatch = await window.electronAPI.repoHasCommit(newPath, lastKnownHash); // WAKE UP MR. FREEMAN! WAKE UP AND... SMELL THE HASHES const isMatch = await window.electronAPI.repoHasCommit(newPath, lastKnownHash);
if (!isMatch) { if (!isMatch) {
alert('Das ist nicht das ursprüngliche Repo (Commit-Hash fehlt).'); alert('Das ist nicht das ursprüngliche Repo (Commit-Hash fehlt).');
return; return;
} }
// 4. Folder umziehen
await window.electronAPI.relocateFolder(folderObj.path, newPath); await window.electronAPI.relocateFolder(folderObj.path, newPath);
await renderSidebar(); await renderSidebar();
// Ggf. neuen Ordner direkt selektieren:
const newFolderObj = (await window.electronAPI.getFolders()) const newFolderObj = (await window.electronAPI.getFolders())
.find(f => f.path === newPath); .find(f => f.path === newPath);
if (newFolderObj) { if (newFolderObj) {
@@ -256,16 +231,12 @@ folders.forEach(folderObj => {
return; return;
} }
// Sonst Standardverhalten (Folder auswählen)
await window.electronAPI.setSelected(folderObj); await window.electronAPI.setSelected(folderObj);
await renderSidebar(); await renderSidebar();
await renderContent(folderObj); await renderContent(folderObj);
}); });
const hasReadme = await window.electronAPI.hasReadme(folderObj.path); // Monitoring-Button
readmeBtn.textContent = hasReadme ? 'Update README' : 'Generate README';
const pauseBtn = li.querySelector('.pause-play-btn'); const pauseBtn = li.querySelector('.pause-play-btn');
pauseBtn.addEventListener('click', async e => { pauseBtn.addEventListener('click', async e => {
e.stopPropagation(); e.stopPropagation();
@@ -273,38 +244,9 @@ folders.forEach(folderObj => {
await renderSidebar(); await renderSidebar();
}); });
// Remove-Button
const removeBtn = li.querySelector('.remove-btn'); const removeBtn = li.querySelector('.remove-btn');
removeBtn.addEventListener('click', async e => { removeBtn.addEventListener('click', async e => {
e.stopPropagation();
// ... dein Remove-Logic hier ...
});
// Kontextmenü / Click zum Select
li.addEventListener('contextmenu', e => {
e.preventDefault();
window.electronAPI.showFolderContextMenu(folderObj.path);
});
li.addEventListener('click', async e => {
if (e.target.closest('.pause-play-btn, .remove-btn')) return;
await window.electronAPI.setSelected(folderObj);
await renderSidebar();
await renderContent(folderObj);
});
folderList.appendChild(li);
li.addEventListener('contextmenu', e => {
e.preventDefault();
window.electronAPI.showFolderContextMenu(folderObj.path);
});
li.addEventListener('click', async e => {
if (e.target.closest('.remove-btn')) return;
await window.electronAPI.setSelected(folderObj);
await renderSidebar();
await renderContent(folderObj);
});
li.querySelector('.remove-btn').addEventListener('click', async e => {
e.stopPropagation(); e.stopPropagation();
const count = await window.electronAPI.getCommitCount(folderObj); const count = await window.electronAPI.getCommitCount(folderObj);
const hasUnstaged= await window.electronAPI.hasDiffs(folderObj); const hasUnstaged= await window.electronAPI.hasDiffs(folderObj);
@@ -343,17 +285,27 @@ folders.forEach(folderObj => {
} }
}); });
folderList.appendChild(li); // Kontextmenü / Click zum Select
li.addEventListener('contextmenu', e => {
e.preventDefault();
window.electronAPI.showFolderContextMenu(folderObj.path);
}); });
folderList.appendChild(li);
}
// Aktualisiere README-Button-Text für das aktuell ausgewählte Repo
const sel = await window.electronAPI.getSelected();
if (sel) {
const hasReadme = await window.electronAPI.hasReadme(sel.path);
readmeBtn.textContent = hasReadme ? 'Update README' : 'Generate README';
}
} }
// Update stats let countdownInterval = null;
// Countdown in MM:SS-Format
let countdownInterval = null; function getCommitColor(commitCount) {
function getCommitColor(commitCount) {
const stops = [ const stops = [
{ c: 0, color: [157, 157, 157] }, { c: 0, color: [157, 157, 157] },
{ c: 5, color: [255, 255, 255] }, { c: 5, color: [255, 255, 255] },
@@ -371,7 +323,7 @@ function getCommitColor(commitCount) {
]; ];
} }
let lower = stops[0], upper = stops[stops.length-1]; let lower = stops[0], upper = stops[stops.length-1];
for (let i=0; i<stops.length-1; ++i) { for (let i = 0; i < stops.length - 1; ++i) {
if (commitCount >= stops[i].c && commitCount < stops[i+1].c) { if (commitCount >= stops[i].c && commitCount < stops[i+1].c) {
lower = stops[i]; upper = stops[i+1]; break; lower = stops[i]; upper = stops[i+1]; break;
} }
@@ -379,31 +331,27 @@ function getCommitColor(commitCount) {
const range = upper.c - lower.c || 1; const range = upper.c - lower.c || 1;
const t = Math.min(Math.max((commitCount - lower.c) / range, 0), 1); const t = Math.min(Math.max((commitCount - lower.c) / range, 0), 1);
return lerpColor(lower.color, upper.color, t); return lerpColor(lower.color, upper.color, t);
} }
function formatCountdown(ms) { function formatCountdown(ms) {
if (!ms || ms <= 0) return '00:00'; if (!ms || ms <= 0) return '00:00';
const s = Math.floor(ms / 1000); const s = Math.floor(ms / 1000);
const m = Math.floor(s / 60).toString().padStart(2, '0'); const m = Math.floor(s / 60).toString().padStart(2, '0');
const sec = (s % 60).toString().padStart(2, '0'); const sec = (s % 60).toString().padStart(2, '0');
return `${m}:${sec}`; return `${m}:${sec}`;
} }
async function updateInteractionBar(folderObj) { async function updateInteractionBar(folderObj) {
// Commits Today
const stats = await window.electronAPI.getDailyCommitStats(); const stats = await window.electronAPI.getDailyCommitStats();
const today = new Date().toISOString().slice(0, 10); const today = new Date().toISOString().slice(0, 10);
const commitsToday = stats[today] || 0; const commitsToday = stats[today] || 0;
// Globale Variablen aus Settings holen (am besten beim Start speichern)
const intelligentCommitThreshold = await window.electronAPI.getIntelligentCommitThreshold?.() || 20; const intelligentCommitThreshold = await window.electronAPI.getIntelligentCommitThreshold?.() || 20;
const minutesCommitThreshold = await window.electronAPI.getMinutesCommitThreshold?.() || 5; const minutesCommitThreshold = await window.electronAPI.getMinutesCommitThreshold?.() || 5;
// Lines until next Rewrite
const linesChanged = folderObj?.linesChanged || 0; const linesChanged = folderObj?.linesChanged || 0;
const linesUntilRewrite = Math.max(0, intelligentCommitThreshold - linesChanged); const linesUntilRewrite = Math.max(0, intelligentCommitThreshold - linesChanged);
// Time until next Rewrite: *Initial berechnen, Live-Countdown separat*
let countdown = "00:00"; let countdown = "00:00";
let msLeft = 0; let msLeft = 0;
if (folderObj?.firstCandidateBirthday) { if (folderObj?.firstCandidateBirthday) {
@@ -413,21 +361,18 @@ async function updateInteractionBar(folderObj) {
countdown = formatCountdown(msLeft); countdown = formatCountdown(msLeft);
} }
// In die Bar schreibenx
const [r, g, b] = getCommitColor(commitsToday); const [r, g, b] = getCommitColor(commitsToday);
document.getElementById('commitsToday').textContent = commitsToday; document.getElementById('commitsToday').textContent = commitsToday;
document.getElementById('commitsToday').style.color = `rgb(${r},${g},${b})`; document.getElementById('commitsToday').style.color = `rgb(${r},${g},${b})`;
document.getElementById('linesUntilRewrite').textContent = linesUntilRewrite; document.getElementById('linesUntilRewrite').textContent = linesUntilRewrite;
document.getElementById('countdown').textContent = countdown; document.getElementById('countdown').textContent = countdown;
// Live-Countdown starten, aber nur wenn noch Zeit übrig
startLiveCountdown(folderObj, msLeft); startLiveCountdown(folderObj, msLeft);
} }
async function startLiveCountdown(folderObj, msLeft) { async function startLiveCountdown(folderObj, msLeft) {
if (countdownInterval) clearInterval(countdownInterval); if (countdownInterval) clearInterval(countdownInterval);
// Wenn kein Countdown nötig: 00:00 anzeigen
if (!folderObj?.firstCandidateBirthday || msLeft <= 0) { if (!folderObj?.firstCandidateBirthday || msLeft <= 0) {
document.getElementById('countdown').textContent = "00:00"; document.getElementById('countdown').textContent = "00:00";
return; return;
@@ -438,18 +383,13 @@ async function startLiveCountdown(folderObj, msLeft) {
const endTime = new Date(folderObj.firstCandidateBirthday).getTime() + msThreshold; const endTime = new Date(folderObj.firstCandidateBirthday).getTime() + msThreshold;
countdownInterval = setInterval(() => { countdownInterval = setInterval(() => {
const msLeft = Math.max(0, endTime - Date.now()); const msL = Math.max(0, endTime - Date.now());
document.getElementById('countdown').textContent = formatCountdown(msLeft); document.getElementById('countdown').textContent = formatCountdown(msL);
if (msLeft <= 0) { if (msL <= 0) {
clearInterval(countdownInterval); clearInterval(countdownInterval);
} }
}, 1000); }, 1000);
} }
const folderTitleDrop = document.getElementById('folderTitleDrop'); const folderTitleDrop = document.getElementById('folderTitleDrop');
@@ -465,16 +405,12 @@ async function startLiveCountdown(folderObj, msLeft) {
const selected = await window.electronAPI.getSelected(); const selected = await window.electronAPI.getSelected();
if (!selected || !selected.path) return; if (!selected || !selected.path) return;
// Show loading text
folderHierarchyDropdown.textContent = 'Lade Verzeichnis…'; folderHierarchyDropdown.textContent = 'Lade Verzeichnis…';
folderHierarchyDropdown.classList.remove('hidden'); folderHierarchyDropdown.classList.remove('hidden');
folderTitleArrow.classList.add('open'); folderTitleArrow.classList.add('open');
isDropdownOpen = true; isDropdownOpen = true;
// Lade Tree
const tree = await window.electronAPI.getFolderTree(selected.path); const tree = await window.electronAPI.getFolderTree(selected.path);
console.log(selected.path);
console.log(tree);
folderHierarchyDropdown.innerHTML = renderFolderTreeAscii(tree, '.', ''); folderHierarchyDropdown.innerHTML = renderFolderTreeAscii(tree, '.', '');
setTextColor(document.body.classList.contains('sky-mode') ? 'sky' : 'default'); setTextColor(document.body.classList.contains('sky-mode') ? 'sky' : 'default');
}); });
@@ -485,10 +421,8 @@ async function startLiveCountdown(folderObj, msLeft) {
e.preventDefault(); e.preventDefault();
const relPath = el.getAttribute('data-path'); const relPath = el.getAttribute('data-path');
const type = el.getAttribute('data-type'); // "file" oder "dir" const type = el.getAttribute('data-type');
const selected = window.electronAPI.getSelectedSync?.() const selected = window.electronAPI.getSelectedSync?.() || (window.currentSelectedFolderObj || {});
|| (window.currentSelectedFolderObj || {});
// Tipp: Implementiere eine Sync-Methode für getSelected (siehe Preload)
const absPath = selected.path + '/' + relPath; const absPath = selected.path + '/' + relPath;
window.electronAPI.showTreeContextMenu({ window.electronAPI.showTreeContextMenu({
@@ -505,7 +439,6 @@ async function startLiveCountdown(folderObj, msLeft) {
isDropdownOpen = false; isDropdownOpen = false;
} }
// Diese Funktion generiert die Treeview-Zeilen mit data-path und data-type
function renderFolderTreeAscii(tree, prefix = '', indent = '', relPath = '.') { function renderFolderTreeAscii(tree, prefix = '', indent = '', relPath = '.') {
if (!Array.isArray(tree)) return ''; if (!Array.isArray(tree)) return '';
let result = ''; let result = '';
@@ -527,29 +460,12 @@ async function startLiveCountdown(folderObj, msLeft) {
async function getCommitPageForHash(folderObj, hash, pageSize = PAGE_SIZE) { async function getCommitPageForHash(folderObj, hash, pageSize = PAGE_SIZE) {
// Hole alle Commits (NICHT paginiert!) const { commits } = await window.electronAPI.getCommits(folderObj, 1, 100000);
const { commits } = await window.electronAPI.getCommits(folderObj, 1, 100000); // genug große Zahl
const idx = commits.findIndex(c => c.hash === hash || hash.startsWith(c.hash)); const idx = commits.findIndex(c => c.hash === hash || hash.startsWith(c.hash));
if (idx === -1) return 1; // fallback: erste Seite
return Math.floor(idx / pageSize) + 1;
}
async function getPageForCurrentCommit(folderObj, pageSize = 50) { //should probably be fused with the function above
// Holt alle Commits (nur die Hashes, schnell genug für moderne Maschinen)
const { head, total } = await window.electronAPI.getCommits(folderObj, 1, 100000); // Großer Wert, um alle zu holen (du kannst auch einen eigenen IPC machen, der NUR die Hashes returned)
const { commits } = await window.electronAPI.getCommits(folderObj, 1, total);
const idx = commits.findIndex(c => c.hash === head);
if (idx === -1) return 1; if (idx === -1) return 1;
return Math.floor(idx / pageSize) + 1; return Math.floor(idx / pageSize) + 1;
} }
// Helper: gibt die Seite für einen Commit-Hash zurück
async function getCommitPageForHash(folderObj, hash, pageSize) {
const allHashes = await window.electronAPI.getAllCommitHashes(folderObj); // Muss in Main implementiert sein!
const idx = allHashes.findIndex(h => h.startsWith(hash));
return idx === -1 ? 1 : Math.floor(idx / pageSize) + 1;
}
async function renderContent(folderObj, page) { async function renderContent(folderObj, page) {
closeDropdown(); closeDropdown();
const folder = folderObj.path; const folder = folderObj.path;
@@ -557,22 +473,17 @@ async function startLiveCountdown(folderObj, msLeft) {
titleEl.textContent = folder; titleEl.textContent = folder;
setTextColor(document.body.classList.contains('sky-mode') ? 'sky' : 'default'); setTextColor(document.body.classList.contains('sky-mode') ? 'sky' : 'default');
// Dynamischer Renderbutton
// statt dessen lieber den tree auslesen?
const hasReadme = await window.electronAPI.hasReadme(folder); const hasReadme = await window.electronAPI.hasReadme(folder);
readmeBtn.textContent = hasReadme ? 'Update README' : 'Generate README'; readmeBtn.textContent = hasReadme ? 'Update README' : 'Generate README';
// --- Seitenwahl beim Ordnerwechsel ---
let usePage = page; let usePage = page;
if (!usePage || folder !== lastFolderPath) { if (!usePage || folder !== lastFolderPath) {
// Wenn keine Seite gegeben oder Ordner gewechselt: Seite für aktuellen HEAD suchen const { head } = await window.electronAPI.getCommits(folderObj, 1, 1);
const { head } = await window.electronAPI.getCommits(folderObj, 1, 1); // nur für den Hash!
usePage = await getCommitPageForHash(folderObj, head, PAGE_SIZE); usePage = await getCommitPageForHash(folderObj, head, PAGE_SIZE);
} }
lastFolderPath = folder; lastFolderPath = folder;
lastPage = usePage; lastPage = usePage;
// Paginierte Commits holen
const { head, commits, total, page: currentPage, pageSize, pages } = const { head, commits, total, page: currentPage, pageSize, pages } =
await window.electronAPI.getCommits(folderObj, usePage, PAGE_SIZE); await window.electronAPI.getCommits(folderObj, usePage, PAGE_SIZE);
@@ -582,7 +493,6 @@ async function startLiveCountdown(folderObj, msLeft) {
return; return;
} }
// Commit-Liste rendern
contentList.innerHTML = commits.map(c => { contentList.innerHTML = commits.map(c => {
const isQueued = folderObj.llmCandidates && folderObj.llmCandidates.some(fullHash => const isQueued = folderObj.llmCandidates && folderObj.llmCandidates.some(fullHash =>
fullHash.startsWith(c.hash) fullHash.startsWith(c.hash)
@@ -645,7 +555,7 @@ async function startLiveCountdown(folderObj, msLeft) {
</li>`; </li>`;
}).join(''); }).join('');
// --- PAGINATION --- // PAGINATION
if (pages > 1) { if (pages > 1) {
paginationEl.innerHTML = ` paginationEl.innerHTML = `
<button id="page-prev" class="px-2 py-1 border rounded" ${currentPage === 1 ? 'disabled' : ''}>«</button> <button id="page-prev" class="px-2 py-1 border rounded" ${currentPage === 1 ? 'disabled' : ''}>«</button>
@@ -660,7 +570,7 @@ async function startLiveCountdown(folderObj, msLeft) {
paginationEl.style.display = 'none'; paginationEl.style.display = 'none';
} }
// Diff-Buttons prüfen und ggf. deaktivieren // Diff-Buttons prüfen
contentList.querySelectorAll('.diff-btn').forEach(async btn => { contentList.querySelectorAll('.diff-btn').forEach(async btn => {
const hash = btn.dataset.hash; const hash = btn.dataset.hash;
const diffText = await window.electronAPI.diffCommit(folderObj, hash); const diffText = await window.electronAPI.diffCommit(folderObj, hash);
@@ -724,7 +634,7 @@ async function startLiveCountdown(folderObj, msLeft) {
}); });
}); });
// Checkout-Button: Seite neu bestimmen! // Checkout-Button
contentList.querySelectorAll('.checkout-btn').forEach(btn => { contentList.querySelectorAll('.checkout-btn').forEach(btn => {
btn.addEventListener('click', async () => { btn.addEventListener('click', async () => {
const hash = btn.dataset.hash; const hash = btn.dataset.hash;
@@ -761,9 +671,6 @@ async function startLiveCountdown(folderObj, msLeft) {
}); });
}); });
// --- Aktuellen Commit in die Mitte scrollen (falls vorhanden) ---
const currentEl = contentList.querySelector('li.current-commit'); const currentEl = contentList.querySelector('li.current-commit');
if (currentEl) { if (currentEl) {
currentEl.scrollIntoView({ behavior: 'smooth', block: 'center' }); currentEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
@@ -781,14 +688,11 @@ async function startLiveCountdown(folderObj, msLeft) {
if (sel) await renderContent(sel); if (sel) await renderContent(sel);
}); });
// Repo-Update Handling jetzt mit Lookup für folderObj
window.addEventListener('repo-updated', async e => { window.addEventListener('repo-updated', async e => {
closeDropdown(); closeDropdown();
const obj = await getFolderObjByPath(e.detail); const obj = await getFolderObjByPath(e.detail);
if (!obj) return; if (!obj) return;
// Hole aktuell selektierten Ordner
const selected = await window.electronAPI.getSelected(); const selected = await window.electronAPI.getSelected();
if (!selected || selected.path !== obj.path) { if (!selected || selected.path !== obj.path) {
await window.electronAPI.setSelected(obj); await window.electronAPI.setSelected(obj);
@@ -803,40 +707,17 @@ async function startLiveCountdown(folderObj, msLeft) {
window.electronAPI.showFolderContextMenu(titleEl.textContent); window.electronAPI.showFolderContextMenu(titleEl.textContent);
} }
}); });
/*
const commitBtn = document.getElementById('commitBtn');
commitBtn.addEventListener('click', async () => {
const folderObj = await window.electronAPI.getSelected();
if (!folderObj || !folderObj.path) {
alert('Kein Ordner ausgewählt!');
return;
}
const message = 'test'
commitBtn.disabled = true;
commitBtn.textContent = 'Committing…';
const result = await window.electronAPI.commitCurrentFolder(folderObj, message);
if (result.success) {
alert('Commit erfolgreich!');
await renderContent(folderObj);
} else {
alert('Commit fehlgeschlagen:\n' + result.error);
}
commitBtn.disabled = false;
commitBtn.textContent = 'Commit';
});
*/
window.electronAPI.onTrayToggleMonitoring(async (_e, folderPath) => { window.electronAPI.onTrayToggleMonitoring(async (_e, folderPath) => {
const folders = await window.electronAPI.getFolders(); const folders = await window.electronAPI.getFolders();
const folder = folders.find(f => f.path === folderPath); const folder = folders.find(f => f.path === folderPath);
if (folder) { if (folder) {
await window.electronAPI.setMonitoring(folder, !folder.monitoring); await window.electronAPI.setMonitoring(folder, !folder.monitoring);
await renderSidebar(); // <--- UI REFRESH! await renderSidebar();
const selected = await window.electronAPI.getSelected(); const selected = await window.electronAPI.getSelected();
if (selected && selected.path === folderPath) if (selected && selected.path === folderPath) {
await renderContent(folder); // falls im Content aktiv await renderContent(folder);
}
} }
}); });
@@ -845,8 +726,7 @@ async function startLiveCountdown(folderObj, msLeft) {
const folder = folders.find(f => f.path === folderPath); const folder = folders.find(f => f.path === folderPath);
if (folder) { if (folder) {
await window.electronAPI.removeFolder(folder); await window.electronAPI.removeFolder(folder);
await renderSidebar(); // <--- UI REFRESH! await renderSidebar();
// Wähle ggf. neuen Folder oder setze UI auf "No folder selected"
const all = await window.electronAPI.getFolders(); const all = await window.electronAPI.getFolders();
if (all.length === 0) { if (all.length === 0) {
titleEl.textContent = 'No folder selected'; titleEl.textContent = 'No folder selected';
@@ -860,47 +740,30 @@ async function startLiveCountdown(folderObj, msLeft) {
window.electronAPI.onTrayAddFolder(async () => { window.electronAPI.onTrayAddFolder(async () => {
await window.electronAPI.addFolder(); await window.electronAPI.addFolder();
await renderSidebar(); // <--- UI REFRESH! await renderSidebar();
const sel = await window.electronAPI.getSelected(); const sel = await window.electronAPI.getSelected();
if (sel) await renderContent(sel); if (sel) await renderContent(sel);
}); });
window.electronAPI.onFoldersLocationUpdated(folderObj => { window.electronAPI.onFoldersLocationUpdated(folderObj => {
const selector = `[data-folder-id="${encodeURIComponent(folderObj.path)}"]`; const selector = `[data-folder-id="${encodeURIComponent(folderObj.path)}"]`;
console.log('Selector:', selector);
const li = document.querySelector(selector); const li = document.querySelector(selector);
console.log('Gefundenes li:', li);
if (li) { if (li) {
if (folderObj.needsRelocation) { if (folderObj.needsRelocation) {
li.classList.add('needs-relocation'); li.classList.add('needs-relocation');
li.setAttribute.disabled; li.setAttribute('disabled', '');
// evtl. !-Icon einblenden
} else { } else {
li.classList.remove('needs-relocation'); li.classList.remove('needs-relocation');
// evtl. !-Icon ausblenden
} }
renderSidebar(); renderSidebar();
} }
}); });
/*
window.cat.beginSpeech();
let msg = "Ich bin wieder da!";
for (let ch of msg) {
setTimeout(() => window.cat.appendSpeech(ch), 50);
}
setTimeout(() => window.cat.endSpeech(), 2000);
*/
window.electronAPI.onCatBegin(() => window.cat && window.cat.beginSpeech()); window.electronAPI.onCatBegin(() => window.cat && window.cat.beginSpeech());
window.electronAPI.onCatChunk((_e, chunk) => window.cat && window.cat.appendSpeech(chunk)); window.electronAPI.onCatChunk((_e, chunk) => window.cat && window.cat.appendSpeech(chunk));
window.electronAPI.onCatEnd(() => window.cat && window.cat.endSpeech()); window.electronAPI.onCatEnd(() => window.cat && window.cat.endSpeech());
const speakToCat = msg => { const speakToCat = msg => {
window.cat.beginSpeech(); window.cat.beginSpeech();
// Zeig Nachricht Zeichen für Zeichen:
let i = 0; let i = 0;
function nextChar() { function nextChar() {
if (i < msg.length) { if (i < msg.length) {
@@ -912,34 +775,14 @@ async function startLiveCountdown(folderObj, msLeft) {
} }
nextChar(); nextChar();
}; };
/*
const slot = document.getElementById('catSlot');
const cat = new AnimeCat(slot, {
images: {
default: 'assets/cat/default.png',
eyesClosed: 'assets/cat/eyes_closed.png',
mouthOpen: 'assets/cat/mouth_open.png'
}
});
// Stelle sie global zur Verfügung:
window.cat = {
begin: () => cat.beginSpeech(),
streamText: txt => cat.appendSpeech(txt),
end: () => cat.endSpeech()
};
*/
// Hole die Commit-Stats beim Laden der Seite
window.electronAPI.getDailyCommitStats().then(stats => { window.electronAPI.getDailyCommitStats().then(stats => {
const today = new Date().toISOString().slice(0, 10); const today = new Date().toISOString().slice(0, 10);
const todayCount = stats[today] || 0; const todayCount = stats[today] || 0;
console.log('Commits heute:', todayCount);
window.updateCatGlow(todayCount); window.updateCatGlow(todayCount);
}); });
window.updateCatGlow = function(commitCount) { window.updateCatGlow = function(commitCount) {
if (window.cat) window.cat.animateCatGlow(commitCount); if (window.cat) window.cat.animateCatGlow(commitCount);
}; };
}); });