diff --git a/src/favorites/FavoriteButton.tsx b/src/favorites/FavoriteButton.tsx index d2824f1..47e27e8 100644 --- a/src/favorites/FavoriteButton.tsx +++ b/src/favorites/FavoriteButton.tsx @@ -57,16 +57,25 @@ export function FavoriteButton({ aria-label={isFavorite ? t("favoriteRemove") : t("favoriteAdd")} title={isFavorite ? t("favoriteRemove") : t("favoriteAdd")} className={[ - "inline-flex shrink-0 items-center justify-center rounded-full border outline-none transition active:scale-95 focus-visible:ring-2 focus-visible:ring-ark-gold/80 disabled:cursor-wait disabled:opacity-70", + "inline-flex shrink-0 items-center justify-center rounded-full border outline-none transition active:scale-95 focus-visible:ring-2 focus-visible:ring-ark-gold/80 disabled:cursor-wait md:disabled:opacity-70", dimension, isFavorite - ? "border-ark-gold/60 bg-ark-gold text-black hover:bg-ark-gold2" - : "border-white/10 bg-[#191921]/90 text-[#A8A9AE] hover:border-ark-gold hover:bg-[#191921] hover:text-ark-gold", + ? "border-ark-gold/60 bg-ark-gold text-black md:hover:bg-ark-gold2" + : "border-white/10 bg-[#191921]/90 text-[#A8A9AE] md:hover:border-ark-gold md:hover:bg-[#191921] md:hover:text-ark-gold", className, ].join(" ")} + aria-busy={pending} > {pending ? ( - + <> + + + + + ) : ( )} diff --git a/src/pages/Favorites/index.tsx b/src/pages/Favorites/index.tsx index 9474251..66d60b1 100644 --- a/src/pages/Favorites/index.tsx +++ b/src/pages/Favorites/index.tsx @@ -1,146 +1,21 @@ import { Heart, RotateCcw } from "lucide-react"; -import { useEffect, useMemo, useState } from "react"; -import { Link } from "react-router-dom"; -import { - assetUrl, - getJSON, - itemsOrEmpty, - readJSONCache, - type Category, - type Resource, -} from "../../api"; -import { FavoriteButton } from "../../favorites/FavoriteButton"; +import { useEffect, useState } from "react"; +import { itemsOrEmpty } from "../../api"; import { isFavoritesAuthError, listFavorites } from "../../favorites/api"; import { useFavorites } from "../../favorites/FavoritesProvider"; -import { langQuery, useI18n, type Lang } from "../../i18n"; +import { useI18n } from "../../i18n"; import { Reveal } from "../../motion"; +import { MessageBubble } from "../../components/messageStream/MessageBubble"; import { useSetPageTitle } from "../../components/PageTitleContext"; import { Skeleton } from "../../components/Skeleton"; import { useWallet } from "../../wallet/WalletProvider"; -import { useLocalizedPath } from "../../useLocalizedPath"; -import { postToResource } from "../../utils/postResourceAdapter"; -import { formatDateYmd } from "../../utils/format"; -import { - resourceLanguageLabel, - resourceTypeLabel, -} from "../../resourceTypeLabels"; const pageSize = 50; -function useCategories(lang: Lang): Category[] { - const [categories, setCategories] = useState([]); - useEffect(() => { - const url = `/api/categories?lang=${encodeURIComponent(langQuery(lang))}`; - const cached = readJSONCache(url); - if (cached) setCategories(itemsOrEmpty(cached)); - let cancelled = false; - getJSON(url) - .then((items) => { - if (!cancelled) setCategories(itemsOrEmpty(items)); - }) - .catch(() => { - if (!cancelled && !cached) setCategories([]); - }); - return () => { - cancelled = true; - }; - }, [lang]); - return categories; -} - -function FavoriteResourceCard({ resource }: { resource: Resource }) { - const { t } = useI18n(); - const lp = useLocalizedPath(); - const unavailable = resource.availability === "unavailable"; - const cover = resource.coverImage || resource.previewUrl; - - return ( -
- {!unavailable ? ( - - ) : null} -
- {cover && !unavailable ? ( - - ) : ( -
- -
- )} - {unavailable ? ( - - {t("favoritesUnavailable")} - - ) : null} -
- -
-

- {resource.title} -

- {resource.description ? ( -

- {resource.description} -

- ) : null} -
- {resource.categoryName ? ( - - {resource.categoryName} - - ) : null} - {resource.type ? ( - {resourceTypeLabel(t, resource.type)} - ) : null} - {resource.language ? ( - <> - · - {resourceLanguageLabel(t, resource.language)} - - ) : null} - {resource.updatedAt ? ( - <> - · - - - ) : null} - {typeof resource.favoriteCount === "number" ? ( - · ♥ {resource.favoriteCount} - ) : null} -
-
- - -
- ); -} - export default function Favorites() { - const { lang, t } = useI18n(); + const { t } = useI18n(); const wallet = useWallet(); const { markFavorite } = useFavorites(); - const categories = useCategories(lang); const [posts, setPosts] = useState< Awaited>["items"] >([]); @@ -195,14 +70,9 @@ export default function Favorites() { }; }, [markFavorite, reloadKey, t, wallet]); - const resources = useMemo( - () => posts.map((post) => postToResource(post, lang, categories)), - [posts, lang, categories], - ); - if (wallet.status === "loading") { return ( - + {Array.from({ length: 4 }).map((_, index) => ( ))} @@ -234,7 +104,7 @@ export default function Favorites() { } return ( -
+
{loading || !loaded ? ( Array.from({ length: 4 }).map((_, index) => ( @@ -251,7 +121,7 @@ export default function Favorites() { {t("walletRetry")}
- ) : resources.length === 0 ? ( + ) : posts.length === 0 ? (

@@ -262,8 +132,10 @@ export default function Favorites() {

) : ( - resources.map((resource) => ( - + posts.map((post, index) => ( + + + )) )}