chore: fix Super read only state (#2992)

This commit is contained in:
Antonella Sgarlatta
2026-03-05 23:47:17 -03:00
committed by GitHub
parent 7f3d2d0c72
commit 449a37a7d7
2 changed files with 33 additions and 10 deletions

View File

@@ -3,26 +3,26 @@ import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext
import { SNNote, ContentType } from '@standardnotes/snjs' import { SNNote, ContentType } from '@standardnotes/snjs'
import { useState, useEffect } from 'react' import { useState, useEffect } from 'react'
const ReadonlyPlugin = ({ note }: { note: SNNote }) => { const ReadonlyPlugin = ({ note, forceReadonly = false }: { note: SNNote; forceReadonly?: boolean }) => {
const application = useApplication() const application = useApplication()
const [editor] = useLexicalComposerContext() const [editor] = useLexicalComposerContext()
const [readOnly, setReadOnly] = useState(note.locked) const [noteLocked, setNoteLocked] = useState(note.locked)
useEffect(() => { useEffect(() => {
return application.items.streamItems<SNNote>(ContentType.TYPES.Note, ({ changed }) => { return application.items.streamItems<SNNote>(ContentType.TYPES.Note, ({ changed }) => {
const changedNoteItem = changed.find((changedItem) => changedItem.uuid === note.uuid) const changedNoteItem = changed.find((changedItem) => changedItem.uuid === note.uuid)
if (changedNoteItem) { if (changedNoteItem) {
setReadOnly(changedNoteItem.locked) setNoteLocked(changedNoteItem.locked)
} }
}) })
}, [application, note.uuid]) }, [application, note.uuid])
useEffect(() => { useEffect(() => {
editor.update(() => { editor.update(() => {
editor.setEditable(!readOnly) editor.setEditable(!(noteLocked || forceReadonly))
}) })
}, [editor, readOnly]) }, [editor, noteLocked, forceReadonly])
return null return null
} }

View File

@@ -1,5 +1,6 @@
import { WebApplication } from '@/Application/WebApplication' import { WebApplication } from '@/Application/WebApplication'
import { import {
ApplicationEvent,
isPayloadSourceRetrieved, isPayloadSourceRetrieved,
NativeFeatureIdentifier, NativeFeatureIdentifier,
FeatureStatus, FeatureStatus,
@@ -71,7 +72,7 @@ export const SuperEditor: FunctionComponent<Props> = ({
const getMarkdownPlugin = useRef<GetMarkdownPluginInterface | null>(null) const getMarkdownPlugin = useRef<GetMarkdownPluginInterface | null>(null)
const [featureStatus, setFeatureStatus] = useState<FeatureStatus>(FeatureStatus.Entitled) const [featureStatus, setFeatureStatus] = useState<FeatureStatus>(FeatureStatus.Entitled)
useEffect(() => { const reloadFeatureStatus = useCallback(() => {
setFeatureStatus( setFeatureStatus(
application.features.getFeatureStatus( application.features.getFeatureStatus(
NativeFeatureIdentifier.create(NativeFeatureIdentifier.TYPES.SuperEditor).getValue(), NativeFeatureIdentifier.create(NativeFeatureIdentifier.TYPES.SuperEditor).getValue(),
@@ -82,7 +83,24 @@ export const SuperEditor: FunctionComponent<Props> = ({
) )
}, [application.features]) }, [application.features])
useEffect(() => {
reloadFeatureStatus()
}, [reloadFeatureStatus])
useEffect(() => {
return application.addEventObserver(async (event) => {
switch (event) {
case ApplicationEvent.FeaturesAvailabilityChanged:
case ApplicationEvent.UserRolesChanged:
case ApplicationEvent.LocalDataLoaded:
reloadFeatureStatus()
break
}
})
}, [application, reloadFeatureStatus])
const keyboardService = application.keyboardService const keyboardService = application.keyboardService
const isEditorReadonly = note.current.locked || Boolean(readonly) || featureStatus !== FeatureStatus.Entitled
useEffect(() => { useEffect(() => {
return application.commands.addWithShortcut( return application.commands.addWithShortcut(
@@ -155,6 +173,9 @@ export const SuperEditor: FunctionComponent<Props> = ({
ignoreNextChange.current = false ignoreNextChange.current = false
return return
} }
if (isEditorReadonly) {
return
}
void controller.saveAndAwaitLocalPropagation({ void controller.saveAndAwaitLocalPropagation({
text: value, text: value,
@@ -165,7 +186,7 @@ export const SuperEditor: FunctionComponent<Props> = ({
}, },
}) })
}, },
[controller], [controller, isEditorReadonly],
) )
const handleBubbleRemove = useCallback( const handleBubbleRemove = useCallback(
@@ -252,13 +273,13 @@ export const SuperEditor: FunctionComponent<Props> = ({
<ErrorBoundary> <ErrorBoundary>
<LinkingControllerProvider controller={linkingController}> <LinkingControllerProvider controller={linkingController}>
<FilesControllerProvider controller={filesController}> <FilesControllerProvider controller={filesController}>
<BlocksEditorComposer readonly={note.current.locked || readonly} initialValue={note.current.text}> <BlocksEditorComposer readonly={isEditorReadonly} initialValue={note.current.text}>
<BlocksEditor <BlocksEditor
onChange={handleChange} onChange={handleChange}
className="blocks-editor h-full resize-none" className="blocks-editor h-full resize-none"
previewLength={SuperNotePreviewCharLimit} previewLength={SuperNotePreviewCharLimit}
spellcheck={spellcheck} spellcheck={spellcheck}
readonly={note.current.locked || readonly} readonly={isEditorReadonly}
onFocus={handleFocus} onFocus={handleFocus}
onBlur={onBlur} onBlur={onBlur}
> >
@@ -271,7 +292,9 @@ export const SuperEditor: FunctionComponent<Props> = ({
/> />
<NodeObserverPlugin nodeType={BubbleNode} onRemove={handleBubbleRemove} /> <NodeObserverPlugin nodeType={BubbleNode} onRemove={handleBubbleRemove} />
<NodeObserverPlugin nodeType={FileNode} onRemove={handleBubbleRemove} /> <NodeObserverPlugin nodeType={FileNode} onRemove={handleBubbleRemove} />
{readonly === undefined && <ReadonlyPlugin note={note.current} />} {readonly === undefined && (
<ReadonlyPlugin note={note.current} forceReadonly={featureStatus !== FeatureStatus.Entitled} />
)}
<AutoFocusPlugin isEnabled={controller.isTemplateNote} /> <AutoFocusPlugin isEnabled={controller.isTemplateNote} />
<BlockPickerMenuPlugin /> <BlockPickerMenuPlugin />
<NoteFromSelectionPlugin currentNote={note.current} /> <NoteFromSelectionPlugin currentNote={note.current} />