From 74b9ef2554b015ed292cb31f428c052c01ffc1a6 Mon Sep 17 00:00:00 2001 From: Alex Kern Date: Sat, 28 Dec 2024 21:39:55 -0800 Subject: [PATCH] more prod changes --- src/components/Downloader.tsx | 1 + src/components/Spinner.tsx | 6 +++-- src/components/Uploader.tsx | 15 +++++++---- src/hooks/useDownloader.ts | 3 +++ src/hooks/useRotatingSpinner.ts | 42 +++++++++++++++++++++++++++++ src/hooks/useUploaderConnections.ts | 3 ++- tailwind.config.js | 6 ++++- 7 files changed, 67 insertions(+), 9 deletions(-) create mode 100644 src/hooks/useRotatingSpinner.ts diff --git a/src/components/Downloader.tsx b/src/components/Downloader.tsx index bdaddfb..09af2bb 100644 --- a/src/components/Downloader.tsx +++ b/src/components/Downloader.tsx @@ -93,6 +93,7 @@ export function ConnectingToUploader({

+ ) } diff --git a/src/components/Spinner.tsx b/src/components/Spinner.tsx index 736f8a9..ff64250 100644 --- a/src/components/Spinner.tsx +++ b/src/components/Spinner.tsx @@ -1,4 +1,7 @@ +'use client' + import React, { JSX } from 'react' +import { useRotatingSpinner } from '../hooks/useRotatingSpinner' function Pizza({ isRotating }: { isRotating?: boolean }): JSX.Element { return ( @@ -1680,11 +1683,10 @@ function Arrow({ direction }: { direction: 'up' | 'down' }): JSX.Element { export default function Spinner({ direction, - isRotating, }: { direction: 'up' | 'down' - isRotating?: boolean }): JSX.Element { + const isRotating = useRotatingSpinner() return (
diff --git a/src/components/Uploader.tsx b/src/components/Uploader.tsx index 9651f89..65ccdb0 100644 --- a/src/components/Uploader.tsx +++ b/src/components/Uploader.tsx @@ -1,6 +1,6 @@ 'use client' -import React, { JSX, useCallback } from 'react' +import React, { JSX, useCallback, useEffect } from 'react' import { UploadedFile, UploaderConnectionStatus } from '../types' import { useWebRTCPeer } from './WebRTCProvider' import QRCode from 'react-qr-code' @@ -11,6 +11,7 @@ import { useUploaderConnections } from '../hooks/useUploaderConnections' import { CopyableInput } from './CopyableInput' import { ConnectionListItem } from './ConnectionListItem' import { ErrorMessage } from './ErrorMessage' +import { setRotating } from '../hooks/useRotatingSpinner' const QR_CODE_SIZE = 128 @@ -33,14 +34,18 @@ export default function Uploader({ onStop() }, [stop, onStop]) - if (isLoading || !longSlug || !shortSlug) { - return - } - const activeDownloaders = connections.filter( (conn) => conn.status === UploaderConnectionStatus.Uploading, ).length + useEffect(() => { + setRotating(activeDownloaders > 0) + }, [activeDownloaders]) + + if (isLoading || !longSlug || !shortSlug) { + return + } + if (error) { return } diff --git a/src/hooks/useDownloader.ts b/src/hooks/useDownloader.ts index ca0f08e..82c352e 100644 --- a/src/hooks/useDownloader.ts +++ b/src/hooks/useDownloader.ts @@ -15,6 +15,7 @@ import { mobileVendor, mobileModel, } from 'react-device-detect' +import { setRotating } from './useRotatingSpinner' const cleanErrorMessage = (errorMessage: string): string => errorMessage.startsWith('Could not connect to peer') ? 'Could not connect to the uploader. Did they close their browser?' @@ -86,6 +87,7 @@ export function useDownloader(uploaderPeerID: string): { break case MessageType.Chunk: processChunk.current?.(message) + setRotating(true) break case MessageType.Error: console.error(message.error) @@ -103,6 +105,7 @@ export function useDownloader(uploaderPeerID: string): { } const handleClose = () => { + setRotating(false) setDataConnection(null) setIsConnected(false) setIsDownloading(false) diff --git a/src/hooks/useRotatingSpinner.ts b/src/hooks/useRotatingSpinner.ts new file mode 100644 index 0000000..8601e13 --- /dev/null +++ b/src/hooks/useRotatingSpinner.ts @@ -0,0 +1,42 @@ +import { useEffect, useState } from 'react' + +type RotationListener = (isRotating: boolean) => void + +let isRotating = false +const listeners = new Set() + +export function setRotating(rotating: boolean): void { + isRotating = rotating + notifyListeners() +} + +export function getRotating(): boolean { + return isRotating +} + +export function addRotationListener(listener: RotationListener): void { + listeners.add(listener) +} + +export function removeRotationListener(listener: RotationListener): void { + listeners.delete(listener) +} + +function notifyListeners(): void { + listeners.forEach(listener => listener(isRotating)) +} + +export function useRotatingSpinner(): boolean { + const [rotating, setRotatingState] = useState(isRotating) + + useEffect(() => { + const listener = (newRotating: boolean) => { + setRotatingState(newRotating) + } + + addRotationListener(listener) + return () => removeRotationListener(listener) + }, []) + + return rotating +} diff --git a/src/hooks/useUploaderConnections.ts b/src/hooks/useUploaderConnections.ts index ee2eb0b..1cc778f 100644 --- a/src/hooks/useUploaderConnections.ts +++ b/src/hooks/useUploaderConnections.ts @@ -7,9 +7,10 @@ import { } from '../types' import { decodeMessage, Message, MessageType } from '../messages' import { getFileName } from '../fs' +import { setRotating } from './useRotatingSpinner' // TODO(@kern): Test for better values -const MAX_CHUNK_SIZE = 10 * 1024 * 1024 // 10 Mi +const MAX_CHUNK_SIZE = 256 * 1024 // 256 KB function validateOffset( files: UploadedFile[], diff --git a/tailwind.config.js b/tailwind.config.js index c4fd157..788f1de 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -2,7 +2,11 @@ export default { content: ['./src/**/*.{js,ts,jsx,tsx,mdx}'], theme: { - extend: {}, + extend: { + animation: { + 'spin-slow': 'spin 16s linear infinite', + }, + }, }, plugins: [], darkMode: 'class',