diff --git a/locales/en/translation.json b/locales/en/translation.json index c27ab50f..0ac29dc0 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -27,7 +27,11 @@ "authorize": "Authorize", "authorization_code": "Authorization Code", "authorization_helper": "Please paste the authorization code from your browser", - "without_code_authorize": "Please approve Whalebird in your browser, and after you approve it please authorize" + "without_code_authorize": "Please approve Whalebird in your browser, and after you approve it please authorize", + "detector_error": "Failed to connect to {domain}, make sure the server URL is valid or correct.", + "register_error": "Failed to add application.", + "token_error": "Failed to authorize.", + "credential_error": "Failed to confirm access token." }, "remove": "Remove" }, diff --git a/renderer/components/accounts/New.tsx b/renderer/components/accounts/New.tsx index 959ca17e..95738941 100644 --- a/renderer/components/accounts/New.tsx +++ b/renderer/components/accounts/New.tsx @@ -1,8 +1,8 @@ -import { Label, Modal, TextInput, Button } from 'flowbite-react' +import { Label, Modal, TextInput, Button, Alert, Spinner } from 'flowbite-react' import generator, { MegalodonInterface, OAuth, detector } from 'megalodon' import { useState } from 'react' import { db } from '@/db' -import { FormattedMessage } from 'react-intl' +import { FormattedMessage, useIntl } from 'react-intl' type NewProps = { opened: boolean @@ -14,29 +14,53 @@ export default function New(props: NewProps) { const [domain, setDomain] = useState('') const [client, setClient] = useState() const [appData, setAppData] = useState() + const [error, setError] = useState("") + const [loading, setLoading] = useState(false) + + const { formatMessage } = useIntl() const close = () => { setSNS(null) setDomain('') setClient(undefined) setAppData(undefined) + setError("") + setLoading(false) props.close() } const checkDomain = async () => { + setError("") + setLoading(true) const input = document.getElementById('domain') as HTMLInputElement setDomain(input.value) const url = `https://${input.value}` - const sns = await detector(url) + const sns = await detector(url).catch(() => { + setError(formatMessage({ id: 'accounts.new.detector_error' }, { domain: input.value})) + return undefined + }) + if (!sns) { + setLoading(false) + return + } setSNS(sns) const client = generator(sns, url) setClient(client) - const appData = await client.registerApp('Whalebird', {}) + const appData = await client.registerApp('Whalebird', {}).catch(() => { + setError(formatMessage({ id: "accounts.new.register_error" })) + return undefined + }) + setLoading(false) + if (!appData) { + return + } setAppData(appData) global.ipc.invoke('open-browser', appData.url) } const authorize = async () => { + setError("") + setLoading(true) if (!client || !appData) return const input = document.getElementById('authorization') as HTMLInputElement let authorizationCode = null @@ -45,10 +69,27 @@ export default function New(props: NewProps) { } else { authorizationCode = input.value } - const tokenData = await client.fetchAccessToken(appData.client_id, appData.client_secret, authorizationCode) - if (!sns) return + const tokenData = await client.fetchAccessToken(appData.client_id, appData.client_secret, authorizationCode).catch(() => { + setError(formatMessage({ id: "accounts.new.token_error" })) + return undefined + }) + if (!tokenData) { + setLoading(false) + return + } + if (!sns) { + setLoading(false) + return + } const cli = generator(sns, `https://${domain}`, tokenData.access_token, 'Whalebird') - const acct = await cli.verifyAccountCredentials() + const acct = await cli.verifyAccountCredentials().catch(() => { + setError(formatMessage({ id: "accounts.new.credential_error" })) + return undefined + }) + setLoading(false) + if (!acct) { + return + } await db.accounts.add({ username: acct.data.username, account_id: acct.data.id, @@ -71,8 +112,13 @@ export default function New(props: NewProps) { + {error && ( + + {error} + + )}
- {sns === null && ( + {sns === null ? ( <>
- - )} - {sns && appData && ( + ) : ( <> - {appData.session_token ? ( + {appData ? ( <> -
- -
+ {appData.session_token ? ( + <> +
+ +
+ + ) : ( + <> +
+ +

+ +

+
+ + + )} + + ) : ( - <> -
- -

- -

-
- - +
+ +
)} - - + )}