feat: git log limited to last 20

This commit is contained in:
2026-02-21 19:05:11 +01:00
parent 73a8b6803f
commit e0536bb4f7
9 changed files with 237 additions and 6 deletions

View File

@@ -732,7 +732,9 @@ export class GitEngine {
}));
}
const remoteHistory = await git.log([status.tracking, '--max-count', String(limit)]);
const behindCount = typeof status.behind === 'number' ? status.behind : Number(status.behind ?? 0);
const remoteHistoryLimit = Math.max(limit, limit + Math.max(behindCount, 0));
const remoteHistory = await git.log([status.tracking, '--max-count', String(remoteHistoryLimit)]);
type CommitLike = {
hash: string;
@@ -762,9 +764,8 @@ export class GitEngine {
}
}
return Array.from(combined.values())
const classifiedEntries = Array.from(combined.values())
.sort((first, second) => new Date(second.date).getTime() - new Date(first.date).getTime())
.slice(0, limit)
.map((entry) => {
const inLocal = localMap.has(entry.hash);
const inRemote = remoteMap.has(entry.hash);
@@ -779,6 +780,12 @@ export class GitEngine {
syncStatus,
};
});
const remoteOnlyEntries = classifiedEntries.filter((entry) => entry.syncStatus === 'remote-only');
const localAndSyncedEntries = classifiedEntries.filter((entry) => entry.syncStatus !== 'remote-only').slice(0, limit);
return [...localAndSyncedEntries, ...remoteOnlyEntries]
.sort((first, second) => new Date(second.date).getTime() - new Date(first.date).getTime());
}
async getFileHistory(projectPath: string, filePath: string, limit = 50): Promise<GitHistoryEntry[]> {

View File

@@ -7,6 +7,7 @@ import './GitSidebar.css';
import '../Sidebar/Sidebar.css';
type GitSidebarStatusFile = { path: string; status: string };
const HISTORY_PAGE_SIZE = 20;
const mergeStatusFilesIncremental = (
previous: GitSidebarStatusFile[],
@@ -45,6 +46,8 @@ export const GitSidebar: React.FC = () => {
const [commitMessage, setCommitMessage] = useState('');
const [historyLoading, setHistoryLoading] = useState(false);
const [historyEntries, setHistoryEntries] = useState<GitHistoryEntry[]>([]);
const [historyLocalLimit, setHistoryLocalLimit] = useState(HISTORY_PAGE_SIZE);
const [hasMoreLocalHistory, setHasMoreLocalHistory] = useState(false);
const [remoteState, setRemoteState] = useState<GitRemoteStateDto | null>(null);
const [remoteStateError, setRemoteStateError] = useState<string | null>(null);
const [initProgress, setInitProgress] = useState<GitInitProgress | null>(null);
@@ -56,12 +59,13 @@ export const GitSidebar: React.FC = () => {
const remoteRefreshInFlightRef = useRef(false);
const refreshRepoDetails = useCallback(
async (targetProjectPath: string, options?: { background?: boolean }) => {
async (targetProjectPath: string, options?: { background?: boolean; historyLimit?: number }) => {
if (statusRefreshInFlightRef.current) {
return;
}
const background = options?.background ?? false;
const historyLimit = options?.historyLimit ?? historyLocalLimit;
statusRefreshInFlightRef.current = true;
if (!background) {
@@ -72,10 +76,12 @@ export const GitSidebar: React.FC = () => {
try {
const [status, history] = await Promise.all([
window.electronAPI.git.getStatus(targetProjectPath),
window.electronAPI.git.getHistory(targetProjectPath, 20),
window.electronAPI.git.getHistory(targetProjectPath, historyLimit),
]);
setStatusFiles((previous) => mergeStatusFilesIncremental(previous, status.files));
setHistoryEntries(history);
const nonRemoteOnlyCount = history.filter((entry) => entry.syncStatus !== 'remote-only').length;
setHasMoreLocalHistory(nonRemoteOnlyCount >= historyLimit);
} finally {
statusRefreshInFlightRef.current = false;
if (!background) {
@@ -84,7 +90,7 @@ export const GitSidebar: React.FC = () => {
}
}
},
[],
[historyLocalLimit],
);
const refreshRemoteState = useCallback(
@@ -192,6 +198,7 @@ export const GitSidebar: React.FC = () => {
if (!availability.gitFound) {
setError(tr('gitSidebar.error.gitMissing'));
setIsRepo(false);
setHasMoreLocalHistory(false);
return;
}
@@ -201,6 +208,7 @@ export const GitSidebar: React.FC = () => {
if (!resolvedProjectPath) {
setError(tr('gitSidebar.error.noActiveProject'));
setIsRepo(false);
setHasMoreLocalHistory(false);
return;
}
@@ -220,6 +228,7 @@ export const GitSidebar: React.FC = () => {
} else {
setStatusFiles([]);
setHistoryEntries([]);
setHasMoreLocalHistory(false);
setRemoteState(null);
setRemoteStateError(null);
}
@@ -229,6 +238,7 @@ export const GitSidebar: React.FC = () => {
setHasRemote(false);
setStatusFiles([]);
setHistoryEntries([]);
setHasMoreLocalHistory(false);
setRemoteState(null);
setRemoteStateError(null);
} finally {
@@ -240,6 +250,11 @@ export const GitSidebar: React.FC = () => {
void loadRepoState();
}, [loadRepoState]);
useEffect(() => {
setHistoryLocalLimit(HISTORY_PAGE_SIZE);
setHasMoreLocalHistory(false);
}, [activeProject?.id]);
useEffect(() => {
const unsubscribe = window.electronAPI.git.onInitProgress((progress) => {
setInitProgress(progress);
@@ -396,6 +411,17 @@ export const GitSidebar: React.FC = () => {
}
};
const handleLoadMoreHistory = async () => {
const effectiveProjectPath = projectPath ?? (await resolveProjectPath());
if (!effectiveProjectPath) {
return;
}
const nextLimit = historyLocalLimit + HISTORY_PAGE_SIZE;
setHistoryLocalLimit(nextLimit);
void refreshRepoDetails(effectiveProjectPath, { historyLimit: nextLimit });
};
if (loading) {
return (
<div className="git-sidebar">
@@ -572,6 +598,16 @@ export const GitSidebar: React.FC = () => {
))}
</div>
)}
{!historyLoading && hasMoreLocalHistory && (
<button
type="button"
className="git-sidebar-button"
onClick={() => void handleLoadMoreHistory()}
disabled={statusRefreshInFlightRef.current}
>
{tr('gitSidebar.action.loadMoreHistory')}
</button>
)}
{currentBranch && <div className="git-sidebar-empty-state">{tr('gitSidebar.branch', { branch: currentBranch })}</div>}
{remoteState?.hasUpstream && remoteState.localBranch && remoteState.upstreamBranch && (
<div className="git-sidebar-empty-state">{remoteState.localBranch} {remoteState.upstreamBranch}</div>

View File

@@ -276,6 +276,7 @@
"gitSidebar.action.pruning": "Bereinigen...",
"gitSidebar.action.commit": "Commit erstellen",
"gitSidebar.action.committing": "Commit wird erstellt...",
"gitSidebar.action.loadMoreHistory": "Mehr laden",
"gitSidebar.action.initializeGit": "Git initialisieren",
"gitSidebar.action.initializing": "Initialisieren...",
"gitSidebar.openChanges": "Offene Änderungen ({count})",

View File

@@ -276,6 +276,7 @@
"gitSidebar.action.pruning": "Pruning...",
"gitSidebar.action.commit": "Commit",
"gitSidebar.action.committing": "Committing...",
"gitSidebar.action.loadMoreHistory": "Load more",
"gitSidebar.action.initializeGit": "Initialize Git",
"gitSidebar.action.initializing": "Initializing...",
"gitSidebar.openChanges": "Open changes ({count})",

View File

@@ -276,6 +276,7 @@
"gitSidebar.action.pruning": "Podando...",
"gitSidebar.action.commit": "Realizar commit",
"gitSidebar.action.committing": "Haciendo commit...",
"gitSidebar.action.loadMoreHistory": "Cargar más",
"gitSidebar.action.initializeGit": "Inicializar Git",
"gitSidebar.action.initializing": "Inicializando...",
"gitSidebar.openChanges": "Cambios abiertos ({count})",

View File

@@ -276,6 +276,7 @@
"gitSidebar.action.pruning": "Purge...",
"gitSidebar.action.commit": "Valider",
"gitSidebar.action.committing": "Commit en cours...",
"gitSidebar.action.loadMoreHistory": "Charger plus",
"gitSidebar.action.initializeGit": "Initialiser Git",
"gitSidebar.action.initializing": "Initialisation...",
"gitSidebar.openChanges": "Modifications ouvertes ({count})",

View File

@@ -276,6 +276,7 @@
"gitSidebar.action.pruning": "Pulizia...",
"gitSidebar.action.commit": "Registra commit",
"gitSidebar.action.committing": "Commit in corso...",
"gitSidebar.action.loadMoreHistory": "Carica altro",
"gitSidebar.action.initializeGit": "Inizializza Git",
"gitSidebar.action.initializing": "Inizializzazione...",
"gitSidebar.openChanges": "Modifiche aperte ({count})",