feat(git-diff): add React Query with pull-to-refresh and cleaner diff display

- Add useGitDiffQuery hook using React Query for caching and revalidation
- Add sendRpcRequest utility for promisified WebSocket RPC with requestId matching
- Add requestId to git_diff_request/response for proper request correlation
- Enable pull-to-refresh via RefreshControl in GitDiffPane
- Auto-revalidate when sidebar opens with "changes" tab active
- Clean up diff display: remove metadata noise, strip +/- prefixes
- Default both sidebars open on web platform

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mohamed Boudra
2026-01-05 21:27:35 +07:00
co-authored by Claude Opus 4.5
parent 8c33df472f
commit 348242541c
9 changed files with 486 additions and 65 deletions
@@ -1,6 +1,7 @@
import { create } from "zustand";
import { persist, createJSONStorage } from "zustand/middleware";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { Platform } from "react-native";
type ExplorerTab = "changes" | "files";
export type ViewMode = "list" | "grid";
@@ -10,6 +11,8 @@ export const DEFAULT_EXPLORER_SIDEBAR_WIDTH = 400;
export const MIN_EXPLORER_SIDEBAR_WIDTH = 280;
export const MAX_EXPLORER_SIDEBAR_WIDTH = 800;
const DEFAULT_OPEN = Platform.OS === "web";
interface ExplorerSidebarState {
isOpen: boolean;
activeTab: ExplorerTab;
@@ -32,7 +35,7 @@ function clampWidth(width: number): number {
export const useExplorerSidebarStore = create<ExplorerSidebarState>()(
persist(
(set) => ({
isOpen: false,
isOpen: DEFAULT_OPEN,
activeTab: "changes",
width: DEFAULT_EXPLORER_SIDEBAR_WIDTH,
viewMode: "list",
+4 -1
View File
@@ -1,6 +1,7 @@
import { create } from "zustand";
import { persist, createJSONStorage } from "zustand/middleware";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { Platform } from "react-native";
interface SidebarState {
isOpen: boolean;
@@ -9,10 +10,12 @@ interface SidebarState {
close: () => void;
}
const DEFAULT_OPEN = Platform.OS === "web";
export const useSidebarStore = create<SidebarState>()(
persist(
(set) => ({
isOpen: false,
isOpen: DEFAULT_OPEN,
toggle: () => set((state) => ({ isOpen: !state.isOpen })),
open: () => set({ isOpen: true }),
close: () => set({ isOpen: false }),