diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 852b40b..952c0b8 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -3,6 +3,7 @@ import { Settings, Calendar, Search, Moon, Sun, LogOut, RefreshCw, TrendingUp, G import { useAppStore } from '../store/useAppStore'; import { GitHubApiService } from '../services/githubApi'; import { useDialog } from '../hooks/useDialog'; +import { forceSyncToBackend } from '../services/autoSync'; export const Header: React.FC = () => { const { @@ -101,6 +102,9 @@ export const Header: React.FC = () => { setRepositories(mergedRepositories); + // Force-push to backend immediately (bypass 2s debounce) so data survives a page refresh + forceSyncToBackend().catch(console.error); + // Note: Release fetching is now handled by the Refresh button in Release Timeline // Header sync only syncs the starred repos list diff --git a/src/services/autoSync.ts b/src/services/autoSync.ts index cb10f5e..611bdbc 100644 --- a/src/services/autoSync.ts +++ b/src/services/autoSync.ts @@ -128,8 +128,20 @@ export async function syncFromBackend(): Promise { // Update store then commit hash — hash only changes if setter succeeds if (changed.repos && reposResult.status === 'fulfilled') { - state.setRepositories(reposResult.value.repositories); - _lastHash.repos = hashes.repos; + const backendRepos = reposResult.value.repositories; + const localRepos = state.repositories; + // Distinguish first-ever sync (bootstrap) from an authoritative empty backend. + // On bootstrap the hash is still '' — preserve local cache and push it to backend. + // On subsequent syncs, accept the backend state even if empty (e.g. user cleared + // stars from another device). + const isBootstrapEmpty = + backendRepos.length === 0 && localRepos.length > 0 && _lastHash.repos === ''; + if (isBootstrapEmpty) { + _hasPendingPush = true; + } else { + state.setRepositories(backendRepos); + _lastHash.repos = hashes.repos; + } } if (changed.releases && releasesResult.status === 'fulfilled') { state.setReleases(releasesResult.value.releases);