2022-10-28 21:21:47 +00:00
|
|
|
import { createMemo, createSignal, For, onMount, Show } from 'solid-js'
|
2022-09-09 11:53:35 +00:00
|
|
|
import '../../styles/Feed.scss'
|
2022-10-25 21:45:37 +00:00
|
|
|
import stylesBeside from '../../components/Feed/Beside.module.scss'
|
2022-09-22 09:37:49 +00:00
|
|
|
import { Icon } from '../Nav/Icon'
|
2022-09-09 11:53:35 +00:00
|
|
|
import { byCreated, sortBy } from '../../utils/sortby'
|
|
|
|
import { TopicCard } from '../Topic/Card'
|
|
|
|
import { ArticleCard } from '../Feed/Card'
|
2022-09-13 09:59:04 +00:00
|
|
|
import { AuthorCard } from '../Author/Card'
|
2022-09-09 11:53:35 +00:00
|
|
|
import { t } from '../../utils/intl'
|
2022-09-13 09:59:04 +00:00
|
|
|
import { FeedSidebar } from '../Feed/Sidebar'
|
2022-09-09 11:53:35 +00:00
|
|
|
import CommentCard from '../Article/Comment'
|
2022-09-13 09:59:04 +00:00
|
|
|
import { loadRecentArticles, useArticlesStore } from '../../stores/zine/articles'
|
2022-09-09 11:53:35 +00:00
|
|
|
import { useReactionsStore } from '../../stores/zine/reactions'
|
|
|
|
import { useAuthorsStore } from '../../stores/zine/authors'
|
2022-09-09 12:18:09 +00:00
|
|
|
import { useTopicsStore } from '../../stores/zine/topics'
|
2022-09-22 09:37:49 +00:00
|
|
|
import { useTopAuthorsStore } from '../../stores/zine/topAuthors'
|
2022-11-13 19:35:57 +00:00
|
|
|
import { useAuth } from '../../context/auth'
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-13 09:59:04 +00:00
|
|
|
// const AUTHORSHIP_REACTIONS = [
|
|
|
|
// ReactionKind.Accept,
|
|
|
|
// ReactionKind.Reject,
|
|
|
|
// ReactionKind.Propose,
|
|
|
|
// ReactionKind.Ask
|
|
|
|
// ]
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-10-28 21:21:47 +00:00
|
|
|
export const FEED_PAGE_SIZE = 20
|
|
|
|
|
|
|
|
export const FeedView = () => {
|
2022-09-09 11:53:35 +00:00
|
|
|
// state
|
2022-10-28 21:21:47 +00:00
|
|
|
const { sortedArticles } = useArticlesStore()
|
2022-09-22 09:37:49 +00:00
|
|
|
const reactions = useReactionsStore()
|
2022-09-28 20:16:44 +00:00
|
|
|
const { sortedAuthors } = useAuthorsStore()
|
|
|
|
const { topTopics } = useTopicsStore()
|
|
|
|
const { topAuthors } = useTopAuthorsStore()
|
2022-11-13 19:35:57 +00:00
|
|
|
const { session } = useAuth()
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-13 09:59:04 +00:00
|
|
|
const topReactions = createMemo(() => sortBy(reactions(), byCreated))
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-10-28 21:21:47 +00:00
|
|
|
const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false)
|
|
|
|
|
2022-09-13 09:59:04 +00:00
|
|
|
// const expectingFocus = createMemo<Shout[]>(() => {
|
|
|
|
// // 1 co-author notifications needs
|
|
|
|
// // TODO: list of articles where you are co-author
|
|
|
|
// // TODO: preload proposals
|
|
|
|
// // TODO: (maybe?) and changes history
|
|
|
|
// console.debug(reactions().filter((r) => r.kind in AUTHORSHIP_REACTIONS))
|
|
|
|
//
|
|
|
|
// // 2 community self-regulating mechanics
|
|
|
|
// // TODO: query all new posts to be rated for publishing
|
|
|
|
// // TODO: query all reactions where user is in authors list
|
|
|
|
// return []
|
|
|
|
// })
|
2022-09-09 14:08:17 +00:00
|
|
|
|
2022-10-28 21:21:47 +00:00
|
|
|
const loadMore = async () => {
|
|
|
|
const { hasMore } = await loadRecentArticles({ limit: FEED_PAGE_SIZE, offset: sortedArticles().length })
|
|
|
|
setIsLoadMoreButtonVisible(hasMore)
|
2022-09-13 09:59:04 +00:00
|
|
|
}
|
2022-10-28 21:21:47 +00:00
|
|
|
|
|
|
|
onMount(() => {
|
|
|
|
loadMore()
|
|
|
|
})
|
|
|
|
|
2022-09-09 11:53:35 +00:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<div class="container feed">
|
|
|
|
<div class="row">
|
|
|
|
<div class="col-md-3 feed-navigation">
|
2022-09-28 20:16:44 +00:00
|
|
|
<FeedSidebar authors={sortedAuthors()} />
|
2022-09-09 11:53:35 +00:00
|
|
|
</div>
|
|
|
|
|
|
|
|
<div class="col-md-6">
|
|
|
|
<ul class="feed-filter">
|
2022-09-30 14:22:33 +00:00
|
|
|
<Show when={!!session()?.user?.slug}>
|
2022-09-09 11:53:35 +00:00
|
|
|
<li class="selected">
|
|
|
|
<a href="/feed/my">{t('My feed')}</a>
|
|
|
|
</li>
|
|
|
|
</Show>
|
|
|
|
<li>
|
|
|
|
<a href="?by=views">{t('Most read')}</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="?by=rating">{t('Top rated')}</a>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<a href="?by=comments">{t('Most commented')}</a>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
<Show when={sortedArticles().length > 0}>
|
|
|
|
<For each={sortedArticles().slice(0, 4)}>
|
2022-09-09 11:53:35 +00:00
|
|
|
{(article) => <ArticleCard article={article} settings={{ isFeedMode: true }} />}
|
|
|
|
</For>
|
|
|
|
|
2022-10-25 21:45:37 +00:00
|
|
|
<div class={stylesBeside.besideColumnTitle}>
|
2022-09-09 11:53:35 +00:00
|
|
|
<h4>{t('Popular authors')}</h4>
|
|
|
|
<a href="/user/list">
|
|
|
|
{t('All authors')}
|
|
|
|
<Icon name="arrow-right" />
|
|
|
|
</a>
|
|
|
|
</div>
|
|
|
|
|
2022-10-25 21:45:37 +00:00
|
|
|
<ul class={stylesBeside.besideColumn}>
|
2022-09-28 20:16:44 +00:00
|
|
|
<For each={topAuthors().slice(0, 5)}>
|
2022-09-13 09:59:04 +00:00
|
|
|
{(author) => (
|
2022-09-09 12:18:09 +00:00
|
|
|
<li>
|
|
|
|
<AuthorCard author={author} compact={true} hasLink={true} />
|
|
|
|
</li>
|
|
|
|
)}
|
|
|
|
</For>
|
|
|
|
</ul>
|
2022-09-09 11:53:35 +00:00
|
|
|
|
2022-09-28 20:16:44 +00:00
|
|
|
<For each={sortedArticles().slice(4)}>
|
2022-09-09 11:53:35 +00:00
|
|
|
{(article) => <ArticleCard article={article} settings={{ isFeedMode: true }} />}
|
|
|
|
</For>
|
|
|
|
</Show>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<aside class="col-md-3">
|
|
|
|
<section class="feed-comments">
|
|
|
|
<h4>{t('Comments')}</h4>
|
2022-09-13 09:59:04 +00:00
|
|
|
<For each={topReactions()}>
|
|
|
|
{(comment) => <CommentCard comment={comment} compact={true} />}
|
2022-09-09 11:53:35 +00:00
|
|
|
</For>
|
|
|
|
</section>
|
2022-09-28 20:16:44 +00:00
|
|
|
<Show when={topTopics().length > 0}>
|
2022-09-09 11:53:35 +00:00
|
|
|
<section class="feed-topics">
|
|
|
|
<h4>{t('Topics')}</h4>
|
2022-09-28 20:16:44 +00:00
|
|
|
<For each={topTopics().slice(0, 5)}>
|
2022-09-09 11:53:35 +00:00
|
|
|
{(topic) => <TopicCard topic={topic} subscribeButtonBottom={true} />}
|
|
|
|
</For>
|
|
|
|
</section>
|
|
|
|
</Show>
|
|
|
|
</aside>
|
|
|
|
</div>
|
2022-10-28 21:21:47 +00:00
|
|
|
<Show when={isLoadMoreButtonVisible()}>
|
|
|
|
<p class="load-more-container">
|
|
|
|
<button class="button" onClick={loadMore}>
|
|
|
|
{t('Load more')}
|
|
|
|
</button>
|
|
|
|
</p>
|
|
|
|
</Show>
|
2022-09-09 11:53:35 +00:00
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|