feat(settings): implement persistent auto-refresh functionality
Adds a configurable and persistable auto-refresh setting to the application's settings dialog. This feature allows users to control whether the repository view automatically updates its status, branch information, and remote tracking in the background. The logic is integrated across core components to manage state changes and provide visual feedback to the user. - Auto-refresh state is now persistent and managed via local storage. - Updated settings dialog UI to include a dedicated toggle for auto-refresh. - Removed manual auto-refresh toggling from the repository toolbar component.
This commit is contained in:
+9
-11
@@ -185,6 +185,7 @@
|
|||||||
const ANALYTICS_SETTINGS_KEY = "gitlite.analyticsSettings.v1";
|
const ANALYTICS_SETTINGS_KEY = "gitlite.analyticsSettings.v1";
|
||||||
const APP_THEME_KEY = "gitlite.theme.v1";
|
const APP_THEME_KEY = "gitlite.theme.v1";
|
||||||
const APP_LANGUAGE_KEY = "gitlite.language.v1";
|
const APP_LANGUAGE_KEY = "gitlite.language.v1";
|
||||||
|
const AUTO_REFRESH_ENABLED_KEY = "gitlite.autoRefreshEnabled.v1";
|
||||||
const COMMIT_PANEL_HEIGHT_KEY = "gitlite.commitPanelHeight.v1";
|
const COMMIT_PANEL_HEIGHT_KEY = "gitlite.commitPanelHeight.v1";
|
||||||
const LEFT_SIDEBAR_WIDTH_KEY = "gitlite.leftSidebarWidth.v1";
|
const LEFT_SIDEBAR_WIDTH_KEY = "gitlite.leftSidebarWidth.v1";
|
||||||
const LEFT_BRANCH_PANEL_HEIGHT_KEY = "gitlite.leftBranchPanelHeight.v1";
|
const LEFT_BRANCH_PANEL_HEIGHT_KEY = "gitlite.leftBranchPanelHeight.v1";
|
||||||
@@ -311,7 +312,7 @@
|
|||||||
let conflictTarget = "";
|
let conflictTarget = "";
|
||||||
let conflict: ConflictFile | null = null;
|
let conflict: ConflictFile | null = null;
|
||||||
let preparedResolutions: Record<string, PreparedResolution> = {};
|
let preparedResolutions: Record<string, PreparedResolution> = {};
|
||||||
let autoRefreshEnabled = true;
|
let autoRefreshEnabled = loadStoredBoolean(AUTO_REFRESH_ENABLED_KEY, true);
|
||||||
let autoRefreshInFlight = false;
|
let autoRefreshInFlight = false;
|
||||||
let credDialogOpen = false;
|
let credDialogOpen = false;
|
||||||
let credDialogAction: CredentialAction | null = null;
|
let credDialogAction: CredentialAction | null = null;
|
||||||
@@ -868,15 +869,19 @@
|
|||||||
if (appTheme === "system") applyThemePreference(appTheme);
|
if (appTheme === "system") applyThemePreference(appTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
function saveAppSettings(next: AnalyticsSettings, nextTheme: AppTheme, nextLanguage: AppLanguage) {
|
function saveAppSettings(next: AnalyticsSettings, nextTheme: AppTheme, nextLanguage: AppLanguage, nextAutoRefresh: boolean) {
|
||||||
|
const autoRefreshWasEnabled = autoRefreshEnabled;
|
||||||
analyticsSettings = next;
|
analyticsSettings = next;
|
||||||
appTheme = nextTheme;
|
appTheme = nextTheme;
|
||||||
appLanguage = nextLanguage;
|
appLanguage = nextLanguage;
|
||||||
|
autoRefreshEnabled = nextAutoRefresh;
|
||||||
persistAnalyticsSettings(next);
|
persistAnalyticsSettings(next);
|
||||||
persistThemePreference(nextTheme);
|
persistThemePreference(nextTheme);
|
||||||
persistLanguagePreference(nextLanguage);
|
persistLanguagePreference(nextLanguage);
|
||||||
|
persistStoredBoolean(AUTO_REFRESH_ENABLED_KEY, nextAutoRefresh);
|
||||||
appSettingsOpen = false;
|
appSettingsOpen = false;
|
||||||
if (next.enabled) trackEvent("settings_saved", { analytics_enabled: 1, theme: nextTheme, language: nextLanguage });
|
if (nextAutoRefresh && !autoRefreshWasEnabled) void autoRefreshTick();
|
||||||
|
if (next.enabled) trackEvent("settings_saved", { analytics_enabled: 1, theme: nextTheme, language: nextLanguage, auto_refresh: nextAutoRefresh ? 1 : 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateCommitMessage(message: string) {
|
function updateCommitMessage(message: string) {
|
||||||
@@ -982,11 +987,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function toggleAutoRefresh() {
|
|
||||||
autoRefreshEnabled = !autoRefreshEnabled;
|
|
||||||
if (autoRefreshEnabled) void autoRefreshTick();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── Updates ────────────────────────────────────────────────────────────────
|
// ── Updates ────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
async function checkForUpdates() {
|
async function checkForUpdates() {
|
||||||
@@ -3609,8 +3609,6 @@
|
|||||||
{operation}
|
{operation}
|
||||||
ahead={status?.ahead ?? 0}
|
ahead={status?.ahead ?? 0}
|
||||||
behind={status?.behind ?? 0}
|
behind={status?.behind ?? 0}
|
||||||
{autoRefreshEnabled}
|
|
||||||
{autoRefreshInFlight}
|
|
||||||
language={appLanguage}
|
language={appLanguage}
|
||||||
onFetch={fetchRepo}
|
onFetch={fetchRepo}
|
||||||
onPull={pullRepo}
|
onPull={pullRepo}
|
||||||
@@ -3621,7 +3619,6 @@
|
|||||||
onInteractiveRebase={openInteractiveRebase}
|
onInteractiveRebase={openInteractiveRebase}
|
||||||
onReflog={openReflog}
|
onReflog={openReflog}
|
||||||
onOpenInExplorer={openActiveRepoInExplorer}
|
onOpenInExplorer={openActiveRepoInExplorer}
|
||||||
onToggleAutoRefresh={toggleAutoRefresh}
|
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@@ -4191,6 +4188,7 @@
|
|||||||
analytics={analyticsSettings}
|
analytics={analyticsSettings}
|
||||||
theme={appTheme}
|
theme={appTheme}
|
||||||
language={appLanguage}
|
language={appLanguage}
|
||||||
|
autoRefresh={autoRefreshEnabled}
|
||||||
onSave={saveAppSettings}
|
onSave={saveAppSettings}
|
||||||
onClose={() => { appSettingsOpen = false; }}
|
onClose={() => { appSettingsOpen = false; }}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -18,8 +18,6 @@
|
|||||||
export let operation: string = "";
|
export let operation: string = "";
|
||||||
export let ahead: number = 0;
|
export let ahead: number = 0;
|
||||||
export let behind: number = 0;
|
export let behind: number = 0;
|
||||||
export let autoRefreshEnabled: boolean = true;
|
|
||||||
export let autoRefreshInFlight: boolean = false;
|
|
||||||
export let language: "en" | "de" = "en";
|
export let language: "en" | "de" = "en";
|
||||||
export let onFetch: () => void = () => {};
|
export let onFetch: () => void = () => {};
|
||||||
export let onPull: () => void = () => {};
|
export let onPull: () => void = () => {};
|
||||||
@@ -30,7 +28,6 @@
|
|||||||
export let onInteractiveRebase: () => void = () => {};
|
export let onInteractiveRebase: () => void = () => {};
|
||||||
export let onReflog: () => void = () => {};
|
export let onReflog: () => void = () => {};
|
||||||
export let onOpenInExplorer: () => void = () => {};
|
export let onOpenInExplorer: () => void = () => {};
|
||||||
export let onToggleAutoRefresh: () => void = () => {};
|
|
||||||
|
|
||||||
let historyOpen = false;
|
let historyOpen = false;
|
||||||
let toolbarElement: HTMLDivElement;
|
let toolbarElement: HTMLDivElement;
|
||||||
@@ -192,26 +189,14 @@
|
|||||||
</button>
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="repo-action icon-action"
|
class="repo-action"
|
||||||
onclick={onRefresh}
|
onclick={onRefresh}
|
||||||
disabled={isBusy || !hasRepository}
|
disabled={isBusy || !hasRepository}
|
||||||
title={isGerman ? "Manuell aktualisieren" : "Refresh now"}
|
title={isGerman ? "Manuell aktualisieren" : "Refresh now"}
|
||||||
aria-label={isGerman ? "Manuell aktualisieren" : "Refresh now"}
|
aria-label={isGerman ? "Manuell aktualisieren" : "Refresh now"}
|
||||||
>
|
>
|
||||||
<RefreshCw class={operation === "Refreshing" ? "spin" : ""} size={15} aria-hidden="true" />
|
<RefreshCw class={operation === "Refreshing" ? "spin" : ""} size={16} aria-hidden="true" />
|
||||||
</button>
|
<span class="repo-action-label utility-label">{isGerman ? "Aktualisieren" : "Refresh"}</span>
|
||||||
|
|
||||||
<button
|
|
||||||
class="repo-auto-toggle"
|
|
||||||
class:active={autoRefreshEnabled}
|
|
||||||
onclick={onToggleAutoRefresh}
|
|
||||||
aria-pressed={autoRefreshEnabled}
|
|
||||||
title={autoRefreshEnabled
|
|
||||||
? (isGerman ? "Auto-Aktualisierung ausschalten" : "Turn auto-refresh off")
|
|
||||||
: (isGerman ? "Auto-Aktualisierung einschalten" : "Turn auto-refresh on")}
|
|
||||||
>
|
|
||||||
<span>{isGerman ? "Auto" : "Auto"}</span>
|
|
||||||
<span class="repo-switch" class:busy={autoRefreshInFlight} aria-hidden="true"><span></span></span>
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,26 +1,29 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Check, Languages, Settings, X } from "@lucide/svelte";
|
import { Check, Languages, RefreshCw, Settings, X } from "@lucide/svelte";
|
||||||
import type { AnalyticsSettings, AppLanguage, AppTheme } from "../types";
|
import type { AnalyticsSettings, AppLanguage, AppTheme } from "../types";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
analytics: AnalyticsSettings;
|
analytics: AnalyticsSettings;
|
||||||
theme: AppTheme;
|
theme: AppTheme;
|
||||||
language: AppLanguage;
|
language: AppLanguage;
|
||||||
onSave: (settings: AnalyticsSettings, theme: AppTheme, language: AppLanguage) => void;
|
autoRefresh: boolean;
|
||||||
|
onSave: (settings: AnalyticsSettings, theme: AppTheme, language: AppLanguage, autoRefresh: boolean) => void;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
let { analytics, theme = "system", language = "en", onSave = () => {}, onClose = () => {} }: Props = $props();
|
let { analytics, theme = "system", language = "en", autoRefresh = true, onSave = () => {}, onClose = () => {} }: Props = $props();
|
||||||
|
|
||||||
let analyticsEnabled = $state(true);
|
let analyticsEnabled = $state(true);
|
||||||
let selectedTheme = $state<AppTheme>("system");
|
let selectedTheme = $state<AppTheme>("system");
|
||||||
let selectedLanguage = $state<AppLanguage>("en");
|
let selectedLanguage = $state<AppLanguage>("en");
|
||||||
|
let autoRefreshEnabled = $state(true);
|
||||||
const isGerman = $derived(selectedLanguage === "de");
|
const isGerman = $derived(selectedLanguage === "de");
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
analyticsEnabled = analytics.enabled;
|
analyticsEnabled = analytics.enabled;
|
||||||
selectedTheme = theme;
|
selectedTheme = theme;
|
||||||
selectedLanguage = language;
|
selectedLanguage = language;
|
||||||
|
autoRefreshEnabled = autoRefresh;
|
||||||
});
|
});
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
@@ -28,7 +31,7 @@
|
|||||||
...analytics,
|
...analytics,
|
||||||
enabled: analyticsEnabled,
|
enabled: analyticsEnabled,
|
||||||
noticeSeen: true,
|
noticeSeen: true,
|
||||||
}, selectedTheme, selectedLanguage);
|
}, selectedTheme, selectedLanguage, autoRefreshEnabled);
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -70,6 +73,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section class="settings-section">
|
||||||
|
<header>
|
||||||
|
<RefreshCw size={16} aria-hidden="true" />
|
||||||
|
<div>
|
||||||
|
<span class="eyebrow">Repository</span>
|
||||||
|
<h3>{isGerman ? "Automatische Aktualisierung" : "Auto refresh"}</h3>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<label class="settings-toggle-row">
|
||||||
|
<input type="checkbox" bind:checked={autoRefreshEnabled} />
|
||||||
|
<span>
|
||||||
|
<strong>{isGerman ? "Repositories automatisch aktualisieren" : "Refresh repositories automatically"}</strong>
|
||||||
|
<small>{isGerman ? "Aktualisiert Arbeitsbereich, Branch-Status und Remotes regelmäßig im Hintergrund." : "Periodically refreshes the working tree, branch status, and remotes in the background."}</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section class="settings-section">
|
<section class="settings-section">
|
||||||
<header>
|
<header>
|
||||||
<Languages size={16} aria-hidden="true" />
|
<Languages size={16} aria-hidden="true" />
|
||||||
|
|||||||
Reference in New Issue
Block a user