From 3e76ef6b6f3fa0bc0174dc83d3a1e8baed69bbd8 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Thu, 1 Jul 2021 14:36:21 -0300 Subject: [PATCH 1/3] fix: fix tags keyboard navigation --- .../components/AutocompleteTagHint.tsx | 1 + .../components/AutocompleteTagInput.tsx | 2 +- .../components/AutocompleteTagResult.tsx | 1 + app/assets/javascripts/components/NoteTag.tsx | 15 +++++++++++++-- 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/components/AutocompleteTagHint.tsx b/app/assets/javascripts/components/AutocompleteTagHint.tsx index 00cc04af7..bbb1ec928 100644 --- a/app/assets/javascripts/components/AutocompleteTagHint.tsx +++ b/app/assets/javascripts/components/AutocompleteTagHint.tsx @@ -62,6 +62,7 @@ export const AutocompleteTagHint = observer( onFocus={onFocus} onBlur={onBlur} onKeyDown={onKeyDown} + tabIndex={-1} > Create new tag: diff --git a/app/assets/javascripts/components/AutocompleteTagInput.tsx b/app/assets/javascripts/components/AutocompleteTagInput.tsx index 2dddf3077..e3771024d 100644 --- a/app/assets/javascripts/components/AutocompleteTagInput.tsx +++ b/app/assets/javascripts/components/AutocompleteTagInput.tsx @@ -92,7 +92,6 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { useEffect(() => { if (autocompleteInputFocused) { inputRef.current.focus(); - appState.noteTags.setAutocompleteInputFocused(false); } }, [appState.noteTags, autocompleteInputFocused]); @@ -113,6 +112,7 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { onBlur={onBlur} onFocus={onFocus} onKeyDown={onKeyDown} + tabIndex={tags.length === 0 ? 0 : -1} /> {dropdownVisible && (autocompleteTagResults.length > 0 || autocompleteTagHintVisible) && ( diff --git a/app/assets/javascripts/components/NoteTag.tsx b/app/assets/javascripts/components/NoteTag.tsx index f08c94ef8..ba80ebe48 100644 --- a/app/assets/javascripts/components/NoteTag.tsx +++ b/app/assets/javascripts/components/NoteTag.tsx @@ -10,7 +10,7 @@ type Props = { }; export const NoteTag = observer(({ appState, tag }: Props) => { - const { focusedTagUuid, tags } = appState.noteTags; + const { autocompleteInputFocused, focusedTagUuid, tags } = appState.noteTags; const [showDeleteButton, setShowDeleteButton] = useState(false); const [tagClicked, setTagClicked] = useState(false); @@ -51,6 +51,16 @@ export const NoteTag = observer(({ appState, tag }: Props) => { } }; + const getTabIndex = () => { + if (focusedTagUuid) { + return focusedTagUuid === tag.uuid ? 0 : -1; + } + if (autocompleteInputFocused) { + return -1; + } + return tags[0].uuid === tag.uuid ? 0 : -1; + }; + const onKeyDown = (event: KeyboardEvent) => { const tagIndex = appState.noteTags.getTagIndex(tag, tags); switch (event.key) { @@ -75,7 +85,6 @@ export const NoteTag = observer(({ appState, tag }: Props) => { useEffect(() => { if (focusedTagUuid === tag.uuid) { tagRef.current.focus(); - appState.noteTags.setFocusedTagUuid(undefined); } }, [appState.noteTags, focusedTagUuid, tag]); @@ -87,6 +96,7 @@ export const NoteTag = observer(({ appState, tag }: Props) => { onKeyDown={onKeyDown} onFocus={onFocus} onBlur={onBlur} + tabIndex={getTabIndex()} > @@ -99,6 +109,7 @@ export const NoteTag = observer(({ appState, tag }: Props) => { className="ml-2 -mr-1 border-0 p-0 bg-transparent cursor-pointer flex" onBlur={onBlur} onClick={onDeleteTagClick} + tabIndex={-1} > Date: Thu, 1 Jul 2021 14:36:56 -0300 Subject: [PATCH 2/3] fix: don't clear search query when navigating back to input --- .../components/AutocompleteTagInput.tsx | 104 ++++++++++-------- 1 file changed, 58 insertions(+), 46 deletions(-) diff --git a/app/assets/javascripts/components/AutocompleteTagInput.tsx b/app/assets/javascripts/components/AutocompleteTagInput.tsx index e3771024d..80c865f39 100644 --- a/app/assets/javascripts/components/AutocompleteTagInput.tsx +++ b/app/assets/javascripts/components/AutocompleteTagInput.tsx @@ -25,10 +25,10 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { const [dropdownMaxHeight, setDropdownMaxHeight] = useState('auto'); - const dropdownRef = useRef(); + const containerRef = useRef(); const inputRef = useRef(); - const [closeOnBlur] = useCloseOnBlur(dropdownRef, (visible: boolean) => { + const [closeOnBlur] = useCloseOnBlur(containerRef, (visible: boolean) => { setDropdownVisible(visible); appState.noteTags.clearAutocompleteSearch(); }); @@ -69,7 +69,9 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { case 'ArrowDown': event.preventDefault(); if (autocompleteTagResults.length > 0) { - appState.noteTags.setFocusedTagResultUuid(autocompleteTagResults[0].uuid); + appState.noteTags.setFocusedTagResultUuid( + autocompleteTagResults[0].uuid + ); } else if (autocompleteTagHintVisible) { appState.noteTags.setAutocompleteTagHintFocused(true); } @@ -96,50 +98,60 @@ export const AutocompleteTagInput = observer(({ appState }: Props) => { }, [appState.noteTags, autocompleteInputFocused]); return ( -
0 ? 'mt-2' : ''}`} - > - - 0 ? 'w-80' : 'w-70 mr-10'} bg-transparent text-xs +
+ 0 ? 'mt-2' : ''}`} + > + + 0 ? 'w-80' : 'w-70 mr-10' + } bg-transparent text-xs color-text no-border h-7 focus:outline-none focus:shadow-none focus:border-bottom`} - value={autocompleteSearchQuery} - onChange={onSearchQueryChange} - type="text" - placeholder="Add tag" - onBlur={onBlur} - onFocus={onFocus} - onKeyDown={onKeyDown} - tabIndex={tags.length === 0 ? 0 : -1} - /> - {dropdownVisible && (autocompleteTagResults.length > 0 || autocompleteTagHintVisible) && ( - 0 ? 'w-80' : 'w-70 mr-10'} sn-dropdown flex flex-col py-2 absolute`} - style={{ maxHeight: dropdownMaxHeight, maxWidth: tagsContainerMaxWidth }} - onBlur={closeOnBlur} - > -
- {autocompleteTagResults.map((tagResult: SNTag) => ( - - ))} -
- {autocompleteTagHintVisible && ( - + value={autocompleteSearchQuery} + onChange={onSearchQueryChange} + type="text" + placeholder="Add tag" + onBlur={onBlur} + onFocus={onFocus} + onKeyDown={onKeyDown} + tabIndex={tags.length === 0 ? 0 : -1} + /> + {dropdownVisible && + (autocompleteTagResults.length > 0 || + autocompleteTagHintVisible) && ( + 0 ? 'w-80' : 'w-70 mr-10' + } sn-dropdown flex flex-col py-2 absolute`} + style={{ + maxHeight: dropdownMaxHeight, + maxWidth: tagsContainerMaxWidth, + }} + onBlur={closeOnBlur} + > +
+ {autocompleteTagResults.map((tagResult: SNTag) => ( + + ))} +
+ {autocompleteTagHintVisible && ( + + )} +
)} -
- )} -
- + + +
); }); From 1d4eae5d0073cdda5f379011e6e76ffe25f155a5 Mon Sep 17 00:00:00 2001 From: Antonella Sgarlatta Date: Thu, 1 Jul 2021 16:44:10 -0300 Subject: [PATCH 3/3] fix: set minimum passcode length --- .../javascripts/directives/views/accountMenu.ts | 14 ++++++++++++-- app/assets/javascripts/strings.ts | 1 + 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/directives/views/accountMenu.ts b/app/assets/javascripts/directives/views/accountMenu.ts index cf6851e4f..cd4ae8984 100644 --- a/app/assets/javascripts/directives/views/accountMenu.ts +++ b/app/assets/javascripts/directives/views/accountMenu.ts @@ -18,6 +18,7 @@ import { STRING_CONFIRM_APP_QUIT_DURING_PASSCODE_REMOVAL, STRING_UNSUPPORTED_BACKUP_FILE_VERSION, StringUtils, + Strings, } from '@/strings'; import { PasswordWizardType } from '@/types'; import { @@ -509,8 +510,17 @@ class AccountMenuCtrl extends PureViewCtrl { } async submitPasscodeForm() { - const passcode = this.getState().formData.passcode!; - if (passcode !== this.getState().formData.confirmPasscode!) { + const passcode = this.getState().formData.passcode; + + if (!passcode || passcode.length === 0) { + await alertDialog({ + text: Strings.enterPasscode, + }); + this.passcodeInput[0].focus(); + return; + } + + if (passcode !== this.getState().formData.confirmPasscode) { await alertDialog({ text: STRING_NON_MATCHING_PASSCODES, }); diff --git a/app/assets/javascripts/strings.ts b/app/assets/javascripts/strings.ts index 1c112f341..217fb366d 100644 --- a/app/assets/javascripts/strings.ts +++ b/app/assets/javascripts/strings.ts @@ -113,6 +113,7 @@ export const Strings = { openAccountMenu: 'Open Account Menu', trashNotesTitle: 'Move to Trash', trashNotesText: 'Are you sure you want to move these notes to the trash?', + enterPasscode: 'Please enter a passcode.', }; export const StringUtils = {