diff --git a/ui/public/index.html b/ui/public/index.html index b7bce50c..b7c08c02 100644 --- a/ui/public/index.html +++ b/ui/public/index.html @@ -3,13 +3,14 @@ - +
+
+
diff --git a/ui/src/common/constants.ts b/ui/src/common/constants.ts index 35643bda..c8bc1345 100644 --- a/ui/src/common/constants.ts +++ b/ui/src/common/constants.ts @@ -8,6 +8,8 @@ export const CAPTCHA_CODE_STORAGE_KEY = '_a_captcha_'; export const DRAFT_QUESTION_STORAGE_KEY = '_a_dq_'; export const DRAFT_ANSWER_STORAGE_KEY = '_a_da_'; export const DRAFT_TIMESIGH_STORAGE_KEY = '|_a_t_s_|'; +export const QUESTIONS_ORDER_STORAGE_KEY = '_a_qok_'; + export const USER_AGENT_NAMES = { SegmentFault: 'SegmentFault', WeChat: 'WeChat', diff --git a/ui/src/components/CustomizeTheme/index.tsx b/ui/src/components/CustomizeTheme/index.tsx index e9f91576..04f98f7b 100644 --- a/ui/src/components/CustomizeTheme/index.tsx +++ b/ui/src/components/CustomizeTheme/index.tsx @@ -1,4 +1,4 @@ -import { FC } from 'react'; +import { FC, useLayoutEffect } from 'react'; import { Helmet } from 'react-helmet-async'; import Color from 'color'; @@ -11,10 +11,17 @@ const Index: FC = () => { let primaryColor; if (theme_config?.[theme]?.primary_color) { primaryColor = Color(theme_config[theme].primary_color); - document - .querySelector('meta[name="theme-color"]') - ?.setAttribute('content', primaryColor.hex()); } + const setThemeColor = () => { + const themeMetaNode = document.querySelector('meta[name="theme-color"]'); + if (themeMetaNode) { + const themeColor = primaryColor ? primaryColor.hex() : '#0033ff'; + themeMetaNode.setAttribute('content', themeColor); + } + }; + useLayoutEffect(() => { + setThemeColor(); + }, [primaryColor]); return ( diff --git a/ui/src/components/PageTags/index.tsx b/ui/src/components/PageTags/index.tsx index bd6d02a4..74d197b5 100644 --- a/ui/src/components/PageTags/index.tsx +++ b/ui/src/components/PageTags/index.tsx @@ -2,6 +2,7 @@ import { FC, useEffect, useLayoutEffect } from 'react'; import { Helmet } from 'react-helmet-async'; import { brandingStore, pageTagStore, siteInfoStore } from '@/stores'; +import { getCurrentLang } from '@/utils/localize'; const doInsertCustomCSS = !document.querySelector('link[href*="custom.css"]'); @@ -32,7 +33,19 @@ const Index: FC = () => { // eslint-disable-next-line no-empty } catch (ex) {} }; + const currentLang = getCurrentLang(); + const setDocLang = () => { + if (currentLang) { + document.documentElement.setAttribute( + 'lang', + currentLang.replace('_', '-'), + ); + } + }; + useEffect(() => { + setDocLang(); + }, [currentLang]); useEffect(() => { setAppGenerator(); }, [appVersion]); diff --git a/ui/src/components/QuestionList/index.tsx b/ui/src/components/QuestionList/index.tsx index 26599c79..d17f8bba 100644 --- a/ui/src/components/QuestionList/index.tsx +++ b/ui/src/components/QuestionList/index.tsx @@ -3,8 +3,8 @@ import { ListGroup } from 'react-bootstrap'; import { NavLink, useSearchParams } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; +import type { QuestionOrderBy } from '@/common/interface'; import { pathFactory } from '@/router/pathFactory'; -import type * as Type from '@/common/interface'; import { Tag, Pagination, @@ -16,25 +16,32 @@ import { Counts, Icon, } from '@/components'; +import * as Type from '@/common/interface'; -const QuestionOrderKeys: Type.QuestionOrderBy[] = [ +export const QUESTION_ORDER_KEYS: Type.QuestionOrderBy[] = [ 'active', 'newest', 'frequent', 'score', 'unanswered', ]; - interface Props { source: 'questions' | 'tag'; + order?: QuestionOrderBy; data; isLoading: boolean; } -const QuestionList: FC = ({ source, data, isLoading = false }) => { +const QuestionList: FC = ({ + source, + order, + data, + isLoading = false, +}) => { const { t } = useTranslation('translation', { keyPrefix: 'question' }); const [urlSearchParams] = useSearchParams(); - const curOrder = urlSearchParams.get('order') || QuestionOrderKeys[0]; + const curOrder = + order || urlSearchParams.get('order') || QUESTION_ORDER_KEYS[0]; const curPage = Number(urlSearchParams.get('page')) || 1; const pageSize = 20; const count = data?.count || 0; @@ -47,7 +54,7 @@ const QuestionList: FC = ({ source, data, isLoading = false }) => { : t('x_questions', { count })} { const { t } = useTranslation('translation', { keyPrefix: 'question' }); @@ -25,7 +27,12 @@ const Questions: FC = () => { const { user: loggedUser } = loggedUserInfoStore((_) => _); const [urlSearchParams] = useSearchParams(); const curPage = Number(urlSearchParams.get('page')) || 1; - const curOrder = urlSearchParams.get('order') || 'active'; + const storageOrder = Storage.get(QUESTIONS_ORDER_STORAGE_KEY); + const curOrder = + urlSearchParams.get('order') || storageOrder || QUESTION_ORDER_KEYS[0]; + if (curOrder !== storageOrder) { + Storage.set(QUESTIONS_ORDER_STORAGE_KEY, curOrder); + } const reqParams: Type.QueryQuestionsReq = { page_size: 20, page: curPage, @@ -50,6 +57,7 @@ const Questions: FC = () => { diff --git a/ui/template/header.html b/ui/template/header.html index 52e40765..54eba80f 100644 --- a/ui/template/header.html +++ b/ui/template/header.html @@ -3,8 +3,9 @@ - {{.title}} + + {{if .keywords }}{{end}} @@ -37,19 +38,23 @@ -
-
{{end}}
+
+ +