show "followed by" on profile pages
Some checks failed
continuous-integration/drone/pr Build is failing
Some checks failed
continuous-integration/drone/pr Build is failing
This commit is contained in:
parent
47aec5437d
commit
13b76e7709
@ -50,10 +50,12 @@ export default function SearchBox() {
|
|||||||
|
|
||||||
const combinedResults = fuseResults.map(result => {
|
const combinedResults = fuseResults.map(result => {
|
||||||
const fuseScore = result.score === undefined ? 1 : result.score;
|
const fuseScore = result.score === undefined ? 1 : result.score;
|
||||||
const followDistance = socialGraphInstance.getFollowDistance(result.item.pubkey) / followDistanceNormalizationFactor;
|
const followDistance =
|
||||||
|
socialGraphInstance.getFollowDistance(result.item.pubkey) / followDistanceNormalizationFactor;
|
||||||
|
|
||||||
const startsWithSearchString = [result.item.name, result.item.display_name, result.item.nip05]
|
const startsWithSearchString = [result.item.name, result.item.display_name, result.item.nip05].some(
|
||||||
.some(field => field && field.toLowerCase?.().startsWith(searchString.toLowerCase()));
|
field => field && field.toLowerCase?.().startsWith(searchString.toLowerCase()),
|
||||||
|
);
|
||||||
|
|
||||||
const boostFactor = startsWithSearchString ? 0.25 : 1;
|
const boostFactor = startsWithSearchString ? 0.25 : 1;
|
||||||
|
|
||||||
@ -65,12 +67,11 @@ export default function SearchBox() {
|
|||||||
return { ...result, combinedScore };
|
return { ...result, combinedScore };
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sort by combined score, lower is better
|
// Sort by combined score, lower is better
|
||||||
combinedResults.sort((a, b) => a.combinedScore - b.combinedScore);
|
combinedResults.sort((a, b) => a.combinedScore - b.combinedScore);
|
||||||
|
|
||||||
setResults(combinedResults.map(r => r.item));
|
|
||||||
}, [search, main]);
|
|
||||||
|
|
||||||
|
setResults(combinedResults.map(r => r.item));
|
||||||
|
}, [search, main]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleGlobalKeyDown = (e: KeyboardEvent) => {
|
const handleGlobalKeyDown = (e: KeyboardEvent) => {
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
MetadataCache,
|
MetadataCache,
|
||||||
NostrLink,
|
NostrLink,
|
||||||
NostrPrefix,
|
NostrPrefix,
|
||||||
|
socialGraphInstance,
|
||||||
TLVEntryType,
|
TLVEntryType,
|
||||||
tryParseNostrLink,
|
tryParseNostrLink,
|
||||||
} from "@snort/system";
|
} from "@snort/system";
|
||||||
@ -152,6 +153,8 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function username() {
|
function username() {
|
||||||
|
const followedByFriends = user.pubkey ? socialGraphInstance.followedByFriends(user.pubkey) : new Set<string>();
|
||||||
|
const MAX_FOLLOWED_BY_FRIENDS = 3;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex flex-col g4">
|
<div className="flex flex-col g4">
|
||||||
@ -160,6 +163,31 @@ export default function ProfilePage({ id: propId, state }: ProfilePageProps) {
|
|||||||
<FollowsYou followsMe={follows.includes(loginPubKey ?? "")} />
|
<FollowsYou followsMe={follows.includes(loginPubKey ?? "")} />
|
||||||
</h2>
|
</h2>
|
||||||
{user?.nip05 && <Nip05 nip05={user.nip05} pubkey={user.pubkey} />}
|
{user?.nip05 && <Nip05 nip05={user.nip05} pubkey={user.pubkey} />}
|
||||||
|
{followedByFriends.size > 0 && (
|
||||||
|
<div className="text-gray-light">
|
||||||
|
<span className="mr-1">
|
||||||
|
<FormattedMessage defaultMessage="Followed by" id="6mr8WU" />
|
||||||
|
</span>
|
||||||
|
{Array.from(followedByFriends)
|
||||||
|
.slice(0, MAX_FOLLOWED_BY_FRIENDS)
|
||||||
|
.map(a => {
|
||||||
|
return (
|
||||||
|
<span className="inline-block" key={a}>
|
||||||
|
<ProfileImage showFollowDistance={false} pubkey={a} size={24} showUsername={false} />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
{followedByFriends.size > MAX_FOLLOWED_BY_FRIENDS && (
|
||||||
|
<span>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="and {count} others you follow"
|
||||||
|
id="CYkOCI"
|
||||||
|
values={{ count: followedByFriends.size - MAX_FOLLOWED_BY_FRIENDS }}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{showBadges && <BadgeList badges={badges} />}
|
{showBadges && <BadgeList badges={badges} />}
|
||||||
{showStatus && <>{musicStatus()}</>}
|
{showStatus && <>{musicStatus()}</>}
|
||||||
|
@ -234,6 +234,9 @@
|
|||||||
"6k7xfM": {
|
"6k7xfM": {
|
||||||
"defaultMessage": "Trending notes"
|
"defaultMessage": "Trending notes"
|
||||||
},
|
},
|
||||||
|
"6mr8WU": {
|
||||||
|
"defaultMessage": "Followed by"
|
||||||
|
},
|
||||||
"6uMqL1": {
|
"6uMqL1": {
|
||||||
"defaultMessage": "Unpaid"
|
"defaultMessage": "Unpaid"
|
||||||
},
|
},
|
||||||
@ -368,6 +371,9 @@
|
|||||||
"CVWeJ6": {
|
"CVWeJ6": {
|
||||||
"defaultMessage": "Trending People"
|
"defaultMessage": "Trending People"
|
||||||
},
|
},
|
||||||
|
"CYkOCI": {
|
||||||
|
"defaultMessage": "and {count} others you follow"
|
||||||
|
},
|
||||||
"CbM2hK": {
|
"CbM2hK": {
|
||||||
"defaultMessage": "Trending hashtags"
|
"defaultMessage": "Trending hashtags"
|
||||||
},
|
},
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
"6bgpn+": "Not all clients support this, you may still receive some zaps as if zap splits was not configured",
|
"6bgpn+": "Not all clients support this, you may still receive some zaps as if zap splits was not configured",
|
||||||
"6ewQqw": "Likes ({n})",
|
"6ewQqw": "Likes ({n})",
|
||||||
"6k7xfM": "Trending notes",
|
"6k7xfM": "Trending notes",
|
||||||
|
"6mr8WU": "Followed by",
|
||||||
"6uMqL1": "Unpaid",
|
"6uMqL1": "Unpaid",
|
||||||
"7+Domh": "Notes",
|
"7+Domh": "Notes",
|
||||||
"712i26": "Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node",
|
"712i26": "Proxy uses HODL invoices to forward the payment, which hides the pubkey of your node",
|
||||||
@ -121,6 +122,7 @@
|
|||||||
"C8HhVE": "Suggested Follows",
|
"C8HhVE": "Suggested Follows",
|
||||||
"CHTbO3": "Failed to load invoice",
|
"CHTbO3": "Failed to load invoice",
|
||||||
"CVWeJ6": "Trending People",
|
"CVWeJ6": "Trending People",
|
||||||
|
"CYkOCI": "and {count} others you follow",
|
||||||
"CbM2hK": "Trending hashtags",
|
"CbM2hK": "Trending hashtags",
|
||||||
"CmZ9ls": "{n} Muted",
|
"CmZ9ls": "{n} Muted",
|
||||||
"CsCUYo": "{n} sats",
|
"CsCUYo": "{n} sats",
|
||||||
|
@ -211,6 +211,17 @@ export default class SocialGraph {
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
followedByFriends(address: HexKey) {
|
||||||
|
const id = ID(address);
|
||||||
|
const set = new Set<HexKey>();
|
||||||
|
for (const follower of this.followersByUser.get(id) ?? []) {
|
||||||
|
if (this.followedByUser.get(this.root)?.has(follower)) {
|
||||||
|
set.add(STR(follower));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
getFollowedByUser(user: HexKey, includeSelf = false): Set<HexKey> {
|
getFollowedByUser(user: HexKey, includeSelf = false): Set<HexKey> {
|
||||||
const userId = ID(user);
|
const userId = ID(user);
|
||||||
const set = new Set<HexKey>();
|
const set = new Set<HexKey>();
|
||||||
|
Loading…
Reference in New Issue
Block a user