From 6d3482a2883605affb7f9783b7a02e13bdc433aa Mon Sep 17 00:00:00 2001 From: Satoshi Nakamoto Date: Tue, 10 Oct 2023 11:15:59 -0400 Subject: [PATCH 1/2] Add auto-complete support when withdrawing to ln addr adds auto-complete support for other stacker.news users when withdrawing to a lightning address implemented via adding an optional `transformUser` prop to the `UserSuggest` and `InputUserSuggest` components, which allows you to transform fetched user results before displaying in the suggestion dropdown this is used to transform a user nym to nym@stacker.news, the corresponding lightning address by default, `transformUser` is an identity fn aka no transformation this change also clears suggestions when the surrounding input field is blurred, which is a better UX IMO --- components/form.js | 17 ++++++++++------- pages/wallet.js | 5 +++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/components/form.js b/components/form.js index eec9212b..4a7e15f9 100644 --- a/components/form.js +++ b/components/form.js @@ -157,7 +157,7 @@ export function MarkdownInput ({ label, topLevel, groupClassName, onChange, setH query={mentionQuery} onSelect={insertMention} dropdownStyle={userSuggestDropdownStyle} - >{({ onKeyDown: userSuggestOnKeyDown }) => ( + >{({ onKeyDown: userSuggestOnKeyDown, resetSuggestions }) => ( { if (onChange) onChange(formik, e) @@ -229,6 +229,7 @@ export function MarkdownInput ({ label, topLevel, groupClassName, onChange, setH if (onKeyDown) onKeyDown(e) }} + onBlur={resetSuggestions} />)} @@ -393,15 +394,15 @@ function InputInner ({ ) } -export function UserSuggest ({ query, onSelect, dropdownStyle, children }) { +export function UserSuggest ({ query, onSelect, dropdownStyle, children, transformUser = user => user }) { const [getUsers] = useLazyQuery(TOP_USERS, { onCompleted: data => { - setSuggestions({ array: data.topUsers.users, index: 0 }) + setSuggestions({ array: data.topUsers.users.map(transformUser), index: 0 }) } }) const [getSuggestions] = useLazyQuery(USER_SEARCH, { onCompleted: data => { - setSuggestions({ array: data.searchUsers, index: 0 }) + setSuggestions({ array: data.searchUsers.map(transformUser), index: 0 }) } }) @@ -465,7 +466,7 @@ export function UserSuggest ({ query, onSelect, dropdownStyle, children }) { }, [onSelect, resetSuggestions, suggestions]) return ( <> - {children?.({ onKeyDown })} + {children?.({ onKeyDown, resetSuggestions })} 0} style={dropdownStyle}> {suggestions.array.map((v, i) => @@ -485,16 +486,17 @@ export function UserSuggest ({ query, onSelect, dropdownStyle, children }) { ) } -export function InputUserSuggest ({ label, groupClassName, ...props }) { +export function InputUserSuggest ({ label, groupClassName, transformUser, ...props }) { const [ovalue, setOValue] = useState() const [query, setQuery] = useState() return ( - {({ onKeyDown }) => ( + {({ onKeyDown, resetSuggestions }) => ( )} diff --git a/pages/wallet.js b/pages/wallet.js index 7fec934d..eb12625d 100644 --- a/pages/wallet.js +++ b/pages/wallet.js @@ -1,5 +1,5 @@ import { useRouter } from 'next/router' -import { Checkbox, Form, Input, SubmitButton } from '../components/form' +import { Checkbox, Form, Input, InputUserSuggest, SubmitButton } from '../components/form' import Link from 'next/link' import Button from 'react-bootstrap/Button' import { gql, useMutation, useQuery } from '@apollo/client' @@ -349,12 +349,13 @@ export function LnAddrWithdrawal () { router.push(`/withdrawals/${data.sendToLnAddr.id}`) }} > - ({ ...user, name: `${user.name}@stacker.news` })} /> Date: Tue, 10 Oct 2023 19:15:10 -0400 Subject: [PATCH 2/2] * Hide suggestions if the user is typing a ln addr that is not on stacker.news * Don't select suggestion with tab in this particular instance of InputUseSuggest --- components/form.js | 26 ++++++++++++++++++++++---- pages/wallet.js | 8 ++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/components/form.js b/components/form.js index 4a7e15f9..3ef15358 100644 --- a/components/form.js +++ b/components/form.js @@ -394,15 +394,28 @@ function InputInner ({ ) } -export function UserSuggest ({ query, onSelect, dropdownStyle, children, transformUser = user => user }) { +export function UserSuggest ({ + query, onSelect, dropdownStyle, children, + transformUser = user => user, selectWithTab = true, filterUsers = () => true +}) { const [getUsers] = useLazyQuery(TOP_USERS, { onCompleted: data => { - setSuggestions({ array: data.topUsers.users.map(transformUser), index: 0 }) + setSuggestions({ + array: data.topUsers.users + .filter((...args) => filterUsers(query, ...args)) + .map(transformUser), + index: 0 + }) } }) const [getSuggestions] = useLazyQuery(USER_SEARCH, { onCompleted: data => { - setSuggestions({ array: data.searchUsers.map(transformUser), index: 0 }) + setSuggestions({ + array: data.searchUsers + .filter((...args) => filterUsers(query, ...args)) + .map(transformUser), + index: 0 + }) } }) @@ -449,6 +462,9 @@ export function UserSuggest ({ query, onSelect, dropdownStyle, children, transfo break case 'Tab': case 'Enter': + if (e.code === 'Tab' && !selectWithTab) { + break + } if (suggestions.array?.length === 0) { break } @@ -486,13 +502,15 @@ export function UserSuggest ({ query, onSelect, dropdownStyle, children, transfo ) } -export function InputUserSuggest ({ label, groupClassName, transformUser, ...props }) { +export function InputUserSuggest ({ label, groupClassName, transformUser, filterUsers, selectWithTab, ...props }) { const [ovalue, setOValue] = useState() const [query, setQuery] = useState() return ( diff --git a/pages/wallet.js b/pages/wallet.js index eb12625d..301cf805 100644 --- a/pages/wallet.js +++ b/pages/wallet.js @@ -356,6 +356,14 @@ export function LnAddrWithdrawal () { autoFocus onChange={onAddrChange} transformUser={user => ({ ...user, name: `${user.name}@stacker.news` })} + selectWithTab={false} + filterUsers={(query) => { + if (!query.includes('@')) { + return true + } + const [, domain] = query.split('@') + return 'stacker.news'.startsWith(domain) + }} />