app.tsx 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { render, h, Fragment } from "preact";
  2. import { useState, useEffect } from "preact/hooks";
  3. import { g, j, r, u, x } from "./xeact.js";
  4. import { Sha256 } from "@aws-crypto/sha256-js";
  5. /** @jsx h */
  6. /** @jsxFrag Fragment */
  7. function toHexString(arr: Uint8Array) {
  8. return Array.from(arr)
  9. .map((c) => c.toString(16).padStart(2, "0"))
  10. .join("");
  11. }
  12. interface PreactInfo {
  13. redir: string;
  14. challenge: string;
  15. difficulty: number;
  16. connection_security_message: string;
  17. loading_message: string;
  18. pensive_url: string;
  19. }
  20. const App = () => {
  21. const [state, setState] = useState<PreactInfo>();
  22. const [imageURL, setImageURL] = useState<string | null>(null);
  23. const [passed, setPassed] = useState<boolean>(false);
  24. const [challenge, setChallenge] = useState<string | null>(null);
  25. useEffect(() => {
  26. setState(j("preact_info"));
  27. });
  28. useEffect(() => {
  29. if (state === undefined) {
  30. return;
  31. }
  32. setImageURL(state?.pensive_url);
  33. const hash = new Sha256("");
  34. hash.update(state.challenge);
  35. setChallenge(toHexString(hash.digestSync()));
  36. }, [state]);
  37. useEffect(() => {
  38. if (state === undefined) {
  39. return;
  40. }
  41. const timer = setTimeout(() => {
  42. setPassed(true);
  43. }, state?.difficulty * 125);
  44. return () => clearTimeout(timer);
  45. }, [challenge]);
  46. useEffect(() => {
  47. if (state === undefined) {
  48. return;
  49. }
  50. if (challenge === null) {
  51. return;
  52. }
  53. window.location.href = u(state.redir, {
  54. result: challenge,
  55. });
  56. }, [passed]);
  57. return (
  58. <>
  59. {imageURL !== null && (
  60. <img src={imageURL} style={{ width: "100%", maxWidth: "256px" }} />
  61. )}
  62. {state !== undefined && (
  63. <>
  64. <p id="status">{state.loading_message}</p>
  65. <p>{state.connection_security_message}</p>
  66. </>
  67. )}
  68. </>
  69. );
  70. };
  71. x(g("app"));
  72. render(<App />, g("app"));