twitch panel logic

This commit is contained in:
mantikoros 2022-08-29 01:18:52 -05:00
parent 1ba1acdd1d
commit 34ad32430a
2 changed files with 62 additions and 88 deletions

View File

@ -3,120 +3,94 @@ import React, { useState } from 'react'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { copyToClipboard } from 'web/lib/util/copy' import { copyToClipboard } from 'web/lib/util/copy'
import { initLinkTwitchAccount } from 'web/lib/twitch/link-twitch-account' import { linkTwitchAccount } from 'web/lib/twitch/link-twitch-account'
import { LinkIcon } from '@heroicons/react/solid' import { LinkIcon } from '@heroicons/react/solid'
import { User, PrivateUser } from 'common/user' import { track } from 'web/lib/service/analytics'
import { Button } from './button'
import { LoadingIndicator } from './loading-indicator'
import { Row } from './layout/row'
import { usePrivateUser, useUser } from 'web/hooks/use-user'
export function TwitchPanel(props: { export function TwitchPanel() {
auth: { user: User; privateUser: PrivateUser } const user = useUser()
}) { const privateUser = usePrivateUser()
const { user, privateUser } = props.auth
const [twitchToken, setTwitchToken] = useState('') const twitchName = privateUser?.twitchInfo?.twitchName
const [twitchLoading, setTwitchLoading] = useState(false) const twitchToken = privateUser?.twitchInfo?.controlToken
const [twitchLinkError, setTwitchLinkError] = useState('')
const [controlToken, setControlToken] = useState<string | undefined>(
undefined
)
const linkTwitchAccount = async () => {
if (!privateUser.apiKey) return // TODO: handle missing API key
try {
setTwitchLoading(true)
const [twitchAuthURL, linkSuccessPromise] = await initLinkTwitchAccount(
privateUser.id,
privateUser.apiKey
)
window.open(twitchAuthURL)
const data = await linkSuccessPromise
setTwitchToken(data.twitchName)
setControlToken(data.controlToken)
} catch (e) {
console.error(e)
toast.error('Failed to link Twitch account: ' + (e as Object).toString())
} finally {
setTwitchLoading(false)
}
}
const linkIcon = <LinkIcon className="mr-2 h-6 w-6" aria-hidden="true" /> const linkIcon = <LinkIcon className="mr-2 h-6 w-6" aria-hidden="true" />
const copyOverlayLink = async () => { const copyOverlayLink = async () => {
copyToClipboard(`http://localhost:1000/overlay?t=${controlToken}`) copyToClipboard(`http://localhost:1000/overlay?t=${twitchToken}`)
toast.success('Overlay link copied!', { toast.success('Overlay link copied!', {
icon: linkIcon, icon: linkIcon,
}) })
} }
const copyDockLink = async () => { const copyDockLink = async () => {
copyToClipboard(`http://localhost:1000/dock?t=${controlToken}`) copyToClipboard(`http://localhost:1000/dock?t=${twitchToken}`)
toast.success('Dock link copied!', { toast.success('Dock link copied!', {
icon: linkIcon, icon: linkIcon,
}) })
} }
const [twitchLoading, setTwitchLoading] = useState(false)
const createLink = async () => {
if (!user || !privateUser) return
setTwitchLoading(true)
const promise = linkTwitchAccount(user, privateUser)
track('link twitch from profile')
await promise
setTwitchLoading(false)
}
return ( return (
<> <>
<div> <div>
<label className="label">Twitch</label> <label className="label">Twitch</label>
<div className="relative flex w-full justify-items-stretch">
<input {!twitchName ? (
type="text" <Row>
placeholder="Click link to connect your Twitch account" <Button
className="input input-bordered w-full" color="indigo"
value={twitchToken} onClick={createLink}
readOnly disabled={twitchLoading}
style={{ >
borderTopRightRadius: '0', Link your Twitch account
borderBottomRightRadius: '0', </Button>
}} {twitchLoading && <LoadingIndicator className="ml-4" />}
/> </Row>
<button ) : (
className={clsx( <Row>
'btn btn-secondary btn-square p-2', <span className="mr-4 text-gray-500">Linked Twitch account</span>{' '}
twitchLoading ? 'loading' : '' {twitchName}
)} </Row>
onClick={linkTwitchAccount} )}
style={{
borderTopLeftRadius: '0',
borderBottomLeftRadius: '0',
}}
>
{!twitchLoading && <LinkIcon />}
</button>
</div>
</div> </div>
<span className="text-sm text-red-400">Not editable for now</span> {twitchToken && (
<div>
<div> <div className="flex w-full">
<div className="flex w-full"> <div
<div
className={clsx(
'flex grow gap-4',
twitchToken ? '' : 'tooltip tooltip-top'
)}
data-tip="You must link your Twitch account first"
>
<button
className={clsx( className={clsx(
'btn grow', 'flex grow gap-4',
twitchToken ? 'btn-primary' : 'btn-disabled' twitchToken ? '' : 'tooltip tooltip-top'
)} )}
onClick={copyOverlayLink} data-tip="You must link your Twitch account first"
> >
Copy overlay link <Button color="blue" size="lg" onClick={copyOverlayLink}>
</button> Copy overlay link
<button </Button>
className={clsx( <Button color="indigo" size="lg" onClick={copyDockLink}>
'btn grow', Copy dock link
twitchToken ? 'btn-primary' : 'btn-disabled' </Button>
)} </div>
onClick={copyDockLink}
>
Copy dock link
</button>
</div> </div>
</div> </div>
</div> )}
</> </>
) )
} }

View File

@ -238,7 +238,7 @@ export default function ProfilePage(props: {
</div> </div>
</div> </div>
<TwitchPanel auth={props.auth} /> <TwitchPanel />
</Col> </Col>
</Col> </Col>
</Page> </Page>