From 05b0fe92199b9db7c8022cb4b52083b0123dd0a3 Mon Sep 17 00:00:00 2001 From: Bojan Mojsilovic Date: Wed, 10 Jan 2024 18:25:24 +0100 Subject: [PATCH] Remember last 10 visited profiles --- src/components/Search/Search.tsx | 6 ++- src/contexts/ProfileContext.tsx | 70 +++++++++++++++++++++++++++----- src/contexts/SearchContext.tsx | 9 +++- 3 files changed, 71 insertions(+), 14 deletions(-) diff --git a/src/components/Search/Search.tsx b/src/components/Search/Search.tsx index e1b3c33..0bc69ca 100644 --- a/src/components/Search/Search.tsx +++ b/src/components/Search/Search.tsx @@ -13,6 +13,7 @@ import { placeholders, search as t } from '../../translations'; import styles from './Search.module.scss'; import SearchOption from './SearchOption'; import { hookForDev } from '../../lib/devTools'; +import { useProfileContext } from '../../contexts/ProfileContext'; const Search: Component<{ @@ -28,6 +29,7 @@ const Search: Component<{ const search = useSearchContext(); const navigate = useNavigate(); const intl = useIntl(); + const profile = useProfileContext(); const [query, setQuery] = createSignal(''); const [isFocused, setIsFocused] = createSignal(false); @@ -103,7 +105,7 @@ const Search: Component<{ createEffect(() => { if (query().length === 0) { - search?.actions.getRecomendedUsers(); + search?.actions.getRecomendedUsers(profile?.profileHistory.profiles || []); return; } @@ -174,7 +176,7 @@ const Search: Component<{ title={userName(user)} description={nip05Verification(user)} icon={} - statNumber={search?.scores[user.pubkey]} + statNumber={profile?.profileHistory.stats[user.pubkey]?.followers_count || search?.scores[user.pubkey]} statLabel={intl.formatMessage(t.followers)} onClick={() => selectUser(user)} /> diff --git a/src/contexts/ProfileContext.tsx b/src/contexts/ProfileContext.tsx index 51189e3..9dd32fb 100644 --- a/src/contexts/ProfileContext.tsx +++ b/src/contexts/ProfileContext.tsx @@ -53,19 +53,22 @@ import { parseBolt11 } from "../utils"; import { convertToUser } from "../stores/profile"; import { sortBreakpoints } from "@solid-primitives/media"; +export type UserStats = { + pubkey: string, + follows_count: number, + followers_count: number, + note_count: number, + reply_count: number, + time_joined: number, + total_zap_count: number, + total_satszapped: number, + relay_count: number, +}; + export type ProfileContextStore = { profileKey: string | undefined, userProfile: PrimalUser | undefined, - userStats: { - follows_count: number, - followers_count: number, - note_count: number, - reply_count: number, - time_joined: number, - total_zap_count: number, - total_satszapped: number, - relay_count: number, - }, + userStats: UserStats, fetchedUserStats: boolean, knownProfiles: VanityProfiles, notes: PrimalNote[], @@ -100,6 +103,10 @@ export type ProfileContextStore = { isFetchingZaps: boolean, profileStats: Record, relays: NostrRelays, + profileHistory: { + profiles: PrimalUser[], + stats: Record, + }, actions: { saveNotes: (newNotes: PrimalNote[]) => void, clearNotes: () => void, @@ -129,6 +136,7 @@ export type ProfileContextStore = { } export const emptyStats = { + pubkey: '', follows_count: 0, followers_count: 0, note_count: 0, @@ -195,6 +203,10 @@ export const initialData = { noteActions: {}, }, }, + profileHistory: { + profiles: [], + stats: {}, + }, }; @@ -892,6 +904,42 @@ export const ProfileProvider = (props: { children: ContextChildren }) => { const refreshNotes = () => { }; + const addProfileToHistory = (user: PrimalUser) => { + let list = [...store.profileHistory.profiles]; + + const index = list.findIndex(u => u.pubkey === user.pubkey) + + // user is first in the list so the job is done + if (index === 0) return; + + if (index > 0) { + list.splice(index, 1); + + updateStore('profileHistory', 'profiles', () => [user, ...list]); + return; + } + + list.unshift(user); + + if (list.length > 10) { + const last = list[list.length - 1].pubkey; + + let stats = { ...store.profileHistory.stats }; + + delete stats[last]; + + updateStore('profileHistory', 'stats', reconcile(stats)); + + list.pop() + } + + updateStore('profileHistory', 'profiles', () => [...list]); + }; + + const addStatsToHistory = (stats: UserStats) => { + updateStore('profileHistory', 'stats', () => ({ [stats.pubkey]: stats })); + }; + // SOCKET HANDLERS ------------------------------ const onMessage = (event: MessageEvent) => { @@ -959,6 +1007,7 @@ export const ProfileProvider = (props: { children: ContextChildren }) => { user.created_at = content.created_at; updateStore('userProfile', () => user); + addProfileToHistory(user); return; } @@ -966,6 +1015,7 @@ export const ProfileProvider = (props: { children: ContextChildren }) => { const stats = JSON.parse(content.content); updateStore('userStats', () => ({ ...stats })); + addStatsToHistory(stats) updateStore('fetchedUserStats', () => true); return; } diff --git a/src/contexts/SearchContext.tsx b/src/contexts/SearchContext.tsx index 5bcb0ea..c1dc251 100644 --- a/src/contexts/SearchContext.tsx +++ b/src/contexts/SearchContext.tsx @@ -26,6 +26,7 @@ import { subscribeTo } from "../sockets"; import { nip19 } from "nostr-tools"; import { useAccountContext } from "./AccountContext"; import { npubToHex } from "../lib/keys"; +import { useProfileContext } from "./ProfileContext"; const recomendedUsers = [ '82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2', // jack @@ -59,7 +60,7 @@ export type SearchContextStore = { findContentUsers: (query: string, pubkey?: string) => void, findContent: (query: string) => void, setContentQuery: (query: string) => void, - getRecomendedUsers: () => void, + getRecomendedUsers: (profiles?: PrimalUser[]) => void, findFilteredUserByNpub: (npub: string) => void, }, } @@ -147,7 +148,7 @@ export function SearchProvider(props: { children: number | boolean | Node | JSX. getUserProfiles([hex], subId); }; - const getRecomendedUsers = () => { + const getRecomendedUsers = (profiles?: PrimalUser[]) => { const subid = `recomended_users_${APP_ID}`; let users: PrimalUser[] = []; @@ -182,6 +183,10 @@ export function SearchProvider(props: { children: number | boolean | Node | JSX. sorted[index] = { ...user }; }); + if (profiles) { + sorted = [...profiles, ...sorted].slice(0, 9); + } + updateStore('users', () => sorted); updateStore('isFetchingUsers', () => false);