mirror of
https://github.com/yu-i-i/overleaf-cep.git
synced 2026-11-14 14:13:43 +01:00
Increase the length of unsaved doc time before the editor is locked (#23431)
* Use opInflightSince to measure unsaved doc time * Use performance.now() for lastAcked timestamp * Use inflightOpCreatedAt * Increase MAX_UNSAVED_ALERT_SECONDS to 15 * Increase MAX_UNSAVED_SECONDS to 30 * Increase FATAL_OP_TIMEOUT to 45000 * Convert "Connection lost" modal to a notification GitOrigin-RevId: 2d4233723620fd03ce6d6c5795c48c33c0b2f92c
This commit is contained in:
+3
-1
@@ -3,13 +3,15 @@ import { useFileTreePathContext } from '@/features/file-tree/contexts/file-tree-
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLNotification from '@/features/ui/components/ol/ol-notification'
|
||||
|
||||
const MAX_UNSAVED_ALERT_SECONDS = 15
|
||||
|
||||
export const UnsavedDocsAlert: FC<{ unsavedDocs: Map<string, number> }> = ({
|
||||
unsavedDocs,
|
||||
}) => (
|
||||
<>
|
||||
{[...unsavedDocs.entries()].map(
|
||||
([docId, seconds]) =>
|
||||
seconds > 8 && (
|
||||
seconds >= MAX_UNSAVED_ALERT_SECONDS && (
|
||||
<UnsavedDocAlert key={docId} docId={docId} seconds={seconds} />
|
||||
)
|
||||
)}
|
||||
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLNotification from '@/features/ui/components/ol/ol-notification'
|
||||
|
||||
export const UnsavedDocsLockedAlert: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<OLNotification
|
||||
type="warning"
|
||||
content={
|
||||
<>
|
||||
<strong>{t('connection_lost_with_unsaved_changes')}</strong>{' '}
|
||||
{t('dont_reload_or_close_this_tab')} {t('your_changes_will_save')}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)
|
||||
}
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
import { FC } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import OLModal, {
|
||||
OLModalBody,
|
||||
OLModalHeader,
|
||||
OLModalTitle,
|
||||
} from '@/features/ui/components/ol/ol-modal'
|
||||
|
||||
export const UnsavedDocsLockedModal: FC = () => {
|
||||
const { t } = useTranslation()
|
||||
|
||||
return (
|
||||
<OLModal
|
||||
show
|
||||
onHide={() => {}} // It's not possible to hide this modal, but it's a required prop
|
||||
className="lock-editor-modal"
|
||||
backdrop={false}
|
||||
keyboard={false}
|
||||
>
|
||||
<OLModalHeader>
|
||||
<OLModalTitle>{t('connection_lost')}</OLModalTitle>
|
||||
</OLModalHeader>
|
||||
<OLModalBody>
|
||||
{t('sorry_the_connection_to_the_server_is_down')}
|
||||
</OLModalBody>
|
||||
</OLModal>
|
||||
)
|
||||
}
|
||||
+18
-12
@@ -2,13 +2,13 @@ import { useEditorManagerContext } from '@/features/ide-react/context/editor-man
|
||||
import { useEditorContext } from '@/shared/context/editor-context'
|
||||
import { FC, useCallback, useEffect, useRef, useState } from 'react'
|
||||
import { PermissionsLevel } from '@/features/ide-react/types/permissions'
|
||||
import { UnsavedDocsLockedModal } from '@/features/ide-react/components/unsaved-docs/unsaved-docs-locked-modal'
|
||||
import { UnsavedDocsLockedAlert } from '@/features/ide-react/components/unsaved-docs/unsaved-docs-locked-alert'
|
||||
import { UnsavedDocsAlert } from '@/features/ide-react/components/unsaved-docs/unsaved-docs-alert'
|
||||
import useEventListener from '@/shared/hooks/use-event-listener'
|
||||
import { createPortal } from 'react-dom'
|
||||
import { useGlobalAlertsContainer } from '@/features/ide-react/context/global-alerts-context'
|
||||
|
||||
const MAX_UNSAVED_SECONDS = 15 // lock the editor after this time if unsaved
|
||||
const MAX_UNSAVED_SECONDS = 30 // lock the editor after this time if unsaved
|
||||
|
||||
export const UnsavedDocs: FC = () => {
|
||||
const { openDocs, debugTimers } = useEditorManagerContext()
|
||||
@@ -19,9 +19,6 @@ export const UnsavedDocs: FC = () => {
|
||||
|
||||
// always contains the latest value
|
||||
const previousUnsavedDocsRef = useRef(unsavedDocs)
|
||||
useEffect(() => {
|
||||
previousUnsavedDocsRef.current = unsavedDocs
|
||||
}, [unsavedDocs])
|
||||
|
||||
// always contains the latest value
|
||||
const permissionsLevelRef = useRef(permissionsLevel)
|
||||
@@ -50,12 +47,16 @@ export const UnsavedDocs: FC = () => {
|
||||
debugTimers.current.CheckUnsavedDocs = Date.now()
|
||||
const unsavedDocs = new Map()
|
||||
|
||||
const unsavedDocIds = openDocs.unsavedDocIds()
|
||||
const docs = openDocs.unsavedDocs()
|
||||
|
||||
for (const docId of unsavedDocIds) {
|
||||
const unsavedSeconds =
|
||||
(previousUnsavedDocsRef.current.get(docId) ?? 0) + 1
|
||||
unsavedDocs.set(docId, unsavedSeconds)
|
||||
for (const doc of docs) {
|
||||
const inflightOpCreatedAt = doc.getInflightOpCreatedAt()
|
||||
if (inflightOpCreatedAt) {
|
||||
const unsavedSeconds = Math.floor(
|
||||
(performance.now() - inflightOpCreatedAt) / 1000
|
||||
)
|
||||
unsavedDocs.set(doc.doc_id, unsavedSeconds)
|
||||
}
|
||||
}
|
||||
|
||||
// avoid setting the unsavedDocs state to a new empty Map every second
|
||||
@@ -100,11 +101,16 @@ export const UnsavedDocs: FC = () => {
|
||||
}
|
||||
}, [unsavedDocs])
|
||||
|
||||
if (!globalAlertsContainer) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isLocked && <UnsavedDocsLockedModal />}
|
||||
{isLocked &&
|
||||
createPortal(<UnsavedDocsLockedAlert />, globalAlertsContainer)}
|
||||
|
||||
{unsavedDocs.size > 0 &&
|
||||
globalAlertsContainer &&
|
||||
createPortal(
|
||||
<UnsavedDocsAlert unsavedDocs={unsavedDocs} />,
|
||||
globalAlertsContainer
|
||||
|
||||
Reference in New Issue
Block a user