Topic links

This commit is contained in:
Bojan Mojsilovic 2024-06-17 14:17:21 +02:00
parent a69f7d5950
commit ccdecc01ce
8 changed files with 88 additions and 26 deletions

View File

@ -110,7 +110,7 @@ const Router: Component = () => {
<Route path="/" component={Layout} > <Route path="/" component={Layout} >
<Route path="/" component={Landing} /> <Route path="/" component={Landing} />
<Route path="/home" component={Home} /> <Route path="/home" component={Home} />
<Route path="/reads" component={Reads} /> <Route path="/reads/:topic?" component={Reads} />
<Route path="/thread/:id" component={Thread} /> <Route path="/thread/:id" component={Thread} />
<Route path="/e/:id" component={Thread} /> <Route path="/e/:id" component={Thread} />
<Route path="/explore/:scope?/:timeframe?" component={Explore} /> <Route path="/explore/:scope?/:timeframe?" component={Explore} />

View File

@ -241,9 +241,9 @@ const ArticlePreview: Component<{
</div> </div>
<For each={props.article.tags.slice(0, 3)}> <For each={props.article.tags.slice(0, 3)}>
{tag => ( {tag => (
<div class={styles.tag}> <A href={`/reads/${tag}`} class={styles.tag}>
{tag} {tag}
</div> </A>
)} )}
</For> </For>
<Show when={props.article.tags.length > 3}> <Show when={props.article.tags.length > 3}>

View File

@ -24,6 +24,7 @@ import { getParametrizedEvent, getParametrizedEvents } from '../../lib/notes';
import { decodeIdentifier } from '../../lib/keys'; import { decodeIdentifier } from '../../lib/keys';
import ArticleShort from '../ArticlePreview/ArticleShort'; import ArticleShort from '../ArticlePreview/ArticleShort';
import AuthorSubscribe from '../AuthorSubscribe/AuthorSubscribe'; import AuthorSubscribe from '../AuthorSubscribe/AuthorSubscribe';
import { A } from '@solidjs/router';
const sidebarOptions = [ const sidebarOptions = [
{ {
@ -227,7 +228,7 @@ const ReadsSidebar: Component< { id?: string } > = (props) => {
> >
<div class={styles.section}> <div class={styles.section}>
<For each={topics}> <For each={topics}>
{(topic) => <div class={styles.topic}>{topic}</div>} {(topic) => <A href={`/reads/${topic}`} class={styles.topic}>{topic}</A>}
</For> </For>
</div> </div>
</Show> </Show>

View File

@ -60,7 +60,7 @@ type ReadsContextStore = {
saveNotes: (newNotes: PrimalArticle[]) => void, saveNotes: (newNotes: PrimalArticle[]) => void,
clearNotes: () => void, clearNotes: () => void,
fetchNotes: (topic: string, subId: string, until?: number) => void, fetchNotes: (topic: string, subId: string, until?: number) => void,
fetchNextPage: () => void, fetchNextPage: (topic?: string) => void,
selectFeed: (feed: PrimalFeed | undefined) => void, selectFeed: (feed: PrimalFeed | undefined) => void,
updateScrollTop: (top: number) => void, updateScrollTop: (top: number) => void,
updatePage: (content: NostrEventContent) => void, updatePage: (content: NostrEventContent) => void,
@ -70,6 +70,7 @@ type ReadsContextStore = {
doSidebarSearch: (query: string) => void, doSidebarSearch: (query: string) => void,
updateSidebarQuery: (selection: SelectionOption) => void, updateSidebarQuery: (selection: SelectionOption) => void,
getFirstPage: () => void, getFirstPage: () => void,
resetSelectedFeed: () => void;
} }
} }
@ -309,6 +310,7 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
}; };
const fetchNotes = (topic: string, subId: string, until = 0, includeReplies?: boolean) => { const fetchNotes = (topic: string, subId: string, until = 0, includeReplies?: boolean) => {
const t = topic === 'none' ? '' : topic;//account?.publicKey || '532d830dffe09c13e75e8b145c825718fc12b0003f61d61e9077721c7fff93cb'; const t = topic === 'none' ? '' : topic;//account?.publicKey || '532d830dffe09c13e75e8b145c825718fc12b0003f61d61e9077721c7fff93cb';
const [scope, timeframe] = t.split(';'); const [scope, timeframe] = t.split(';');
@ -317,6 +319,11 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
if (scope && timeframe) { if (scope && timeframe) {
if (scope === 'filter') {
getArticlesFeed(account?.publicKey, undefined, `reads_feed_${subId}`, until, 20, timeframe);
return;
}
if (scope === 'search') { if (scope === 'search') {
searchContent(account?.publicKey, `reads_feed_${subId}`, decodeURI(timeframe)); searchContent(account?.publicKey, `reads_feed_${subId}`, decodeURI(timeframe));
return; return;
@ -345,7 +352,7 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
clearFuture(); clearFuture();
}; };
const fetchNextPage = () => { const fetchNextPage = (mainTopic?: string) => {
if (store.isFetching) { if (store.isFetching) {
return; return;
} }
@ -357,7 +364,7 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
updateStore('lastNote', () => ({ ...lastNote })); updateStore('lastNote', () => ({ ...lastNote }));
const topic = store.selectedFeed?.hex; const topic = mainTopic ? `filter;${mainTopic}` : store.selectedFeed?.hex;
const includeReplies = store.selectedFeed?.includeReplies; const includeReplies = store.selectedFeed?.includeReplies;
if (!topic) { if (!topic) {
@ -391,7 +398,7 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
let currentFeed: PrimalFeed | undefined; let currentFeed: PrimalFeed | undefined;
const selectFeed = (feed: PrimalFeed | undefined) => { const selectFeed = (feed: PrimalFeed | undefined, force?: boolean) => {
if (feed?.hex !== undefined && (feed.hex !== currentFeed?.hex || feed.includeReplies !== currentFeed?.includeReplies)) { if (feed?.hex !== undefined && (feed.hex !== currentFeed?.hex || feed.includeReplies !== currentFeed?.includeReplies)) {
currentFeed = { ...feed }; currentFeed = { ...feed };
// saveStoredFeed(account?.publicKey, currentFeed); // saveStoredFeed(account?.publicKey, currentFeed);
@ -402,6 +409,11 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
} }
}; };
const resetSelectedFeed = () => {
currentFeed = undefined;
updateStore('selectedFeed', () => undefined);
};
const getFirstPage = () => { const getFirstPage = () => {
const feed = store.selectedFeed; const feed = store.selectedFeed;
if (!feed?.hex) return; if (!feed?.hex) return;
@ -792,13 +804,6 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
} }
}); });
createEffect(() => {
if (account?.isKeyLookupDone && account.publicKey) {
selectFeed({ hex: account.publicKey, name: 'My Reads'});
}
});
onCleanup(() => { onCleanup(() => {
removeSocketListeners( removeSocketListeners(
socket(), socket(),
@ -817,6 +822,7 @@ export const ReadsProvider = (props: { children: ContextChildren }) => {
fetchNotes, fetchNotes,
fetchNextPage, fetchNextPage,
selectFeed, selectFeed,
resetSelectedFeed,
updateScrollTop, updateScrollTop,
updatePage, updatePage,
savePage, savePage,

View File

@ -47,7 +47,7 @@ export const getFeed = (user_pubkey: string | undefined, pubkey: string | undef
])); ]));
} }
export const getArticlesFeed = (user_pubkey: string | undefined, pubkey: string | undefined, subid: string, until = 0, limit = 20) => { export const getArticlesFeed = (user_pubkey: string | undefined, pubkey: string | undefined, subid: string, until = 0, limit = 20, topic?: string) => {
// if (!pubkey) { // if (!pubkey) {
// return; // return;
// } // }
@ -66,6 +66,11 @@ export const getArticlesFeed = (user_pubkey: string | undefined, pubkey: string
payload.user_pubkey = user_pubkey; payload.user_pubkey = user_pubkey;
} }
if (topic) {
// @ts-ignore
payload.topic = topic;
}
sendMessage(JSON.stringify([ sendMessage(JSON.stringify([
"REQ", "REQ",
subid, subid,

View File

@ -70,6 +70,21 @@
} }
} }
.backIcon {
display: inline-block;
border: none;
box-shadow: none;
background-color: unset;
margin: 0px;
padding: 0px;
width: 16px;
height: 16px;
background-color: var(--text-secondary);
-webkit-mask: url(../assets/icons/back.svg) no-repeat center;
mask: url(../assets/icons/back.svg) no-repeat center;
}
@media only screen and (max-width: 1300px) { @media only screen and (max-width: 1300px) {
.newContentNotification { .newContentNotification {
left: calc(calc(100vw - 1032px) / 2 + 48px + 32px); left: calc(calc(100vw - 1032px) / 2 + 48px + 32px);

View File

@ -982,9 +982,9 @@ const Longform: Component< { naddr: string } > = (props) => {
<div class={styles.tags}> <div class={styles.tags}>
<For each={store.article?.tags}> <For each={store.article?.tags}>
{tag => ( {tag => (
<div class={styles.tag}> <A href={`/reads/${tag}`} class={styles.tag}>
{tag} {tag}
</div> </A>
)} )}
</For> </For>
</div> </div>

View File

@ -38,6 +38,9 @@ import PageCaption from '../components/PageCaption/PageCaption';
import ReadsSidebar from '../components/HomeSidebar/ReadsSidebar'; import ReadsSidebar from '../components/HomeSidebar/ReadsSidebar';
import ReedSelect from '../components/FeedSelect/ReedSelect'; import ReedSelect from '../components/FeedSelect/ReedSelect';
import ReadsHeader from '../components/HomeHeader/ReadsHeader'; import ReadsHeader from '../components/HomeHeader/ReadsHeader';
import { Link, useParams } from '@solidjs/router';
import { APP_ID } from '../App';
import ButtonGhost from '../components/Buttons/ButtonGhost';
const Home: Component = () => { const Home: Component = () => {
@ -46,6 +49,7 @@ const Home: Component = () => {
const account = useAccountContext(); const account = useAccountContext();
const intl = useIntl(); const intl = useIntl();
const app = useAppContext(); const app = useAppContext();
const params = useParams();
const isPageLoading = () => context?.isFetching; const isPageLoading = () => context?.isFetching;
@ -130,7 +134,21 @@ const Home: Component = () => {
onMount(() => { onMount(() => {
context?.actions.doSidebarSearch('') context?.actions.doSidebarSearch('')
}) });
createEffect(() => {
if (account?.isKeyLookupDone && account.publicKey) {
context?.actions.clearNotes();
if (params.topic) {
context?.actions.fetchNotes(`filter;${decodeURIComponent(params.topic)}`, APP_ID);
return;
}
context?.actions.resetSelectedFeed();
context?.actions.selectFeed({ hex: account.publicKey, name: 'My Reads'});
}
});
return ( return (
<div class={styles.homeContent}> <div class={styles.homeContent}>
@ -142,12 +160,29 @@ const Home: Component = () => {
</Wormhole> </Wormhole>
<PageCaption title={intl.formatMessage(reads.pageTitle)}> <PageCaption title={intl.formatMessage(reads.pageTitle)}>
<Show
when={params.topic}
fallback={
<ReadsHeader <ReadsHeader
hasNewPosts={() => {}} hasNewPosts={() => {}}
loadNewContent={() => {}} loadNewContent={() => {}}
newPostCount={() => {}} newPostCount={() => {}}
newPostAuthors={[]} newPostAuthors={[]}
/> />
}
>
<div class={styles.readsTopicHeader}>
<Link
class={styles.backToReads}
href={'/reads'}
>
Reads:
</Link>
<span>
&nbsp;{decodeURIComponent(params.topic)}
</span>
</div>
</Show>
</PageCaption> </PageCaption>
<StickySidebar> <StickySidebar>
@ -181,7 +216,7 @@ const Home: Component = () => {
</div> </div>
</Match> </Match>
</Switch> </Switch>
<Paginator loadNextPage={context?.actions.fetchNextPage}/> <Paginator loadNextPage={() => context?.actions.fetchNextPage(params.topic)}/>
</div> </div>
</div> </div>
) )