1
0
mirror of https://github.com/MisskeyIO/misskey synced 2024-11-27 14:28:49 +09:00

enhance(frontend): 定義されていないエラーも表示できるように (MisskeyIO#738)

+登録時のAPIエラーを表示できるように
This commit is contained in:
まっちゃとーにゅ 2024-09-17 21:00:49 +09:00 committed by GitHub
parent c82bf7583a
commit 69f31e6246
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 84 additions and 74 deletions

View File

@ -189,7 +189,7 @@ async function onSubmit(): Promise<void> {
submitting.value = true; submitting.value = true;
try { try {
await misskeyApi('signup', { await os.apiWithDialog('signup', {
username: username.value, username: username.value,
password: password.value.password, password: password.value.password,
emailAddress: email.value, emailAddress: email.value,
@ -198,7 +198,7 @@ async function onSubmit(): Promise<void> {
'm-captcha-response': mCaptchaResponse.value, 'm-captcha-response': mCaptchaResponse.value,
'g-recaptcha-response': reCaptchaResponse.value, 'g-recaptcha-response': reCaptchaResponse.value,
'turnstile-response': turnstileResponse.value, 'turnstile-response': turnstileResponse.value,
}); }, undefined, (res) => {
if (instance.emailRequiredForSignup) { if (instance.emailRequiredForSignup) {
os.alert({ os.alert({
type: 'success', type: 'success',
@ -207,26 +207,18 @@ async function onSubmit(): Promise<void> {
}); });
emit('signupEmailPending'); emit('signupEmailPending');
} else { } else {
const res = await misskeyApi('signin', { emit('signup', { id: res.id, i: res.token });
username: username.value,
password: password.value.password,
});
emit('signup', res);
if (props.autoSet) { if (props.autoSet) {
return login(res.i); login(res.token);
} }
} }
});
} catch { } catch {
submitting.value = false; submitting.value = false;
hcaptcha.value?.reset?.(); hcaptcha.value?.reset?.();
recaptcha.value?.reset?.(); recaptcha.value?.reset?.();
turnstile.value?.reset?.(); turnstile.value?.reset?.();
os.alert({
type: 'error',
text: i18n.ts.somethingHappened,
});
} }
} }
</script> </script>

View File

@ -34,11 +34,19 @@ export const apiWithDialog = (<E extends keyof Misskey.Endpoints = keyof Misskey
endpoint: E, endpoint: E,
data: P = {} as P, data: P = {} as P,
token?: string | null | undefined, token?: string | null | undefined,
) => { onSuccess?: ((res: Misskey.api.SwitchCaseResponseType<E, P>) => void) | null | undefined,
onFailure?: ((err: Misskey.api.APIError) => void) | null,
): Promise<Misskey.api.SwitchCaseResponseType<E, P>> => {
const promise = misskeyApi(endpoint, data, token); const promise = misskeyApi(endpoint, data, token);
promiseDialog(promise, null, async (err) => { promiseDialog(promise, onSuccess, onFailure ?? (err => apiErrorHandler(err, endpoint)));
return promise;
});
export async function apiErrorHandler(err: Misskey.api.APIError, endpoint?: string): Promise<void> {
let title: string | undefined; let title: string | undefined;
let text = err.message + '\n' + err.id; let text = err.message + '\n' + err.id;
if (err.code === 'INTERNAL_ERROR') { if (err.code === 'INTERNAL_ERROR') {
title = i18n.ts.internalServerError; title = i18n.ts.internalServerError;
text = i18n.ts.internalServerErrorDescription; text = i18n.ts.internalServerErrorDescription;
@ -71,23 +79,32 @@ export const apiWithDialog = (<E extends keyof Misskey.Endpoints = keyof Misskey
} else if (err.code === 'ROLE_PERMISSION_DENIED') { } else if (err.code === 'ROLE_PERMISSION_DENIED') {
title = i18n.ts.permissionDeniedError; title = i18n.ts.permissionDeniedError;
text = i18n.ts.permissionDeniedErrorDescription; text = i18n.ts.permissionDeniedErrorDescription;
} else if (err.code.startsWith('TOO_MANY')) { } else if (err.code?.startsWith('TOO_MANY')) {
title = i18n.ts.youCannotCreateAnymore; title = i18n.ts.youCannotCreateAnymore;
text = `${i18n.ts.error}: ${err.id}`; text = `${i18n.ts.error}: ${err.id}`;
} else if (err.message.startsWith('Unexpected token')) { }
// @ts-expect-error Misskey内部で定義されていない不明なエラー
if (!err.id && (err.statusCode ?? 0) > 499) {
title = i18n.ts.gotInvalidResponseError; title = i18n.ts.gotInvalidResponseError;
text = i18n.ts.gotInvalidResponseErrorDescription; text = i18n.ts.gotInvalidResponseErrorDescription;
} }
if (err.id && !title) {
title = i18n.ts.somethingHappened;
} else if (!title) {
title = i18n.ts.somethingHappened;
text = err.message;
}
alert({ alert({
type: 'error', type: 'error',
title, title,
text, text,
details: err.info, // @ts-expect-error Misskeyのエラーならinfoを、そうでなければそのまま表示
details: err.id ? err.info : err as unknown,
}); });
}); }
return promise;
}) as typeof misskeyApi;
export function promiseDialog<T>( export function promiseDialog<T>(
promise: Promise<T>, promise: Promise<T>,

View File

@ -44,14 +44,15 @@ export function misskeyApi<
}, },
signal, signal,
}).then(async (res) => { }).then(async (res) => {
const body = res.status === 204 ? null : await res.json(); if (res.ok && res.status !== 204) {
const body = await res.json();
if (res.status === 200) {
resolve(body); resolve(body);
} else if (res.status === 204) { } else if (res.status === 204) {
resolve(undefined as _ResT); // void -> undefined resolve(undefined as _ResT); // void -> undefined
} else { } else {
reject(body.error); // エラー応答で JSON.parse に失敗した場合は HTTP ステータスコードとメッセージを返す
const body = await res.json().catch(() => ({ statusCode: res.status, message: res.statusText }));
reject(typeof body.error === 'object' ? body.error : body);
} }
}).catch(reject); }).catch(reject);
}); });