diff --git a/packages/web/lib/networking/queries/useGetArticleQuery.tsx b/packages/web/lib/networking/queries/useGetArticleQuery.tsx index a75f5f72a..0d7422db2 100644 --- a/packages/web/lib/networking/queries/useGetArticleQuery.tsx +++ b/packages/web/lib/networking/queries/useGetArticleQuery.tsx @@ -1,11 +1,11 @@ import { gql } from 'graphql-request' -import useSWRImmutable from 'swr' -import useSWR from 'swr' +import useSWRImmutable, { Cache } from 'swr' import { makeGqlFetcher, RequestContext, ssrFetcher } from '../networkHelpers' import { articleFragment, ContentReader } from '../fragments/articleFragment' import { Highlight, highlightFragment } from '../fragments/highlightFragment' -import { KeyedMutator, ScopedMutator } from 'swr/dist/types' +import { ScopedMutator } from 'swr/dist/types' import { Label, labelFragment } from '../fragments/labelFragment' +import { LibraryItems } from './useGetLibraryItemsQuery' type ArticleQueryInput = { username?: string @@ -17,7 +17,6 @@ type ArticleQueryOutput = { articleData?: ArticleData articleFetchError: unknown isLoading: boolean - mutate: KeyedMutator } type ArticleData = { @@ -79,16 +78,7 @@ const query = gql` ${highlightFragment} ${labelFragment} ` -export const cacheArticle = ( - mutate: ScopedMutator, - username: string, - article: ArticleAttributes, - includeFriendsHighlights = false -) => { - mutate([query, username, article.slug, includeFriendsHighlights], { - article: { article: { ...article, cached: true } }, - }) -} + export function useGetArticleQuery({ username, @@ -101,7 +91,7 @@ export function useGetArticleQuery({ includeFriendsHighlights, } - const { data, error, mutate } = useSWR( + const { data, error, mutate } = useSWRImmutable( slug ? [query, username, slug, includeFriendsHighlights] : null, makeGqlFetcher(variables) ) @@ -118,7 +108,6 @@ export function useGetArticleQuery({ } return { - mutate, articleData: resultData, articleFetchError: resultError as unknown, isLoading: !error && !data, @@ -136,3 +125,46 @@ export async function articleQuery( return Promise.reject() } + +export const cacheArticle = ( + mutate: ScopedMutator, + username: string, + article: ArticleAttributes, + includeFriendsHighlights = false +) => { + mutate([query, username, article.slug, includeFriendsHighlights], { + article: { article: { ...article, cached: true } }, + }) +} + + +export const removeItemFromCache = ( + cache: Cache, + mutate: ScopedMutator, + itemId: string, +) => { + try { + const mappedCache = cache as Map + mappedCache.forEach((value: any, key) => { + if (typeof value == 'object' && 'articles' in value) { + const articles = value.articles as LibraryItems + const idx = articles.edges.findIndex((edge) => edge.node.id == itemId) + if (idx > -1) { + value.articles.edges.splice(idx, 1) + mutate(key, value, false) + } + } + }) + + mappedCache.forEach((value: any, key) => { + if (Array.isArray(value)) { + const idx = value.findIndex((item) => 'articles' in item) + if (idx > -1) { + mutate(key, value, false) + } + } + }) + } catch (error) { + console.log('error removing item from cache', error) + } +} diff --git a/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx b/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx index 3a761076e..ad02f5e96 100644 --- a/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx +++ b/packages/web/lib/networking/queries/useGetLibraryItemsQuery.tsx @@ -40,7 +40,7 @@ export type LibraryItemsData = { articles: LibraryItems } -type LibraryItems = { +export type LibraryItems = { edges: LibraryItem[] pageInfo: PageInfo errorCodes?: string[] diff --git a/packages/web/pages/[username]/[slug]/index.tsx b/packages/web/pages/[username]/[slug]/index.tsx index 7eb2c194e..dbfbb69d6 100644 --- a/packages/web/pages/[username]/[slug]/index.tsx +++ b/packages/web/pages/[username]/[slug]/index.tsx @@ -1,7 +1,7 @@ import { PrimaryLayout } from '../../../components/templates/PrimaryLayout' import { LoadingView } from '../../../components/patterns/LoadingView' import { useGetViewerQuery } from '../../../lib/networking/queries/useGetViewerQuery' -import { useGetArticleQuery } from '../../../lib/networking/queries/useGetArticleQuery' +import { removeItemFromCache, useGetArticleQuery } from '../../../lib/networking/queries/useGetArticleQuery' import { useRouter } from 'next/router' import { VStack } from './../../../components/elements/LayoutPrimitives' import { ArticleContainer } from './../../../components/templates/article/ArticleContainer' @@ -25,6 +25,8 @@ import { ArticleActionsMenu } from '../../../components/templates/article/Articl import { HighlightsModal } from '../../../components/templates/article/HighlightsModal' import { setLinkArchivedMutation } from '../../../lib/networking/mutations/setLinkArchivedMutation' import { Label } from '../../../lib/networking/fragments/labelFragment' +import { useSWRConfig } from 'swr' +import { showErrorToast, showSuccessToast } from '../../../lib/toastHelpers' const PdfArticleContainerNoSSR = dynamic( @@ -34,6 +36,7 @@ const PdfArticleContainerNoSSR = dynamic( export default function Home(): JSX.Element { const router = useRouter() + const { cache, mutate } = useSWRConfig() const scrollRef = useRef(null) const { slug } = router.query const [showHighlightsModal, setShowHighlightsModal] = useState(false) @@ -73,12 +76,20 @@ export default function Home(): JSX.Element { switch (action) { case 'archive': if (article) { + removeItemFromCache(cache, mutate, article.id) + await setLinkArchivedMutation({ linkId: article.id, archived: true, + }).then((res) => { + if (res) { + showSuccessToast('Link archived', { position: 'bottom-right' }) + } else { + // todo: + showErrorToast('Error archiving link', { position: 'bottom-right' }) + } }) - // TODO: merge from article actions PR - // removeItemFromCache(cache, mutate, props.article.id) + router.push(`/home`) } break