mirror of https://github.com/fantasticit/think.git
tiptap: only auto show picker when user is author
This commit is contained in:
parent
2643c5a42e
commit
a5a4d95c1b
|
@ -5,6 +5,7 @@ import { KatexWrapper } from '../wrappers/katex';
|
||||||
type IKatexAttrs = {
|
type IKatexAttrs = {
|
||||||
text?: string;
|
text?: string;
|
||||||
defaultShowPicker?: boolean;
|
defaultShowPicker?: boolean;
|
||||||
|
createUser: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
declare module '@tiptap/core' {
|
declare module '@tiptap/core' {
|
||||||
|
@ -43,6 +44,9 @@ export const Katex = Node.create({
|
||||||
defaultShowPicker: {
|
defaultShowPicker: {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
createUser: {
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -57,7 +61,7 @@ export const Katex = Node.create({
|
||||||
addCommands() {
|
addCommands() {
|
||||||
return {
|
return {
|
||||||
setKatex:
|
setKatex:
|
||||||
(options = {}) =>
|
(options) =>
|
||||||
({ commands }) => {
|
({ commands }) => {
|
||||||
return commands.insertContent({
|
return commands.insertContent({
|
||||||
type: this.name,
|
type: this.name,
|
||||||
|
|
|
@ -26,7 +26,7 @@ export const QuickInsert = Node.create({
|
||||||
const $from = state.selection.$from;
|
const $from = state.selection.$from;
|
||||||
const tr = state.tr.deleteRange($from.start(), $from.pos);
|
const tr = state.tr.deleteRange($from.start(), $from.pos);
|
||||||
dispatch(tr);
|
dispatch(tr);
|
||||||
props?.command(editor);
|
props?.command(editor, props.user);
|
||||||
editor?.view?.focus();
|
editor?.view?.focus();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,6 +7,7 @@ type IStatusAttrs = {
|
||||||
color?: string;
|
color?: string;
|
||||||
text?: string;
|
text?: string;
|
||||||
defaultShowPicker?: boolean;
|
defaultShowPicker?: boolean;
|
||||||
|
createUser: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
declare module '@tiptap/core' {
|
declare module '@tiptap/core' {
|
||||||
|
@ -37,6 +38,9 @@ export const Status = Node.create({
|
||||||
defaultShowPicker: {
|
defaultShowPicker: {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
createUser: {
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -63,7 +67,7 @@ export const Status = Node.create({
|
||||||
addCommands() {
|
addCommands() {
|
||||||
return {
|
return {
|
||||||
setStatus:
|
setStatus:
|
||||||
(options = {}) =>
|
(options) =>
|
||||||
({ commands }) => {
|
({ commands }) => {
|
||||||
return commands.insertContent({
|
return commands.insertContent({
|
||||||
type: this.name,
|
type: this.name,
|
||||||
|
|
|
@ -18,6 +18,7 @@ import {
|
||||||
} from 'components/icons';
|
} from 'components/icons';
|
||||||
import { GridSelect } from 'components/grid-select';
|
import { GridSelect } from 'components/grid-select';
|
||||||
import { useToggle } from 'hooks/use-toggle';
|
import { useToggle } from 'hooks/use-toggle';
|
||||||
|
import { useUser } from 'data/user';
|
||||||
import { createKeysLocalStorageLRUCache } from 'helpers/lru-cache';
|
import { createKeysLocalStorageLRUCache } from 'helpers/lru-cache';
|
||||||
import { isTitleActive } from '../../utils/is-active';
|
import { isTitleActive } from '../../utils/is-active';
|
||||||
import { createCountdown } from '../countdown/service';
|
import { createCountdown } from '../countdown/service';
|
||||||
|
@ -92,12 +93,13 @@ const COMMANDS = [
|
||||||
{
|
{
|
||||||
icon: <IconMath />,
|
icon: <IconMath />,
|
||||||
label: '数学公式',
|
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 />,
|
icon: <IconStatus />,
|
||||||
label: '状态',
|
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 />,
|
icon: <IconCallout />,
|
||||||
|
@ -120,6 +122,7 @@ const COMMANDS = [
|
||||||
];
|
];
|
||||||
|
|
||||||
export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
|
export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
|
const { user } = useUser();
|
||||||
const [recentUsed, setRecentUsed] = useState([]);
|
const [recentUsed, setRecentUsed] = useState([]);
|
||||||
const [visible, toggleVisible] = useToggle(false);
|
const [visible, toggleVisible] = useToggle(false);
|
||||||
|
|
||||||
|
@ -141,7 +144,7 @@ export const Insert: React.FC<{ editor: Editor }> = ({ editor }) => {
|
||||||
return () => {
|
return () => {
|
||||||
insertMenuLRUCache.put(command.label);
|
insertMenuLRUCache.put(command.label);
|
||||||
setRecentUsed(transformToCommands(insertMenuLRUCache.get() as string[]));
|
setRecentUsed(transformToCommands(insertMenuLRUCache.get() as string[]));
|
||||||
command.action(editor);
|
command.action(editor, user);
|
||||||
toggleVisible(false);
|
toggleVisible(false);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
|
@ -209,14 +209,19 @@ export const QUICK_INSERT_ITEMS = [
|
||||||
数学公式
|
数学公式
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
command: (editor: Editor) =>
|
command: (editor: Editor, user) => {
|
||||||
|
console.log('user', user);
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
.focus()
|
.focus()
|
||||||
.setKatex({
|
.setKatex({
|
||||||
defaultShowPicker: true,
|
defaultShowPicker: true,
|
||||||
|
createUser: user.name,
|
||||||
})
|
})
|
||||||
.run(),
|
.run();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -227,14 +232,18 @@ export const QUICK_INSERT_ITEMS = [
|
||||||
状态
|
状态
|
||||||
</Space>
|
</Space>
|
||||||
),
|
),
|
||||||
command: (editor: Editor) =>
|
command: (editor: Editor, user) => {
|
||||||
|
if (!user) return;
|
||||||
|
|
||||||
editor
|
editor
|
||||||
.chain()
|
.chain()
|
||||||
.focus()
|
.focus()
|
||||||
.setStatus({
|
.setStatus({
|
||||||
defaultShowPicker: true,
|
defaultShowPicker: true,
|
||||||
|
createUser: user.name,
|
||||||
})
|
})
|
||||||
.run(),
|
.run();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,13 +5,15 @@ import { Popover, TextArea, Typography, Space } from '@douyinfe/semi-ui';
|
||||||
import { IconHelpCircle } from '@douyinfe/semi-icons';
|
import { IconHelpCircle } from '@douyinfe/semi-icons';
|
||||||
import katex from 'katex';
|
import katex from 'katex';
|
||||||
import { useToggle } from 'hooks/use-toggle';
|
import { useToggle } from 'hooks/use-toggle';
|
||||||
|
import { useUser } from 'data/user';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
|
|
||||||
export const KatexWrapper = ({ editor, node, updateAttributes }) => {
|
export const KatexWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
const isEditable = editor.isEditable;
|
const isEditable = editor.isEditable;
|
||||||
const { text, defaultShowPicker } = node.attrs;
|
const { text, defaultShowPicker, createUser } = node.attrs;
|
||||||
|
const { user } = useUser();
|
||||||
const ref = useRef<HTMLTextAreaElement>();
|
const ref = useRef<HTMLTextAreaElement>();
|
||||||
const [visible, toggleVisible] = useToggle(false);
|
const [visible, toggleVisible] = useToggle(false);
|
||||||
|
|
||||||
|
@ -36,19 +38,19 @@ export const KatexWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
const onVisibleChange = useCallback(
|
const onVisibleChange = useCallback(
|
||||||
(value) => {
|
(value) => {
|
||||||
toggleVisible(value);
|
toggleVisible(value);
|
||||||
if (defaultShowPicker) {
|
if (defaultShowPicker && user && createUser === user.name) {
|
||||||
updateAttributes({ defaultShowPicker: false });
|
updateAttributes({ defaultShowPicker: false });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[defaultShowPicker, updateAttributes]
|
[defaultShowPicker, updateAttributes, createUser, user]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (defaultShowPicker) {
|
if (defaultShowPicker && user && createUser === user.name) {
|
||||||
toggleVisible(true);
|
toggleVisible(true);
|
||||||
setTimeout(() => ref.current?.focus(), 100);
|
setTimeout(() => ref.current?.focus(), 100);
|
||||||
}
|
}
|
||||||
}, [defaultShowPicker]);
|
}, [defaultShowPicker, createUser, user]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<NodeViewWrapper as="span" className={cls(styles.wrap, 'render-wrapper')} contentEditable={false}>
|
<NodeViewWrapper as="span" className={cls(styles.wrap, 'render-wrapper')} contentEditable={false}>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Editor } from '@tiptap/core';
|
||||||
import React, { useState, useEffect, forwardRef, useImperativeHandle, useRef } from 'react';
|
import React, { useState, useEffect, forwardRef, useImperativeHandle, useRef } from 'react';
|
||||||
import cls from 'classnames';
|
import cls from 'classnames';
|
||||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||||
|
import { useUser } from 'data/user';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
|
@ -11,6 +12,7 @@ interface IProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const MenuList: React.FC<IProps> = forwardRef((props, ref) => {
|
export const MenuList: React.FC<IProps> = forwardRef((props, ref) => {
|
||||||
|
const { user } = useUser();
|
||||||
const $container = useRef<HTMLDivElement>();
|
const $container = useRef<HTMLDivElement>();
|
||||||
const [selectedIndex, setSelectedIndex] = useState(0);
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
||||||
|
|
||||||
|
@ -18,6 +20,8 @@ export const MenuList: React.FC<IProps> = forwardRef((props, ref) => {
|
||||||
const item = props.items[index];
|
const item = props.items[index];
|
||||||
|
|
||||||
if (item) {
|
if (item) {
|
||||||
|
// @ts-ignore
|
||||||
|
item.user = user; // 注入用户信息
|
||||||
props.command(item);
|
props.command(item);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
|
import { NodeViewWrapper, NodeViewContent } from '@tiptap/react';
|
||||||
import { Button, Collapsible, Space, Popover, Tag, Input } from '@douyinfe/semi-ui';
|
import { Button, Collapsible, Space, Popover, Tag, Input } from '@douyinfe/semi-ui';
|
||||||
import cls from 'classnames';
|
import cls from 'classnames';
|
||||||
|
import { useCallback, useEffect, useRef } from 'react';
|
||||||
|
import { useUser } from 'data/user';
|
||||||
import { useToggle } from 'hooks/use-toggle';
|
import { useToggle } from 'hooks/use-toggle';
|
||||||
import styles from './index.module.scss';
|
import styles from './index.module.scss';
|
||||||
import { useCallback, useEffect, useRef } from 'react';
|
|
||||||
|
|
||||||
const colors = [
|
const colors = [
|
||||||
'#F5222D',
|
'#F5222D',
|
||||||
|
@ -52,7 +53,8 @@ const colors = [
|
||||||
|
|
||||||
export const StatusWrapper = ({ editor, node, updateAttributes }) => {
|
export const StatusWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
const isEditable = editor.isEditable;
|
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 ref = useRef<HTMLInputElement>();
|
||||||
const [visible, toggleVisible] = useToggle(false);
|
const [visible, toggleVisible] = useToggle(false);
|
||||||
const [isOpen, toggleOpen] = useToggle(false);
|
const [isOpen, toggleOpen] = useToggle(false);
|
||||||
|
@ -66,19 +68,19 @@ export const StatusWrapper = ({ editor, node, updateAttributes }) => {
|
||||||
const onVisibleChange = useCallback(
|
const onVisibleChange = useCallback(
|
||||||
(value) => {
|
(value) => {
|
||||||
toggleVisible(value);
|
toggleVisible(value);
|
||||||
if (defaultShowPicker) {
|
if (defaultShowPicker && user && user.name === createUser) {
|
||||||
updateAttributes({ defaultShowPicker: false });
|
updateAttributes({ defaultShowPicker: false });
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[defaultShowPicker, updateAttributes]
|
[defaultShowPicker, updateAttributes, createUser, user]
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (defaultShowPicker) {
|
if (defaultShowPicker && user && user.name === createUser) {
|
||||||
toggleVisible(true);
|
toggleVisible(true);
|
||||||
setTimeout(() => ref.current?.focus(), 100);
|
setTimeout(() => ref.current?.focus(), 100);
|
||||||
}
|
}
|
||||||
}, [defaultShowPicker]);
|
}, [defaultShowPicker, createUser, user]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
|
Loading…
Reference in New Issue