summaryrefslogtreecommitdiffhomepage
path: root/gui/src/renderer/lib/api-access-methods.ts
blob: fd78d1484a99e20fb1c392c3a0e7141b857afcba (plain)
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
import { useCallback, useRef, useState } from 'react';

import { CustomProxy } from '../../shared/daemon-rpc-types';
import { useScheduler } from '../../shared/scheduler';
import { useAppContext } from '../context';
import { useBoolean } from './utilityHooks';

export function useApiAccessMethodTest(
  autoReset = true,
  minDuration = 0,
): [
  boolean,
  boolean | undefined,
  (method: CustomProxy | string) => Promise<boolean | void>,
  () => void,
] {
  const { testApiAccessMethodById, testCustomApiAccessMethod } = useAppContext();
  const delayScheduler = useScheduler();

  // Whether or not the method is currently being tested.
  const [testing, setTesting, unsetTesting] = useBoolean();
  const [testResult, setTestResult] = useState<boolean>();
  // We keep the promise for the most recent test to compare it when we receive the results to know
  // if it's canceled or not.
  const lastTestPromise = useRef<Promise<boolean>>();

  // A few seconds after the test has finished the result should not be displayed anymore. This
  // scheduler is used to clear it.
  const testResultResetScheduler = useScheduler();

  const testApiAccessMethod = useCallback(async (method: CustomProxy | string) => {
    testResultResetScheduler.cancel();
    setTestResult(undefined);

    setTesting();
    let reachable;
    let testPromise;

    const submitTimestamp = Date.now();
    try {
      testPromise =
        typeof method === 'string'
          ? testApiAccessMethodById(method)
          : testCustomApiAccessMethod(method);

      lastTestPromise.current = testPromise;
      reachable = await testPromise;
    } catch {
      reachable = false;
    }

    // Make sure the loading text is displayed for at least `minDuration` milliseconds.
    const submitDuration = Date.now() - submitTimestamp;
    if (submitDuration < minDuration) {
      await new Promise<void>((resolve) =>
        delayScheduler.schedule(resolve, minDuration - submitDuration),
      );
    }

    if (testPromise !== lastTestPromise.current) {
      return;
    }

    setTestResult(reachable);
    unsetTesting();

    if (autoReset) {
      testResultResetScheduler.schedule(() => setTestResult(undefined), 5000);
    }

    return reachable;
  }, []);

  const resetTestResult = useCallback(() => {
    lastTestPromise.current = undefined;
    unsetTesting();
    setTestResult(undefined);
  }, []);

  return [testing, testResult, testApiAccessMethod, resetTestResult];
}