Fixes for telegram

- fix type for an error in fetcher
- use is-object func for checks
- better error handling for auth requests
This commit is contained in:
Paul Mineev
2022-02-11 10:59:19 -06:00
committed by Umputun
parent 7b47bd2f05
commit 9bae155e79
8 changed files with 89 additions and 22 deletions
+1 -1
View File
@@ -106,7 +106,7 @@ const createFetcher = (baseUrl: string = ''): Methods => {
return res.text();
} catch (e) {
if (e?.message === 'Failed to fetch') {
if (e instanceof Error && e.message === 'Failed to fetch') {
throw new RequestError(e.message, 'fetch-error');
}
+2 -1
View File
@@ -1,3 +1,4 @@
import { isObject } from 'utils/is-object';
import { IS_STORAGE_AVAILABLE } from './constants';
const failMessage = 'remark42: localStorage access denied, check browser preferences';
@@ -57,7 +58,7 @@ export function updateJsonItem<T>(key: string, value: T) {
return;
}
if (value !== null && typeof value === 'object') {
if (isObject(value)) {
setJsonItem(key, { ...savedData, ...value });
return;
}
+18 -6
View File
@@ -2,6 +2,7 @@ import { useEffect, useRef, useState, useMemo } from 'preact/hooks';
import { useIntl } from 'react-intl';
import { errorMessages, RequestError } from 'utils/errorUtils';
import { isObject } from 'utils/is-object';
import { parseMessage, postMessageToParent } from 'utils/post-message';
import { messages } from './auth.messsages';
@@ -16,9 +17,10 @@ export function useDropdown(disableClosing?: boolean) {
const rootRef = useRef<HTMLDivElement>(null);
const clickInsideRef = useRef<boolean>(false);
const [showDropdown, setShowDropdown] = useState(false);
const toggleDropdownState = () => {
function toggleDropdownState() {
setShowDropdown((s) => !s);
};
}
useEffect(() => {
const dropdownElement = rootRef.current;
@@ -93,19 +95,24 @@ export function useDropdown(disableClosing?: boolean) {
export function useErrorMessage(): [string | null, (e: unknown) => void] {
const intl = useIntl();
const [invalidReason, setInvalidReason] = useState<string | null>(null);
const [invalidReason, setInvalidReason] = useState<string | number | null>(null);
return useMemo(() => {
let errorMessage = invalidReason;
if (invalidReason && messages[invalidReason]) {
if (invalidReason !== null && typeof invalidReason === 'string' && messages[invalidReason]) {
errorMessage = intl.formatMessage(messages[invalidReason]);
}
if (invalidReason && errorMessages[invalidReason]) {
if (invalidReason !== null && errorMessages[invalidReason]) {
errorMessage = intl.formatMessage(errorMessages[invalidReason]);
}
if (typeof errorMessage === 'number') {
console.error('Wrong error message', errorMessage);
errorMessage = null;
}
function setError(err: unknown): void {
if (err === null) {
setInvalidReason(null);
@@ -117,7 +124,12 @@ export function useErrorMessage(): [string | null, (e: unknown) => void] {
return;
}
const errorReason = err instanceof RequestError ? err.error : err instanceof Error ? err.message : 'error.0';
const errorReason =
err instanceof RequestError || (isObject(err) && typeof (err as Record<string, string>).error === 'string')
? (err as Record<'error', string>).error
: err instanceof Error
? err.message
: 0;
setInvalidReason(errorReason);
}
@@ -65,9 +65,13 @@ export const messages = defineMessages<string>({
id: 'auth.telegram-check',
defaultMessage: 'Check',
},
telegramQR: {
id: 'auth.telegram-qr',
defaultMessage: 'Telegram QR-code',
},
telegramMessage1: {
id: 'auth.telegram-message-1',
defaultMessage: 'Open the Telegram',
defaultMessage: 'Open Telegram',
},
telegramOptionalQR: {
id: 'auth.telegram-optional-qr',
+1 -1
View File
@@ -198,7 +198,7 @@
.telegramQR {
display: block;
margin: 0 auto 0 auto;
margin: 12px auto;
width: 75%;
}
+31 -12
View File
@@ -69,21 +69,29 @@ export function Auth() {
const { href, dataset } = evt.currentTarget;
if (dataset.providerName?.toLowerCase() === 'telegram') {
telegramParamsRef.current = await getTelegramSigninParams();
window.open(`https://t.me/${telegramParamsRef.current.bot}/?start=${telegramParamsRef.current.token}`);
try {
telegramParamsRef.current = await getTelegramSigninParams();
} catch (e) {
setError(e);
return;
}
setView('telegram');
setError(null);
return;
}
const user = await oauthSignin(href);
try {
const user = await oauthSignin(href);
if (user === null) {
// TODO: add error message when user is null
return;
if (user === null) {
// TODO: add error message when user is null
return;
}
dispatch(setUser(user));
} catch (e) {
setError(e);
}
dispatch(setUser(user));
}
function handleProviderChange(evt: Event) {
@@ -144,7 +152,12 @@ export function Auth() {
setError(null);
if (telegramParamsRef.current === null) {
telegramParamsRef.current = await getTelegramSigninParams();
try {
telegramParamsRef.current = await getTelegramSigninParams();
} catch (e) {
setError(e);
return;
}
}
try {
@@ -218,7 +231,11 @@ export function Auth() {
</div>
<p className={clsx('telegram', styles.telegram)}>
{intl.formatMessage(messages.telegramMessage1)}{' '}
<a href={`https://t.me/${telegramParamsRef.current.bot}/?start=${telegramParamsRef.current.token}`}>
<a
target="_blank"
rel="noopener noreferrer"
href={`https://t.me/${telegramParamsRef.current.bot}/?start=${telegramParamsRef.current.token}`}
>
{intl.formatMessage(messages.telegramLink)}
</a>
{window.screen.width >= 768 && ` ${intl.formatMessage(messages.telegramOptionalQR)}`}{' '}
@@ -229,14 +246,16 @@ export function Auth() {
{window.screen.width >= 768 && (
<img
src={`${BASE_URL}${API_BASE}/qr/telegram?url=https://t.me/${telegramParamsRef.current.bot}/?start=${telegramParamsRef.current.token}`}
height="180"
width="200"
className={clsx('telegram-qr', styles.telegramQR)}
alt={'telegram QR-code'}
alt={intl.formatMessage(messages.telegramQR)}
/>
)}
{errorMessage && <div className={clsx('auth-error', styles.error)}>{errorMessage}</div>}
<Button key="submit" className="auth-submit" type="submit" onClick={handleTelegramSubmit}>
{intl.formatMessage(messages.telegramCheck)}
</Button>
{errorMessage && <div className={clsx('auth-error', styles.error)}>{errorMessage}</div>}
</>
) : view === 'token' ? (
<>
+28
View File
@@ -0,0 +1,28 @@
import { isObject } from './is-object';
describe('is-object', () => {
it.each`
input
${null}
${undefined}
${0}
${1}
${''}
${'string'}
${true}
${false}
${[]}
${[1, 2, 3]}
`('should return false if is NOT an object', ({ input }) => {
expect(isObject(input)).toBe(false);
});
it.each`
input
${{}}
${{ a: 1 }}
${{ a: 1, b: 2 }}
${new Error()}
`('should return true if IS an object', ({ input }) => {
expect(isObject(input)).toBe(true);
});
});
+3
View File
@@ -0,0 +1,3 @@
export function isObject(value: unknown): boolean {
return value !== null && typeof value === 'object' && !Array.isArray(value);
}