From f8f6a5212b608c7a43957449d42b1d462134773c Mon Sep 17 00:00:00 2001 From: Aman Harwara Date: Mon, 26 Sep 2022 21:15:11 +0530 Subject: [PATCH] feat: sticky header on mobile if plaintext note is scrolled (#1645) --- .../Components/NoteView/NoteView.tsx | 144 ++++++++++-------- 1 file changed, 83 insertions(+), 61 deletions(-) diff --git a/packages/web/src/javascripts/Components/NoteView/NoteView.tsx b/packages/web/src/javascripts/Components/NoteView/NoteView.tsx index caf69c914..9535dc61a 100644 --- a/packages/web/src/javascripts/Components/NoteView/NoteView.tsx +++ b/packages/web/src/javascripts/Components/NoteView/NoteView.tsx @@ -14,7 +14,7 @@ import { PayloadEmitSource, WebAppEvent, } from '@standardnotes/snjs' -import { debounce, isDesktopApplication } from '@/Utils' +import { debounce, isDesktopApplication, isIOS } from '@/Utils' import { EditorEventSource } from '../../Types/EditorEventSource' import { confirmDialog, KeyboardModifier, KeyboardKey } from '@standardnotes/ui-services' import { STRING_DELETE_PLACEHOLDER_ATTEMPT, STRING_DELETE_LOCKED_ATTEMPT, StringDeleteNote } from '@/Constants/Strings' @@ -22,7 +22,6 @@ import { PureComponent } from '@/Components/Abstract/PureComponent' import ProtectedItemOverlay from '@/Components/ProtectedItemOverlay/ProtectedItemOverlay' import PinNoteButton from '@/Components/PinNoteButton/PinNoteButton' import NotesOptionsPanel from '@/Components/NotesOptions/NotesOptionsPanel' -import NoteTagsContainer from '@/Components/NoteTags/NoteTagsContainer' import ComponentView from '@/Components/ComponentView/ComponentView' import PanelResizer, { PanelSide, PanelResizeType } from '@/Components/PanelResizer/PanelResizer' import { ElementIds } from '@/Constants/ElementIDs' @@ -41,9 +40,10 @@ import AutoresizingNoteViewTextarea from './AutoresizingTextarea' import MobileItemsListButton from '../NoteGroupView/MobileItemsListButton' import NoteTagsPanel from '../NoteTags/NoteTagsPanel' -const MINIMUM_STATUS_DURATION = 400 -const TEXTAREA_DEBOUNCE = 100 -const NOTE_EDITING_DISABLED_TEXT = 'Note editing disabled.' +const MinimumStatusDuration = 400 +const TextareaDebounce = 100 +const NoteEditingDisabledText = 'Note editing disabled.' +const StickyHeaderScrollThresholdInPx = 20 type NoteStatus = { message?: string @@ -81,6 +81,8 @@ type State = { leftResizerOffset: number rightResizerWidth: number rightResizerOffset: number + + shouldStickyHeader: boolean } class NoteView extends PureComponent { @@ -112,7 +114,9 @@ class NoteView extends PureComponent { this.debounceReloadEditorComponent = debounce(this.debounceReloadEditorComponent.bind(this), 25) - this.textAreaChangeDebounceSave = debounce(this.textAreaChangeDebounceSave, TEXTAREA_DEBOUNCE) + this.textAreaChangeDebounceSave = debounce(this.textAreaChangeDebounceSave, TextareaDebounce) + + this.handleWindowScroll = debounce(this.handleWindowScroll, 10) this.state = { availableStackComponents: [], @@ -120,7 +124,7 @@ class NoteView extends PureComponent { editorText: '', editorTitle: '', isDesktop: isDesktopApplication(), - lockText: NOTE_EDITING_DISABLED_TEXT, + lockText: NoteEditingDisabledText, noteStatus: undefined, noteLocked: this.controller.item.locked, showLockedIcon: true, @@ -133,12 +137,17 @@ class NoteView extends PureComponent { leftResizerOffset: 0, rightResizerWidth: 0, rightResizerOffset: 0, + shouldStickyHeader: false, } this.editorContentRef = createRef() + + window.addEventListener('scroll', this.handleWindowScroll) } override deinit() { + window.removeEventListener('scroll', this.handleWindowScroll) + this.removeComponentStreamObserver?.() ;(this.removeComponentStreamObserver as unknown) = undefined @@ -522,7 +531,7 @@ class NoteView extends PureComponent { this.setState({ noteStatus: status, }) - }, MINIMUM_STATUS_DURATION) + }, MinimumStatusDuration) } else { this.setState({ noteStatus: status, @@ -872,6 +881,12 @@ class NoteView extends PureComponent { } } + handleWindowScroll = () => { + this.setState({ + shouldStickyHeader: window.scrollY > StickyHeaderScrollThresholdInPx, + }) + } + override render() { if (this.state.showProtectedWarning) { return ( @@ -890,7 +905,7 @@ class NoteView extends PureComponent { { this.setState({ - lockText: NOTE_EDITING_DISABLED_TEXT, + lockText: NoteEditingDisabledText, showLockedIcon: true, }) }} @@ -907,7 +922,14 @@ class NoteView extends PureComponent { )} {this.note && ( -
+
@@ -927,62 +949,62 @@ class NoteView extends PureComponent { />
-
- {this.state.noteStatus?.message?.length && ( -
-
-
- {this.state.noteStatus?.message} + {!this.state.shouldStickyHeader && ( +
+ {this.state.noteStatus?.message?.length && ( +
+
+
+ {this.state.noteStatus?.message} +
+ {this.state.noteStatus?.desc && ( +
{this.state.noteStatus.desc}
+ )}
- {this.state.noteStatus?.desc &&
{this.state.noteStatus.desc}
}
+ )} +
+ + + + +
- )} -
- - - - -
-
+ )}
-
)}