Обновлены компоненты NoteEditor, NoteItem и NotesList для улучшения обработки сохранения заметок и добавления фокуса на сохраненные заметки. Изменены типы параметров функций и добавлена логика для плавного прокручивания к заметкам. Обновлен сервисный работник с новым ревизионным номером для кэширования.
This commit is contained in:
parent
06400d6e97
commit
05a9275253
@ -82,7 +82,7 @@ define(['./workbox-47da91e0'], (function (workbox) { 'use strict';
|
||||
"revision": "3ca0b8505b4bec776b69afdba2768812"
|
||||
}, {
|
||||
"url": "/index.html",
|
||||
"revision": "0.9eood2uf828"
|
||||
"revision": "0.9t777mpmecg"
|
||||
}], {
|
||||
"ignoreURLParametersMatching": [/^utm_/, /^fbclid$/]
|
||||
});
|
||||
|
||||
@ -14,7 +14,7 @@ import { ImproveTextModal } from "./ImproveTextModal";
|
||||
import { extractTags } from "../../utils/markdown";
|
||||
|
||||
interface NoteEditorProps {
|
||||
onSave: () => void;
|
||||
onSave: (noteId?: number | string) => void;
|
||||
}
|
||||
|
||||
export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
|
||||
@ -80,7 +80,7 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
|
||||
setContent("");
|
||||
setImages([]);
|
||||
setFiles([]);
|
||||
onSave();
|
||||
onSave(note.id);
|
||||
} catch (error) {
|
||||
console.error("Ошибка сохранения заметки:", error);
|
||||
showNotification("Ошибка сохранения заметки", "error");
|
||||
@ -106,7 +106,9 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
|
||||
console.error("Ошибка улучшения текста:", error);
|
||||
setImproveError(true);
|
||||
setImproveErrorMessage(
|
||||
error.response?.data?.error || error.message || "Ошибка улучшения текста"
|
||||
error.response?.data?.error ||
|
||||
error.message ||
|
||||
"Ошибка улучшения текста"
|
||||
);
|
||||
} finally {
|
||||
setIsAiLoading(false);
|
||||
@ -147,7 +149,10 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
|
||||
console.error("Детали ошибки:", error.response?.data);
|
||||
setTagsGenerationError(true);
|
||||
setShowTagsModal(false);
|
||||
const errorMessage = error.response?.data?.error || error.message || "Ошибка генерации тегов";
|
||||
const errorMessage =
|
||||
error.response?.data?.error ||
|
||||
error.message ||
|
||||
"Ошибка генерации тегов";
|
||||
showNotification(errorMessage, "error");
|
||||
} finally {
|
||||
setIsGeneratingTags(false);
|
||||
@ -159,13 +164,19 @@ export const NoteEditor: React.FC<NoteEditorProps> = ({ onSave }) => {
|
||||
|
||||
const existingTags = extractTags(content);
|
||||
const tagsToAdd = tags
|
||||
.filter((tag) => !existingTags.some((existing) => existing.toLowerCase() === tag.toLowerCase()))
|
||||
.filter(
|
||||
(tag) =>
|
||||
!existingTags.some(
|
||||
(existing) => existing.toLowerCase() === tag.toLowerCase()
|
||||
)
|
||||
)
|
||||
.map((tag) => `#${tag}`)
|
||||
.join(" ");
|
||||
|
||||
if (tagsToAdd) {
|
||||
// Добавляем теги в конец заметки
|
||||
const newContent = content.trim() + (content.trim() ? "\n\n" : "") + tagsToAdd;
|
||||
const newContent =
|
||||
content.trim() + (content.trim() ? "\n\n" : "") + tagsToAdd;
|
||||
setContent(newContent);
|
||||
showNotification(`Добавлено тегов: ${tags.length}`, "success");
|
||||
} else {
|
||||
|
||||
@ -31,6 +31,7 @@ interface NoteItemProps {
|
||||
onReload: () => void;
|
||||
isSelected?: boolean;
|
||||
onSelect?: (id: number | string) => void;
|
||||
onFocusNote?: (id: number | string) => void;
|
||||
}
|
||||
|
||||
export const NoteItem: React.FC<NoteItemProps> = ({
|
||||
@ -41,6 +42,7 @@ export const NoteItem: React.FC<NoteItemProps> = ({
|
||||
onReload,
|
||||
isSelected = false,
|
||||
onSelect,
|
||||
onFocusNote,
|
||||
}) => {
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [editContent, setEditContent] = useState(note.content);
|
||||
@ -138,6 +140,13 @@ export const NoteItem: React.FC<NoteItemProps> = ({
|
||||
setDeletedImageIds([]);
|
||||
setDeletedFileIds([]);
|
||||
onReload();
|
||||
// Устанавливаем фокус на заметку после сохранения
|
||||
if (onFocusNote) {
|
||||
// Небольшая задержка для завершения обновления DOM
|
||||
setTimeout(() => {
|
||||
onFocusNote(note.id);
|
||||
}, 100);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Ошибка обновления заметки:", error);
|
||||
showNotification("Ошибка обновления заметки", "error");
|
||||
|
||||
@ -8,6 +8,7 @@ import { extractTags } from "../../utils/markdown";
|
||||
|
||||
export interface NotesListRef {
|
||||
reloadNotes: () => void;
|
||||
focusNote: (noteId: number | string) => void;
|
||||
}
|
||||
|
||||
interface NotesListProps {
|
||||
@ -81,8 +82,34 @@ export const NotesList = forwardRef<NotesListRef, NotesListProps>(
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [userId, searchQuery, selectedDate, selectedTag]);
|
||||
|
||||
const focusNote = (noteId: number | string) => {
|
||||
// Используем data-атрибут для поиска элемента заметки
|
||||
const noteElement = document.querySelector(
|
||||
`[data-note-id="${noteId}"]`
|
||||
) as HTMLDivElement | null;
|
||||
|
||||
if (noteElement) {
|
||||
// Прокручиваем к верхней части заметки
|
||||
noteElement.scrollIntoView({ behavior: "smooth", block: "start", inline: "nearest" });
|
||||
// Добавляем визуальное выделение на короткое время
|
||||
// Очищаем предыдущий таймер, если он был установлен
|
||||
const existingTimeout = (noteElement as any).__focusTimeout;
|
||||
if (existingTimeout) {
|
||||
clearTimeout(existingTimeout);
|
||||
}
|
||||
noteElement.style.transition = "box-shadow 0.3s ease";
|
||||
noteElement.style.boxShadow = "0 0 0 3px rgba(33, 150, 243, 0.5)";
|
||||
const timeout = setTimeout(() => {
|
||||
noteElement.style.boxShadow = "";
|
||||
(noteElement as any).__focusTimeout = null;
|
||||
}, 2000);
|
||||
(noteElement as any).__focusTimeout = timeout;
|
||||
}
|
||||
};
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
reloadNotes: loadNotes,
|
||||
focusNote: focusNote,
|
||||
}));
|
||||
|
||||
const handleDelete = async (id: number | string) => {
|
||||
@ -167,6 +194,7 @@ export const NotesList = forwardRef<NotesListRef, NotesListProps>(
|
||||
onReload={loadNotes}
|
||||
isSelected={selectedNoteIds.includes(note.id)}
|
||||
onSelect={onNoteSelect}
|
||||
onFocusNote={focusNote}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
@ -63,10 +63,32 @@ const NotesPage: React.FC = () => {
|
||||
|
||||
const activeFilters = getActiveFilters();
|
||||
|
||||
const handleNoteSave = () => {
|
||||
const handleNoteSave = (noteId?: number | string) => {
|
||||
// Вызываем перезагрузку заметок после создания новой заметки
|
||||
if (notesListRef.current) {
|
||||
notesListRef.current.reloadNotes();
|
||||
// Устанавливаем фокус на сохраненную заметку после небольшой задержки,
|
||||
// чтобы дать время для перезагрузки и рендеринга заметок
|
||||
if (noteId) {
|
||||
let attempts = 0;
|
||||
const maxAttempts = 15;
|
||||
const attemptFocus = () => {
|
||||
attempts++;
|
||||
if (notesListRef.current) {
|
||||
// Проверяем, есть ли элемент заметки в DOM
|
||||
const noteElement = document.querySelector(
|
||||
`[data-note-id="${noteId}"]`
|
||||
);
|
||||
if (noteElement || attempts >= maxAttempts) {
|
||||
notesListRef.current.focusNote(noteId);
|
||||
} else if (attempts < maxAttempts) {
|
||||
// Пытаемся еще раз, если заметка еще не появилась в DOM
|
||||
setTimeout(attemptFocus, 100);
|
||||
}
|
||||
}
|
||||
};
|
||||
setTimeout(attemptFocus, 200);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user