Fixed line endings.

This commit is contained in:
Phil 2022-09-13 18:21:03 +01:00
parent dc5742b28c
commit ec9525619b
2 changed files with 174 additions and 174 deletions

View File

@ -1,133 +1,133 @@
import clsx from 'clsx' import clsx from 'clsx'
import { MouseEventHandler, ReactNode, useState } from 'react' import { MouseEventHandler, ReactNode, useState } from 'react'
import toast from 'react-hot-toast' import toast from 'react-hot-toast'
import { LinkIcon } from '@heroicons/react/solid' import { LinkIcon } from '@heroicons/react/solid'
import { usePrivateUser, useUser } from 'web/hooks/use-user' import { usePrivateUser, useUser } from 'web/hooks/use-user'
import { updatePrivateUser } from 'web/lib/firebase/users' import { updatePrivateUser } from 'web/lib/firebase/users'
import { track } from 'web/lib/service/analytics' import { track } from 'web/lib/service/analytics'
import { linkTwitchAccountRedirect } from 'web/lib/twitch/link-twitch-account' import { linkTwitchAccountRedirect } from 'web/lib/twitch/link-twitch-account'
import { copyToClipboard } from 'web/lib/util/copy' import { copyToClipboard } from 'web/lib/util/copy'
import { Button, ColorType } from './../button' import { Button, ColorType } from './../button'
import { Row } from './../layout/row' import { Row } from './../layout/row'
import { LoadingIndicator } from './../loading-indicator' import { LoadingIndicator } from './../loading-indicator'
function BouncyButton(props: { function BouncyButton(props: {
children: ReactNode children: ReactNode
onClick?: MouseEventHandler<any> onClick?: MouseEventHandler<any>
color?: ColorType color?: ColorType
}) { }) {
const { children, onClick, color } = props const { children, onClick, color } = props
return ( return (
<Button <Button
color={color} color={color}
size="lg" size="lg"
onClick={onClick} onClick={onClick}
className="btn h-[inherit] flex-shrink-[inherit] border-none font-normal normal-case" className="btn h-[inherit] flex-shrink-[inherit] border-none font-normal normal-case"
> >
{children} {children}
</Button> </Button>
) )
} }
export function TwitchPanel() { export function TwitchPanel() {
const user = useUser() const user = useUser()
const privateUser = usePrivateUser() const privateUser = usePrivateUser()
const twitchInfo = privateUser?.twitchInfo const twitchInfo = privateUser?.twitchInfo
const twitchName = privateUser?.twitchInfo?.twitchName const twitchName = privateUser?.twitchInfo?.twitchName
const twitchToken = privateUser?.twitchInfo?.controlToken const twitchToken = privateUser?.twitchInfo?.controlToken
const twitchBotConnected = privateUser?.twitchInfo?.botEnabled const twitchBotConnected = privateUser?.twitchInfo?.botEnabled
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=${twitchToken}`) 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=${twitchToken}`) copyToClipboard(`http://localhost:1000/dock?t=${twitchToken}`)
toast.success('Dock link copied!', { toast.success('Dock link copied!', {
icon: linkIcon, icon: linkIcon,
}) })
} }
const updateBotConnected = (connected: boolean) => async () => { const updateBotConnected = (connected: boolean) => async () => {
if (user && twitchInfo) { if (user && twitchInfo) {
twitchInfo.botEnabled = connected twitchInfo.botEnabled = connected
await updatePrivateUser(user.id, { twitchInfo }) await updatePrivateUser(user.id, { twitchInfo })
} }
} }
const [twitchLoading, setTwitchLoading] = useState(false) const [twitchLoading, setTwitchLoading] = useState(false)
const createLink = async () => { const createLink = async () => {
if (!user || !privateUser) return if (!user || !privateUser) return
setTwitchLoading(true) setTwitchLoading(true)
const promise = linkTwitchAccountRedirect(user, privateUser) const promise = linkTwitchAccountRedirect(user, privateUser)
track('link twitch from profile') track('link twitch from profile')
await promise await promise
setTwitchLoading(false) setTwitchLoading(false)
} }
return ( return (
<> <>
<div> <div>
<label className="label">Twitch</label> <label className="label">Twitch</label>
{!twitchName ? ( {!twitchName ? (
<Row> <Row>
<Button <Button
color="indigo" color="indigo"
onClick={createLink} onClick={createLink}
disabled={twitchLoading} disabled={twitchLoading}
> >
Link your Twitch account Link your Twitch account
</Button> </Button>
{twitchLoading && <LoadingIndicator className="ml-4" />} {twitchLoading && <LoadingIndicator className="ml-4" />}
</Row> </Row>
) : ( ) : (
<Row> <Row>
<span className="mr-4 text-gray-500">Linked Twitch account</span>{' '} <span className="mr-4 text-gray-500">Linked Twitch account</span>{' '}
{twitchName} {twitchName}
</Row> </Row>
)} )}
</div> </div>
{twitchToken && ( {twitchToken && (
<div> <div>
<div className="flex w-full"> <div className="flex w-full">
<div <div
className={clsx( className={clsx(
'flex grow gap-4', 'flex grow gap-4',
twitchToken ? '' : 'tooltip tooltip-top' twitchToken ? '' : 'tooltip tooltip-top'
)} )}
data-tip="You must link your Twitch account first" data-tip="You must link your Twitch account first"
> >
<BouncyButton color="blue" onClick={copyOverlayLink}> <BouncyButton color="blue" onClick={copyOverlayLink}>
Copy overlay link Copy overlay link
</BouncyButton> </BouncyButton>
<BouncyButton color="indigo" onClick={copyDockLink}> <BouncyButton color="indigo" onClick={copyDockLink}>
Copy dock link Copy dock link
</BouncyButton> </BouncyButton>
{twitchBotConnected ? ( {twitchBotConnected ? (
<BouncyButton color="red" onClick={updateBotConnected(false)}> <BouncyButton color="red" onClick={updateBotConnected(false)}>
Remove bot from your channel Remove bot from your channel
</BouncyButton> </BouncyButton>
) : ( ) : (
<BouncyButton color="green" onClick={updateBotConnected(true)}> <BouncyButton color="green" onClick={updateBotConnected(true)}>
Add bot to your channel Add bot to your channel
</BouncyButton> </BouncyButton>
)} )}
</div> </div>
</div> </div>
</div> </div>
)} )}
</> </>
) )
} }

View File

@ -1,41 +1,41 @@
import { PrivateUser, User } from 'common/user' import { PrivateUser, User } from 'common/user'
import { generateNewApiKey } from '../api/api-key' import { generateNewApiKey } from '../api/api-key'
const TWITCH_BOT_PUBLIC_URL = 'https://king-prawn-app-5btyw.ondigitalocean.app' // TODO: Add this to env config appropriately const TWITCH_BOT_PUBLIC_URL = 'https://king-prawn-app-5btyw.ondigitalocean.app' // TODO: Add this to env config appropriately
export async function initLinkTwitchAccount( export async function initLinkTwitchAccount(
manifoldUserID: string, manifoldUserID: string,
manifoldUserAPIKey: string manifoldUserAPIKey: string
): Promise<[string, Promise<{ twitchName: string; controlToken: string }>]> { ): Promise<[string, Promise<{ twitchName: string; controlToken: string }>]> {
const response = await fetch(`${TWITCH_BOT_PUBLIC_URL}/api/linkInit`, { const response = await fetch(`${TWITCH_BOT_PUBLIC_URL}/api/linkInit`, {
method: 'POST', method: 'POST',
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ body: JSON.stringify({
manifoldID: manifoldUserID, manifoldID: manifoldUserID,
apiKey: manifoldUserAPIKey, apiKey: manifoldUserAPIKey,
redirectURL: window.location.href, redirectURL: window.location.href,
}), }),
}) })
const responseData = await response.json() const responseData = await response.json()
if (!response.ok) { if (!response.ok) {
throw new Error(responseData.message) throw new Error(responseData.message)
} }
const responseFetch = fetch( const responseFetch = fetch(
`${TWITCH_BOT_PUBLIC_URL}/api/linkResult?userID=${manifoldUserID}` `${TWITCH_BOT_PUBLIC_URL}/api/linkResult?userID=${manifoldUserID}`
) )
return [responseData.twitchAuthURL, responseFetch.then((r) => r.json())] return [responseData.twitchAuthURL, responseFetch.then((r) => r.json())]
} }
export async function linkTwitchAccountRedirect( export async function linkTwitchAccountRedirect(
user: User, user: User,
privateUser: PrivateUser privateUser: PrivateUser
) { ) {
const apiKey = privateUser.apiKey ?? (await generateNewApiKey(user.id)) const apiKey = privateUser.apiKey ?? (await generateNewApiKey(user.id))
if (!apiKey) throw new Error("Couldn't retrieve or create Manifold api key") if (!apiKey) throw new Error("Couldn't retrieve or create Manifold api key")
const [twitchAuthURL] = await initLinkTwitchAccount(user.id, apiKey) const [twitchAuthURL] = await initLinkTwitchAccount(user.id, apiKey)
window.location.href = twitchAuthURL window.location.href = twitchAuthURL
} }