diff --git a/packages/website/src/components/Embeds/CopyURL.tsx b/packages/website/src/components/Embeds/CopyURL.tsx deleted file mode 100644 index 931075b51..000000000 --- a/packages/website/src/components/Embeds/CopyURL.tsx +++ /dev/null @@ -1,151 +0,0 @@ -import { - searchPlayersAcrossRegions, - type AccountListWithServer, -} from '@blitzkit/core'; -import strings from '@blitzkit/core/lang/en-US.json'; -import { Link2Icon, PersonIcon } from '@radix-ui/react-icons'; -import { - Badge, - Button, - Dialog, - Flex, - Heading, - Spinner, - Text, - TextField, -} from '@radix-ui/themes'; -import { debounce } from 'lodash-es'; -import { useCallback, useRef, useState } from 'react'; -import { stringify } from 'urlon'; -import type { embedConfigurations } from '../../constants/embeds'; -import { EmbedState, type EmbedStateStore } from '../../stores/embedState'; -import { CopyButton } from '../CopyButton'; - -interface CopyURLProps { - embed: keyof typeof embedConfigurations; -} - -export function CopyURL({ embed }: CopyURLProps) { - const [dialogOpen, setDialogOpen] = useState(false); - const embedStateStore = EmbedState.useStore(); - const input = useRef(null); - const [searching, setSearching] = useState(false); - const [results, setResults] = useState([]); - const performSearch = useCallback( - debounce(async () => { - if (!input.current) return; - - const sanitized = input.current.value.trim(); - - if (sanitized.length === 0) { - setSearching(false); - return; - } - - const results = await searchPlayersAcrossRegions(sanitized, 12); - - setSearching(false); - setResults(results); - }, 500), - [], - ); - const handleChange = useCallback(() => { - if (!input.current) return; - - const sanitized = input.current.value.trim(); - - if (sanitized.length === 0) { - setSearching(false); - setResults([]); - } else { - setSearching(true); - performSearch(); - } - }, []); - - return ( - - - - - - - - Copy URL - Search an account to track - - - - - - - - - - {searching && ( - - - Searching - - - )} - {!searching && results.length === 0 && ( - No results - )} - - - {!searching && results.length > 0 && ( - - - {results.map((result) => ( - { - const state = embedStateStore.getState(); - const initial = embedStateStore.getInitialState(); - const shallowState: EmbedStateStore = {}; - - Object.entries(state).forEach(([key, value]) => { - if (value !== initial[key]) { - shallowState[key] = value; - } - }); - - const searchParams = new URLSearchParams({ - id: `${result.account_id}`, - state: stringify(shallowState), - }); - - setDialogOpen(false); - - return `${location.origin}/tools/embed/${embed}/host?${searchParams.toString()}`; - }} - > - - {result.nickname} - {strings.common.regions.short[result.region]} - - - ))} - - - )} - - - ); -} diff --git a/packages/website/src/components/Embeds/GenerateURL.tsx b/packages/website/src/components/Embeds/GenerateURL.tsx new file mode 100644 index 000000000..35afb117d --- /dev/null +++ b/packages/website/src/components/Embeds/GenerateURL.tsx @@ -0,0 +1,196 @@ +import { + searchPlayersAcrossRegions, + type AccountListItem, + type AccountListWithServer, +} from '@blitzkit/core'; +import strings from '@blitzkit/core/lang/en-US.json'; +import { CaretLeftIcon, Link2Icon, PersonIcon } from '@radix-ui/react-icons'; +import { + Badge, + Button, + Dialog, + Flex, + Heading, + Spinner, + Text, + TextField, +} from '@radix-ui/themes'; +import { debounce } from 'lodash-es'; +import { useCallback, useRef, useState } from 'react'; +import { stringify } from 'urlon'; +import type { embedConfigurations } from '../../constants/embeds'; +import { EmbedState, type EmbedStateStore } from '../../stores/embedState'; +import { CopyButton } from '../CopyButton'; + +interface GenerateURLProps { + embed: keyof typeof embedConfigurations; +} + +export function GenerateURL({ embed }: GenerateURLProps) { + const [searchDialogOpen, setSearchDialogOpen] = useState(false); + const [copyDialogOpen, setCopyDialogOpen] = useState(false); + const [copyUser, setCopyUser] = useState(null); + const embedStateStore = EmbedState.useStore(); + const input = useRef(null); + const [searching, setSearching] = useState(false); + const [results, setResults] = useState([]); + const performSearch = useCallback( + debounce(async () => { + if (!input.current) return; + + const sanitized = input.current.value.trim(); + + if (sanitized.length === 0) { + setSearching(false); + return; + } + + const results = await searchPlayersAcrossRegions(sanitized, 12); + + setSearching(false); + setResults(results); + }, 500), + [], + ); + const handleChange = useCallback(() => { + if (!input.current) return; + + const sanitized = input.current.value.trim(); + + if (sanitized.length === 0) { + setSearching(false); + setResults([]); + } else { + setSearching(true); + performSearch(); + } + }, []); + + return ( + <> + + + + + + + + Generate URL + Search an account to track + + + + + + + + + + {searching && ( + + + Searching + + + )} + {!searching && results.length === 0 && ( + No results + )} + + {!searching && results.length > 0 && ( + + {results.map((result) => ( + + ))} + + )} + + + + + + + + + + + + Copy URL + + Generated the URL for {copyUser?.nickname}. The embed will start + tracking as soon as the URL is pasted. Reset at any time by + right-clicking on PC or long-pressing on mobile and then selecting + "Reset". + + + + + + { + if (!copyUser) return; + + const state = embedStateStore.getState(); + const initial = embedStateStore.getInitialState(); + const shallowState: EmbedStateStore = {}; + + Object.entries(state).forEach(([key, value]) => { + if (value !== initial[key]) { + shallowState[key] = value; + } + }); + + const searchParams = new URLSearchParams({ + id: `${copyUser.account_id}`, + state: stringify(shallowState), + }); + + setSearchDialogOpen(false); + setCopyDialogOpen(false); + + return `${location.origin}/tools/embed/${embed}/host?${searchParams.toString()}`; + }} + > + Copy URL + + + + + + ); +} diff --git a/packages/website/src/pages/tools/embed/[embed]/_index.tsx b/packages/website/src/pages/tools/embed/[embed]/_index.tsx index 9a7c7b8db..b46446d07 100644 --- a/packages/website/src/pages/tools/embed/[embed]/_index.tsx +++ b/packages/website/src/pages/tools/embed/[embed]/_index.tsx @@ -13,8 +13,8 @@ import { useEffect, useRef, useState, type ReactNode } from 'react'; import { CopyButton } from '../../../../components/CopyButton'; import { Boolean } from '../../../../components/Embeds/Boolean'; import { Color } from '../../../../components/Embeds/Color'; -import { CopyURL } from '../../../../components/Embeds/CopyURL'; import { Enum } from '../../../../components/Embeds/Enum'; +import { GenerateURL } from '../../../../components/Embeds/GenerateURL'; import { Import } from '../../../../components/Embeds/Import'; import { PreviewWrapper } from '../../../../components/Embeds/PreviewWrapper'; import { Radius } from '../../../../components/Embeds/Radius'; @@ -90,7 +90,7 @@ function Content({ embed }: PageProps) { - +