diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 40efff78..e1fb8c6d 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,9 @@ +[0.6.1] +[+] auth ver. 0.9 +[+] load-by interfaces for shouts, authors and messages +[+] inbox logix and markup +[-] old views counting + [0.6.0] [+] hybrid routing ssr/spa [+] 'expo' pages diff --git a/package.json b/package.json index 3acba0ba..0053d436 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "discoursio-webapp", - "version": "0.6.0", + "version": "0.6.1", "private": true, "license": "MIT", "scripts": { diff --git a/src/components/Article/AudioPlayer.tsx b/src/components/Article/AudioPlayer.tsx index 08dcf621..870a6448 100644 --- a/src/components/Article/AudioPlayer.tsx +++ b/src/components/Article/AudioPlayer.tsx @@ -1,5 +1,5 @@ -import { createEffect, createMemo, createSignal, onMount } from 'solid-js' -import { For } from 'solid-js/web' +import { createEffect, createMemo, createSignal, onMount, For } from 'solid-js' + import type { Shout } from '../../graphql/types.gen' import { Soundwave } from './Soundwave' @@ -40,7 +40,7 @@ export default (props: { shout: Shout }) => {
{currentTrack().title}
- +
{`${audioRef.currentTime} / ${audioRef.duration}`} @@ -53,7 +53,7 @@ export default (props: { shout: Shout }) => { {(m: MediaItem) => (
  • - playMedia(m)}> + playMedia(m)} />
    {m.title}
  • diff --git a/src/components/Article/FullArticle.tsx b/src/components/Article/FullArticle.tsx index ecd9f72b..6046c682 100644 --- a/src/components/Article/FullArticle.tsx +++ b/src/components/Article/FullArticle.tsx @@ -7,7 +7,6 @@ import { createMemo, For, onMount, Show } from 'solid-js' import type { Author, Reaction, Shout } from '../../graphql/types.gen' import { t } from '../../utils/intl' import { showModal } from '../../stores/ui' -import { incrementView } from '../../stores/zine/articles' import MD from './MD' import { SharePopup } from './SharePopup' import { useSession } from '../../context/session' @@ -39,11 +38,6 @@ const formatDate = (date: Date) => { export const FullArticle = (props: ArticleProps) => { const { session } = useSession() - - onMount(() => { - incrementView({ articleSlug: props.article.slug }) - }) - const formattedDate = createMemo(() => formatDate(new Date(props.article.createdAt))) const mainTopic = () => diff --git a/src/components/Article/Soundwave.tsx b/src/components/Article/Soundwave.tsx index 27164504..ba04b9d0 100644 --- a/src/components/Article/Soundwave.tsx +++ b/src/components/Article/Soundwave.tsx @@ -105,5 +105,5 @@ export const Soundwave = (props: SoundwaveProps) => { onMount(() => { drawAudio(props.context, props.url) }) - return + return } diff --git a/src/components/Inbox/DialogCard.module.scss b/src/components/Inbox/DialogCard.module.scss index c66470f5..723c344e 100644 --- a/src/components/Inbox/DialogCard.module.scss +++ b/src/components/Inbox/DialogCard.module.scss @@ -28,10 +28,12 @@ text-overflow: ellipsis; white-space: nowrap; } + .name { color: #141414; font-weight: 500; } + .message { color: #9fa1a7; } @@ -40,6 +42,7 @@ .activity { font-size: 12px; margin-left: 12px; + .time { text-align: right; color: #ccc; diff --git a/src/components/Inbox/DialogCard.tsx b/src/components/Inbox/DialogCard.tsx index e31b55d5..9d43a4e8 100644 --- a/src/components/Inbox/DialogCard.tsx +++ b/src/components/Inbox/DialogCard.tsx @@ -1,13 +1,10 @@ -import './DialogCard.module.scss' import styles from './DialogCard.module.scss' import DialogAvatar from './DialogAvatar' -import type { Author } from '../../graphql/types.gen' -// import { useAuthStore } from '../../stores/auth' -import { createEffect, createSignal } from 'solid-js' +import type { Author, AuthResult } from '../../graphql/types.gen' +import { useSession } from '../../context/session' +import { createMemo, InitializedResource } from 'solid-js' import { apiClient } from '../../utils/apiClient' -const { session } = useAuthStore() - type DialogProps = { online?: boolean message?: string @@ -20,20 +17,18 @@ const createChat = async ({ title, members }: { title?: string; members?: string } const DialogCard = (props: DialogProps) => { - const [currentUser, setCurrentUser] = createSignal(undefined) - createEffect(() => { - setCurrentUser(session()?.user?.slug) - }) + const { session } = useSession() + const currentSession = createMemo(() => session) const handleOpenChat = async () => { try { const test = await apiClient.createChat({ title: 'test chat', - members: [props.author.slug, currentUser()] + members: [props.author.slug, currentSession().user.slug] }) console.log('!!! test:', test) - } catch (err) { - console.log('!!! errr:', err) + } catch (error) { + console.log('!!! errr:', error) } } diff --git a/src/components/Inbox/Search.module.scss b/src/components/Inbox/Search.module.scss index 2808aba0..207ad6a6 100644 --- a/src/components/Inbox/Search.module.scss +++ b/src/components/Inbox/Search.module.scss @@ -1,7 +1,7 @@ .Search { .field { position: relative; - background: #ffffff; + background: #fff; border: 2px solid #e8e8e8; border-radius: 2px; overflow: hidden; @@ -22,8 +22,10 @@ color: #858585; font-family: inherit; } + &:focus { outline: none; + & + .icon { opacity: 0; right: -30px; diff --git a/src/components/Nav/ProfileModal.tsx b/src/components/Nav/ProfileModal.tsx index ddfabe87..d67cda93 100644 --- a/src/components/Nav/ProfileModal.tsx +++ b/src/components/Nav/ProfileModal.tsx @@ -18,7 +18,6 @@ export const ProfileModal = () => { const author = createMemo(() => { const a: Author = { - id: null, name: 'anonymous', userpic: '', slug: '' diff --git a/src/components/Pages/ArticlePage.tsx b/src/components/Pages/ArticlePage.tsx index e7877680..460a7f5f 100644 --- a/src/components/Pages/ArticlePage.tsx +++ b/src/components/Pages/ArticlePage.tsx @@ -1,14 +1,14 @@ import { PageWrap } from '../_shared/PageWrap' import { ArticleView } from '../Views/Article' import type { PageProps } from '../types' -import { loadArticle, useArticlesStore } from '../../stores/zine/articles' +import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles' import { createMemo, onMount, Show } from 'solid-js' import type { Shout } from '../../graphql/types.gen' import { useRouter } from '../../stores/router' import { Loading } from '../Loading' export const ArticlePage = (props: PageProps) => { - const sortedArticles = props.article ? [props.article] : [] + const shouts = props.article ? [props.article] : [] const slug = createMemo(() => { const { page: getPage } = useRouter() @@ -23,16 +23,16 @@ export const ArticlePage = (props: PageProps) => { }) const { articleEntities } = useArticlesStore({ - sortedArticles + shouts }) const article = createMemo(() => articleEntities()[slug()]) - onMount(() => { + onMount(async () => { const articleValue = articleEntities()[slug()] if (!articleValue || !articleValue.body) { - loadArticle({ slug: slug() }) + await loadShoutsBy({ by: { slug: slug() }, limit: 1, offset: 0 }) } }) diff --git a/src/components/Pages/AuthorPage.tsx b/src/components/Pages/AuthorPage.tsx index d8f7f755..7bde9aaa 100644 --- a/src/components/Pages/AuthorPage.tsx +++ b/src/components/Pages/AuthorPage.tsx @@ -2,7 +2,7 @@ import { PageWrap } from '../_shared/PageWrap' import { AuthorView, PRERENDERED_ARTICLES_COUNT } from '../Views/Author' import type { PageProps } from '../types' import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' -import { loadAuthorArticles, resetSortedArticles } from '../../stores/zine/articles' +import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles' import { useRouter } from '../../stores/router' import { loadAuthor } from '../../stores/zine/authors' import { Loading } from '../Loading' @@ -27,7 +27,7 @@ export const AuthorPage = (props: PageProps) => { return } - await loadAuthorArticles({ authorSlug: slug(), limit: PRERENDERED_ARTICLES_COUNT }) + await loadShoutsBy({ by: { author: slug() }, limit: PRERENDERED_ARTICLES_COUNT }) await loadAuthor({ slug: slug() }) setIsLoaded(true) @@ -38,7 +38,7 @@ export const AuthorPage = (props: PageProps) => { return ( }> - + ) diff --git a/src/components/Pages/HomePage.tsx b/src/components/Pages/HomePage.tsx index f29a8111..1522db48 100644 --- a/src/components/Pages/HomePage.tsx +++ b/src/components/Pages/HomePage.tsx @@ -2,7 +2,7 @@ import { HomeView, PRERENDERED_ARTICLES_COUNT } from '../Views/Home' import { PageWrap } from '../_shared/PageWrap' import type { PageProps } from '../types' import { createSignal, onCleanup, onMount, Show } from 'solid-js' -import { loadPublishedArticles, resetSortedArticles } from '../../stores/zine/articles' +import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles' import { loadRandomTopics } from '../../stores/zine/topics' import { Loading } from '../Loading' @@ -14,7 +14,7 @@ export const HomePage = (props: PageProps) => { return } - await loadPublishedArticles({ limit: PRERENDERED_ARTICLES_COUNT, offset: 0 }) + await loadShoutsBy({ by: { visibility: 'public' }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 }) await loadRandomTopics() setIsLoaded(true) @@ -25,7 +25,7 @@ export const HomePage = (props: PageProps) => { return ( }> - + ) diff --git a/src/components/Pages/SearchPage.tsx b/src/components/Pages/SearchPage.tsx index 84d3547d..aabf7214 100644 --- a/src/components/Pages/SearchPage.tsx +++ b/src/components/Pages/SearchPage.tsx @@ -2,7 +2,7 @@ import { PageWrap } from '../_shared/PageWrap' import { SearchView } from '../Views/Search' import type { PageProps } from '../types' import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' -import { loadSearchResults, resetSortedArticles } from '../../stores/zine/articles' +import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles' import { useRouter } from '../../stores/router' import { Loading } from '../Loading' @@ -26,7 +26,7 @@ export const SearchPage = (props: PageProps) => { return } - await loadSearchResults({ query: q(), limit: 50, offset: 0 }) + await loadShoutsBy({ by: { title: q(), body: q() }, limit: 50, offset: 0 }) setIsLoaded(true) }) diff --git a/src/components/Pages/TopicPage.tsx b/src/components/Pages/TopicPage.tsx index 289dabd9..fc314cd7 100644 --- a/src/components/Pages/TopicPage.tsx +++ b/src/components/Pages/TopicPage.tsx @@ -2,7 +2,7 @@ import { PageWrap } from '../_shared/PageWrap' import { PRERENDERED_ARTICLES_COUNT, TopicView } from '../Views/Topic' import type { PageProps } from '../types' import { createMemo, createSignal, onCleanup, onMount, Show } from 'solid-js' -import { loadTopicArticles, resetSortedArticles } from '../../stores/zine/articles' +import { loadShoutsBy, resetSortedArticles } from '../../stores/zine/articles' import { useRouter } from '../../stores/router' import { loadTopic } from '../../stores/zine/topics' import { Loading } from '../Loading' @@ -27,7 +27,7 @@ export const TopicPage = (props: PageProps) => { return } - await loadTopicArticles({ topicSlug: slug(), limit: PRERENDERED_ARTICLES_COUNT, offset: 0 }) + await loadShoutsBy({ by: { topics: [slug()] }, limit: PRERENDERED_ARTICLES_COUNT, offset: 0 }) await loadTopic({ slug: slug() }) setIsLoaded(true) @@ -38,7 +38,7 @@ export const TopicPage = (props: PageProps) => { return ( }> - + ) diff --git a/src/components/Views/Author.tsx b/src/components/Views/Author.tsx index 2114ce1b..ff4d47c7 100644 --- a/src/components/Views/Author.tsx +++ b/src/components/Views/Author.tsx @@ -5,7 +5,7 @@ import { Row3 } from '../Feed/Row3' import { AuthorFull } from '../Author/Full' import { t } from '../../utils/intl' import { useAuthorsStore } from '../../stores/zine/authors' -import { loadAuthorArticles, useArticlesStore } from '../../stores/zine/articles' +import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles' import { useTopicsStore } from '../../stores/zine/topics' import { useRouter } from '../../stores/router' @@ -15,7 +15,7 @@ import { splitToPages } from '../../utils/splitToPages' // TODO: load reactions on client type AuthorProps = { - authorArticles: Shout[] + shouts: Shout[] author: Author authorSlug: string // FIXME author topics fro server @@ -31,7 +31,7 @@ const LOAD_MORE_PAGE_SIZE = 9 // Row3 + Row3 + Row3 export const AuthorView = (props: AuthorProps) => { const { sortedArticles } = useArticlesStore({ - sortedArticles: props.authorArticles + shouts: props.shouts }) const { authorEntities } = useAuthorsStore({ authors: [props.author] }) const { topicsByAuthor } = useTopicsStore() @@ -42,8 +42,8 @@ export const AuthorView = (props: AuthorProps) => { const loadMore = async () => { saveScrollPosition() - const { hasMore } = await loadAuthorArticles({ - authorSlug: author().slug, + const { hasMore } = await loadShoutsBy({ + by: { author: author().slug }, limit: LOAD_MORE_PAGE_SIZE, offset: sortedArticles().length }) diff --git a/src/components/Views/Feed.tsx b/src/components/Views/Feed.tsx index bb7b7fe8..62681044 100644 --- a/src/components/Views/Feed.tsx +++ b/src/components/Views/Feed.tsx @@ -9,7 +9,7 @@ import { AuthorCard } from '../Author/Card' import { t } from '../../utils/intl' import { FeedSidebar } from '../Feed/Sidebar' import CommentCard from '../Article/Comment' -import { loadRecentArticles, useArticlesStore } from '../../stores/zine/articles' +import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles' import { useReactionsStore } from '../../stores/zine/reactions' import { useAuthorsStore } from '../../stores/zine/authors' import { useTopicsStore } from '../../stores/zine/topics' @@ -52,7 +52,11 @@ export const FeedView = () => { // }) const loadMore = async () => { - const { hasMore } = await loadRecentArticles({ limit: FEED_PAGE_SIZE, offset: sortedArticles().length }) + const { hasMore } = await loadShoutsBy({ + by: { visibility: 'community' }, + limit: FEED_PAGE_SIZE, + offset: sortedArticles().length + }) setIsLoadMoreButtonVisible(hasMore) } diff --git a/src/components/Views/Home.tsx b/src/components/Views/Home.tsx index d8dd693f..d3823320 100644 --- a/src/components/Views/Home.tsx +++ b/src/components/Views/Home.tsx @@ -14,12 +14,7 @@ import type { Shout, Topic } from '../../graphql/types.gen' import { Icon } from '../_shared/Icon' import { t } from '../../utils/intl' import { useTopicsStore } from '../../stores/zine/topics' -import { - loadPublishedArticles, - loadTopArticles, - loadTopMonthArticles, - useArticlesStore -} from '../../stores/zine/articles' +import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles' import { useTopAuthorsStore } from '../../stores/zine/topAuthors' import { locale } from '../../stores/ui' import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll' @@ -27,7 +22,7 @@ import { splitToPages } from '../../utils/splitToPages' type HomeProps = { randomTopics: Topic[] - recentPublishedArticles: Shout[] + shouts: Shout[] } export const PRERENDERED_ARTICLES_COUNT = 5 @@ -37,26 +32,24 @@ const LOAD_MORE_PAGE_SIZE = 16 // Row1 + Row3 + Row2 + Beside (3 + 1) + Row1 + R export const HomeView = (props: HomeProps) => { const { sortedArticles, + articlesByLayout, topArticles, - topMonthArticles, - topViewedArticles, topCommentedArticles, - articlesByLayout + topMonthArticles, + topViewedArticles } = useArticlesStore({ - sortedArticles: props.recentPublishedArticles + shouts: props.shouts }) const { randomTopics, topTopics } = useTopicsStore({ randomTopics: props.randomTopics }) const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) - const { topAuthors } = useTopAuthorsStore() onMount(async () => { - loadTopArticles() - loadTopMonthArticles() if (sortedArticles().length < PRERENDERED_ARTICLES_COUNT + CLIENT_LOAD_ARTICLES_COUNT) { - const { hasMore } = await loadPublishedArticles({ + const { hasMore } = await loadShoutsBy({ + by: {}, limit: CLIENT_LOAD_ARTICLES_COUNT, offset: sortedArticles().length }) @@ -91,7 +84,8 @@ export const HomeView = (props: HomeProps) => { const loadMore = async () => { saveScrollPosition() - const { hasMore } = await loadPublishedArticles({ + const { hasMore } = await loadShoutsBy({ + by: { visibility: 'public' }, limit: LOAD_MORE_PAGE_SIZE, offset: sortedArticles().length }) diff --git a/src/components/Views/Search.tsx b/src/components/Views/Search.tsx index a899cde8..b63dffd8 100644 --- a/src/components/Views/Search.tsx +++ b/src/components/Views/Search.tsx @@ -3,7 +3,7 @@ import '../../styles/Search.scss' import type { Shout } from '../../graphql/types.gen' import { ArticleCard } from '../Feed/Card' import { t } from '../../utils/intl' -import { useArticlesStore, loadSearchResults } from '../../stores/zine/articles' +import { useArticlesStore, loadShoutsBy } from '../../stores/zine/articles' import { handleClientRouteLinkClick, useRouter } from '../../stores/router' type SearchPageSearchParams = { @@ -16,7 +16,7 @@ type Props = { } export const SearchView = (props: Props) => { - const { sortedArticles } = useArticlesStore({ sortedArticles: props.results }) + const { sortedArticles } = useArticlesStore({ shouts: props.results }) const [getQuery, setQuery] = createSignal(props.query) const { searchParams } = useRouter() @@ -28,7 +28,7 @@ export const SearchView = (props: Props) => { const handleSubmit = (_ev) => { // TODO page // TODO sort - loadSearchResults({ query: getQuery() }) + loadShoutsBy({ by: { title: getQuery(), body: getQuery() }, limit: 50 }) } return ( diff --git a/src/components/Views/Topic.tsx b/src/components/Views/Topic.tsx index fca408f4..81316cd6 100644 --- a/src/components/Views/Topic.tsx +++ b/src/components/Views/Topic.tsx @@ -8,7 +8,7 @@ import { FullTopic } from '../Topic/Full' import { t } from '../../utils/intl' import { useRouter } from '../../stores/router' import { useTopicsStore } from '../../stores/zine/topics' -import { loadTopicArticles, useArticlesStore } from '../../stores/zine/articles' +import { loadShoutsBy, useArticlesStore } from '../../stores/zine/articles' import { useAuthorsStore } from '../../stores/zine/authors' import { restoreScrollPosition, saveScrollPosition } from '../../utils/scroll' import { splitToPages } from '../../utils/splitToPages' @@ -22,7 +22,7 @@ type TopicsPageSearchParams = { interface TopicProps { topic: Topic - topicArticles: Shout[] + shouts: Shout[] topicSlug: string } @@ -34,7 +34,7 @@ export const TopicView = (props: TopicProps) => { const [isLoadMoreButtonVisible, setIsLoadMoreButtonVisible] = createSignal(false) - const { sortedArticles } = useArticlesStore({ sortedArticles: props.topicArticles }) + const { sortedArticles } = useArticlesStore({ shouts: props.shouts }) const { topicEntities } = useTopicsStore({ topics: [props.topic] }) const { authorsByTopic } = useAuthorsStore() @@ -44,8 +44,8 @@ export const TopicView = (props: TopicProps) => { const loadMore = async () => { saveScrollPosition() - const { hasMore } = await loadTopicArticles({ - topicSlug: topic().slug, + const { hasMore } = await loadShoutsBy({ + by: { topic: topic().slug }, limit: LOAD_MORE_PAGE_SIZE, offset: sortedArticles().length }) diff --git a/src/graphql/mutation/increment-view.ts b/src/graphql/mutation/increment-view.ts deleted file mode 100644 index 14c84b69..00000000 --- a/src/graphql/mutation/increment-view.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { gql } from '@urql/core' - -export default gql` - mutation IncrementViewMutation($shout: String!) { - incrementView(shout: $shout) { - error - } - } -` diff --git a/src/graphql/types.gen.ts b/src/graphql/types.gen.ts index b8ebab27..708b4194 100644 --- a/src/graphql/types.gen.ts +++ b/src/graphql/types.gen.ts @@ -494,6 +494,7 @@ export type ReactionBy = { days?: InputMaybe order?: InputMaybe shout?: InputMaybe + shouts?: InputMaybe>> stat?: InputMaybe topic?: InputMaybe } @@ -618,6 +619,7 @@ export type ShoutsBy = { stat?: InputMaybe title?: InputMaybe topic?: InputMaybe + topics?: InputMaybe>> visibility?: InputMaybe } diff --git a/src/pages/[...slug].astro b/src/pages/[...slug].astro index 49621307..7d9f337e 100644 --- a/src/pages/[...slug].astro +++ b/src/pages/[...slug].astro @@ -9,7 +9,7 @@ if (slug.endsWith('.map')) { return Astro.redirect('/404') } -const article = await apiClient.getArticle({ slug }) +const article = await apiClient.loadShoutsBy({ by: { slug }, amount: 1}) if (!article) { return Astro.redirect('/404') } @@ -21,5 +21,5 @@ Astro.response.headers.set('Cache-Control', 's-maxage=1, stale-while-revalidate' --- - + diff --git a/src/pages/author/[slug]/index.astro b/src/pages/author/[slug]/index.astro index 7316a87f..30ebeb87 100644 --- a/src/pages/author/[slug]/index.astro +++ b/src/pages/author/[slug]/index.astro @@ -6,8 +6,8 @@ import { initRouter } from '../../../stores/router' import { PRERENDERED_ARTICLES_COUNT } from '../../../components/Views/Author' const slug = Astro.params.slug.toString() -const shouts = await apiClient.getArticlesForAuthors({ authorSlugs: [slug], limit: PRERENDERED_ARTICLES_COUNT }) -const author = await apiClient.getAuthor({ slug }) +const shouts = await apiClient.loadShoutsBy({ by: { authors: [slug] } , amount: PRERENDERED_ARTICLES_COUNT }) +const author = await apiClient.loadAuthorsBy({ by: { slug } }) const { pathname, search } = Astro.url initRouter(pathname, search) diff --git a/src/pages/expo/[...layout].astro b/src/pages/expo/[...layout].astro index 0516163b..858bbf01 100644 --- a/src/pages/expo/[...layout].astro +++ b/src/pages/expo/[...layout].astro @@ -10,7 +10,7 @@ const layout = (Astro.params.layout?.toString() || 'article') as LayoutType if (!layout || layout.endsWith('.map')) { return Astro.redirect('/404') } -const shouts = await apiClient.getRecentLayoutShouts({ layout }) +const shouts = await apiClient.loadShoutsBy({ by: { layout } }) const { pathname, search } = Astro.url initRouter(pathname, search) --- diff --git a/src/pages/index.astro b/src/pages/index.astro index d83c2c50..1c1ecff7 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -6,7 +6,8 @@ import { initRouter } from '../stores/router' import { PRERENDERED_ARTICLES_COUNT } from '../components/Views/Home' const randomTopics = await apiClient.getRandomTopics({ amount: 12 }) -const articles = await apiClient.getRecentPublishedArticles({ limit: PRERENDERED_ARTICLES_COUNT }) +const articles = await apiClient.loadShoutsBy( + { by: { visibility: "public" }, amount: PRERENDERED_ARTICLES_COUNT, offset: 0 }) const { pathname, search } = Astro.url initRouter(pathname, search) diff --git a/src/pages/search.astro b/src/pages/search.astro index 4ce22e04..5107c7b6 100644 --- a/src/pages/search.astro +++ b/src/pages/search.astro @@ -6,7 +6,7 @@ import { initRouter } from '../stores/router' const params: URLSearchParams = Astro.url.searchParams const q = params.get('q') -const searchResults = await apiClient.getSearchResults({ query: q, limit: 50 }) +const searchResults = await apiClient.loadShoutsBy({ by: { title: q, body: q }, amount: 50 }) const { pathname, search } = Astro.url initRouter(pathname, search) diff --git a/src/pages/topic/[slug].astro b/src/pages/topic/[slug].astro index 491c30fa..2f780e86 100644 --- a/src/pages/topic/[slug].astro +++ b/src/pages/topic/[slug].astro @@ -5,7 +5,7 @@ import { apiClient } from '../../utils/apiClient' import { PRERENDERED_ARTICLES_COUNT } from '../../components/Views/Topic' const slug = Astro.params.slug?.toString() || '' -const shouts = await apiClient.getArticlesForTopics({ topicSlugs: [slug], limit: PRERENDERED_ARTICLES_COUNT }) +const shouts = await apiClient.loadShoutsBy({ by: { topics: [slug] }, amount: PRERENDERED_ARTICLES_COUNT }) const topic = await apiClient.getTopic({ slug }) import { initRouter } from '../../stores/router' diff --git a/src/stores/zine/articles.ts b/src/stores/zine/articles.ts index a7ac1eee..5955c11d 100644 --- a/src/stores/zine/articles.ts +++ b/src/stores/zine/articles.ts @@ -1,4 +1,4 @@ -import type { Author, Shout, ShoutInput, Topic } from '../../graphql/types.gen' +import type { Author, Shout, ShoutInput, ShoutsBy, Topic } from '../../graphql/types.gen' import { apiClient } from '../../utils/apiClient' import { addAuthorsByTopic } from './authors' import { addTopicsByAuthor } from './topics' @@ -123,96 +123,18 @@ const addSortedArticles = (articles: Shout[]) => { setSortedArticles((prevSortedArticles) => [...prevSortedArticles, ...articles]) } -export const loadFeed = async ({ - limit, - offset -}: { - limit: number - offset?: number -}): Promise<{ hasMore: boolean }> => { - // TODO: load actual feed - return await loadRecentArticles({ limit, offset }) -} - -export const loadRecentArticles = async ({ - limit, - offset -}: { - limit: number - offset?: number -}): Promise<{ hasMore: boolean }> => { - const newArticles = await apiClient.getRecentArticles({ limit: limit + 1, offset }) - const hasMore = newArticles.length === limit + 1 - - if (hasMore) { - newArticles.splice(-1) - } - - addArticles(newArticles) - addSortedArticles(newArticles) - - return { hasMore } -} - -export const loadPublishedArticles = async ({ +export const loadShoutsBy = async ({ + by, limit, offset = 0 }: { + by: ShoutsBy limit: number offset?: number }): Promise<{ hasMore: boolean }> => { - const newArticles = await apiClient.getPublishedArticles({ limit: limit + 1, offset }) - const hasMore = newArticles.length === limit + 1 - - if (hasMore) { - newArticles.splice(-1) - } - - addArticles(newArticles) - addSortedArticles(newArticles) - - return { hasMore } -} - -export const loadAuthorArticles = async ({ - authorSlug, - limit, - offset = 0 -}: { - authorSlug: string - limit: number - offset?: number -}): Promise<{ hasMore: boolean }> => { - const newArticles = await apiClient.getArticlesForAuthors({ - authorSlugs: [authorSlug], - limit: limit + 1, - offset - }) - - const hasMore = newArticles.length === limit + 1 - - if (hasMore) { - newArticles.splice(-1) - } - - addArticles(newArticles) - addSortedArticles(newArticles) - - return { hasMore } -} - -export const loadTopicArticles = async ({ - topicSlug, - limit, - offset -}: { - topicSlug: string - limit: number - offset: number -}): Promise<{ hasMore: boolean }> => { - const newArticles = await apiClient.getArticlesForTopics({ - topicSlugs: [topicSlug], - limit: limit + 1, + const newArticles = await apiClient.loadShoutsBy({ + by, + amount: limit + 1, offset }) @@ -232,46 +154,6 @@ export const resetSortedArticles = () => { setSortedArticles([]) } -export const loadTopMonthArticles = async (): Promise => { - const articles = await apiClient.getTopMonthArticles() - addArticles(articles) - setTopMonthArticles(articles) -} - -export const loadTopArticles = async (): Promise => { - const articles = await apiClient.getTopArticles() - addArticles(articles) - setTopArticles(articles) -} - -export const loadSearchResults = async ({ - query, - limit, - offset -}: { - query: string - limit?: number - offset?: number -}): Promise => { - const newArticles = await apiClient.getSearchResults({ query, limit, offset }) - addArticles(newArticles) - addSortedArticles(newArticles) -} - -export const incrementView = async ({ articleSlug }: { articleSlug: string }): Promise => { - await apiClient.incrementView({ articleSlug }) -} - -export const loadArticle = async ({ slug }: { slug: string }): Promise => { - const article = await apiClient.getArticle({ slug }) - - if (!article) { - throw new Error(`Can't load article, slug: "${slug}"`) - } - - addArticles([article]) -} - export const createArticle = async ({ article }: { article: ShoutInput }) => { try { await apiClient.createArticle({ article }) @@ -281,27 +163,26 @@ export const createArticle = async ({ article }: { article: ShoutInput }) => { } type InitialState = { - sortedArticles?: Shout[] - topRatedArticles?: Shout[] - topRatedMonthArticles?: Shout[] + shouts?: Shout[] } export const useArticlesStore = (initialState: InitialState = {}) => { - addArticles([...(initialState.sortedArticles || [])]) + addArticles([...(initialState.shouts || [])]) - if (initialState.sortedArticles) { - setSortedArticles([...initialState.sortedArticles]) + if (initialState.shouts) { + setSortedArticles([...initialState.shouts]) } return { articleEntities, sortedArticles, - articlesByTopic, + loadShoutsBy, articlesByAuthor, - topArticles, + articlesByLayout, + articlesByTopic, topMonthArticles, - topViewedArticles, + topArticles, topCommentedArticles, - articlesByLayout + topViewedArticles } } diff --git a/src/stores/zine/layouts.ts b/src/stores/zine/layouts.ts index b13521ba..aff62841 100644 --- a/src/stores/zine/layouts.ts +++ b/src/stores/zine/layouts.ts @@ -32,11 +32,11 @@ export const loadRecentLayoutShouts = async ({ amount: number offset?: number }): Promise<{ hasMore: boolean }> => { - const layoutShouts: Shout[] = await apiClient.getRecentLayoutShouts({ layout, amount, offset }) + const layoutShouts: Shout[] = await apiClient.loadShoutsBy({ by: { layout }, amount, offset }) const hasMore = layoutShouts.length < amount if (hasMore) layoutShouts.splice(-1) - const sortedArticles = layoutShouts.sort(byCreated) - const { articlesByLayout } = useArticlesStore({ sortedArticles }) + const shouts = layoutShouts.sort(byCreated) + const { articlesByLayout } = useArticlesStore({ shouts }) addLayoutShouts(layout, articlesByLayout()[layout]) return { hasMore } } @@ -46,7 +46,7 @@ export const loadTopMonthLayoutShouts = async ( amount: number, offset: number ): Promise<{ hasMore: boolean }> => { - const shouts = await apiClient.getTopMonthLayoutShouts({ layout }) + const shouts = await apiClient.loadShoutsBy({ by: { layout, stat: 'rating', days: 30 } }) const hasMore = shouts.length < amount if (hasMore) shouts.splice(-1) addLayoutShouts(layout, shouts) @@ -58,14 +58,14 @@ export const loadTopLayoutShouts = async ( amount, offset ): Promise<{ hasMore: boolean }> => { - const shouts = await apiClient.getTopLayoutShouts({ layout }) + const shouts = await apiClient.loadShoutsBy({ by: { layout, stat: 'rating' } }) const hasMore = shouts.length < amount if (hasMore) shouts.splice(-1) addLayoutShouts(layout, shouts) return { hasMore } } -export const loadSearchResults = async ({ +export const loadShoutsSearch = async ({ layout, query, limit, @@ -76,25 +76,21 @@ export const loadSearchResults = async ({ limit?: number offset?: number }): Promise => { - const newLayoutShouts = await apiClient.getSearchResults({ layout, query, limit, offset }) + const by = { + layout: layout, + query: query + } + const amount = limit + const newLayoutShouts = await apiClient.loadShoutsBy({ by, amount, offset }) addLayoutShouts(layout, newLayoutShouts) } -type InitialState = { - sortedLayoutShouts?: Shout[] - topRatedLayoutShouts?: Shout[] - topRatedMonthLayoutShouts?: Shout[] -} - export const useLayoutsStore = (layout: LayoutType, initialData: Shout[]) => { addLayoutShouts(layout, initialData || []) return { addLayoutShouts, sortedLayoutShouts, - loadSearchResults, - loadRecentLayoutShouts, - loadTopMonthLayoutShouts, - loadTopLayoutShouts + loadShoutsSearch } } diff --git a/src/stores/zine/reactions.ts b/src/stores/zine/reactions.ts index 63273a09..9e66faac 100644 --- a/src/stores/zine/reactions.ts +++ b/src/stores/zine/reactions.ts @@ -6,6 +6,8 @@ import { reduceBy } from '../../utils/reduce' // import { roomConnect } from '../../utils/p2p' // FIXME +export const REACTIONS_AMOUNT_PER_PAGE = 100 + let reactionsOrdered: WritableAtom export const reactions = atom<{ [slug: string]: Reaction[] }>({}) // by shout @@ -19,14 +21,14 @@ export const useReactionsStore = (initial?: Reaction[]) => { export const loadArticleReactions = async ({ articleSlug, - limit = 100, + limit = REACTIONS_AMOUNT_PER_PAGE, offset = 0 }: { articleSlug: string limit?: number offset?: number }): Promise => { - const data = await apiClient.getReactionsForShouts({ shoutSlugs: [articleSlug], limit, offset }) + const data = await apiClient.loadReactionsBy({ by: { shout: articleSlug }, amount: limit, offset }) // TODO: const [data, provider] = roomConnect(articleSlug, username, "reactions") reactionsOrdered.set(data) } @@ -40,7 +42,11 @@ export const loadReactions = async ({ limit: number offset: number }): Promise => { - const reactionsForShouts = await apiClient.getReactionsForShouts({ shoutSlugs, limit, offset }) + const reactionsForShouts = await apiClient.loadReactionsBy({ + by: { shouts: shoutSlugs }, + amount: limit, + offset + }) reactionsOrdered.set(reactionsForShouts) } diff --git a/src/styles/Inbox.scss b/src/styles/Inbox.scss index 581f29db..59e2b3c5 100644 --- a/src/styles/Inbox.scss +++ b/src/styles/Inbox.scss @@ -4,6 +4,7 @@ main { flex-direction: column; position: relative; } + // TODO: добавлять когда открыт чат body { overflow: hidden; @@ -35,6 +36,7 @@ body { position: relative; } } + // список диалогов и юзеров .chat-list { display: flex; @@ -43,6 +45,7 @@ body { height: calc(100% - 10px); $fade-height: 10px; + .holder { overflow: hidden; flex: 1; @@ -63,6 +66,7 @@ body { top: 0; background: linear-gradient(white, transparent $fade-height); } + &::after { bottom: 0; background: linear-gradient(transparent, white $fade-height); @@ -93,7 +97,9 @@ body { // табы выбора списка .chat-list__types { @include font-size(1.7rem); + margin: 16px 0; + ul { display: flex; flex-wrap: wrap; @@ -243,7 +249,6 @@ body { .conversation__message { font-size: 14px; - max-width: 60%; border-radius: 16px; padding: 12px 16px; diff --git a/src/utils/apiClient.ts b/src/utils/apiClient.ts index e05dc69c..3d860197 100644 --- a/src/utils/apiClient.ts +++ b/src/utils/apiClient.ts @@ -10,7 +10,6 @@ import type { import { publicGraphQLClient } from '../graphql/publicGraphQLClient' import { getToken, privateGraphQLClient } from '../graphql/privateGraphQLClient' import topicsAll from '../graphql/query/topics-all' -import reactionsForShouts from '../graphql/query/reactions-load-by' import mySession from '../graphql/mutation/my-session' import authLogoutQuery from '../graphql/mutation/auth-logout' import authLoginQuery from '../graphql/query/auth-login' @@ -25,7 +24,6 @@ import authorsAll from '../graphql/query/authors-all' import reactionCreate from '../graphql/mutation/reaction-create' import reactionDestroy from '../graphql/mutation/reaction-destroy' import reactionUpdate from '../graphql/mutation/reaction-update' -import incrementView from '../graphql/mutation/increment-view' import createArticle from '../graphql/mutation/article-create' import myChats from '../graphql/query/chats-load' import loadChat from '../graphql/query/chat-messages-load-by' @@ -35,6 +33,7 @@ import shoutsLoadBy from '../graphql/query/articles-load-by' import reactionsLoadBy from '../graphql/query/reactions-load-by' import authorsLoadBy from '../graphql/query/authors-load-by' import createChatQuery from '../graphql/mutation/create-chat' +import { REACTIONS_AMOUNT_PER_PAGE } from '../stores/zine/reactions' const FEED_SIZE = 50 @@ -148,37 +147,6 @@ export const apiClient = { return response.data.confirmEmail }, - getTopArticles: async () => { - const by = { - stat: 'rating', - visibility: 'public' - } - const response = await publicGraphQLClient.query(shoutsLoadBy, { by, limit: 10, offset: 0 }).toPromise() - return response.data.loadShoutsBy - }, - getTopMonthArticles: async () => { - const by = { - stat: 'rating', - visibility: 'public', - days: 30 - } - const response = await publicGraphQLClient.query(shoutsLoadBy, { by, limit: 10, offset: 0 }).toPromise() - return response.data.loadShoutsBy - }, - getRecentPublishedArticles: async ({ - limit = FEED_SIZE, - offset = 0 - }: { - limit?: number - offset?: number - }) => { - const by = { - visibility: 'public' - } - const response = await publicGraphQLClient.query(shoutsLoadBy, { by, limit, offset }).toPromise() - - return response.data.loadShoutsBy - }, getRandomTopics: async ({ amount }: { amount: number }) => { const response = await publicGraphQLClient.query(topicsRandomQuery, { amount }).toPromise() @@ -188,100 +156,6 @@ export const apiClient = { return response.data.topicsRandom }, - getSearchResults: async ({ - query, - limit = FEED_SIZE, - offset = 0 - }: { - query: string - limit: number - offset?: number - }): Promise => { - const by = { - title: query, - body: query - } - const response = await publicGraphQLClient - .query(shoutsLoadBy, { - by, - limit, - offset - }) - .toPromise() - - return response.data?.searchQuery || [] - }, - getRecentArticles: async ({ - limit = FEED_SIZE, - offset = 0 - }: { - limit: number - offset?: number - }): Promise => { - const response = await publicGraphQLClient - .query(shoutsLoadBy, { - by: {}, - limit, - offset - }) - .toPromise() - - return response.data.recentAll - }, - getArticlesForTopics: async ({ - topicSlugs, - limit, - offset = 0 - }: { - topicSlugs: string[] - limit: number - offset?: number - }): Promise => { - const by = { - topics: topicSlugs, - visibility: 'public' - } - const response = await publicGraphQLClient - .query(shoutsLoadBy, { - by, - limit, - offset - }) - .toPromise() - - if (response.error) { - console.error('[api-client] getArticlesForTopics', response.error) - } - - return response.data.shoutsByTopics - }, - getArticlesForAuthors: async ({ - authorSlugs, - limit, - offset = 0 - }: { - authorSlugs: string[] - limit: number - offset?: number - }): Promise => { - const by = { - authors: authorSlugs, - visibility: 'public' - } - const vars = { - by, - limit, - offset - } - // console.debug(vars) - const response = await publicGraphQLClient.query(shoutsLoadBy, vars).toPromise() - - if (response.error) { - console.error('[api-client] getArticlesForAuthors', response.error) - } - - return response.data.shoutsByAuthors - }, // subscribe @@ -312,18 +186,6 @@ export const apiClient = { return response.data.refreshSession }, - getPublishedArticles: async ({ limit = FEED_SIZE, offset }: { limit?: number; offset?: number }) => { - const by = { - visibility: 'public' - } - const response = await publicGraphQLClient.query(shoutsLoadBy, { by, limit, offset }).toPromise() - - if (response.error) { - console.error('[api-client] getPublishedArticles', response.error) - } - - return response.data.recentPublished - }, getAllTopics: async () => { const response = await publicGraphQLClient.query(topicsAll, {}).toPromise() if (response.error) { @@ -346,34 +208,6 @@ export const apiClient = { const response = await publicGraphQLClient.query(topicBySlug, { slug }).toPromise() return response.data.getTopic }, - getArticle: async ({ slug }: { slug: string }): Promise => { - const response = await publicGraphQLClient - .query(shoutsLoadBy, { by: { slug }, amount: 1, offset: 0 }) - .toPromise() - return response.data?.getShoutBySlug - }, - - // reactions - - getReactionsForShouts: async ({ - shoutSlugs, - limit = FEED_SIZE, - offset = 0 - }: { - shoutSlugs: string[] - limit?: number - offset?: number - }): Promise => { - const response = await publicGraphQLClient - .query(reactionsForShouts, { - shouts: shoutSlugs, - limit, - offset - }) - .toPromise() - - return response.data.reactionsForShouts - }, createArticle: async ({ article }: { article: ShoutInput }) => { const response = await privateGraphQLClient.mutation(createArticle, { shout: article }).toPromise() console.debug('createArticle response:', response) @@ -394,9 +228,6 @@ export const apiClient = { return response.data.deleteReaction }, - incrementView: async ({ articleSlug }) => { - await privateGraphQLClient.mutation(incrementView, { shout: articleSlug }) - }, createChat: async ({ title, members }) => { return await privateGraphQLClient .mutation(createChatQuery, { title: title, members: members }) @@ -407,31 +238,17 @@ export const apiClient = { const resp = await privateGraphQLClient.query(myChats, payload).toPromise() return resp.data.myChats }, - getRecentLayoutShouts: async ({ layout = 'article', amount = 50, offset = 0 }) => { - const by = { - layout - } - const resp = await publicGraphQLClient.query(shoutsLoadBy, { by, amount, offset }).toPromise() - return resp.data.recentLayoutShouts + loadAuthorsBy: async ({ by, amount = 50, offset = 0 }) => { + const resp = await publicGraphQLClient.query(authorsLoadBy, { by, amount, offset }).toPromise() + return resp.data.loadShoutsBy }, - getTopLayoutShouts: async ({ layout = 'article', amount = 50, offset = 0 }) => { - const by = { - layout, - stat: 'rating', - order: 'rating' - } + loadShoutsBy: async ({ by, amount = 50, offset = 0 }) => { const resp = await publicGraphQLClient.query(shoutsLoadBy, { by, amount, offset }).toPromise() - return resp.data.topLayoutShouts + return resp.data.loadShoutsBy }, - getTopMonthLayoutShouts: async ({ layout = 'article', amount = 50, offset = 0 }) => { - const by = { - layout, - stat: 'rating', - order: 'rating', - days: 30 - } - const resp = await publicGraphQLClient.query(shoutsLoadBy, { amount, offset, layout }).toPromise() - return resp.data.topMonthLayoutShouts + loadReactionsBy: async ({ by, amount = REACTIONS_AMOUNT_PER_PAGE, offset = 0 }) => { + const resp = await publicGraphQLClient.query(reactionsLoadBy, { by, amount, offset }).toPromise() + return resp.data.loadReactionsBy }, getChatMessages: async ({ chat, diff --git a/src/utils/config.ts b/src/utils/config.ts index 8501f5bd..68aa58b1 100644 --- a/src/utils/config.ts +++ b/src/utils/config.ts @@ -1,6 +1,6 @@ export const isDev = import.meta.env.MODE === 'development' -export const apiBaseUrl = 'https://testapi.discours.io' +//export const apiBaseUrl = 'https://testapi.discours.io' // export const apiBaseUrl = 'https://newapi.discours.io' // testapi.discours.io -// export const apiBaseUrl = 'http://localhost:8080' +export const apiBaseUrl = 'http://localhost:8080'