From 781051367c30d544ce89d04617a6cc5c8c54eb15 Mon Sep 17 00:00:00 2001 From: linonetwo Date: Wed, 10 Jan 2024 19:08:55 +0800 Subject: [PATCH] feat: add error message when server is not connected fixes #8 --- src/i18n/en-UK/translation.json | 3 +- src/i18n/zh-Hans/translation.json | 3 +- src/popup/Form.tsx | 2 +- src/shared/hooks/useAddTiddlerToServer.ts | 39 +++++++++++++++-------- src/shared/hooks/useAvailableTags.ts | 20 +++++++++--- 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/src/i18n/en-UK/translation.json b/src/i18n/en-UK/translation.json index d204465..f36603b 100644 --- a/src/i18n/en-UK/translation.json +++ b/src/i18n/en-UK/translation.json @@ -47,6 +47,7 @@ "Error": { "WebServer403": "错误403:你需要允许太微服务器执行任意筛选器", "WebServerCORS": "错误CORS:你的浏览器擅自把请求改为了HTTPS,导致请求失败", - "WebServerUnknown": "错误:未知的请求错误" + "WebServerUnknown": "错误:未知的请求错误", + "GetUserName": "Error: Get user name" } } diff --git a/src/i18n/zh-Hans/translation.json b/src/i18n/zh-Hans/translation.json index e5ac6bf..bbf0b18 100644 --- a/src/i18n/zh-Hans/translation.json +++ b/src/i18n/zh-Hans/translation.json @@ -47,6 +47,7 @@ "Error": { "WebServer403": "Error403: You need to enable server AllowAllExternalFilters", "WebServerCORS": "ErrorCORS: Your browsr turn request to HTTPS cuase it failed", - "WebServerUnknown": "Error: Unknown request error" + "WebServerUnknown": "Error: Unknown request error", + "GetUserName": "错误:获取用户名" } } diff --git a/src/popup/Form.tsx b/src/popup/Form.tsx index 71c7a6a..a2a0e5a 100644 --- a/src/popup/Form.tsx +++ b/src/popup/Form.tsx @@ -23,7 +23,7 @@ export function Form(props: { assets: Asset[]; content: IContent; selectedConten /** * A list of available servers for autocomplete */ - const { activeServers, onlineServers, setActiveServers } = useAddTiddlerToServer(); + const { activeServers, onlineServers, setActiveServers, checkConnectionAndGetUsername } = useAddTiddlerToServer(); const activeServerOptionsForSelectUI = useMemo( () => activeServers.map(item => ({ diff --git a/src/shared/hooks/useAddTiddlerToServer.ts b/src/shared/hooks/useAddTiddlerToServer.ts index ff75fbf..90ce964 100644 --- a/src/shared/hooks/useAddTiddlerToServer.ts +++ b/src/shared/hooks/useAddTiddlerToServer.ts @@ -1,5 +1,6 @@ import { useCallback } from 'react'; import { useTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; import { IServerStatus } from 'tiddlywiki'; import type { ITiddlerFieldsParam } from 'tw5-typed'; import { Writable } from 'type-fest'; @@ -30,17 +31,27 @@ export function useAddTiddlerToServer() { }, ); - const getusername = async (server: IServerInfo) => { - const baseURL = new URL('status', addProtocolToUrl(server.uri)); + const checkConnectionAndGetUsername = useCallback(async (server: IServerInfo) => { + const statusUrl = new URL( + `status`, + addProtocolToUrl(server.uri), + ); + let response: Response; try { - const data = await fetch(baseURL); - const { username } = await data.json() as IServerStatus; - return username; + response = await fetch(statusUrl); } catch (error) { - // 即使报错, 控制台也看不到, 因为点击保存后窗口就关闭了, 也许可以使用notify - console.error('[获取用户名]:', error); + throw new Error(`${t('Disconnected')} ${(error as Error).message}`); } - }; + if (!response.ok) { + throw new Error(`${t('Disconnected')} ${response.statusText}`); + } + try { + const status = await response.json() as IServerStatus; + return status.username; + } catch (error) { + throw new Error(`${t('Error.GetUserName')} ${(error as Error).message}`); + } + }, [t]); const addTiddlerToServer = useCallback( async (server: IServerInfo, tiddler: ITiddlerToAdd): Promise => { @@ -48,9 +59,10 @@ export function useAddTiddlerToServer() { `recipes/default/tiddlers/${tiddler.title as string}`, addProtocolToUrl(server.uri), ); - const username = await getusername(server); try { + const username = await checkConnectionAndGetUsername(server); + tiddler.created = toTWUTCString(new Date()); tiddler.creator = username ?? t('TWCollector'); tiddler.modifier = username ?? t('TWCollector'); @@ -66,12 +78,12 @@ export function useAddTiddlerToServer() { body: JSON.stringify({ title: tiddler.title, fields: tiddler }), }); } catch (error) { - console.error( - `${server.name} ${t('Log.SaveFailed')} Error: ${(error as Error).message}`, - ); + const message = `${server.name} ${t('Log.SaveFailed')} Error: ${(error as Error).message}`; + toast(message); + console.error(message, error); } }, - [t], + [checkConnectionAndGetUsername, t], ); const addTiddlerToAllActiveServers = useCallback( async (newTiddler: ITiddlerToAdd) => { @@ -91,6 +103,7 @@ export function useAddTiddlerToServer() { setActiveServers, addTiddlerToServer, addTiddlerToAllActiveServers, + checkConnectionAndGetUsername, }; } diff --git a/src/shared/hooks/useAvailableTags.ts b/src/shared/hooks/useAvailableTags.ts index 8803327..6b98546 100644 --- a/src/shared/hooks/useAvailableTags.ts +++ b/src/shared/hooks/useAvailableTags.ts @@ -4,16 +4,26 @@ import { useEffect, useState } from 'react'; import { toast } from 'react-toastify'; import type { ITiddlerFields } from 'tw5-typed'; import { addProtocolToUrl } from '../../utils'; -import { useServerStore } from '../server'; +import { useAddTiddlerToServer } from './useAddTiddlerToServer'; export function useAvailableTags() { - const activeServers = useServerStore(({ servers }) => Object.values(servers).filter(server => server.active)); + const { activeServers, checkConnectionAndGetUsername } = useAddTiddlerToServer(); + /** fetched all tags from active servers */ const [availableTagOptions, setAvailableTagOptions] = useState>([]); useEffect(() => { + // FIXME: activeServers change cause this hook render 6 times if (availableTagOptions.length > 0) return; - const getTagsTask = activeServers.map(item => item.uri).map(async serverUriBase => { - const url = new URL('/recipes/default/tiddlers.json?filter=[tags[]]', addProtocolToUrl(serverUriBase)); + const getTagsTask = activeServers.map(async server => { + const url = new URL('/recipes/default/tiddlers.json?filter=[tags[]]', addProtocolToUrl(server.uri)); + try { + await checkConnectionAndGetUsername(server); + } catch (error) { + const message = `${server.name} ${(error as Error).message}`; + toast(message); + console.error(message, error); + return []; + } try { // FIXME: will auto become https and cause CORS error const response = await fetch(url); @@ -50,6 +60,6 @@ export function useAvailableTags() { if (tagsFromServer.length === 0) return; setAvailableTagOptions(tagsFromServer); }); - }, [activeServers, availableTagOptions.length]); + }, [activeServers, availableTagOptions.length, checkConnectionAndGetUsername]); return availableTagOptions; }