tiptap: only auto show picker when user is author

This commit is contained in:
fantasticit 2022-04-27 12:11:03 +08:00
parent 2643c5a42e
commit a5a4d95c1b
8 changed files with 49 additions and 21 deletions

View File

@ -5,6 +5,7 @@ import { KatexWrapper } from '../wrappers/katex';
type IKatexAttrs = {
text?: string;
defaultShowPicker?: boolean;
createUser: string;
};
declare module '@tiptap/core' {
@ -43,6 +44,9 @@ export const Katex = Node.create({
defaultShowPicker: {
default: false,
},
createUser: {
default: null,
},
};
},
@ -57,7 +61,7 @@ export const Katex = Node.create({
addCommands() {
return {
setKatex:
(options = {}) =>
(options) =>
({ commands }) => {
return commands.insertContent({
type: this.name,

View File

@ -26,7 +26,7 @@ export const QuickInsert = Node.create({
const $from = state.selection.$from;
const tr = state.tr.deleteRange($from.start(), $from.pos);
dispatch(tr);
props?.command(editor);
props?.command(editor, props.user);
editor?.view?.focus();
},
},

View File

@ -7,6 +7,7 @@ type IStatusAttrs = {
color?: string;
text?: string;
defaultShowPicker?: boolean;
createUser: string;
};
declare module '@tiptap/core' {
@ -37,6 +38,9 @@ export const Status = Node.create({
defaultShowPicker: {
default: false,
},
createUser: {
default: null,
},
};
},
@ -63,7 +67,7 @@ export const Status = Node.create({
addCommands() {
return {
setStatus:
(options = {}) =>
(options) =>
({ commands }) => {
return commands.insertContent({
type: this.name,

View File

@ -18,6 +18,7 @@ import {
} from 'components/icons';
import { GridSelect } from 'components/grid-select';
import { useToggle } from 'hooks/use-toggle';
import { useUser } from 'data/user';
import { createKeysLocalStorageLRUCache } from 'helpers/lru-cache';
import { isTitleActive } from '../../utils/is-active';
import { createCountdown } from '../countdown/service';
@ -92,12 +93,13 @@ const COMMANDS = [
{
icon: <IconMath />,
label: '数学公式',
action: (editor) => editor.chain().focus().setKatex({ defaultShowPicker: true }).run(),
action: (editor, user) => editor.chain().focus().setKatex({ defaultShowPicker: true, createUser: user.name }).run(),
},
{
icon: <IconStatus />,
label: '状态',
action: (editor) => editor.chain().focus().setStatus({ defaultShowPicker: true }).run(),
action: (editor, user) =>
editor.chain().focus().setStatus({ defaultShowPicker: true, createUser: user.name }).run(),
},
{
icon: <IconCallout />,
@ -120,6 +122,7 @@ const COMMANDS = [
];
export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
const { user } = useUser();
const [recentUsed, setRecentUsed] = useState([]);
const [visible, toggleVisible] = useToggle(false);
@ -141,7 +144,7 @@ export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
return () => {
insertMenuLRUCache.put(command.label);
setRecentUsed(transformToCommands(insertMenuLRUCache.get() as string[]));
command.action(editor);
command.action(editor, user);
toggleVisible(false);
};
},

View File

@ -209,14 +209,19 @@ export const QUICK_INSERT_ITEMS = [
</Space>
),
command: (editor: Editor) =>
command: (editor: Editor, user) => {
console.log('user', user);
if (!user) return;
editor
.chain()
.focus()
.setKatex({
defaultShowPicker: true,
createUser: user.name,
})
.run(),
.run();
},
},
{
@ -227,14 +232,18 @@ export const QUICK_INSERT_ITEMS = [
</Space>
),
command: (editor: Editor) =>
command: (editor: Editor, user) => {
if (!user) return;
editor
.chain()
.focus()
.setStatus({
defaultShowPicker: true,
createUser: user.name,
})
.run(),
.run();
},
},
{

View File

@ -5,13 +5,15 @@ import { Popover, TextArea, Typography, Space } from '@douyinfe/semi-ui';
import { IconHelpCircle } from '@douyinfe/semi-icons';
import katex from 'katex';
import { useToggle } from 'hooks/use-toggle';
import { useUser } from 'data/user';
import styles from './index.module.scss';
const { Text } = Typography;
export const KatexWrapper = ({ editor, node, updateAttributes }) => {
const isEditable = editor.isEditable;
const { text, defaultShowPicker } = node.attrs;
const { text, defaultShowPicker, createUser } = node.attrs;
const { user } = useUser();
const ref = useRef<HTMLTextAreaElement>();
const [visible, toggleVisible] = useToggle(false);
@ -36,19 +38,19 @@ export const KatexWrapper = ({ editor, node, updateAttributes }) => {
const onVisibleChange = useCallback(
(value) => {
toggleVisible(value);
if (defaultShowPicker) {
if (defaultShowPicker && user && createUser === user.name) {
updateAttributes({ defaultShowPicker: false });
}
},
[defaultShowPicker, updateAttributes]
[defaultShowPicker, updateAttributes, createUser, user]
);
useEffect(() => {
if (defaultShowPicker) {
if (defaultShowPicker && user && createUser === user.name) {
toggleVisible(true);
setTimeout(() => ref.current?.focus(), 100);
}
}, [defaultShowPicker]);
}, [defaultShowPicker, createUser, user]);
return (
<NodeViewWrapper as="span" className={cls(styles.wrap, 'render-wrapper')} contentEditable={false}>

View File

@ -2,6 +2,7 @@ import { Editor } from '@tiptap/core';
import React, { useState, useEffect, forwardRef, useImperativeHandle, useRef } from 'react';
import cls from 'classnames';
import scrollIntoView from 'scroll-into-view-if-needed';
import { useUser } from 'data/user';
import styles from './index.module.scss';
interface IProps {
@ -11,6 +12,7 @@ interface IProps {
}
export const MenuList: React.FC<IProps> = forwardRef((props, ref) => {
const { user } = useUser();
const $container = useRef<HTMLDivElement>();
const [selectedIndex, setSelectedIndex] = useState(0);
@ -18,6 +20,8 @@ export const MenuList: React.FC<IProps> = forwardRef((props, ref) => {
const item = props.items[index];
if (item) {
// @ts-ignore
item.user = user; // 注入用户信息
props.command(item);
}
};

View File

@ -1,9 +1,10 @@
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
import { Button, Collapsible, Space, Popover, Tag, Input } from '@douyinfe/semi-ui';
import cls from 'classnames';
import { useCallback, useEffect, useRef } from 'react';
import { useUser } from 'data/user';
import { useToggle } from 'hooks/use-toggle';
import styles from './index.module.scss';
import { useCallback, useEffect, useRef } from 'react';
const colors = [
'#F5222D',
@ -52,7 +53,8 @@ const colors = [
export const StatusWrapper = ({ editor, node, updateAttributes }) => {
const isEditable = editor.isEditable;
const { color, text, defaultShowPicker } = node.attrs;
const { color, text, defaultShowPicker, createUser } = node.attrs;
const { user } = useUser();
const ref = useRef<HTMLInputElement>();
const [visible, toggleVisible] = useToggle(false);
const [isOpen, toggleOpen] = useToggle(false);
@ -66,19 +68,19 @@ export const StatusWrapper = ({ editor, node, updateAttributes }) => {
const onVisibleChange = useCallback(
(value) => {
toggleVisible(value);
if (defaultShowPicker) {
if (defaultShowPicker && user && user.name === createUser) {
updateAttributes({ defaultShowPicker: false });
}
},
[defaultShowPicker, updateAttributes]
[defaultShowPicker, updateAttributes, createUser, user]
);
useEffect(() => {
if (defaultShowPicker) {
if (defaultShowPicker && user && user.name === createUser) {
toggleVisible(true);
setTimeout(() => ref.current?.focus(), 100);
}
}, [defaultShowPicker]);
}, [defaultShowPicker, createUser, user]);
useEffect(() => {
if (visible) {