File size: 2,576 Bytes
709db16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/** Shared pending-resolve queue: Home banner / Log after-save / Entry detail. */

import { createContext } from "preact";
import { useCallback, useContext, useMemo, useState } from "preact/hooks";
import type { ComponentChildren } from "preact";
import { listPending, type Entry } from "../api";
import { ResolvePendingSheet } from "./ResolvePendingSheet";

type PendingApi = {
  openResolve: (entries?: Entry[]) => void;
  openResolveId: (id: string, fallback?: Entry) => void;
  refreshPendingSignal: number;
  bumpRefresh: () => void;
};

const PendingContext = createContext<PendingApi | null>(null);

export function usePendingResolve(): PendingApi {
  const ctx = useContext(PendingContext);
  if (!ctx) throw new Error("usePendingResolve requires PendingResolveProvider");
  return ctx;
}

export function PendingResolveProvider({ children }: { children: ComponentChildren }) {
  const [queue, setQueue] = useState<Entry[]>([]);
  const [open, setOpen] = useState(false);
  const [refreshPendingSignal, setRefresh] = useState(0);

  const bumpRefresh = useCallback(() => {
    setRefresh((n) => n + 1);
  }, []);

  const openResolve = useCallback(async (entries?: Entry[]) => {
    if (entries && entries.length) {
      setQueue(entries);
      setOpen(true);
      return;
    }
    try {
      const data = await listPending(50);
      if (!data.items.length) return;
      setQueue(data.items);
      setOpen(true);
    } catch {
      // leave closed
    }
  }, []);

  const openResolveId = useCallback(async (id: string, fallback?: Entry) => {
    if (fallback && fallback.id === id) {
      setQueue([fallback]);
      setOpen(true);
      return;
    }
    try {
      const data = await listPending(50);
      const hit = data.items.find((item) => item.id === id);
      const rest = data.items.filter((item) => item.id !== id);
      setQueue(hit ? [hit, ...rest] : fallback ? [fallback, ...rest] : rest);
      setOpen(true);
    } catch {
      if (fallback) {
        setQueue([fallback]);
        setOpen(true);
      }
    }
  }, []);

  const api = useMemo(
    () => ({ openResolve, openResolveId, refreshPendingSignal, bumpRefresh }),
    [openResolve, openResolveId, refreshPendingSignal, bumpRefresh],
  );

  return (
    <PendingContext.Provider value={api}>
      {children}
      <ResolvePendingSheet
        open={open}
        queue={queue}
        onClose={() => {
          setOpen(false);
          setQueue([]);
        }}
        onQueueChange={setQueue}
        onResolved={bumpRefresh}
      />
    </PendingContext.Provider>
  );
}