diff --git a/ui/src/components/Editor/Viewer.tsx b/ui/src/components/Editor/Viewer.tsx
index db036f90..357be508 100644
--- a/ui/src/components/Editor/Viewer.tsx
+++ b/ui/src/components/Editor/Viewer.tsx
@@ -8,6 +8,7 @@ import {
} from 'react';
import { markdownToHtml } from '@/services';
+import ImgViewer from '@/components/ImgViewer';
import { htmlRender } from './utils';
@@ -48,11 +49,13 @@ const Index = ({ value }, ref) => {
});
return (
-
+
+
+
);
};
diff --git a/ui/src/components/ImgViewer/index.css b/ui/src/components/ImgViewer/index.css
new file mode 100644
index 00000000..c70399f1
--- /dev/null
+++ b/ui/src/components/ImgViewer/index.css
@@ -0,0 +1,7 @@
+.img-viewer .cursor-zoom-out {
+ cursor: zoom-out !important;
+}
+
+.img-viewer img:not(a img, img.broken) {
+ cursor: zoom-in;
+}
diff --git a/ui/src/hooks/useImgViewer/index.tsx b/ui/src/components/ImgViewer/index.tsx
similarity index 67%
rename from ui/src/hooks/useImgViewer/index.tsx
rename to ui/src/components/ImgViewer/index.tsx
index 6b3a30c2..eceb45b4 100644
--- a/ui/src/hooks/useImgViewer/index.tsx
+++ b/ui/src/components/ImgViewer/index.tsx
@@ -1,14 +1,13 @@
-import { useLayoutEffect, useState, MouseEvent, useEffect } from 'react';
+import { FC, MouseEvent, ReactNode, useEffect, useState } from 'react';
import { Modal } from 'react-bootstrap';
-import { useLocation } from 'react-router-dom';
-import ReactDOM from 'react-dom/client';
+import './index.css';
+import classnames from 'classnames';
-const div = document.createElement('div');
-const root = ReactDOM.createRoot(div);
-
-const useImgViewer = () => {
- const location = useLocation();
+const Index: FC<{
+ children: ReactNode;
+ className?: classnames.Argument;
+}> = ({ children, className }) => {
const [visible, setVisible] = useState(false);
const [imgSrc, setImgSrc] = useState('');
const onClose = () => {
@@ -47,8 +46,18 @@ const useImgViewer = () => {
}
};
- useLayoutEffect(() => {
- root.render(
+ useEffect(() => {
+ return () => {
+ onClose();
+ };
+ }, []);
+
+ return (
+ // eslint-disable-next-line jsx-a11y/click-events-have-key-events
+
+ {children}
{
scrollable
contentClassName="bg-transparent"
onHide={onClose}>
-
+
- ,
- );
- });
- useEffect(() => {
- onClose();
- }, [location]);
- return {
- onClose,
- checkClickForImgView,
- };
+
+
+ );
};
-export default useImgViewer;
+export default Index;
diff --git a/ui/src/components/index.ts b/ui/src/components/index.ts
index 840d3f4a..ad83636b 100644
--- a/ui/src/components/index.ts
+++ b/ui/src/components/index.ts
@@ -39,6 +39,7 @@ import QuestionList from './QuestionList';
import HotQuestions from './HotQuestions';
import HttpErrorContent from './HttpErrorContent';
import CustomSidebar from './CustomSidebar';
+import ImgViewer from './ImgViewer';
export {
Avatar,
@@ -84,5 +85,6 @@ export {
HotQuestions,
HttpErrorContent,
CustomSidebar,
+ ImgViewer,
};
export type { EditorRef, JSONSchema, UISchema };
diff --git a/ui/src/hooks/index.ts b/ui/src/hooks/index.ts
index f7942048..756d8724 100644
--- a/ui/src/hooks/index.ts
+++ b/ui/src/hooks/index.ts
@@ -10,7 +10,6 @@ import useChangePasswordModal from './useChangePasswordModal';
import usePageTags from './usePageTags';
import useLoginRedirect from './useLoginRedirect';
import usePromptWithUnload from './usePrompt';
-import useImgViewer from './useImgViewer';
export {
useTagModal,
@@ -25,5 +24,4 @@ export {
usePageTags,
useLoginRedirect,
usePromptWithUnload,
- useImgViewer,
};
diff --git a/ui/src/index.scss b/ui/src/index.scss
index 5a6efe88..29191bb8 100644
--- a/ui/src/index.scss
+++ b/ui/src/index.scss
@@ -120,14 +120,6 @@ a {
cursor: pointer;
}
-.cursor-zoom-out {
- cursor: zoom-out !important;
-}
-
-img:not(a img, img.broken) {
- cursor: zoom-in;
-}
-
.resize-none {
resize: none;
}
diff --git a/ui/src/pages/Admin/Branding/index.tsx b/ui/src/pages/Admin/Branding/index.tsx
index acbe1e32..93a86d2d 100644
--- a/ui/src/pages/Admin/Branding/index.tsx
+++ b/ui/src/pages/Admin/Branding/index.tsx
@@ -1,7 +1,7 @@
import { FC, memo, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { JSONSchema, SchemaForm, UISchema } from '@/components';
+import { JSONSchema, SchemaForm, UISchema, ImgViewer } from '@/components';
import { FormDataType } from '@/common/interface';
import { brandSetting, getBrandSetting } from '@/services';
import { brandingStore } from '@/stores';
@@ -142,7 +142,7 @@ const Index: FC = () => {
}, []);
return (
-
+
{t('page_title')}
{
onSubmit={onSubmit}
onChange={handleOnChange}
/>
-
+
);
};
diff --git a/ui/src/pages/Admin/SettingsUsers/index.tsx b/ui/src/pages/Admin/SettingsUsers/index.tsx
index b8da8529..ad0ca476 100644
--- a/ui/src/pages/Admin/SettingsUsers/index.tsx
+++ b/ui/src/pages/Admin/SettingsUsers/index.tsx
@@ -146,6 +146,9 @@ const Index: FC = () => {
useEffect(() => {
getUsersSetting().then((resp) => {
+ if (!resp) {
+ return;
+ }
const formMeta: Type.FormDataType = {};
Object.keys(formData).forEach((k) => {
let v = resp[k];
diff --git a/ui/src/pages/Layout/index.tsx b/ui/src/pages/Layout/index.tsx
index 97a682f2..e64925ff 100644
--- a/ui/src/pages/Layout/index.tsx
+++ b/ui/src/pages/Layout/index.tsx
@@ -15,7 +15,6 @@ import {
HttpErrorContent,
} from '@/components';
import { LoginToContinueModal } from '@/components/Modal';
-import { useImgViewer } from '@/hooks';
const Layout: FC = () => {
const location = useLocation();
@@ -24,7 +23,6 @@ const Layout: FC = () => {
toastClear();
};
const { code: httpStatusCode, reset: httpStatusReset } = errorCodeStore();
- const imgViewer = useImgViewer();
const { show: showLoginToContinueModal } = loginToContinueStore();
useEffect(() => {
@@ -40,9 +38,7 @@ const Layout: FC = () => {
}}>
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events */}
-
+
{httpStatusCode ? (
) : (
diff --git a/ui/src/pages/Questions/Detail/components/Question/index.tsx b/ui/src/pages/Questions/Detail/components/Question/index.tsx
index 3cfb7de0..40fc0a25 100644
--- a/ui/src/pages/Questions/Detail/components/Question/index.tsx
+++ b/ui/src/pages/Questions/Detail/components/Question/index.tsx
@@ -12,6 +12,7 @@ import {
FormatTime,
htmlRender,
Icon,
+ ImgViewer,
} from '@/components';
import { formatCount, guard } from '@/utils';
import { following } from '@/services';
@@ -114,11 +115,13 @@ const Index: FC
= ({ data, initPage, hasAnswer, isLogged }) => {
return ;
})}
-
+
+
+
{
const [mailHash, setMailHash] = useState('');
const [count] = useState(0);
const [profileAgent, setProfileAgent] = useState();
-
const [formData, setFormData] = useState({
display_name: {
value: '',
@@ -343,66 +342,68 @@ const Index: React.FC = () => {
-
- {formData.avatar.type === 'gravatar' && (
-
- 0 ? `&t=${new Date().valueOf()}` : ''
- }`}
- className="me-3 rounded"
- />
-
-
- You can change image on
-
- gravatar.com
-
-
-
-
- )}
-
- {formData.avatar.type === 'custom' && (
-
-
+
+
+ {formData.avatar.type === 'gravatar' && (
+
0 ? `&t=${new Date().valueOf()}` : ''
+ }`}
+ className="me-3 rounded"
/>
-
-
-
-
-
-
+
+
+ You can change image on
+
+ gravatar.com
+
+
+
-
-
- You can upload your image.
-
-
-
- )}
- {formData.avatar.type === 'default' && (
-
- )}
-
+ )}
+
+ {formData.avatar.type === 'custom' && (
+
+
+
+
+
+
+
+
+
+
+
+
+ You can upload your image.
+
+
+
+ )}
+ {formData.avatar.type === 'default' && (
+
+ )}
+
+
void;
}
+const defaultUsersConf: AdminSettingsUsers = {
+ allow_update_avatar: false,
+ allow_update_bio: false,
+ allow_update_display_name: false,
+ allow_update_location: false,
+ allow_update_username: false,
+ allow_update_website: false,
+ default_avatar: 'system',
+};
+
const siteInfo = create((set) => ({
siteInfo: {
name: DEFAULT_SITE_NAME,
@@ -22,15 +32,7 @@ const siteInfo = create((set) => ({
contact_email: '',
permalink: 1,
},
- users: {
- allow_update_avatar: false,
- allow_update_bio: false,
- allow_update_display_name: false,
- allow_update_location: false,
- allow_update_username: false,
- allow_update_website: false,
- default_avatar: 'system',
- },
+ users: defaultUsersConf,
version: '',
revision: '',
update: (params) =>
@@ -50,6 +52,7 @@ const siteInfo = create((set) => ({
},
updateUsers: (users) => {
set(() => {
+ users ||= defaultUsersConf;
return { users };
});
},