diff --git a/ui/src/components/Header/index.tsx b/ui/src/components/Header/index.tsx index 297ac5b9..8698ea24 100644 --- a/ui/src/components/Header/index.tsx +++ b/ui/src/components/Header/index.tsx @@ -81,7 +81,9 @@ const Header: FC = () => { } if (floppyNavigation.shouldProcessLinkClick(evt)) { evt.preventDefault(); - floppyNavigation.navigateToLogin(); + floppyNavigation.navigateToLogin({ + handler: navigate, + }); } }; diff --git a/ui/src/pages/Questions/index.tsx b/ui/src/pages/Questions/index.tsx index 075b74d8..be432871 100644 --- a/ui/src/pages/Questions/index.tsx +++ b/ui/src/pages/Questions/index.tsx @@ -8,7 +8,7 @@ import { FollowingTags, QuestionList, HotQuestions } from '@/components'; import { siteInfoStore, loggedUserInfoStore } from '@/stores'; import { useQuestionList } from '@/services'; import * as Type from '@/common/interface'; -import { userCenter } from '@/utils'; +import { userCenter, floppyNavigation } from '@/utils'; const Questions: FC = () => { const { t } = useTranslation('translation', { keyPrefix: 'question' }); @@ -53,12 +53,16 @@ const Questions: FC = () => { })}
{siteInfo.description}
- + {t('login', { keyPrefix: 'btns' })} + className="btn btn-link ms-2" + onClick={floppyNavigation.handleRouteLinkClick}> {t('signup', { keyPrefix: 'btns' })} diff --git a/ui/src/utils/floppyNavigation.ts b/ui/src/utils/floppyNavigation.ts index f1492a97..e62447bd 100644 --- a/ui/src/utils/floppyNavigation.ts +++ b/ui/src/utils/floppyNavigation.ts @@ -21,17 +21,25 @@ const storageLoginRedirect = () => { }; /** - * Determining whether an url is an external link + * Determining if an url is a full link */ -const isExternalLink = (url = '') => { +const isFullLink = (url = '') => { let ret = false; - try { - const urlObject = new URL(url, document.baseURI); - if (urlObject && urlObject.origin !== window.location.origin) { - ret = true; - } - // eslint-disable-next-line no-empty - } catch (ex) {} + if (/^(http:|https:|\/\/)/i.test(url)) { + ret = true; + } + return ret; +}; + +/** + * Determining if a link is routable + */ +const isRoutableLink = (url = '') => { + let ret = true; + if (isFullLink(url)) { + ret = false; + } + return ret; }; @@ -55,7 +63,7 @@ const navigate = ( if (to === RouteAlias.login || to === getLoginUrl()) { storageLoginRedirect(); } - if (isExternalLink(to)) { + if (!isRoutableLink(to) && handler !== 'href' && handler !== 'replace') { handler = 'href'; } if (handler === 'href') { @@ -86,10 +94,11 @@ const shouldProcessLinkClick = (evt) => { if (evt.defaultPrevented) { return false; } - const { target, nodeName } = evt.currentTarget; - if (nodeName.toLowerCase() !== 'a') { + const nodeName = evt.currentTarget?.nodeName; + if (nodeName?.toLowerCase() !== 'a') { return false; } + const target = evt.currentTarget?.target; return ( evt.button === 0 && (!target || target === '_self') && @@ -97,9 +106,27 @@ const shouldProcessLinkClick = (evt) => { ); }; +/** + * Automatic handling of click events on route links + */ +const handleRouteLinkClick = (evt) => { + if (!shouldProcessLinkClick(evt)) { + return; + } + const curTarget = evt.currentTarget; + const href = curTarget?.getAttribute('href'); + if (!isRoutableLink(href)) { + evt.preventDefault(); + navigate(href); + } +}; + export const floppyNavigation = { differentCurrent, navigate, navigateToLogin, shouldProcessLinkClick, + isFullLink, + isRoutableLink, + handleRouteLinkClick, };