Merge pull request #76 from v0l/autocomplete-query

feat: query for autocompletion using local db
This commit is contained in:
Alejandro 2023-01-17 11:22:28 +01:00 committed by GitHub
commit 5fceb969ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 40 additions and 25 deletions

View File

@ -15,7 +15,7 @@ export default function Mention({ pubkey }: { pubkey: HexKey }) {
name = user!.name!;
}
return name;
}, [user]);
}, [user, pubkey]);
return <Link to={profileLink(pubkey)} onClick={(e) => e.stopPropagation()}>@{name}</Link>
}

View File

@ -1,7 +1,7 @@
import { useQuery } from "react-query";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faCheck, faSpinner, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
import { faSpinner, faTriangleExclamation } from "@fortawesome/free-solid-svg-icons";
import './Nip05.css'
import { HexKey } from "../nostr";
@ -14,12 +14,16 @@ async function fetchNip05Pubkey(name: string, domain: string) {
if (!name || !domain) {
return undefined;
}
const res = await fetch(`https://${domain}/.well-known/nostr.json?name=${encodeURIComponent(name)}`);
const data: NostrJson = await res.json();
const match = Object.keys(data.names).find(n => {
return n.toLowerCase() === name.toLowerCase();
});
return match ? data.names[match] : undefined;
try {
const res = await fetch(`https://${domain}/.well-known/nostr.json?name=${encodeURIComponent(name)}`);
const data: NostrJson = await res.json();
const match = Object.keys(data.names).find(n => {
return n.toLowerCase() === name.toLowerCase();
});
return match ? data.names[match] : undefined;
} catch (error) {
return undefined
}
}
const VERIFICATION_CACHE_TIME = 24 * 60 * 60 * 1000

View File

@ -28,7 +28,7 @@ export default function ProfileImage({ pubkey, subHeader, showUsername = true, c
name = user!.name!;
}
return name;
}, [user]);
}, [user, pubkey]);
return (
<div className={`pfp${className ? ` ${className}` : ""}`}>

View File

@ -3,7 +3,7 @@ import ReactMarkdown from "react-markdown";
import { TwitterTweetEmbed } from "react-twitter-embed";
import { UrlRegex, FileExtensionRegex, MentionRegex, InvoiceRegex, YoutubeUrlRegex, TweetUrlRegex, HashtagRegex } from "../Const";
import { eventLink, hexToBech32, profileLink } from "../Util";
import { eventLink, hexToBech32 } from "../Util";
import Invoice from "./Invoice";
import LazyImage from "./LazyImage";
import Hashtag from "./Hashtag";

View File

@ -24,6 +24,12 @@
margin-right: 8px;
}
.user-picture .avatar {
border-width: 1px;
width: 40px;
height: 40px;
}
.user-details {
display: flex;
flex-direction: column;

View File

@ -1,31 +1,23 @@
import "@webscopeio/react-textarea-autocomplete/style.css";
import "./Textarea.css";
import Nostrich from "../nostrich.jpg";
import { useState } from "react";
import { useLiveQuery } from "dexie-react-hooks";
import ReactTextareaAutocomplete from "@webscopeio/react-textarea-autocomplete";
import TextareaAutosize from "react-textarea-autosize";
import Avatar from "./Avatar";
import Nip05 from "./Nip05";
import { hexToBech32 } from "../Util";
import { db } from "../db";
import { MetadataCache } from "../db/User";
function searchUsers(query: string, users: MetadataCache[]) {
const q = query.toLowerCase()
return users.filter(({ name, display_name, about, nip05 }: MetadataCache) => {
return name?.toLowerCase().includes(q)
|| display_name?.toLowerCase().includes(q)
|| about?.toLowerCase().includes(q)
|| nip05?.toLowerCase().includes(q)
}).slice(0, 3)
}
const UserItem = ({ pubkey, display_name, picture, nip05, ...rest }: MetadataCache) => {
const UserItem = (metadata: MetadataCache) => {
const { pubkey, display_name, picture, nip05, ...rest } = metadata
return (
<div key={pubkey} className="user-item">
<div className="user-picture">
{picture && <img src={picture ? picture : Nostrich} className="picture" />}
<Avatar user={metadata} />
</div>
<div className="user-details">
<strong>{display_name || rest.name}</strong>
@ -36,10 +28,23 @@ const UserItem = ({ pubkey, display_name, picture, nip05, ...rest }: MetadataCac
}
const Textarea = ({ users, onChange, ...rest }: any) => {
const [query, setQuery] = useState('')
const allUsers = useLiveQuery(
() => db.users.toArray()
() => db.users
.where("name").startsWithIgnoreCase(query)
.or("display_name").startsWithIgnoreCase(query)
.or("nip05").startsWithIgnoreCase(query)
.limit(5)
.toArray(),
[query],
);
const userDataProvider = (token: string) => {
setQuery(token)
return allUsers
}
return (
<ReactTextareaAutocomplete
{...rest}
@ -50,7 +55,7 @@ const Textarea = ({ users, onChange, ...rest }: any) => {
trigger={{
"@": {
afterWhitespace: true,
dataProvider: token => allUsers ? searchUsers(token, allUsers) : [],
dataProvider: userDataProvider,
component: (props: any) => <UserItem {...props.entity} />,
output: (item: any) => `@${hexToBech32("npub", item.pubkey)}`
}