this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Prevent repetitive unfurling

+50 -48
+50 -48
src/components/status.jsx
··· 18 18 import { useLongPress } from 'use-long-press'; 19 19 import useResizeObserver from 'use-resize-observer'; 20 20 import { useSnapshot } from 'valtio'; 21 + import { snapshot } from 'valtio/vanilla'; 21 22 22 23 import AccountBlock from '../components/account-block'; 23 24 import Loader from '../components/loader'; ··· 1701 1702 const failedUnfurls = {}; 1702 1703 1703 1704 function _unfurlMastodonLink(instance, url) { 1705 + const snapStates = snapshot(states); 1704 1706 if (denylistDomains.test(url)) { 1705 1707 return; 1706 1708 } ··· 1708 1710 return; 1709 1711 } 1710 1712 const instanceRegex = new RegExp(instance + '/'); 1711 - if (instanceRegex.test(states.unfurledLinks[url]?.url)) { 1712 - return Promise.resolve(states.unfurledLinks[url]); 1713 + if (instanceRegex.test(snapStates.unfurledLinks[url]?.url)) { 1714 + return Promise.resolve(snapStates.unfurledLinks[url]); 1713 1715 } 1714 1716 console.debug('🦦 Unfurling URL', url); 1715 1717 ··· 1723 1725 if (statusMatch) { 1724 1726 const id = statusMatch[3]; 1725 1727 const { masto } = api({ instance: domain }); 1726 - remoteInstanceFetch = masto.v1.statuses 1727 - .fetch(id) 1728 - .then((status) => { 1729 - if (status?.id) { 1730 - const statusURL = `/${domain}/s/${id}`; 1731 - const result = { 1732 - id, 1733 - instance: domain, 1734 - url: statusURL, 1735 - }; 1736 - console.debug('🦦 Unfurled URL', url, id, statusURL); 1737 - states.unfurledLinks[url] = result; 1738 - saveStatus(status, domain, { 1739 - skipThreading: true, 1740 - }); 1741 - return result; 1742 - } else { 1743 - failedUnfurls[url] = true; 1744 - throw new Error('No results'); 1745 - } 1746 - }) 1747 - .catch((e) => { 1748 - failedUnfurls[url] = true; 1749 - }); 1728 + remoteInstanceFetch = masto.v1.statuses.fetch(id).then((status) => { 1729 + if (status?.id) { 1730 + return { 1731 + status, 1732 + instance: domain, 1733 + }; 1734 + } else { 1735 + throw new Error('No results'); 1736 + } 1737 + }); 1750 1738 } 1751 1739 1752 1740 const { masto } = api({ instance }); ··· 1760 1748 .then((results) => { 1761 1749 if (results.statuses.length > 0) { 1762 1750 const status = results.statuses[0]; 1763 - const { id } = status; 1764 - const statusURL = `/${instance}/s/${id}`; 1765 - const result = { 1766 - id, 1751 + return { 1752 + status, 1767 1753 instance, 1768 - url: statusURL, 1769 1754 }; 1770 - console.debug('🦦 Unfurled URL', url, id, statusURL); 1771 - states.unfurledLinks[url] = result; 1772 - saveStatus(status, instance, { 1773 - skipThreading: true, 1774 - }); 1775 - return result; 1776 1755 } else { 1777 - failedUnfurls[url] = true; 1778 1756 throw new Error('No results'); 1779 1757 } 1780 - }) 1781 - .catch((e) => { 1782 - failedUnfurls[url] = true; 1783 - // console.warn(e); 1784 - // Silently fail 1758 + }); 1759 + 1760 + function handleFulfill(result) { 1761 + const { status, instance } = result; 1762 + const { id } = status; 1763 + const url = `/${instance}/s/${id}`; 1764 + console.debug('🦦 Unfurled URL', url, id, url); 1765 + const data = { 1766 + id, 1767 + instance, 1768 + url, 1769 + }; 1770 + states.unfurledLinks[url] = data; 1771 + saveStatus(status, instance, { 1772 + skipThreading: true, 1785 1773 }); 1774 + return data; 1775 + } 1776 + function handleCatch(e) { 1777 + failedUnfurls[url] = true; 1778 + } 1786 1779 1787 1780 if (remoteInstanceFetch) { 1788 - return Promise.any([remoteInstanceFetch, mastoSearchFetch]); 1781 + return Promise.any([remoteInstanceFetch, mastoSearchFetch]) 1782 + .then(handleFulfill) 1783 + .catch(handleCatch); 1789 1784 } else { 1790 - return mastoSearchFetch; 1785 + return mastoSearchFetch.then(handleFulfill).catch(handleCatch); 1791 1786 } 1792 1787 } 1793 1788 ··· 1814 1809 ); 1815 1810 } 1816 1811 1817 - const unfurlMastodonLink = throttle(_unfurlMastodonLink); 1812 + const unfurlMastodonLink = throttle( 1813 + mem(_unfurlMastodonLink, { 1814 + cacheKey: (instance, url) => `${instance}:${url}`, 1815 + }), 1816 + ); 1818 1817 1819 1818 const root = document.documentElement; 1820 1819 const defaultBoundingBoxPadding = 8; ··· 1958 1957 const snapStates = useSnapshot(states); 1959 1958 const sKey = statusKey(id, instance); 1960 1959 const quotes = snapStates.statusQuotes[sKey]; 1960 + const uniqueQuotes = quotes?.filter( 1961 + (q, i, arr) => arr.findIndex((q2) => q2.url === q.url) === i, 1962 + ); 1961 1963 1962 - if (!quotes?.length) return; 1964 + if (!uniqueQuotes?.length) return; 1963 1965 if (level > 2) return; 1964 1966 1965 - return quotes.map((q) => { 1967 + return uniqueQuotes.map((q) => { 1966 1968 return ( 1967 1969 <Link 1968 1970 key={q.instance + q.id}