Client-Side State Stores
Relevant source files
The following files were used as context for generating this wiki page:
Client-Side State Stores in the Refined GitHub Projects extension manage transient, reactive data within the browser's content scripts and UI components. These stores facilitate synchronization between decoupled UI elements—such as the GitHub Projects table, the floating bulk actions bar, and background process trackers—without relying on a heavy state management framework.
The architecture utilizes a subscription-based pattern where stores hold internal state and notify listeners of changes. This ensures that when a user selects items in the GitHub UI, the extension can immediately update the "Bulk Actions Bar" or trigger modal transitions based on the current selection state. Sources: src/entries/content/index.ts:1-40, src/lib/selection-store.ts:1-50
Selection Store
The selectionStore is the primary mechanism for tracking user-selected items within the GitHub Projects table view. It maintains a set of unique identifiers (DOM IDs) representing issues or pull requests selected by the user. Sources: src/lib/selection-store.ts:1-10
Architecture and Data Flow
The store operates as a singleton that manages a Set of strings. It provides methods to add, remove, or batch-update selections. When the state changes, it iterates through a list of registered callback functions to notify subscribers. Sources: src/lib/selection-store.ts:5-25
The diagram shows how the Selection Store acts as a central hub between DOM interactions, keyboard shortcuts, and the extension UI.
Sources: src/components/bulk/bulk-actions-bar.tsx:110-150, src/lib/selection-store.ts:15-30
Key Methods
| Method | Description |
|---|---|
toggle(id: string) | Adds an ID if missing, or removes it if present. |
selectBatch(ids: string[]) | Replaces the entire selection with a new list of IDs. |
clear() | Empties the selection and notifies subscribers. |
subscribe(cb: () => void) | Registers a listener and returns an unsubscribe function. |
requestFocus() | Triggers a focus event for UI components to highlight actions. |
Sources: src/lib/selection-store.ts:12-65
Queue Store
The queueStore manages the state of background operations, specifically tracking the progress of bulk mutations that must run sequentially to avoid GitHub API rate limits. Sources: src/lib/queue-store.ts:1-15
Background Integration
The store receives updates from the background service worker via a messaging bridge. As the sequential queue processes items, it broadcasts queueStateUpdate messages. The content script's queueStore captures these to update the "Live Queue Tracker" UI. Sources: src/entries/background/helpers.ts:600-620, src/lib/queue-store.ts:20-40
Sequence of state updates from background mutations to the user interface.
Sources: src/entries/background/helpers.ts:605, src/lib/queue-store.ts:35
Sprint Management Stores
Sprint-related states are handled by specialized stores that manage modal visibility and confirmation flows for ending iterations.
Sprint Confirm End Store
The sprintConfirmEndStore is a simple boolean store used to trigger the "End Sprint" workflow. It allows disparate components, like the status bar button or the sprint widget, to signal that a sprint closure modal should be displayed. Sources: src/components/sprint/sprint-store.ts:1-10, src/components/sprint/sprint-modal.tsx:880-900
Logic and State transitions
- Acknowledge: When a user tracks a new sprint, the state moves to
acknowledged. - Active: Once the sprint duration starts, the status becomes
active. - End Sprint: Triggers a migration flow where incomplete items are moved to a target iteration.
Sources: src/components/sprint/sprint-modal.tsx:50-100, src/components/sprint/sprint-modal.tsx:890-950
Implementation Patterns
The stores in this project follow a consistent "Observer" implementation pattern to minimize dependencies. Sources: src/lib/selection-store.ts:5-15, src/lib/queue-store.ts:5-15
// Common Store Pattern
const listeners = new Set<() => void>();
let state = initialValue;
export const store = {
get: () => state,
set: (val) => {
state = val;
listeners.forEach(l => l());
},
subscribe: (cb) => {
listeners.add(cb);
return () => listeners.delete(cb);
}
};
Example of the generic subscription pattern used across the selection and sprint stores. Sources: src/lib/selection-store.ts:5-30, src/components/sprint/sprint-store.ts:1-12
Conclusion
Client-Side State Stores provide the reactive glue between the native GitHub DOM and the extension's React-based overlays. By centralizing selection and background progress in dedicated stores, the extension maintains a synchronized UI state even as the user interacts with complex project tables or long-running background tasks. Sources: src/entries/content/index.ts:15-50, src/components/bulk/bulk-actions-bar.tsx:100-150