2023-01-15 01:46:13 +00:00
|
|
|
import { useSelector } from "react-redux";
|
|
|
|
import { useLiveQuery } from "dexie-react-hooks";
|
2023-01-14 10:07:49 +00:00
|
|
|
|
|
|
|
import ReactTextareaAutocomplete from "@webscopeio/react-textarea-autocomplete";
|
2023-01-15 23:44:50 +00:00
|
|
|
import TextareaAutosize from "react-textarea-autosize";
|
2023-01-14 10:07:49 +00:00
|
|
|
|
2023-01-14 22:46:28 +00:00
|
|
|
// @ts-expect-error
|
2023-01-15 12:02:45 +00:00
|
|
|
import Nip05 from "./Nip05";
|
2023-01-14 10:18:01 +00:00
|
|
|
import "@webscopeio/react-textarea-autocomplete/style.css";
|
2023-01-14 10:07:49 +00:00
|
|
|
import "./Textarea.css";
|
2023-01-14 22:46:28 +00:00
|
|
|
// @ts-expect-error
|
2023-01-14 10:07:49 +00:00
|
|
|
import Nostrich from "../nostrich.jpg";
|
2023-01-14 22:46:28 +00:00
|
|
|
import { hexToBech32 } from "../Util";
|
|
|
|
import type { User } from "../nostr/types";
|
2023-01-15 01:46:13 +00:00
|
|
|
import { db } from "../db";
|
2023-01-14 10:07:49 +00:00
|
|
|
|
2023-01-15 01:46:13 +00:00
|
|
|
function searchUsers(query: string, users: User[]) {
|
2023-01-14 10:18:01 +00:00
|
|
|
const q = query.toLowerCase()
|
2023-01-15 01:46:13 +00:00
|
|
|
return users.filter(({ name, display_name, about, nip05 }: User) => {
|
2023-01-14 22:46:28 +00:00
|
|
|
return name?.toLowerCase().includes(q)
|
|
|
|
|| display_name?.toLowerCase().includes(q)
|
|
|
|
|| about?.toLowerCase().includes(q)
|
|
|
|
|| nip05?.toLowerCase().includes(q)
|
2023-01-14 10:18:01 +00:00
|
|
|
}).slice(0, 3)
|
2023-01-14 10:07:49 +00:00
|
|
|
}
|
|
|
|
|
2023-01-14 22:46:28 +00:00
|
|
|
const UserItem = ({ pubkey, display_name, picture, nip05, ...rest }: User) => {
|
2023-01-14 10:07:49 +00:00
|
|
|
return (
|
2023-01-14 10:18:01 +00:00
|
|
|
<div key={pubkey} className="user-item">
|
2023-01-14 10:07:49 +00:00
|
|
|
<div className="user-picture">
|
|
|
|
{picture && <img src={picture ? picture : Nostrich} className="picture" />}
|
|
|
|
</div>
|
|
|
|
<div className="user-details">
|
2023-01-14 10:18:01 +00:00
|
|
|
<strong>{display_name || rest.name}</strong>
|
2023-01-15 12:02:45 +00:00
|
|
|
<Nip05 nip05={nip05} pubkey={pubkey} />
|
2023-01-14 10:07:49 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2023-01-15 12:26:21 +00:00
|
|
|
function normalizeUser({ pubkey, picture, nip05, name, display_name }: User) {
|
|
|
|
return { pubkey, nip05, name, picture, display_name }
|
2023-01-15 01:46:13 +00:00
|
|
|
}
|
|
|
|
|
2023-01-15 10:41:34 +00:00
|
|
|
const Textarea = ({ users, onChange, ...rest }: any) => {
|
|
|
|
const normalizedUsers = Object.keys(users).reduce((acc, pk) => {
|
|
|
|
return {...acc, [pk]: normalizeUser(users[pk]) }
|
|
|
|
}, {})
|
2023-01-15 01:46:13 +00:00
|
|
|
const dbUsers = useLiveQuery(
|
|
|
|
() => db.users.toArray().then(usrs => {
|
|
|
|
return usrs.reduce((acc, usr) => {
|
|
|
|
return { ...acc, [usr.pubkey]: normalizeUser(usr)}
|
|
|
|
}, {})
|
|
|
|
})
|
|
|
|
)
|
2023-01-15 10:41:34 +00:00
|
|
|
const allUsers: User[] = Object.values({...normalizedUsers, ...dbUsers})
|
2023-01-15 01:46:13 +00:00
|
|
|
|
2023-01-14 10:07:49 +00:00
|
|
|
return (
|
|
|
|
<ReactTextareaAutocomplete
|
|
|
|
{...rest}
|
|
|
|
loadingComponent={() => <span>Loading....</span>}
|
|
|
|
placeholder="Say something!"
|
|
|
|
onChange={onChange}
|
2023-01-15 23:44:50 +00:00
|
|
|
textAreaComponent={TextareaAutosize}
|
2023-01-14 10:07:49 +00:00
|
|
|
trigger={{
|
|
|
|
"@": {
|
2023-01-14 10:18:01 +00:00
|
|
|
afterWhitespace: true,
|
2023-01-15 01:46:13 +00:00
|
|
|
dataProvider: token => dbUsers ? searchUsers(token, allUsers) : [],
|
2023-01-14 22:46:28 +00:00
|
|
|
component: (props: any) => <UserItem {...props.entity} />,
|
|
|
|
output: (item: any) => `@${hexToBech32("npub", item.pubkey)}`
|
2023-01-14 10:07:49 +00:00
|
|
|
}
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
}
|
2023-01-15 01:46:13 +00:00
|
|
|
|
|
|
|
export default Textarea
|