diff --git a/src/components/status.css b/src/components/status.css index a2d861fd..f9de945a 100644 --- a/src/components/status.css +++ b/src/components/status.css @@ -282,7 +282,9 @@ } &.status-card-ghost { - border-style: dashed; + color: var(--text-insignificant-color); + border: var(--hairline-width) dashed var(--text-insignificant-color); + box-shadow: none; } } diff --git a/src/components/status.jsx b/src/components/status.jsx index 80294568..45f1c32b 100644 --- a/src/components/status.jsx +++ b/src/components/status.jsx @@ -378,7 +378,6 @@ function Status({ showActionsBar, showReplyParent, mediaFirst, - showFilteredHidden, }) { const { _, t, i18n } = useLingui(); const rtf = RTF(i18n.locale); @@ -500,16 +499,6 @@ function Status({ isFiltered(filtered, filterContext); if (filterInfo?.action === 'hide') { - if (showFilteredHidden) { - return ( -
- - - Post hidden by your filters - -
- ); - } return null; } @@ -3886,6 +3875,22 @@ function FilteredStatus({ ); } +const handledUnfulfilledStates = [ + 'deleted', + 'unauthorized', + 'pending', + 'rejected', + 'revoked', +]; +const unfulfilledText = { + filterHidden: msg`Post hidden by your filters`, + deleted: msg`Post removed by author.`, + unauthorized: msg`You’re not authorized to view this post.`, + pending: msg`Post pending author approval.`, + rejected: msg`Quoting not allowed by the author.`, + revoked: msg`Quoting not allowed by the author.`, +}; + const QuoteStatuses = memo(({ id, instance, level = 0 }) => { if (!id || !instance) return; const { _ } = useLingui(); @@ -3899,43 +3904,43 @@ const QuoteStatuses = memo(({ id, instance, level = 0 }) => { if (!uniqueQuotes?.length) return; if (level > 2) return; + const filterContext = useContext(FilterContext); + const currentAccount = getCurrentAccID(); + return uniqueQuotes.map((q) => { - if (q.state === 'deleted') + let unfulfilledState; + + const quoteStatus = snapStates.statuses[statusKey(q.id, q.instance)]; + if (quoteStatus) { + const isSelf = + currentAccount && currentAccount === quoteStatus.account?.id; + const filterInfo = + !isSelf && isFiltered(quoteStatus.filtered, filterContext); + + if (filterInfo?.action === 'hide') { + unfulfilledState = 'filterHidden'; + } + } + + if (!unfulfilledState) { + unfulfilledState = handledUnfulfilledStates.find( + (state) => q.state === state, + ); + } + + if (unfulfilledState) { return ( -
+
- - Post removed by author. - -
- ); - if (q.state === 'unauthorized') - return ( -
- - - You’re not authorized to view this post. - -
- ); - if (q.state === 'pending') - return ( -
- - - Post pending author approval. - -
- ); - if (q.state === 'rejected' || q.state === 'revoked') - return ( -
- - - Quoting not allowed by the author. - + {_(unfulfilledText[unfulfilledState])}
); + } + const Parent = q.native ? Fragment : LazyShazam; return ( @@ -3951,7 +3956,6 @@ const QuoteStatuses = memo(({ id, instance, level = 0 }) => { size="s" quoted={level + 1} enableCommentHint - showFilteredHidden /> diff --git a/src/locales/en.po b/src/locales/en.po index 47eeca6e..73842b85 100644 --- a/src/locales/en.po +++ b/src/locales/en.po @@ -34,7 +34,7 @@ msgstr "" #: src/components/account-block.jsx:170 #: src/components/account-info.jsx:715 -#: src/components/status.jsx:601 +#: src/components/status.jsx:590 msgid "Group" msgstr "" @@ -111,11 +111,11 @@ msgstr "" #: src/components/compose.jsx:2792 #: src/components/media-alt-modal.jsx:55 #: src/components/media-modal.jsx:363 -#: src/components/status.jsx:1847 -#: src/components/status.jsx:1864 -#: src/components/status.jsx:1989 -#: src/components/status.jsx:2610 -#: src/components/status.jsx:2613 +#: src/components/status.jsx:1836 +#: src/components/status.jsx:1853 +#: src/components/status.jsx:1978 +#: src/components/status.jsx:2599 +#: src/components/status.jsx:2602 #: src/pages/account-statuses.jsx:531 #: src/pages/accounts.jsx:118 #: src/pages/hashtag.jsx:203 @@ -203,7 +203,7 @@ msgid "Original" msgstr "" #: src/components/account-info.jsx:946 -#: src/components/status.jsx:2394 +#: src/components/status.jsx:2383 #: src/pages/catchup.jsx:71 #: src/pages/catchup.jsx:1448 #: src/pages/catchup.jsx:2061 @@ -329,30 +329,30 @@ msgid "Add/Remove from Lists" msgstr "" #: src/components/account-info.jsx:1490 -#: src/components/status.jsx:1269 +#: src/components/status.jsx:1258 msgid "Link copied" msgstr "" #: src/components/account-info.jsx:1493 -#: src/components/status.jsx:1272 +#: src/components/status.jsx:1261 msgid "Unable to copy link" msgstr "" #: src/components/account-info.jsx:1499 #: src/components/shortcuts-settings.jsx:1059 -#: src/components/status.jsx:1278 -#: src/components/status.jsx:3388 +#: src/components/status.jsx:1267 +#: src/components/status.jsx:3377 msgid "Copy" msgstr "" #: src/components/account-info.jsx:1514 #: src/components/shortcuts-settings.jsx:1077 -#: src/components/status.jsx:1294 +#: src/components/status.jsx:1283 msgid "Sharing doesn't seem to work." msgstr "" #: src/components/account-info.jsx:1520 -#: src/components/status.jsx:1300 +#: src/components/status.jsx:1289 msgid "Share…" msgstr "" @@ -466,9 +466,9 @@ msgstr "" #: src/components/shortcuts-settings.jsx:230 #: src/components/shortcuts-settings.jsx:583 #: src/components/shortcuts-settings.jsx:783 -#: src/components/status.jsx:3112 -#: src/components/status.jsx:3352 -#: src/components/status.jsx:3861 +#: src/components/status.jsx:3101 +#: src/components/status.jsx:3341 +#: src/components/status.jsx:3850 #: src/pages/accounts.jsx:45 #: src/pages/catchup.jsx:1584 #: src/pages/filters.jsx:225 @@ -718,7 +718,7 @@ msgid "Attachment #{i} failed" msgstr "Attachment #{i} failed" #: src/components/compose.jsx:1221 -#: src/components/status.jsx:2177 +#: src/components/status.jsx:2166 #: src/components/timeline.jsx:1023 msgid "Content warning" msgstr "" @@ -754,7 +754,7 @@ msgstr "" #: src/components/compose.jsx:1288 #: src/components/status.jsx:100 -#: src/components/status.jsx:2053 +#: src/components/status.jsx:2042 msgid "Private mention" msgstr "" @@ -791,10 +791,10 @@ msgstr "Schedule" #: src/components/compose.jsx:1677 #: src/components/keyboard-shortcuts-help.jsx:155 -#: src/components/status.jsx:1041 -#: src/components/status.jsx:1827 -#: src/components/status.jsx:1828 -#: src/components/status.jsx:2514 +#: src/components/status.jsx:1030 +#: src/components/status.jsx:1816 +#: src/components/status.jsx:1817 +#: src/components/status.jsx:2503 msgid "Reply" msgstr "" @@ -1016,7 +1016,7 @@ msgstr "" #: src/components/drafts.jsx:128 #: src/components/list-add-edit.jsx:188 -#: src/components/status.jsx:1444 +#: src/components/status.jsx:1433 #: src/pages/filters.jsx:603 #: src/pages/scheduled-posts.jsx:369 msgid "Delete…" @@ -1225,10 +1225,10 @@ msgid "<0>l or <1>f" msgstr "" #: src/components/keyboard-shortcuts-help.jsx:176 -#: src/components/status.jsx:1049 -#: src/components/status.jsx:2541 -#: src/components/status.jsx:2564 -#: src/components/status.jsx:2565 +#: src/components/status.jsx:1038 +#: src/components/status.jsx:2530 +#: src/components/status.jsx:2553 +#: src/components/status.jsx:2554 msgid "Boost" msgstr "" @@ -1237,9 +1237,9 @@ msgid "<0>Shift + <1>b" msgstr "" #: src/components/keyboard-shortcuts-help.jsx:184 -#: src/components/status.jsx:1112 -#: src/components/status.jsx:2589 -#: src/components/status.jsx:2590 +#: src/components/status.jsx:1101 +#: src/components/status.jsx:2578 +#: src/components/status.jsx:2579 msgid "Bookmark" msgstr "" @@ -1304,14 +1304,14 @@ msgid "Media description" msgstr "" #: src/components/media-alt-modal.jsx:67 -#: src/components/status.jsx:1155 -#: src/components/status.jsx:1164 +#: src/components/status.jsx:1144 +#: src/components/status.jsx:1153 #: src/components/translation-block.jsx:239 msgid "Translate" msgstr "" #: src/components/media-alt-modal.jsx:78 -#: src/components/status.jsx:1183 +#: src/components/status.jsx:1172 msgid "Speak" msgstr "" @@ -1348,9 +1348,9 @@ msgid "Filtered: {filterTitleStr}" msgstr "" #: src/components/media-post.jsx:133 -#: src/components/status.jsx:3691 -#: src/components/status.jsx:3787 -#: src/components/status.jsx:3865 +#: src/components/status.jsx:3680 +#: src/components/status.jsx:3776 +#: src/components/status.jsx:3854 #: src/components/timeline.jsx:1012 #: src/pages/catchup.jsx:75 #: src/pages/catchup.jsx:1880 @@ -1662,8 +1662,8 @@ msgid "[Unknown notification type: {type}]" msgstr "" #: src/components/notification.jsx:451 -#: src/components/status.jsx:1126 -#: src/components/status.jsx:1136 +#: src/components/status.jsx:1115 +#: src/components/status.jsx:1125 msgid "Boosted/Liked by…" msgstr "" @@ -1993,7 +1993,7 @@ msgid "Move down" msgstr "" #: src/components/shortcuts-settings.jsx:379 -#: src/components/status.jsx:1406 +#: src/components/status.jsx:1395 #: src/pages/list.jsx:195 msgid "Edit" msgstr "" @@ -2192,345 +2192,346 @@ msgstr "" msgid "Import/export settings from/to instance server (Very experimental)" msgstr "" -#: src/components/status.jsx:508 -msgid "Post hidden by your filters" -msgstr "Post hidden by your filters" - -#: src/components/status.jsx:625 +#: src/components/status.jsx:614 msgid "<0/> <1>boosted" msgstr "" -#: src/components/status.jsx:724 +#: src/components/status.jsx:713 msgid "Sorry, your current logged-in instance can't interact with this post from another instance." msgstr "" #. placeholder {0}: username || acct -#: src/components/status.jsx:878 +#: src/components/status.jsx:867 msgid "Unliked @{0}'s post" msgstr "" #. placeholder {0}: username || acct -#: src/components/status.jsx:879 +#: src/components/status.jsx:868 msgid "Liked @{0}'s post" msgstr "Liked @{0}'s post" #. placeholder {0}: username || acct -#: src/components/status.jsx:918 +#: src/components/status.jsx:907 msgid "Unbookmarked @{0}'s post" msgstr "Unbookmarked @{0}'s post" #. placeholder {0}: username || acct -#: src/components/status.jsx:919 +#: src/components/status.jsx:908 msgid "Bookmarked @{0}'s post" msgstr "Bookmarked @{0}'s post" -#: src/components/status.jsx:1018 +#: src/components/status.jsx:1007 msgid "Some media have no descriptions." msgstr "" #. placeholder {0}: rtf.format(-statusMonthsAgo, 'month') -#: src/components/status.jsx:1025 +#: src/components/status.jsx:1014 msgid "Old post (<0>{0})" msgstr "" -#: src/components/status.jsx:1049 -#: src/components/status.jsx:1089 -#: src/components/status.jsx:2541 -#: src/components/status.jsx:2564 +#: src/components/status.jsx:1038 +#: src/components/status.jsx:1078 +#: src/components/status.jsx:2530 +#: src/components/status.jsx:2553 msgid "Unboost" msgstr "" -#: src/components/status.jsx:1065 -#: src/components/status.jsx:2556 +#: src/components/status.jsx:1054 +#: src/components/status.jsx:2545 msgid "Quote" msgstr "" #. placeholder {0}: username || acct -#: src/components/status.jsx:1077 -#: src/components/status.jsx:1543 +#: src/components/status.jsx:1066 +#: src/components/status.jsx:1532 msgid "Unboosted @{0}'s post" msgstr "Unboosted @{0}'s post" #. placeholder {0}: username || acct -#: src/components/status.jsx:1078 -#: src/components/status.jsx:1544 +#: src/components/status.jsx:1067 +#: src/components/status.jsx:1533 msgid "Boosted @{0}'s post" msgstr "Boosted @{0}'s post" -#: src/components/status.jsx:1090 +#: src/components/status.jsx:1079 msgid "Boost…" msgstr "" -#: src/components/status.jsx:1102 -#: src/components/status.jsx:1837 -#: src/components/status.jsx:2577 +#: src/components/status.jsx:1091 +#: src/components/status.jsx:1826 +#: src/components/status.jsx:2566 msgid "Unlike" msgstr "" -#: src/components/status.jsx:1103 -#: src/components/status.jsx:1837 -#: src/components/status.jsx:1838 -#: src/components/status.jsx:2577 -#: src/components/status.jsx:2578 +#: src/components/status.jsx:1092 +#: src/components/status.jsx:1826 +#: src/components/status.jsx:1827 +#: src/components/status.jsx:2566 +#: src/components/status.jsx:2567 msgid "Like" msgstr "" -#: src/components/status.jsx:1112 -#: src/components/status.jsx:2589 +#: src/components/status.jsx:1101 +#: src/components/status.jsx:2578 msgid "Unbookmark" msgstr "" -#: src/components/status.jsx:1195 +#: src/components/status.jsx:1184 msgid "Post text copied" msgstr "Post text copied" -#: src/components/status.jsx:1198 +#: src/components/status.jsx:1187 msgid "Unable to copy post text" msgstr "Unable to copy post text" -#: src/components/status.jsx:1204 +#: src/components/status.jsx:1193 msgid "Copy post text" msgstr "Copy post text" #. placeholder {0}: username || acct -#: src/components/status.jsx:1222 +#: src/components/status.jsx:1211 msgid "View post by <0>@{0}" msgstr "" -#: src/components/status.jsx:1243 +#: src/components/status.jsx:1232 msgid "Show Edit History" msgstr "" -#: src/components/status.jsx:1246 +#: src/components/status.jsx:1235 msgid "Edited: {editedDateText}" msgstr "" -#: src/components/status.jsx:1313 -#: src/components/status.jsx:3357 +#: src/components/status.jsx:1302 +#: src/components/status.jsx:3346 msgid "Embed post" msgstr "" -#: src/components/status.jsx:1327 +#: src/components/status.jsx:1316 msgid "Conversation unmuted" msgstr "" -#: src/components/status.jsx:1327 +#: src/components/status.jsx:1316 msgid "Conversation muted" msgstr "" -#: src/components/status.jsx:1333 +#: src/components/status.jsx:1322 msgid "Unable to unmute conversation" msgstr "" -#: src/components/status.jsx:1334 +#: src/components/status.jsx:1323 msgid "Unable to mute conversation" msgstr "" -#: src/components/status.jsx:1343 +#: src/components/status.jsx:1332 msgid "Unmute conversation" msgstr "" -#: src/components/status.jsx:1350 +#: src/components/status.jsx:1339 msgid "Mute conversation" msgstr "" -#: src/components/status.jsx:1366 +#: src/components/status.jsx:1355 msgid "Post unpinned from profile" msgstr "" -#: src/components/status.jsx:1367 +#: src/components/status.jsx:1356 msgid "Post pinned to profile" msgstr "" -#: src/components/status.jsx:1372 +#: src/components/status.jsx:1361 msgid "Unable to unpin post" msgstr "" -#: src/components/status.jsx:1372 +#: src/components/status.jsx:1361 msgid "Unable to pin post" msgstr "" -#: src/components/status.jsx:1381 +#: src/components/status.jsx:1370 msgid "Unpin from profile" msgstr "" -#: src/components/status.jsx:1388 +#: src/components/status.jsx:1377 msgid "Pin to profile" msgstr "" -#: src/components/status.jsx:1417 +#: src/components/status.jsx:1406 msgid "Delete this post?" msgstr "" -#: src/components/status.jsx:1433 +#: src/components/status.jsx:1422 msgid "Post deleted" msgstr "" -#: src/components/status.jsx:1436 +#: src/components/status.jsx:1425 msgid "Unable to delete post" msgstr "" -#: src/components/status.jsx:1464 +#: src/components/status.jsx:1453 msgid "Report post…" msgstr "" -#: src/components/status.jsx:1838 -#: src/components/status.jsx:1874 -#: src/components/status.jsx:2578 +#: src/components/status.jsx:1827 +#: src/components/status.jsx:1863 +#: src/components/status.jsx:2567 msgid "Liked" msgstr "" -#: src/components/status.jsx:1871 -#: src/components/status.jsx:2565 +#: src/components/status.jsx:1860 +#: src/components/status.jsx:2554 msgid "Boosted" msgstr "" -#: src/components/status.jsx:1881 -#: src/components/status.jsx:2590 +#: src/components/status.jsx:1870 +#: src/components/status.jsx:2579 msgid "Bookmarked" msgstr "" -#: src/components/status.jsx:1885 +#: src/components/status.jsx:1874 msgid "Pinned" msgstr "" -#: src/components/status.jsx:1931 -#: src/components/status.jsx:2402 +#: src/components/status.jsx:1920 +#: src/components/status.jsx:2391 msgid "Deleted" msgstr "" -#: src/components/status.jsx:1972 +#: src/components/status.jsx:1961 msgid "{repliesCount, plural, one {# reply} other {# replies}}" msgstr "" #. placeholder {0}: snapStates.statusThreadNumber[sKey] ? ` ${snapStates.statusThreadNumber[sKey]}/X` : '' -#: src/components/status.jsx:2062 +#: src/components/status.jsx:2051 msgid "Thread{0}" msgstr "" -#: src/components/status.jsx:2140 -#: src/components/status.jsx:2202 -#: src/components/status.jsx:2298 +#: src/components/status.jsx:2129 +#: src/components/status.jsx:2191 +#: src/components/status.jsx:2287 msgid "Show less" msgstr "" -#: src/components/status.jsx:2140 -#: src/components/status.jsx:2202 +#: src/components/status.jsx:2129 +#: src/components/status.jsx:2191 msgid "Show content" msgstr "" #. placeholder {0}: filterInfo.titlesStr #. placeholder {0}: filterInfo?.titlesStr -#: src/components/status.jsx:2294 +#: src/components/status.jsx:2283 #: src/pages/catchup.jsx:1879 msgid "Filtered: {0}" msgstr "Filtered: {0}" -#: src/components/status.jsx:2298 +#: src/components/status.jsx:2287 msgid "Show media" msgstr "" -#: src/components/status.jsx:2438 +#: src/components/status.jsx:2427 msgid "Edited" msgstr "" -#: src/components/status.jsx:2515 +#: src/components/status.jsx:2504 msgid "Comments" msgstr "" #. More from [Author] -#: src/components/status.jsx:2815 +#: src/components/status.jsx:2804 msgid "More from <0/>" msgstr "More from <0/>" -#: src/components/status.jsx:3117 +#: src/components/status.jsx:3106 msgid "Edit History" msgstr "" -#: src/components/status.jsx:3121 +#: src/components/status.jsx:3110 msgid "Failed to load history" msgstr "" -#: src/components/status.jsx:3126 +#: src/components/status.jsx:3115 #: src/pages/annual-report.jsx:45 msgid "Loading…" msgstr "" -#: src/components/status.jsx:3362 +#: src/components/status.jsx:3351 msgid "HTML Code" msgstr "" -#: src/components/status.jsx:3379 +#: src/components/status.jsx:3368 msgid "HTML code copied" msgstr "" -#: src/components/status.jsx:3382 +#: src/components/status.jsx:3371 msgid "Unable to copy HTML code" msgstr "" -#: src/components/status.jsx:3394 +#: src/components/status.jsx:3383 msgid "Media attachments:" msgstr "" -#: src/components/status.jsx:3416 +#: src/components/status.jsx:3405 msgid "Account Emojis:" msgstr "" -#: src/components/status.jsx:3447 -#: src/components/status.jsx:3492 +#: src/components/status.jsx:3436 +#: src/components/status.jsx:3481 msgid "static URL" msgstr "" -#: src/components/status.jsx:3461 +#: src/components/status.jsx:3450 msgid "Emojis:" msgstr "" -#: src/components/status.jsx:3506 +#: src/components/status.jsx:3495 msgid "Notes:" msgstr "" -#: src/components/status.jsx:3510 +#: src/components/status.jsx:3499 msgid "This is static, unstyled and scriptless. You may need to apply your own styles and edit as needed." msgstr "" -#: src/components/status.jsx:3516 +#: src/components/status.jsx:3505 msgid "Polls are not interactive, becomes a list with vote counts." msgstr "" -#: src/components/status.jsx:3521 +#: src/components/status.jsx:3510 msgid "Media attachments can be images, videos, audios or any file types." msgstr "" -#: src/components/status.jsx:3527 +#: src/components/status.jsx:3516 msgid "Post could be edited or deleted later." msgstr "" -#: src/components/status.jsx:3533 +#: src/components/status.jsx:3522 msgid "Preview" msgstr "" -#: src/components/status.jsx:3542 +#: src/components/status.jsx:3531 msgid "Note: This preview is lightly styled." msgstr "" #. [Name] [Visibility icon] boosted -#: src/components/status.jsx:3795 +#: src/components/status.jsx:3784 msgid "<0/> <1/> boosted" msgstr "" -#: src/components/status.jsx:3908 +#: src/components/status.jsx:3886 +msgid "Post hidden by your filters" +msgstr "Post hidden by your filters" + +#: src/components/status.jsx:3887 msgid "Post removed by author." msgstr "Post removed by author." -#: src/components/status.jsx:3917 +#: src/components/status.jsx:3888 msgid "You’re not authorized to view this post." msgstr "You’re not authorized to view this post." -#: src/components/status.jsx:3926 +#: src/components/status.jsx:3889 msgid "Post pending author approval." msgstr "Post pending author approval." -#: src/components/status.jsx:3935 +#: src/components/status.jsx:3890 +#: src/components/status.jsx:3891 msgid "Quoting not allowed by the author." msgstr "Quoting not allowed by the author." diff --git a/src/pages/sandbox.jsx b/src/pages/sandbox.jsx index d70f27d3..e5981be6 100644 --- a/src/pages/sandbox.jsx +++ b/src/pages/sandbox.jsx @@ -311,6 +311,7 @@ const INITIAL_STATE = { showQuotes: false, quotesCount: '1', quoteNestingLevel: '0', + quoteState: 'accepted', // State for all quote posts size: 'medium', filters: [false, false, false], // hide, blur, warn quoteFilters: [false, false, false], // hide, blur, warn for quotes @@ -398,6 +399,7 @@ export default function Sandbox() { showQuotes: toggleState.showQuotes, quotesCount: toggleState.quotesCount, quoteNestingLevel: toggleState.quoteNestingLevel, + quoteState: toggleState.quoteState, size: toggleState.size, filters: toggleState.filters, quoteFilters: toggleState.quoteFilters, @@ -528,162 +530,173 @@ export default function Sandbox() { id: quoteId, instance: DEFAULT_INSTANCE, url: `https://example.social/s/${quoteId}`, // Include URL to ensure uniqueness check works + state: + toggleState.quoteState === 'accepted' + ? undefined + : toggleState.quoteState, // Only set state if not accepted }; // First, delete any existing status with this ID to avoid duplicates - delete states.statuses[quoteId]; + const quoteStatusKey = statusKey(quoteId, DEFAULT_INSTANCE); + delete states.statuses[quoteStatusKey]; - // Create the actual status object that will be retrieved by QuoteStatuses - const quoteStatus = { - id: quoteId, - content: `

This is quote post ${i + 1}${i % 2 === 0 ? '' : ' with some extra text'}

`, - account: { - id: `quote-account-${i}`, - username: `quote${i}`, - name: `Quote User ${i}`, - avatar: '/logo-192.png', - acct: `quote${i}@example.social`, - url: `https://example.social/@quote${i}`, - }, - visibility: 'public', - createdAt: new Date(Date.now() - i * 3600000).toISOString(), // Each post 1 hour older - emojis: [], - // First quote post should be plain (no media, no poll) - mediaAttachments: - i > 0 && i % 2 === 0 - ? [ - { - // Only non-first posts can have media (every 3rd post after the 1st) - id: `quote-media-${i}`, - type: 'image', - url: `https://picsum.photos/seed/quote-${i}/600/400`, - previewUrl: `https://picsum.photos/seed/quote-${i}/300/200`, - meta: { - original: { width: 600, height: 400 }, - small: { width: 300, height: 200 }, - }, - }, - ] - : [], - poll: - i > 0 && i % 3 === 0 - ? { - // Only non-first posts can have polls (every 4th post after the 1st) - id: `quote-poll-${i}`, - options: [ - { - title: 'Option A', - votesCount: Math.floor(Math.random() * 50), - }, - { - title: 'Option B', - votesCount: Math.floor(Math.random() * 50), - }, - ], - expiresAt: new Date( - Date.now() + 24 * 60 * 60 * 1000, - ).toISOString(), - multiple: false, - votesCount: Math.floor(Math.random() * 100), - } - : null, - }; - - // Add filtering to quote posts if enabled - if ( - toggleState.quoteFilters && - toggleState.quoteFilters.some((f) => f) - ) { - quoteStatus.filtered = toggleState.quoteFilters - .map((enabled, filterIndex) => { - if (!enabled) return null; - const filterTypes = ['hide', 'blur', 'warn']; - return { - filter: { - id: `quote-filter-${i}-${filterIndex}`, - title: `Quote ${filterTypes[filterIndex]} filter`, - context: ['home', 'public', 'thread', 'account'], - filterAction: filterTypes[filterIndex], - }, - keywordMatches: [], - statusMatches: [], - }; - }) - .filter(Boolean); - } - - // Assign the quote status to the states - states.statuses[quoteId] = quoteStatus; - - // If nesting level > 0, add nested quotes to each quote post - if (nestingLevel > 0 && i % 2 === 0) { - // Add nested quotes to every other quote - use stable ID - const nestedQuoteId = `nested-quote-${i}-12345`; - - // Add the nested quote post to states.statuses - states.statuses[nestedQuoteId] = { - id: nestedQuoteId, - content: `

This is a nested quote inside quote ${i + 1}

`, + // Create the actual status object for all quote states + // This allows filtering logic to run even for non-accepted states + { + // Create the actual status object that will be retrieved by QuoteStatuses + const quoteStatus = { + id: quoteId, + content: `

This is quote post ${i + 1}${i % 2 === 0 ? '' : ' with some extra text'}

`, account: { - id: `nested-account-${i}`, - username: `nested${i}`, - name: `Nested User ${i}`, + id: `quote-account-${i}`, + username: `quote${i}`, + name: `Quote User ${i}`, avatar: '/logo-192.png', - acct: `nested${i}@example.social`, - url: `https://example.social/@nested${i}`, + acct: `quote${i}@example.social`, + url: `https://example.social/@quote${i}`, }, visibility: 'public', - createdAt: new Date(Date.now() - (i + 1) * 3600000).toISOString(), + createdAt: new Date(Date.now() - i * 3600000).toISOString(), // Each post 1 hour older emojis: [], - mediaAttachments: [], // No media in nested quotes for simplicity + // First quote post should be plain (no media, no poll) + mediaAttachments: + i > 0 && i % 2 === 0 + ? [ + { + // Only non-first posts can have media (every 3rd post after the 1st) + id: `quote-media-${i}`, + type: 'image', + url: `https://picsum.photos/seed/quote-${i}/600/400`, + previewUrl: `https://picsum.photos/seed/quote-${i}/300/200`, + meta: { + original: { width: 600, height: 400 }, + small: { width: 300, height: 200 }, + }, + }, + ] + : [], + poll: + i > 0 && i % 3 === 0 + ? { + // Only non-first posts can have polls (every 4th post after the 1st) + id: `quote-poll-${i}`, + options: [ + { + title: 'Option A', + votesCount: Math.floor(Math.random() * 50), + }, + { + title: 'Option B', + votesCount: Math.floor(Math.random() * 50), + }, + ], + expiresAt: new Date( + Date.now() + 24 * 60 * 60 * 1000, + ).toISOString(), + multiple: false, + votesCount: Math.floor(Math.random() * 100), + } + : null, }; - // Create reference object for nested quote - critical for proper rendering - const nestedQuoteRef = { - id: nestedQuoteId, - instance: DEFAULT_INSTANCE, - url: `https://example.social/s/${nestedQuoteId}`, - }; + // Add filtering to quote posts if enabled + if ( + toggleState.quoteFilters && + toggleState.quoteFilters.some((f) => f) + ) { + quoteStatus.filtered = toggleState.quoteFilters + .map((enabled, filterIndex) => { + if (!enabled) return null; + const filterTypes = ['hide', 'blur', 'warn']; + return { + filter: { + id: `quote-filter-${i}-${filterIndex}`, + title: `Quote ${filterTypes[filterIndex]} filter`, + context: ['home', 'public', 'thread', 'account'], + filterAction: filterTypes[filterIndex], + }, + keywordMatches: [], + statusMatches: [], + }; + }) + .filter(Boolean); + } - // Add another level of nesting if specified - if (nestingLevel > 1 && i === 0) { - // Only add deepest nesting to first quote - const deepNestedId = `deep-nested-${i}-12345`; + // Assign the quote status to the states using the correct key format + states.statuses[quoteStatusKey] = quoteStatus; - states.statuses[deepNestedId] = { - id: deepNestedId, - content: `

This is a deeply nested quote (level 2)

`, + // If nesting level > 0, add nested quotes to each quote post + if (nestingLevel > 0 && i % 2 === 0) { + // Add nested quotes to every other quote - use stable ID + const nestedQuoteId = `nested-quote-${i}-12345`; + + // Add the nested quote post to states.statuses + states.statuses[nestedQuoteId] = { + id: nestedQuoteId, + content: `

This is a nested quote inside quote ${i + 1}

`, account: { - id: `deep-account-${i}`, - username: `deep${i}`, - name: `Deep User ${i}`, + id: `nested-account-${i}`, + username: `nested${i}`, + name: `Nested User ${i}`, avatar: '/logo-192.png', - acct: `deep${i}@example.social`, - url: `https://example.social/@deep${i}`, + acct: `nested${i}@example.social`, + url: `https://example.social/@nested${i}`, }, visibility: 'public', createdAt: new Date( - Date.now() - (i + 2) * 3600000, + Date.now() - (i + 1) * 3600000, ).toISOString(), emojis: [], + mediaAttachments: [], // No media in nested quotes for simplicity }; - // Create deep nested reference - const deepNestedRef = { - id: deepNestedId, + // Create reference object for nested quote - critical for proper rendering + const nestedQuoteRef = { + id: nestedQuoteId, instance: DEFAULT_INSTANCE, - url: `https://example.social/s/${deepNestedId}`, + url: `https://example.social/s/${nestedQuoteId}`, }; - // Important: Use the proper key format for the nested quote - const nestedKey = statusKey(nestedQuoteId, DEFAULT_INSTANCE); - states.statusQuotes[nestedKey] = [deepNestedRef]; - } + // Add another level of nesting if specified + if (nestingLevel > 1 && i === 0) { + // Only add deepest nesting to first quote + const deepNestedId = `deep-nested-${i}-12345`; - // Add nested quote to the quote's quotes using the proper key format - const quoteKey = statusKey(quoteId, DEFAULT_INSTANCE); - states.statusQuotes[quoteKey] = [nestedQuoteRef]; - } + states.statuses[deepNestedId] = { + id: deepNestedId, + content: `

This is a deeply nested quote (level 2)

`, + account: { + id: `deep-account-${i}`, + username: `deep${i}`, + name: `Deep User ${i}`, + avatar: '/logo-192.png', + acct: `deep${i}@example.social`, + url: `https://example.social/@deep${i}`, + }, + visibility: 'public', + createdAt: new Date( + Date.now() - (i + 2) * 3600000, + ).toISOString(), + emojis: [], + }; + + // Create deep nested reference + const deepNestedRef = { + id: deepNestedId, + instance: DEFAULT_INSTANCE, + url: `https://example.social/s/${deepNestedId}`, + }; + + // Important: Use the proper key format for the nested quote + const nestedKey = statusKey(nestedQuoteId, DEFAULT_INSTANCE); + states.statusQuotes[nestedKey] = [deepNestedRef]; + } + + // Add nested quote to the quote's quotes using the proper key format + const quoteKey = statusKey(quoteId, DEFAULT_INSTANCE); + states.statusQuotes[quoteKey] = [nestedQuoteRef]; + } + } // Close the quote status creation block return quoteRef; }); @@ -699,6 +712,7 @@ export default function Sandbox() { toggleState.showQuotes, toggleState.quotesCount, toggleState.quoteNestingLevel, + toggleState.quoteState, toggleState.quoteFilters, ]); @@ -1251,6 +1265,98 @@ export default function Sandbox() { /> + +
  • + Quote state + +
  • Quote Filters