diff --git a/src/renderer/components/ActivityBar/ActivityBar.tsx b/src/renderer/components/ActivityBar/ActivityBar.tsx index 8b113d2..20d6695 100644 --- a/src/renderer/components/ActivityBar/ActivityBar.tsx +++ b/src/renderer/components/ActivityBar/ActivityBar.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; import { useAppStore } from '../../store'; import { useI18n } from '../../i18n'; import { @@ -65,7 +65,71 @@ const GitIcon = () => ( export const ActivityBar: React.FC = () => { const { t } = useI18n(); - const { activeView, setActiveView, sidebarVisible, toggleSidebar, tabs, activeTabId } = useAppStore(); + const { activeView, setActiveView, sidebarVisible, toggleSidebar, tabs, activeTabId, activeProject } = useAppStore(); + const [pendingPullCount, setPendingPullCount] = useState(0); + const gitRefreshInFlightRef = useRef(false); + + const refreshPendingPullCount = useCallback(async () => { + if (gitRefreshInFlightRef.current) { + return; + } + + if (typeof navigator !== 'undefined' && navigator.onLine === false) { + setPendingPullCount(0); + return; + } + + if (!activeProject) { + setPendingPullCount(0); + return; + } + + const gitApi = window.electronAPI?.git; + if (!gitApi?.getRepoState || !gitApi?.fetch || !gitApi?.getRemoteState) { + setPendingPullCount(0); + return; + } + + gitRefreshInFlightRef.current = true; + try { + const targetProjectPath = activeProject.dataPath || (await window.electronAPI?.app.getDefaultProjectPath(activeProject.id)); + if (!targetProjectPath) { + setPendingPullCount(0); + return; + } + + const repoState = await gitApi.getRepoState(targetProjectPath); + if (!repoState.isRepo || !repoState.hasRemote) { + setPendingPullCount(0); + return; + } + + const fetchResult = await gitApi.fetch(targetProjectPath); + if (!fetchResult.success) { + return; + } + + const remoteState = await gitApi.getRemoteState(targetProjectPath); + setPendingPullCount(Math.max(0, remoteState.behind)); + } catch { + setPendingPullCount(0); + } finally { + gitRefreshInFlightRef.current = false; + } + }, [activeProject]); + + useEffect(() => { + void refreshPendingPullCount(); + + const intervalId = globalThis.setInterval(() => { + void refreshPendingPullCount(); + }, 30000); + + return () => { + globalThis.clearInterval(intervalId); + }; + }, [refreshPendingPullCount]); + const snapshot: ActivitySnapshot = { activeView, sidebarVisible, @@ -136,6 +200,7 @@ export const ActivityBar: React.FC = () => { title={getTitle('git')} > + {pendingPullCount > 0 ? {pendingPullCount > 99 ? '99+' : pendingPullCount} : null}