fix: profile mentions
This commit is contained in:
parent
d3873ea281
commit
f10ad6dd53
@ -1,3 +1,4 @@
|
||||
/* eslint-disable max-lines */
|
||||
import "./NoteCreator.css";
|
||||
|
||||
import { fetchNip05Pubkey, unixNow } from "@snort/shared";
|
||||
|
@ -1,14 +1,15 @@
|
||||
import "@webscopeio/react-textarea-autocomplete/style.css";
|
||||
import "./Textarea.css";
|
||||
|
||||
import { CachedMetadata, NostrPrefix } from "@snort/system";
|
||||
import { NostrPrefix } from "@snort/system";
|
||||
import ReactTextareaAutocomplete from "@webscopeio/react-textarea-autocomplete";
|
||||
import { useIntl } from "react-intl";
|
||||
import TextareaAutosize from "react-textarea-autosize";
|
||||
|
||||
import { UserCache } from "@/Cache";
|
||||
import Avatar from "@/Components/User/Avatar";
|
||||
import Nip05 from "@/Components/User/Nip05";
|
||||
import { FuzzySearchResult } from "@/Db/FuzzySearch";
|
||||
import { userSearch } from "@/Hooks/useProfileSearch";
|
||||
import { hexToBech32 } from "@/Utils";
|
||||
import searchEmoji from "@/Utils/emoji-search";
|
||||
|
||||
@ -28,7 +29,7 @@ const EmojiItem = ({ entity: { name, char } }: { entity: EmojiItemProps }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const UserItem = (metadata: CachedMetadata) => {
|
||||
const UserItem = (metadata: FuzzySearchResult) => {
|
||||
const { pubkey, display_name, nip05, ...rest } = metadata;
|
||||
return (
|
||||
<div key={pubkey} className="user-item">
|
||||
@ -45,7 +46,7 @@ const UserItem = (metadata: CachedMetadata) => {
|
||||
|
||||
interface TextareaProps {
|
||||
autoFocus: boolean;
|
||||
className: string;
|
||||
className?: string;
|
||||
placeholder?: string;
|
||||
onChange(ev: React.ChangeEvent<HTMLTextAreaElement>): void;
|
||||
value: string;
|
||||
@ -59,8 +60,8 @@ interface TextareaProps {
|
||||
const Textarea = (props: TextareaProps) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
const userDataProvider = async (token: string) => {
|
||||
return await UserCache.search(token);
|
||||
const userDataProvider = (token: string) => {
|
||||
return userSearch(token).slice(0, 10);
|
||||
};
|
||||
|
||||
const emojiDataProvider = async (token: string) => {
|
||||
@ -84,7 +85,7 @@ const Textarea = (props: TextareaProps) => {
|
||||
"@": {
|
||||
afterWhitespace: true,
|
||||
dataProvider: userDataProvider,
|
||||
component: (props: { entity: CachedMetadata }) => <UserItem {...props.entity} />,
|
||||
component: (props: { entity: FuzzySearchResult }) => <UserItem {...props.entity} />,
|
||||
output: (item: { pubkey: string }) => `@${hexToBech32(NostrPrefix.PublicKey, item.pubkey)}`,
|
||||
},
|
||||
}}
|
||||
|
@ -5,44 +5,48 @@ import fuzzySearch from "@/Db/FuzzySearch";
|
||||
|
||||
export default function useProfileSearch(search: string) {
|
||||
const results = useMemo(() => {
|
||||
const searchString = search.trim();
|
||||
const fuseResults = fuzzySearch.search(searchString);
|
||||
|
||||
const followDistanceNormalizationFactor = 3;
|
||||
const seenIds = new Set();
|
||||
|
||||
const combinedResults = fuseResults
|
||||
.map(result => {
|
||||
const fuseScore = result.score === undefined ? 1 : result.score;
|
||||
const followDistance =
|
||||
socialGraphInstance.getFollowDistance(result.item.pubkey) / followDistanceNormalizationFactor;
|
||||
|
||||
const startsWithSearchString = [result.item.name, result.item.display_name, result.item.nip05].some(
|
||||
field => field && field.toLowerCase?.().startsWith(searchString.toLowerCase()),
|
||||
);
|
||||
|
||||
const boostFactor = startsWithSearchString ? 0.25 : 1;
|
||||
|
||||
const weightForFuseScore = 0.8;
|
||||
const weightForFollowDistance = 0.2;
|
||||
|
||||
const combinedScore = (fuseScore * weightForFuseScore + followDistance * weightForFollowDistance) * boostFactor;
|
||||
|
||||
return { ...result, combinedScore };
|
||||
})
|
||||
// Sort by combined score, lower is better
|
||||
.sort((a, b) => a.combinedScore - b.combinedScore)
|
||||
.filter(r => {
|
||||
// for some reason we get duplicates even though fuzzySearch should be removing existing profile on update
|
||||
if (seenIds.has(r.item.pubkey)) {
|
||||
return false;
|
||||
}
|
||||
seenIds.add(r.item.pubkey);
|
||||
return true;
|
||||
});
|
||||
|
||||
return combinedResults.map(r => r.item);
|
||||
return userSearch(search);
|
||||
}, [search]);
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
export function userSearch(search: string) {
|
||||
const searchString = search.trim();
|
||||
const fuseResults = fuzzySearch.search(searchString);
|
||||
|
||||
const followDistanceNormalizationFactor = 3;
|
||||
const seenIds = new Set();
|
||||
|
||||
const combinedResults = fuseResults
|
||||
.map(result => {
|
||||
const fuseScore = result.score === undefined ? 1 : result.score;
|
||||
const followDistance =
|
||||
socialGraphInstance.getFollowDistance(result.item.pubkey) / followDistanceNormalizationFactor;
|
||||
|
||||
const startsWithSearchString = [result.item.name, result.item.display_name, result.item.nip05].some(
|
||||
field => field && field.toLowerCase?.().startsWith(searchString.toLowerCase()),
|
||||
);
|
||||
|
||||
const boostFactor = startsWithSearchString ? 0.25 : 1;
|
||||
|
||||
const weightForFuseScore = 0.8;
|
||||
const weightForFollowDistance = 0.2;
|
||||
|
||||
const combinedScore = (fuseScore * weightForFuseScore + followDistance * weightForFollowDistance) * boostFactor;
|
||||
|
||||
return { ...result, combinedScore };
|
||||
})
|
||||
// Sort by combined score, lower is better
|
||||
.sort((a, b) => a.combinedScore - b.combinedScore)
|
||||
.filter(r => {
|
||||
// for some reason we get duplicates even though fuzzySearch should be removing existing profile on update
|
||||
if (seenIds.has(r.item.pubkey)) {
|
||||
return false;
|
||||
}
|
||||
seenIds.add(r.item.pubkey);
|
||||
return true;
|
||||
});
|
||||
|
||||
return combinedResults.map(r => r.item);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user