Fix home sidebar refreshing when navigating to home

This commit is contained in:
Bojan Mojsilovic 2023-11-29 14:20:07 +01:00
parent ccfb955a46
commit 674738ed01
2 changed files with 156 additions and 160 deletions

View File

@ -1,45 +1,17 @@
import { Component, createEffect, createSignal, For, onCleanup, onMount, Show } from 'solid-js';
import { createStore } from 'solid-js/store';
import { APP_ID } from '../../App';
import { getMostZapped4h, getTrending24h } from '../../lib/feed';
import { humanizeNumber } from '../../lib/stats';
import { convertToNotes, sortByRecency, sortingPlan } from '../../stores/note';
import { Kind } from '../../constants';
import { Component, For, onMount, Show } from 'solid-js';
import {
isConnected,
refreshSocketListeners,
removeSocketListeners,
socket,
subscribeTo
} from '../../sockets';
import {
FeedPage,
NostrEOSE,
NostrEvent,
NostrEventContent,
NostrMentionContent,
NostrNoteActionsContent,
NostrNoteContent,
NostrStatsContent,
NostrUserContent,
NoteActions,
PrimalNote,
SelectionOption
} from '../../types/primal';
import styles from './HomeSidebar.module.scss';
import SmallNote from '../SmallNote/SmallNote';
import { useIntl } from '@cookbook/solid-intl';
import { hourNarrow } from '../../formats';
import { home as t } from '../../translations';
import { useAccountContext } from '../../contexts/AccountContext';
import { hookForDev } from '../../lib/devTools';
import SelectionBox from '../SelectionBox/SelectionBox';
import { getScoredUsers, searchContent } from '../../lib/search';
import { store } from '../../services/StoreService';
import Loader from '../Loader/Loader';
import { readHomeSidebarSelection, saveHomeSidebarSelection } from '../../lib/localStore';
import { useHomeContext } from '../../contexts/HomeContext';
const sidebarOptions = [
{
@ -85,132 +57,15 @@ const sidebarOptions = [
const HomeSidebar: Component< { id?: string } > = (props) => {
const intl = useIntl();
const account = useAccountContext();
const home = useHomeContext();
const [searchResults, setSearchResults] = createStore<{ notes: PrimalNote[], page: FeedPage, isFetching: boolean, query: SelectionOption | undefined }>({
notes: [],
page: {
messages: [],
users: {},
postStats: {},
mentions: {},
noteActions: {},
},
isFetching: false,
query: undefined,
});
onMount(() => {
if (account?.isKeyLookupDone && home?.sidebar.notes.length === 0) {
const stored = readHomeSidebarSelection(account.publicKey) || sidebarOptions[0];
const saveNotes = (newNotes: PrimalNote[]) => {
setSearchResults('notes', () => [ ...newNotes.slice(0, 24) ]);
setSearchResults('isFetching', () => false);
};
const updatePage = (content: NostrEventContent) => {
if (content.kind === Kind.Metadata) {
const user = content as NostrUserContent;
setSearchResults('page', 'users',
(usrs) => ({ ...usrs, [user.pubkey]: { ...user } })
);
return;
}
if ([Kind.Text, Kind.Repost].includes(content.kind)) {
const message = content as NostrNoteContent;
if (searchResults.page.messages.find(m => m.id === message.id)) {
return;
}
setSearchResults('page', 'messages',
(msgs) => [ ...msgs, { ...message }]
);
return;
}
if (content.kind === Kind.NoteStats) {
const statistic = content as NostrStatsContent;
const stat = JSON.parse(statistic.content);
setSearchResults('page', 'postStats',
(stats) => ({ ...stats, [stat.event_id]: { ...stat } })
);
return;
}
if (content.kind === Kind.Mentions) {
const mentionContent = content as NostrMentionContent;
const mention = JSON.parse(mentionContent.content);
setSearchResults('page', 'mentions',
(mentions) => ({ ...mentions, [mention.id]: { ...mention } })
);
return;
}
if (content.kind === Kind.NoteActions) {
const noteActionContent = content as NostrNoteActionsContent;
const noteActions = JSON.parse(noteActionContent.content) as NoteActions;
setSearchResults('page', 'noteActions',
(actions) => ({ ...actions, [noteActions.event_id]: { ...noteActions } })
);
return;
}
};
const savePage = (page: FeedPage) => {
const newPosts = convertToNotes(page);
saveNotes(newPosts);
};
const doSearch = (query: string) => {
const subid = `home_sidebar_${APP_ID}`;
const unsub = subscribeTo(subid, (type, _, content) => {
if (type === 'EOSE') {
savePage(searchResults.page);
unsub();
return;
}
if (!content) {
return;
}
if (type === 'EVENT') {
updatePage(content);
return;
}
});
setSearchResults('isFetching', () => true);
setSearchResults('notes', () => []);
setSearchResults('page', { messages: [], users: {}, postStats: {}, mentions: {}, noteActions: {} });
getScoredUsers(account?.publicKey, query, 10, subid);
}
createEffect(() => {
const query = searchResults.query?.value;
query && doSearch(query);
});
createEffect(() => {
if (account?.isKeyLookupDone) {
const stored = readHomeSidebarSelection(account.publicKey);
if (stored) {
setSearchResults('query', () => ({...stored}));
return;
}
setSearchResults('query', () => ({ ...sidebarOptions[0]}));
home?.actions.updateSidebarQuery(stored);
home?.actions.doSidebarSearch(home?.sidebar.query?.value || '');
}
});
@ -220,21 +75,22 @@ const HomeSidebar: Component< { id?: string } > = (props) => {
<div class={styles.headingTrending}>
<SelectionBox
options={sidebarOptions}
value={searchResults.query}
value={home?.sidebar.query}
onChange={(option: SelectionOption) => {
setSearchResults('query', () => ({...option}));
saveHomeSidebarSelection(account?.publicKey, option)
home?.actions.updateSidebarQuery(option);
saveHomeSidebarSelection(account?.publicKey, option);
home?.actions.doSidebarSearch(home?.sidebar.query?.value || '');
}}
/>
</div>
<Show
when={!searchResults.isFetching}
when={!home?.sidebar.isFetching}
fallback={
<Loader />
}
>
<For each={searchResults.notes}>
<For each={home?.sidebar.notes}>
{(note) => <SmallNote note={note} />}
</For>
</Show>

View File

@ -5,7 +5,7 @@ import { APP_ID } from "../App";
import { Kind } from "../constants";
import { getEvents, getExploreFeed, getFeed, getFutureExploreFeed, getFutureFeed } from "../lib/feed";
import { setLinkPreviews } from "../lib/notes";
import { searchContent } from "../lib/search";
import { getScoredUsers, searchContent } from "../lib/search";
import { isConnected, refreshSocketListeners, removeSocketListeners, socket } from "../sockets";
import { sortingPlan, convertToNotes, parseEmptyReposts, paginationPlan } from "../stores/note";
import {
@ -22,6 +22,7 @@ import {
NoteActions,
PrimalFeed,
PrimalNote,
SelectionOption,
} from "../types/primal";
import { useAccountContext } from "./AccountContext";
import { useSettingsContext } from "./SettingsContext";
@ -40,6 +41,12 @@ type HomeContextStore = {
page: FeedPage,
reposts: Record<string, string> | undefined,
},
sidebar: {
notes: PrimalNote[],
page: FeedPage,
isFetching: boolean,
query: SelectionOption | undefined,
},
actions: {
saveNotes: (newNotes: PrimalNote[]) => void,
clearNotes: () => void,
@ -51,6 +58,8 @@ type HomeContextStore = {
savePage: (page: FeedPage) => void,
checkForNewNotes: (topic: string | undefined) => void,
loadFutureContent: () => void,
doSidebarSearch: (query: string) => void,
updateSidebarQuery: (selection: SelectionOption) => void,
}
}
@ -80,6 +89,18 @@ const initialHomeData = {
noteActions: {},
},
},
sidebar: {
notes: [],
page: {
messages: [],
users: {},
postStats: {},
mentions: {},
noteActions: {},
},
isFetching: false,
query: undefined,
}
};
export const HomeContext = createContext<HomeContextStore>();
@ -91,6 +112,106 @@ export const HomeProvider = (props: { children: ContextChildren }) => {
// ACTIONS --------------------------------------
const updateSidebarQuery = (selection: SelectionOption) => {
updateStore('sidebar', 'query', () => ({ ...selection }));
};
const saveSidebarNotes = (newNotes: PrimalNote[]) => {
updateStore('sidebar', 'notes', () => [ ...newNotes.slice(0, 24) ]);
updateStore('sidebar', 'isFetching', () => false);
};
const updateSidebarPage = (content: NostrEventContent) => {
if (content.kind === Kind.Metadata) {
const user = content as NostrUserContent;
updateStore('sidebar', 'page', 'users',
(usrs) => ({ ...usrs, [user.pubkey]: { ...user } })
);
return;
}
if ([Kind.Text, Kind.Repost].includes(content.kind)) {
const message = content as NostrNoteContent;
if (store.sidebar.page.messages.find(m => m.id === message.id)) {
return;
}
updateStore('sidebar', 'page', 'messages',
(msgs) => [ ...msgs, { ...message }]
);
return;
}
if (content.kind === Kind.NoteStats) {
const statistic = content as NostrStatsContent;
const stat = JSON.parse(statistic.content);
updateStore('sidebar', 'page', 'postStats',
(stats) => ({ ...stats, [stat.event_id]: { ...stat } })
);
return;
}
if (content.kind === Kind.Mentions) {
const mentionContent = content as NostrMentionContent;
const mention = JSON.parse(mentionContent.content);
updateStore('sidebar', 'page', 'mentions',
(mentions) => ({ ...mentions, [mention.id]: { ...mention } })
);
return;
}
if (content.kind === Kind.NoteActions) {
const noteActionContent = content as NostrNoteActionsContent;
const noteActions = JSON.parse(noteActionContent.content) as NoteActions;
updateStore('sidebar', 'page', 'noteActions',
(actions) => ({ ...actions, [noteActions.event_id]: { ...noteActions } })
);
return;
}
};
const saveSidebarPage = (page: FeedPage) => {
const newPosts = convertToNotes(page);
saveSidebarNotes(newPosts);
};
const doSidebarSearch = (query: string) => {
const subid = `home_sidebar_${APP_ID}`;
// const unsub = subscribeTo(subid, (type, _, content) => {
// if (type === 'EOSE') {
// saveSidebarPage(store.sidebar.page);
// unsub();
// return;
// }
// if (!content) {
// return;
// }
// if (type === 'EVENT') {
// updateSidebarPage(content);
// return;
// }
// });
updateStore('sidebar', 'isFetching', () => true);
updateStore('sidebar', 'notes', () => []);
updateStore('sidebar', 'page', { messages: [], users: {}, postStats: {}, mentions: {}, noteActions: {} });
getScoredUsers(account?.publicKey, query, 10, subid);
}
const clearFuture = () => {
updateStore('future', () => ({
notes: [],
@ -388,6 +509,23 @@ export const HomeProvider = (props: { children: ContextChildren }) => {
const [type, subId, content] = message;
if (subId === `home_sidebar_${APP_ID}`) {
if (type === 'EOSE') {
saveSidebarPage(store.sidebar.page);
return;
}
if (!content) {
return;
}
if (type === 'EVENT') {
updateSidebarPage(content);
return;
}
}
if (subId === `home_feed_${APP_ID}`) {
if (type === 'EOSE') {
const reposts = parseEmptyReposts(store.page);
@ -524,6 +662,8 @@ export const HomeProvider = (props: { children: ContextChildren }) => {
savePage,
checkForNewNotes,
loadFutureContent,
doSidebarSearch,
updateSidebarQuery,
},
});