Skip to content

Commit

Permalink
deploy: d6a1c29
Browse files Browse the repository at this point in the history
  • Loading branch information
JST5000 committed Nov 7, 2023
1 parent 7d00843 commit 44045ea
Show file tree
Hide file tree
Showing 5 changed files with 393 additions and 167 deletions.
27 changes: 27 additions & 0 deletions pr-preview/jm-faucets/ja/static/js/type-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
type TypeofType =
| 'bigint'
| 'boolean'
| 'function'
| 'number'
| 'object'
| 'string'
| 'undefined'

type TypeCheckFn = (thing: unknown) => boolean


/**
* Curried function for creating typeof checker functions.
* @param {string} type The type to check against (eg 'string', 'number')
* @param {function} [secondaryTest] Optional additional test function to run in cases where a type match isn't always a sure indicator.
* @returns {boolean} Whether the value matches the type
*/
const isTypeof =
<T>(type: TypeofType, secondaryTest?: TypeCheckFn) =>
(thing: unknown): thing is T => {
const matches = typeof thing === type
if (matches && secondaryTest) return secondaryTest(thing)
return matches
}

export const isFunction = isTypeof<(...args: unknown[]) => unknown>('function')
86 changes: 86 additions & 0 deletions pr-preview/jm-faucets/ja/static/js/xrpl-guard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { useTranslate } from '@portal/hooks';
import { isFunction } from './type-helpers'
import { FC } from 'react'
import { useEffect, useState } from 'react'
import React = require('react');

export const MIN_LOADER_MS = 1250
export const DEFAULT_TIMEOUT = 1000

const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))

/**
* Evaluate a check function will eventually resolve to `true`
*
* If check is initially true, immediatly return `isTrue`
* If check is initially false and becomes true, return true after `timeoutMs`
*/
export const useThrottledCheck = (
check: () => boolean,
timeoutMs = DEFAULT_TIMEOUT,
) => {
const [isTrue, setIsTrue] = useState(() => check())

useEffect(() => {
const doCheck = async (tries = 0) => {
const waitMs = 250,
waitedMs = tries * waitMs

if (check()) {
const debouncedDelay =
waitedMs < timeoutMs ? timeoutMs - (waitedMs % timeoutMs) : 0

setTimeout(() => setIsTrue(true), debouncedDelay)
return
}

await sleep(waitMs)

doCheck(tries + 1)
}

if (!isTrue) {
doCheck()
}
}, [check, isTrue])

return isTrue
}

/**
* Show a loading spinner if XRPL isn't loaded yet by
* waiting at least MIN_LOADER_MS before rendering children
* in order to make the visual loading transition smooth
*
* e.g. if xrpl loads after 500ms, wait
* another MIN_LOADER_MS - 500ms before rendering children
*
* @param {function} testCheck for testing only, a check function to use
*/
export const XRPLGuard: FC<{ testCheck?: () => boolean, children }> = ({
testCheck,
children,
}) => {

const { translate } = useTranslate();
const isXRPLLoaded = useThrottledCheck(
// @ts-expect-error - xrpl is added via a script tag (TODO: Directly import when xrpl.js 3.0 is released)
testCheck ?? (() => typeof xrpl === 'object'),
MIN_LOADER_MS,
)

return (
<>
{isXRPLLoaded ? (
isFunction(children) ? (
children()
) : (
children
)
) : (
<div id="loader">
<img alt="(loading)" className="throbber" src="/img/xrp-loader-96.png" />{translate("Loading...")}
</div>)}
</>
)
}
27 changes: 27 additions & 0 deletions pr-preview/jm-faucets/static/js/type-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
type TypeofType =
| 'bigint'
| 'boolean'
| 'function'
| 'number'
| 'object'
| 'string'
| 'undefined'

type TypeCheckFn = (thing: unknown) => boolean


/**
* Curried function for creating typeof checker functions.
* @param {string} type The type to check against (eg 'string', 'number')
* @param {function} [secondaryTest] Optional additional test function to run in cases where a type match isn't always a sure indicator.
* @returns {boolean} Whether the value matches the type
*/
const isTypeof =
<T>(type: TypeofType, secondaryTest?: TypeCheckFn) =>
(thing: unknown): thing is T => {
const matches = typeof thing === type
if (matches && secondaryTest) return secondaryTest(thing)
return matches
}

export const isFunction = isTypeof<(...args: unknown[]) => unknown>('function')
86 changes: 86 additions & 0 deletions pr-preview/jm-faucets/static/js/xrpl-guard.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { useTranslate } from '@portal/hooks';
import { isFunction } from './type-helpers'
import { FC } from 'react'
import { useEffect, useState } from 'react'
import React = require('react');

export const MIN_LOADER_MS = 1250
export const DEFAULT_TIMEOUT = 1000

const sleep = (delay) => new Promise((resolve) => setTimeout(resolve, delay))

/**
* Evaluate a check function will eventually resolve to `true`
*
* If check is initially true, immediatly return `isTrue`
* If check is initially false and becomes true, return true after `timeoutMs`
*/
export const useThrottledCheck = (
check: () => boolean,
timeoutMs = DEFAULT_TIMEOUT,
) => {
const [isTrue, setIsTrue] = useState(() => check())

useEffect(() => {
const doCheck = async (tries = 0) => {
const waitMs = 250,
waitedMs = tries * waitMs

if (check()) {
const debouncedDelay =
waitedMs < timeoutMs ? timeoutMs - (waitedMs % timeoutMs) : 0

setTimeout(() => setIsTrue(true), debouncedDelay)
return
}

await sleep(waitMs)

doCheck(tries + 1)
}

if (!isTrue) {
doCheck()
}
}, [check, isTrue])

return isTrue
}

/**
* Show a loading spinner if XRPL isn't loaded yet by
* waiting at least MIN_LOADER_MS before rendering children
* in order to make the visual loading transition smooth
*
* e.g. if xrpl loads after 500ms, wait
* another MIN_LOADER_MS - 500ms before rendering children
*
* @param {function} testCheck for testing only, a check function to use
*/
export const XRPLGuard: FC<{ testCheck?: () => boolean, children }> = ({
testCheck,
children,
}) => {

const { translate } = useTranslate();
const isXRPLLoaded = useThrottledCheck(
// @ts-expect-error - xrpl is added via a script tag (TODO: Directly import when xrpl.js 3.0 is released)
testCheck ?? (() => typeof xrpl === 'object'),
MIN_LOADER_MS,
)

return (
<>
{isXRPLLoaded ? (
isFunction(children) ? (
children()
) : (
children
)
) : (
<div id="loader">
<img alt="(loading)" className="throbber" src="/img/xrp-loader-96.png" />{translate("Loading...")}
</div>)}
</>
)
}
Loading

0 comments on commit 44045ea

Please sign in to comment.