feat: Editing large notes (greater than 1.5MB) will result in more optimized syncing, in which changes are saved locally immediately, but sync with the server less frequently (roughly every 30 seconds rather than after every change). (#2768)

This commit is contained in:
Aman Harwara
2024-01-20 15:22:09 +05:30
committed by GitHub
parent c6060aaab3
commit 396ee3f449
32 changed files with 408 additions and 163 deletions

View File

@@ -4,6 +4,7 @@ import { formatDateForContextMenu } from '@/Utils/DateUtils'
import { calculateReadTime } from './Utils/calculateReadTime'
import { countNoteAttributes } from './Utils/countNoteAttributes'
import { WebApplicationInterface } from '@standardnotes/ui-services'
import { formatSizeToReadableString } from '@standardnotes/filepicker'
export const useNoteAttributes = (application: WebApplicationInterface, note: SNNote) => {
const { words, characters, paragraphs } = useMemo(() => countNoteAttributes(note.text), [note.text])
@@ -15,10 +16,13 @@ export const useNoteAttributes = (application: WebApplicationInterface, note: SN
const dateCreated = useMemo(() => formatDateForContextMenu(note.created_at), [note.created_at])
const size = useMemo(() => new Blob([note.text]).size, [note.text])
const editor = application.componentManager.editorForNote(note)
const format = editor.fileType
return {
size,
words,
characters,
paragraphs,
@@ -35,14 +39,16 @@ export const NoteAttributes: FunctionComponent<{
note: SNNote
className?: string
}> = ({ application, note, className }) => {
const { words, characters, paragraphs, readTime, userModifiedDate, dateCreated, format } = useNoteAttributes(
const { size, words, characters, paragraphs, readTime, userModifiedDate, dateCreated, format } = useNoteAttributes(
application,
note,
)
const canShowWordCount = typeof words === 'number' && (format === 'txt' || format === 'md')
return (
<div className={classNames('select-text px-3 py-1.5 text-sm font-medium text-neutral lg:text-xs', className)}>
{typeof words === 'number' && (format === 'txt' || format === 'md') ? (
{canShowWordCount ? (
<>
<div className="mb-1">
{words} words · {characters} characters · {paragraphs} paragraphs
@@ -58,9 +64,12 @@ export const NoteAttributes: FunctionComponent<{
<div className="mb-1">
<span className="font-semibold">Created:</span> {dateCreated}
</div>
<div>
<div className="mb-1">
<span className="font-semibold">Note ID:</span> {note.uuid}
</div>
<div>
<span className="font-semibold">Size:</span> {formatSizeToReadableString(size)}
</div>
</div>
)
}

View File

@@ -1,17 +1,15 @@
import Icon from '@/Components/Icon/Icon'
import { FunctionComponent } from 'react'
import { SNNote } from '@standardnotes/snjs'
import { BYTES_IN_ONE_MEGABYTE } from '@/Constants/Constants'
import { LargeNoteThreshold } from '@/Constants/Constants'
import HorizontalSeparator from '../Shared/HorizontalSeparator'
export const NOTE_SIZE_WARNING_THRESHOLD = 0.5 * BYTES_IN_ONE_MEGABYTE
export const NoteSizeWarning: FunctionComponent<{
note: SNNote
}> = ({ note }) => {
return new Blob([note.text]).size > NOTE_SIZE_WARNING_THRESHOLD ? (
return new Blob([note.text]).size > LargeNoteThreshold ? (
<>
<HorizontalSeparator classes="my-2" />
<HorizontalSeparator classes="mt-2" />
<div className="bg-warning-faded relative flex items-center px-3 py-3.5">
<Icon type="warning" className="mr-3 flex-shrink-0 text-accessory-tint-3" />
<div className="leading-140% max-w-80% select-none text-warning">

View File

@@ -9,11 +9,12 @@ import { ElementIds } from '@/Constants/ElementIDs'
type Props = {
notesController: NotesController
onClick?: () => void
onClickPreprocessing?: () => Promise<void>
onButtonBlur?: (event: FocusEvent) => void
}
const NotesOptionsPanel = ({ notesController, onClickPreprocessing, onButtonBlur }: Props) => {
const NotesOptionsPanel = ({ notesController, onClick, onClickPreprocessing, onButtonBlur }: Props) => {
const [isOpen, setIsOpen] = useState(false)
const buttonRef = useRef<HTMLButtonElement>(null)
@@ -23,7 +24,10 @@ const NotesOptionsPanel = ({ notesController, onClickPreprocessing, onButtonBlur
await onClickPreprocessing()
}
setIsOpen(willMenuOpen)
}, [onClickPreprocessing, isOpen])
if (onClick) {
onClick()
}
}, [isOpen, onClickPreprocessing, onClick])
const [disableClickOutside, setDisableClickOutside] = useState(false)
const handleDisableClickOutsideRequest = useCallback((disabled: boolean) => {