From 0765c766b3ea8590a04154e13a9f177da4e62f48 Mon Sep 17 00:00:00 2001 From: Untone Date: Wed, 9 Oct 2024 17:07:05 +0300 Subject: [PATCH] theme-fix+draftslist-fix+minieditor-cancel-fix --- README.en.md | 6 +- README.md | 6 +- src/components/Draft/Draft.tsx | 2 +- src/components/Editor/Editor.tsx | 129 ++++++++++++------ src/components/Editor/MiniEditor.tsx | 9 +- .../Editor/Toolbar/TextBubbleMenu.tsx | 3 +- src/components/Inbox/DialogCard.module.scss | 4 +- .../_shared/LoadMoreWrapper.module.scss | 8 ++ src/components/_shared/LoadMoreWrapper.tsx | 4 +- src/styles/_global.scss | 10 +- src/styles/_theme.scss | 5 +- src/styles/app.scss | 40 ++++-- src/styles/views/Inbox.module.scss | 4 +- 13 files changed, 147 insertions(+), 83 deletions(-) create mode 100644 src/components/_shared/LoadMoreWrapper.module.scss diff --git a/README.en.md b/README.en.md index 4cefb21f..f428df7e 100644 --- a/README.en.md +++ b/README.en.md @@ -42,12 +42,8 @@ bun run e2e:tests # Run tests bun run e2e:tests:ci # Run tests in CI ``` -Structure: -- `/tests/*`: Tests without authentication -- `/tests-with-auth/*`: Tests with authentication - ## CI/CD Tests are executed in GitHub Actions. Make sure `BASE_URL` is correctly configured in CI. -## Project version: 0.9.7 +## Version: 0.9.7 diff --git a/README.md b/README.md index a0e885a5..e0bbf1d0 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,8 @@ bun run e2e:tests # Запуск тестов bun run e2e:tests:ci # Запуск тестов в CI ``` -Структура: -- `/tests/*`: Тесты без аутентификации -- `/tests-with-auth/*`: Тесты с аутентификацией - ## CI/CD Тесты выполняются в GitHub Actions. Убедитесь, что `BASE_URL` корректно настроен в CI. -## Версия проекта: 0.9.7 \ No newline at end of file +## Версия: 0.9.7 \ No newline at end of file diff --git a/src/components/Draft/Draft.tsx b/src/components/Draft/Draft.tsx index c1a3262f..2cda102e 100644 --- a/src/components/Draft/Draft.tsx +++ b/src/components/Draft/Draft.tsx @@ -53,7 +53,7 @@ export const Draft = (props: Props) => { {props.shout.title || t('Unnamed draft')} {props.shout.subtitle}
- + {t('Edit')} diff --git a/src/components/Editor/Editor.tsx b/src/components/Editor/Editor.tsx index 082ad00c..018fec27 100644 --- a/src/components/Editor/Editor.tsx +++ b/src/components/Editor/Editor.tsx @@ -1,6 +1,6 @@ import { HocuspocusProvider } from '@hocuspocus/provider' import { UploadFile } from '@solid-primitives/upload' -import { Editor, EditorOptions } from '@tiptap/core' +import { Editor, EditorOptions, isTextSelection } from '@tiptap/core' import { BubbleMenu } from '@tiptap/extension-bubble-menu' import { CharacterCount } from '@tiptap/extension-character-count' import { Collaboration } from '@tiptap/extension-collaboration' @@ -43,13 +43,8 @@ export const EditorComponent = (props: EditorComponentProps) => { const { t } = useLocalize() const { session, requireAuthentication } = useSession() const author = createMemo(() => session()?.user?.app_data?.profile as Author) - const [isCommonMarkup, _setIsCommonMarkup] = createSignal(false) - const createMenuSignal = () => createSignal(false) - const [shouldShowTextBubbleMenu, _setShouldShowTextBubbleMenu] = createMenuSignal() - const [shouldShowBlockquoteBubbleMenu, _setShouldShowBlockquoteBubbleMenu] = createMenuSignal() - const [shouldShowFigureBubbleMenu, _setShouldShowFigureBubbleMenu] = createMenuSignal() - const [shouldShowIncutBubbleMenu, _setShouldShowIncutBubbleMenu] = createMenuSignal() - const [shouldShowFloatingMenu, _setShouldShowFloatingMenu] = createMenuSignal() + const [isCommonMarkup, setIsCommonMarkup] = createSignal(false) + const [shouldShowTextBubbleMenu, setShouldShowTextBubbleMenu] = createSignal(false) const { showSnackbar } = useSnackbar() const { countWords, setEditing } = useEditorContext() const [editorOptions, setEditorOptions] = createSignal>({}) @@ -180,14 +175,8 @@ export const EditorComponent = (props: EditorComponentProps) => { requireAuthentication(() => { setTimeout(() => { setupEditor() - - // Создаем экземпляр редактора после монтирования createEditorInstance(editorOptions()) - - // Инициализируем меню после создания редактора - if (editor()) { - initializeMenus() - } + initializeMenus() }, 1200) }, 'edit') }) @@ -196,30 +185,80 @@ export const EditorComponent = (props: EditorComponentProps) => { if (menusInitialized() || !editor()) return if (blockquoteBubbleMenuRef() && figureBubbleMenuRef() && incutBubbleMenuRef() && floatingMenuRef()) { console.log('stage 3: initialize menus when editor instance is ready') - const menuConfigs = [ - { key: 'textBubbleMenu', ref: textBubbleMenuRef, shouldShow: shouldShowTextBubbleMenu }, - { - key: 'blockquoteBubbleMenu', - ref: blockquoteBubbleMenuRef, - shouldShow: shouldShowBlockquoteBubbleMenu - }, - { key: 'figureBubbleMenu', ref: figureBubbleMenuRef, shouldShow: shouldShowFigureBubbleMenu }, - { key: 'incutBubbleMenu', ref: incutBubbleMenuRef, shouldShow: shouldShowIncutBubbleMenu }, - { key: 'floatingMenu', ref: floatingMenuRef, shouldShow: shouldShowFloatingMenu, isFloating: true } + const menus = [ + BubbleMenu.configure({ + pluginKey: 'textBubbleMenu', + element: textBubbleMenuRef()!, + shouldShow: ({ editor: e, view, state: { doc, selection }, from, to }) => { + const isEmptyTextBlock = + doc.textBetween(from, to).length === 0 && isTextSelection(selection) + if (isEmptyTextBlock) { + e?.chain().focus().removeTextWrap({ class: 'highlight-fake-selection' }).run() + } + const hasSelection = !selection.empty && from !== to + const isFootnoteOrFigcaption = e.isActive('footnote') || (e.isActive('figcaption') && hasSelection) + + setIsCommonMarkup(e?.isActive('figcaption')) + + const result = view.hasFocus() && + hasSelection && + !e.isActive('image') && + !e.isActive('figure') && + (isFootnoteOrFigcaption || !e.isActive('figcaption')) + + setShouldShowTextBubbleMenu(result) + return result + }, + tippyOptions: { + sticky: true, + // onHide: () => { editor()?.commands.focus() } + } + }), + BubbleMenu.configure({ + pluginKey: 'blockquoteBubbleMenu', + element: blockquoteBubbleMenuRef()!, + shouldShow: ({ editor: e, state: { selection } }) => e.isFocused && !selection.empty && e.isActive('blockquote'), + tippyOptions: { + offset: [0, 0], + placement: 'top', + getReferenceClientRect: () => { + const selectedElement = editor()?.view.dom.querySelector('.has-focus') + return selectedElement?.getBoundingClientRect() || new DOMRect() + } + } + }), + BubbleMenu.configure({ + pluginKey: 'figureBubbleMenu', + element: figureBubbleMenuRef()!, + shouldShow: ({ editor: e, view }) => view.hasFocus() && e.isActive('figure') + }), + BubbleMenu.configure({ + pluginKey: 'incutBubbleMenu', + element: incutBubbleMenuRef()!, + shouldShow: ({ editor: e, state: { selection } }) => e.isFocused && !selection.empty && e.isActive('figcaption'), + tippyOptions: { + offset: [0, -16], + placement: 'top', + getReferenceClientRect: () => { + const selectedElement = editor()?.view.dom.querySelector('.has-focus') + return selectedElement?.getBoundingClientRect() || new DOMRect() + }, + }, + }), + FloatingMenu.configure({ + element: floatingMenuRef()!, + pluginKey: 'floatingMenu', + shouldShow: ({ editor: e, state: { selection } }) => { + const { $anchor, empty } = selection + const isRootDepth = $anchor.depth === 1 + if (!(isRootDepth && empty)) return false + return !(e.isActive('codeBlock') || e.isActive('heading')) + }, + tippyOptions: { + placement: 'left', + } + }) ] - const menus = menuConfigs.map((config) => - config.isFloating - ? FloatingMenu.configure({ - pluginKey: config.key, - element: config.ref(), - shouldShow: config.shouldShow - }) - : BubbleMenu.configure({ - pluginKey: config.key, - element: config.ref(), - shouldShow: config.shouldShow - }) - ) setEditorOptions((prev) => ({ ...prev, extensions: [...(prev.extensions || []), ...menus] })) setMenusInitialized(true) } else { @@ -311,12 +350,12 @@ export const EditorComponent = (props: EditorComponentProps) => { {(ed: Editor) => ( <> - + @@ -338,4 +377,4 @@ export const EditorComponent = (props: EditorComponentProps) => { ) -} +} \ No newline at end of file diff --git a/src/components/Editor/MiniEditor.tsx b/src/components/Editor/MiniEditor.tsx index 6fe5d0aa..35a19ad7 100644 --- a/src/components/Editor/MiniEditor.tsx +++ b/src/components/Editor/MiniEditor.tsx @@ -162,11 +162,14 @@ export function MiniEditor(props: MiniEditorProps): JSX.Element {
0}> diff --git a/src/components/Editor/Toolbar/TextBubbleMenu.tsx b/src/components/Editor/Toolbar/TextBubbleMenu.tsx index 188de1e3..6fa0c596 100644 --- a/src/components/Editor/Toolbar/TextBubbleMenu.tsx +++ b/src/components/Editor/Toolbar/TextBubbleMenu.tsx @@ -16,11 +16,10 @@ import { Icon } from '~/components/_shared/Icon' import { Popover } from '~/components/_shared/Popover' import { useLocalize } from '~/context/localize' import { InsertLinkForm } from './InsertLinkForm' +import { MiniEditor } from '../MiniEditor' import styles from './TextBubbleMenu.module.scss' -const MiniEditor = lazy(() => import('../MiniEditor')) - type BubbleMenuProps = { editor: Editor isCommonMarkup: boolean diff --git a/src/components/Inbox/DialogCard.module.scss b/src/components/Inbox/DialogCard.module.scss index 447f4cee..38c8fff0 100644 --- a/src/components/Inbox/DialogCard.module.scss +++ b/src/components/Inbox/DialogCard.module.scss @@ -77,7 +77,7 @@ .name, .message, .time { - color: #fff !important; + color: var(--default-color-invert) !important; } } -} +} \ No newline at end of file diff --git a/src/components/_shared/LoadMoreWrapper.module.scss b/src/components/_shared/LoadMoreWrapper.module.scss new file mode 100644 index 00000000..00524916 --- /dev/null +++ b/src/components/_shared/LoadMoreWrapper.module.scss @@ -0,0 +1,8 @@ + +.loadMoreWrapper { + text-align: center; + + button { + padding: 0.6em 1.5em; + } + } \ No newline at end of file diff --git a/src/components/_shared/LoadMoreWrapper.tsx b/src/components/_shared/LoadMoreWrapper.tsx index 5625e077..5f69aa72 100644 --- a/src/components/_shared/LoadMoreWrapper.tsx +++ b/src/components/_shared/LoadMoreWrapper.tsx @@ -6,6 +6,8 @@ import { SortFunction } from '~/types/common' import { restoreScrollPosition, saveScrollPosition } from '~/utils/scroll' import { byCreated } from '~/utils/sort' +import styles from './LoadMoreWrapper.module.scss' + export type LoadMoreItems = Shout[] | Author[] | Reaction[] type LoadMoreProps = { @@ -58,7 +60,7 @@ export const LoadMoreWrapper = (props: LoadMoreProps) => { {props.children}
-
+