client: imporve reader

pull/60/head
fantasticit 2022-05-26 00:15:32 +08:00
parent 3337ea5593
commit cfadcf22a0
7 changed files with 61 additions and 38 deletions

View File

@ -15,17 +15,19 @@ import {
Tooltip,
Typography,
} from '@douyinfe/semi-ui';
import { IUser } from '@think/domains';
import { DataRender } from 'components/data-render';
import { DocumentLinkCopyer } from 'components/document/link';
import { useDoumentMembers } from 'data/document';
import { useUser } from 'data/user';
import { event, JOIN_USER } from 'event';
import { useToggle } from 'hooks/use-toggle';
import React, { useEffect, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
interface IProps {
wikiId: string;
documentId: string;
disabled?: boolean;
}
const { Paragraph } = Typography;
@ -45,7 +47,8 @@ const renderChecked = (onChange, authKey: 'readable' | 'editable') => (checked,
return <Checkbox style={{ display: 'inline-block' }} checked={checked} onChange={handle} />;
};
export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId }) => {
export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId, disabled = false }) => {
const toastedUsersRef = useRef<Array<IUser['id']>>([]);
const { user: currentUser } = useUser();
const [visible, toggleVisible] = useToggle(false);
const { users, loading, error, addUser, updateUser, deleteUser } = useDoumentMembers(documentId);
@ -84,8 +87,9 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
}
newCollaborationUsers.forEach((newUser) => {
if (currentUser && newUser.name !== currentUser.name) {
if (currentUser && newUser.name !== currentUser.name && !toastedUsersRef.current.includes(newUser.id)) {
Toast.info(`${newUser.name}加入文档`);
toastedUsersRef.current.push(newUser.id);
}
});
@ -95,6 +99,7 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
event.on(JOIN_USER, handler);
return () => {
toastedUsersRef.current = [];
event.off(JOIN_USER, handler);
};
}, [collaborationUsers, currentUser]);
@ -120,7 +125,13 @@ export const DocumentCollaboration: React.FC<IProps> = ({ wikiId, documentId })
})}
</AvatarGroup>
<Tooltip content="邀请他人协作" position="bottom">
<Button theme="borderless" type="tertiary" icon={<IconUserAdd />} onClick={toggleVisible}></Button>
<Button
theme="borderless"
type="tertiary"
disabled={disabled}
icon={<IconUserAdd />}
onClick={toggleVisible}
></Button>
</Tooltip>
<Modal
title={'文档协作'}

View File

@ -1,5 +1,5 @@
import { IconArticle, IconEdit } from '@douyinfe/semi-icons';
import { BackTop, Button, Layout, Nav, Popover, Skeleton, Space, Spin, Tooltip, Typography } from '@douyinfe/semi-ui';
import { IconEdit } from '@douyinfe/semi-icons';
import { BackTop, Button, Layout, Nav, Skeleton, Space, Tooltip, Typography } from '@douyinfe/semi-ui';
import cls from 'classnames';
import { DataRender } from 'components/data-render';
import { DocumentCollaboration } from 'components/document/collaboration';
@ -55,11 +55,14 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
const { user } = useUser();
const { data: documentAndAuth, loading: docAuthLoading, error: docAuthError } = useDocumentDetail(documentId);
const { document, authority } = documentAndAuth || {};
const [readable, editable] = useMemo(() => {
if (!authority) return [false, false];
return [authority.readable, authority.editable];
}, [authority]);
const renderAuthor = useCallback(
(element) => {
if (!document) return null;
const target = element && element.querySelector('.ProseMirror .title');
if (target) {
@ -75,29 +78,28 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
Router.push(`/wiki/${document.wikiId}/document/${document.id}/edit`);
}, [document]);
const actions = useMemo(
() => (
const actions = useMemo(() => {
console.log({ readable, editable });
return (
<Space>
{document && authority.readable && (
<DocumentCollaboration key="collaboration" wikiId={document.wikiId} documentId={documentId} />
)}
{authority && authority.editable && (
<Tooltip key="edit" content="编辑" position="bottom">
<Button icon={<IconEdit />} onMouseDown={gotoEdit} />
</Tooltip>
)}
{authority && authority.readable && (
<>
<DocumentShare key="share" documentId={documentId} />
<DocumentVersion key="version" documentId={documentId} />
<DocumentStar key="star" documentId={documentId} />
</>
{document && (
<DocumentCollaboration
disabled={!readable}
key="collaboration"
wikiId={document.wikiId}
documentId={documentId}
/>
)}
<Tooltip key="edit" content="编辑" position="bottom">
<Button disabled={!editable} icon={<IconEdit />} onMouseDown={gotoEdit} />
</Tooltip>
<DocumentShare disabled={!readable} key="share" documentId={documentId} />
<DocumentVersion disabled={!readable} key="version" documentId={documentId} />
<DocumentStar disabled={!readable} key="star" documentId={documentId} />
<DocumentStyle />
</Space>
),
[document, documentId, authority, gotoEdit]
);
);
}, [document, documentId, readable, editable, gotoEdit]);
const editBtnStyle = useMemo(() => getEditBtnStyle(isMobile ? 16 : 100), [isMobile]);
@ -133,7 +135,7 @@ export const DocumentReader: React.FC<IProps> = ({ documentId }) => {
<div className={cls(styles.editorWrap, editorWrapClassNames)} style={{ fontSize }}>
<div id="js-reader-container">
{document && <Seo title={document.title} />}
{user && (
{user && readable && (
<CollaborationEditor
editable={false}
user={user}

View File

@ -10,12 +10,13 @@ import React, { useEffect, useMemo, useState } from 'react';
interface IProps {
documentId: string;
render?: (arg: { isPublic: boolean; toggleVisible: (arg: boolean) => void }) => React.ReactNode;
disabled?: boolean;
render?: (arg: { isPublic: boolean; disabled: boolean; toggleVisible: (arg: boolean) => void }) => React.ReactNode;
}
const { Text } = Typography;
export const DocumentShare: React.FC<IProps> = ({ documentId, render }) => {
export const DocumentShare: React.FC<IProps> = ({ documentId, disabled = false, render }) => {
const [visible, toggleVisible] = useToggle(false);
const { data, loading, error, toggleStatus } = useDocumentDetail(documentId);
const [sharePassword, setSharePassword] = useState('');
@ -34,9 +35,9 @@ export const DocumentShare: React.FC<IProps> = ({ documentId, render }) => {
return (
<>
{render ? (
render({ isPublic, toggleVisible })
render({ isPublic, disabled, toggleVisible })
) : (
<Button type="primary" theme="light" onClick={toggleVisible}>
<Button disabled={disabled} type="primary" theme="light" onClick={toggleVisible}>
{isPublic ? '分享中' : '分享'}
</Button>
)}

View File

@ -5,17 +5,23 @@ import React from 'react';
interface IProps {
documentId: string;
render?: (arg: { star: boolean; text: string; toggleStar: () => Promise<void> }) => React.ReactNode;
disabled?: boolean;
render?: (arg: {
star: boolean;
disabled: boolean;
text: string;
toggleStar: () => Promise<void>;
}) => React.ReactNode;
}
export const DocumentStar: React.FC<IProps> = ({ documentId, render }) => {
export const DocumentStar: React.FC<IProps> = ({ documentId, disabled = false, render }) => {
const { data, toggle: toggleStar } = useDocumentCollectToggle(documentId);
const text = data ? '取消收藏' : '收藏文档';
return (
<>
{render ? (
render({ star: data, toggleStar, text })
render({ star: data, disabled, toggleStar, text })
) : (
<Tooltip content={text} position="bottom">
<Button
@ -24,6 +30,7 @@ export const DocumentStar: React.FC<IProps> = ({ documentId, render }) => {
style={{
color: data ? 'rgba(var(--semi-amber-4), 1)' : 'rgba(var(--semi-grey-3), 1)',
}}
disabled={disabled}
onClick={(e) => {
e.stopPropagation();
e.preventDefault();

View File

@ -14,13 +14,14 @@ import styles from './index.module.scss';
interface IProps {
documentId: string;
disabled?: boolean;
onSelect?: (data) => void;
}
const { Sider, Content } = Layout;
const { Title } = Typography;
export const DocumentVersion: React.FC<IProps> = ({ documentId, onSelect }) => {
export const DocumentVersion: React.FC<IProps> = ({ documentId, disabled = false, onSelect }) => {
const [visible, toggleVisible] = useToggle(false);
const { data, loading, error, refresh } = useDocumentVersion(documentId);
const [selectedVersion, setSelectedVersion] = useState(null);
@ -65,7 +66,7 @@ export const DocumentVersion: React.FC<IProps> = ({ documentId, onSelect }) => {
return (
<>
<Button type="primary" theme="light" onClick={toggleVisible}>
<Button type="primary" theme="light" disabled={disabled} onClick={toggleVisible}>
</Button>
<Modal
@ -87,7 +88,7 @@ export const DocumentVersion: React.FC<IProps> = ({ documentId, onSelect }) => {
theme="light"
type="primary"
style={{ marginRight: 8 }}
disabled={loading || error}
disabled={loading || !!error}
loading={loading}
onClick={() => refresh()}
>

View File

@ -139,7 +139,7 @@ export const useDocumentDetail = (documentId) => {
const { data, error, isLoading, refetch } = useQuery(
DocumentApiDefinition.getDetailById.client(documentId),
() => getDocumentDetail(documentId),
{ staleTime: 3000 }
{ staleTime: 3000, refetchOnReconnect: true, refetchOnMount: true, refetchOnWindowFocus: true }
);
/**

View File

@ -2,6 +2,7 @@
display: flex;
width: 100%;
height: 100%;
min-height: 100px;
overflow: hidden;
flex-direction: column;