feat(workspace): persist workspace UI filters and disable drag-drop
Add a lightweight workspace preferences helper to store optional UI settings in localStorage and integrate it with the issues views so filters, queries, and view mode are restored per source. The integration board now remembers repository and query filters, and the Issue Center restores state filters and view mode across sessions. Also disable drag and drop for the main Tauri window to avoid accidental file drops. - Add read/write helpers for workspace preferences in localStorage - Persist and restore filters, queries, and view mode for issue views - Disable window drag-and-drop to prevent accidental file drops
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
import { issueTone, issueStateLabel } from "../issuePresentation";
|
||||
import IntegrationBoardView from "./IntegrationBoardView.svelte";
|
||||
import SelectMenu from "./SelectMenu.svelte";
|
||||
import { readWorkspacePreferences, writeWorkspacePreferences } from "../workspacePreferences";
|
||||
import { listIntegrationIssues, closeIntegrationIssue, openInBrowser } from "../git";
|
||||
import { configuredIntegrationSources, integrationCredentialKey } from "../integrations";
|
||||
import type { GitIntegrationSettings, IntegrationIssue, StoredCredential } from "../types";
|
||||
@@ -44,6 +45,7 @@
|
||||
let mounted = false;
|
||||
let generation = 0;
|
||||
let lastKey = "";
|
||||
const preferenceKey = "gitty.issues.v1";
|
||||
$: de = language === "de";
|
||||
$: sources = configuredIntegrationSources(integrations);
|
||||
$: source = sources.find(item => item.id === sourceId) ?? sources[0];
|
||||
@@ -56,11 +58,14 @@
|
||||
issues = saved?.issues ?? [];
|
||||
nextCursor = saved?.nextCursor ?? null;
|
||||
selectedId = "";
|
||||
stateFilter = "";
|
||||
repositoryFilter = "";
|
||||
restoreFilters(sourceKey);
|
||||
error = "";
|
||||
if (source) void loadIssues();
|
||||
}
|
||||
$: if (mounted && sourceKey && sourceKey === lastKey) {
|
||||
writeWorkspacePreferences(preferenceKey, { sourceId: source?.id ?? "", viewMode });
|
||||
writeWorkspacePreferences(`${preferenceKey}:${sourceKey}`, { stateFilter, repositoryFilter, query });
|
||||
}
|
||||
$: normalizedQuery = query.trim().toLocaleLowerCase();
|
||||
$: filtered = issues.filter(issue => (!repositoryFilter || issue.repositoryName === repositoryFilter) && (!stateFilter || issue.state === stateFilter) &&
|
||||
`${issue.title} ${issue.number} ${issue.repositoryName} ${issue.author} ${issue.labels.join(" ")} ${issue.assignees.join(" ")}`.toLocaleLowerCase().includes(normalizedQuery));
|
||||
@@ -71,6 +76,9 @@
|
||||
$: description = selected ? plainDescription(selected) : "";
|
||||
|
||||
onMount(() => {
|
||||
const saved = readWorkspacePreferences(preferenceKey);
|
||||
sourceId = saved.sourceId ?? "";
|
||||
viewMode = saved.viewMode === "board" ? "board" : "list";
|
||||
mounted = true;
|
||||
reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||||
const closeDetailsOutside = (event: PointerEvent) => {
|
||||
@@ -87,6 +95,13 @@
|
||||
});
|
||||
onDestroy(() => { generation++; });
|
||||
|
||||
function restoreFilters(key: string) {
|
||||
const saved = readWorkspacePreferences(`${preferenceKey}:${key}`);
|
||||
stateFilter = saved.stateFilter ?? "";
|
||||
repositoryFilter = saved.repositoryFilter ?? "";
|
||||
query = saved.query ?? "";
|
||||
}
|
||||
|
||||
async function withTimeout<T>(promise: Promise<T>, ms: number): Promise<T> {
|
||||
let timer: ReturnType<typeof setTimeout>;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user