this repo has no description
0
fork

Configure Feed

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

Refactor thread badge

Use more of it

+627 -526
+13 -1
src/components/status.css
··· 368 368 gap: 8px; 369 369 padding-block: 8px; 370 370 } 371 - .status.compact-thread .status-thread-badge { 371 + .status.compact-thread .status-thread-badge-container { 372 372 flex-shrink: 0; 373 373 min-width: 50px; 374 374 justify-content: center; 375 + display: flex; 375 376 } 376 377 .status.compact-thread .content-compact { 377 378 overflow: hidden; ··· 589 590 var(--reply-to-faded-color) 4px 590 591 ); 591 592 font-weight: bold; 593 + align-self: center; 594 + flex-shrink: 0; 595 + 596 + .meta-name + & { 597 + margin-inline-start: 4px; 598 + margin-block: 0; 599 + 600 + + .time { 601 + margin-inline-start: 0 !important; 602 + } 603 + } 592 604 } 593 605 .status-direct-badge { 594 606 vertical-align: middle;
+12 -9
src/components/status.jsx
··· 81 81 import Media, { isMediaCaptionLong } from './media'; 82 82 import MenuLink from './menu-link'; 83 83 import RelativeTime from './relative-time'; 84 + import ThreadBadge from './thread-badge'; 84 85 import TranslationBlock from './translation-block'; 85 86 86 87 const SHOW_COMMENT_COUNT_LIMIT = 280; ··· 2064 2065 showAcct={isSizeLarge} 2065 2066 /> 2066 2067 </span> 2068 + {withinContext && isThread && ( 2069 + <ThreadBadge 2070 + showIcon={isSizeLarge} 2071 + index={snapStates.statusThreadNumber[sKey]} 2072 + /> 2073 + )} 2067 2074 {/* {inReplyToAccount && !withinContext && size !== 's' && ( 2068 2075 <> 2069 2076 {' '} ··· 2206 2213 {!withinContext && ( 2207 2214 <> 2208 2215 {isThread ? ( 2209 - <div class="status-thread-badge"> 2210 - <Icon icon="thread" size="s" /> 2211 - <Trans> 2212 - Thread 2213 - {snapStates.statusThreadNumber[sKey] 2214 - ? ` ${snapStates.statusThreadNumber[sKey]}/X` 2215 - : ''} 2216 - </Trans> 2217 - </div> 2216 + <ThreadBadge 2217 + showIcon 2218 + showText 2219 + index={snapStates.statusThreadNumber[sKey]} 2220 + /> 2218 2221 ) : ( 2219 2222 !!inReplyToId && 2220 2223 !!inReplyToAccount &&
+58
src/components/thread-badge.jsx
··· 1 + import { Trans, useLingui } from '@lingui/react/macro'; 2 + import { useContext } from 'preact/hooks'; 3 + 4 + import { ThreadCountContext } from '../utils/thread-count-context'; 5 + 6 + import Icon from './icon'; 7 + 8 + function ThreadIcon({ alt }) { 9 + return <Icon icon="thread" size="s" alt={alt} />; 10 + } 11 + 12 + function ThreadBadge({ index, showIcon, showText }) { 13 + const { t } = useLingui(); 14 + const total = useContext(ThreadCountContext); 15 + const hasIndex = index > 0; 16 + const hasTotal = (total || 0) > 0; 17 + 18 + return ( 19 + <div class="status-thread-badge"> 20 + {showIcon && ( 21 + <> 22 + <ThreadIcon alt={showText ? '' : t`Thread`} />{' '} 23 + </> 24 + )} 25 + {showText ? ( 26 + hasIndex ? ( 27 + hasTotal ? ( 28 + <Trans> 29 + Thread {index}/{total} 30 + </Trans> 31 + ) : ( 32 + <Trans comment="X is the unspecified total number of posts in a thread"> 33 + Thread {index}/X 34 + </Trans> 35 + ) 36 + ) : ( 37 + t`Thread` 38 + ) 39 + ) : hasIndex ? ( 40 + hasTotal ? ( 41 + t({ 42 + message: `${index}/${total}`, 43 + comment: 'index/total posts in a thread', 44 + }) 45 + ) : ( 46 + t({ 47 + message: `${index}/X`, 48 + comment: 'X is the unspecified total number of posts in a thread', 49 + }) 50 + ) 51 + ) : ( 52 + !showIcon && <ThreadIcon alt={t`Thread`} /> 53 + )} 54 + </div> 55 + ); 56 + } 57 + 58 + export default ThreadBadge;
+4 -12
src/components/timeline.jsx
··· 31 31 import MediaPost from './media-post'; 32 32 import NavMenu from './nav-menu'; 33 33 import Status from './status'; 34 + import ThreadBadge from './thread-badge'; 34 35 35 36 const scrollIntoViewOptions = { 36 37 block: 'start', ··· 980 981 }`} 981 982 tabindex="-1" 982 983 > 983 - {!!snapStates.statusThreadNumber[sKey] ? ( 984 - <div class="status-thread-badge"> 985 - <Icon icon="thread" size="s" alt={t`Thread`} /> 986 - {snapStates.statusThreadNumber[sKey] 987 - ? ` ${snapStates.statusThreadNumber[sKey]}/X` 988 - : ''} 989 - </div> 990 - ) : ( 991 - <div class="status-thread-badge"> 992 - <Icon icon="thread" size="s" alt={t`Thread`} /> 993 - </div> 994 - )} 984 + <div class="status-thread-badge-container"> 985 + <ThreadBadge index={snapStates.statusThreadNumber[sKey]} /> 986 + </div> 995 987 <div 996 988 class="content-compact" 997 989 title={statusPeekText}
+214 -199
src/locales/en.po
··· 34 34 35 35 #: src/components/account-block.jsx:190 36 36 #: src/components/account-info.jsx:710 37 - #: src/components/status.jsx:748 37 + #: src/components/status.jsx:749 38 38 msgid "Group" 39 39 msgstr "" 40 40 ··· 108 108 #: src/components/compose.jsx:2819 109 109 #: src/components/media-alt-modal.jsx:55 110 110 #: src/components/media-modal.jsx:363 111 - #: src/components/status.jsx:1996 112 - #: src/components/status.jsx:2013 113 - #: src/components/status.jsx:2138 114 - #: src/components/status.jsx:2767 111 + #: src/components/status.jsx:1997 112 + #: src/components/status.jsx:2014 113 + #: src/components/status.jsx:2145 115 114 #: src/components/status.jsx:2770 115 + #: src/components/status.jsx:2773 116 116 #: src/pages/account-statuses.jsx:539 117 117 #: src/pages/accounts.jsx:118 118 118 #: src/pages/hashtag.jsx:203 119 119 #: src/pages/list.jsx:171 120 120 #: src/pages/public.jsx:116 121 121 #: src/pages/scheduled-posts.jsx:89 122 - #: src/pages/status.jsx:1306 122 + #: src/pages/status.jsx:1323 123 123 #: src/pages/trending.jsx:474 124 124 msgid "More" 125 125 msgstr "" ··· 217 217 msgstr "" 218 218 219 219 #: src/components/account-info.jsx:978 220 - #: src/components/status.jsx:2551 220 + #: src/components/status.jsx:2554 221 221 #: src/pages/catchup.jsx:71 222 222 #: src/pages/catchup.jsx:1448 223 223 #: src/pages/catchup.jsx:2061 224 - #: src/pages/status.jsx:1025 225 - #: src/pages/status.jsx:1652 224 + #: src/pages/status.jsx:1040 225 + #: src/pages/status.jsx:1670 226 226 msgid "Replies" 227 227 msgstr "" 228 228 ··· 343 343 msgstr "" 344 344 345 345 #: src/components/account-info.jsx:1522 346 - #: src/components/status.jsx:1418 346 + #: src/components/status.jsx:1419 347 347 msgid "Link copied" 348 348 msgstr "" 349 349 350 350 #: src/components/account-info.jsx:1525 351 - #: src/components/status.jsx:1421 351 + #: src/components/status.jsx:1422 352 352 msgid "Unable to copy link" 353 353 msgstr "" 354 354 355 355 #: src/components/account-info.jsx:1531 356 356 #: src/components/shortcuts-settings.jsx:1059 357 - #: src/components/status.jsx:1427 358 - #: src/components/status.jsx:3545 357 + #: src/components/status.jsx:1428 358 + #: src/components/status.jsx:3548 359 359 msgid "Copy" 360 360 msgstr "" 361 361 362 362 #: src/components/account-info.jsx:1546 363 363 #: src/components/shortcuts-settings.jsx:1077 364 - #: src/components/status.jsx:1443 364 + #: src/components/status.jsx:1444 365 365 msgid "Sharing doesn't seem to work." 366 366 msgstr "" 367 367 368 368 #: src/components/account-info.jsx:1552 369 - #: src/components/status.jsx:1449 369 + #: src/components/status.jsx:1450 370 370 msgid "Share…" 371 371 msgstr "" 372 372 ··· 480 480 #: src/components/shortcuts-settings.jsx:230 481 481 #: src/components/shortcuts-settings.jsx:583 482 482 #: src/components/shortcuts-settings.jsx:783 483 - #: src/components/status.jsx:3269 484 - #: src/components/status.jsx:3509 485 - #: src/components/status.jsx:4018 483 + #: src/components/status.jsx:3272 484 + #: src/components/status.jsx:3512 485 + #: src/components/status.jsx:4021 486 486 #: src/pages/accounts.jsx:45 487 487 #: src/pages/catchup.jsx:1584 488 488 #: src/pages/filters.jsx:225 ··· 490 490 #: src/pages/notifications.jsx:942 491 491 #: src/pages/scheduled-posts.jsx:259 492 492 #: src/pages/settings.jsx:90 493 - #: src/pages/status.jsx:1393 493 + #: src/pages/status.jsx:1410 494 494 msgid "Close" 495 495 msgstr "" 496 496 ··· 608 608 #: src/components/columns.jsx:27 609 609 #: src/components/nav-menu.jsx:181 610 610 #: src/components/shortcuts-settings.jsx:139 611 - #: src/components/timeline.jsx:469 611 + #: src/components/timeline.jsx:470 612 612 #: src/pages/catchup.jsx:883 613 613 #: src/pages/filters.jsx:90 614 614 #: src/pages/followed-hashtags.jsx:41 ··· 732 732 msgstr "Attachment #{i} failed" 733 733 734 734 #: src/components/compose.jsx:1222 735 - #: src/components/status.jsx:2326 736 - #: src/components/timeline.jsx:1023 735 + #: src/components/status.jsx:2329 736 + #: src/components/timeline.jsx:1015 737 737 msgid "Content warning" 738 738 msgstr "" 739 739 ··· 742 742 msgstr "Content warning or sensitive media" 743 743 744 744 #: src/components/compose.jsx:1274 745 - #: src/components/status.jsx:99 745 + #: src/components/status.jsx:100 746 746 #: src/pages/settings.jsx:318 747 747 msgid "Public" 748 748 msgstr "" ··· 750 750 #: src/components/compose.jsx:1279 751 751 #: src/components/nav-menu.jsx:349 752 752 #: src/components/shortcuts-settings.jsx:165 753 - #: src/components/status.jsx:100 753 + #: src/components/status.jsx:101 754 754 msgid "Local" 755 755 msgstr "" 756 756 757 757 #: src/components/compose.jsx:1283 758 - #: src/components/status.jsx:101 758 + #: src/components/status.jsx:102 759 759 #: src/pages/settings.jsx:321 760 760 msgid "Unlisted" 761 761 msgstr "" 762 762 763 763 #: src/components/compose.jsx:1286 764 - #: src/components/status.jsx:102 764 + #: src/components/status.jsx:103 765 765 #: src/pages/settings.jsx:324 766 766 msgid "Followers only" 767 767 msgstr "" 768 768 769 769 #: src/components/compose.jsx:1289 770 - #: src/components/status.jsx:103 771 - #: src/components/status.jsx:2202 770 + #: src/components/status.jsx:104 771 + #: src/components/status.jsx:2209 772 772 msgid "Private mention" 773 773 msgstr "" 774 774 ··· 805 805 806 806 #: src/components/compose.jsx:1678 807 807 #: src/components/keyboard-shortcuts-help.jsx:155 808 - #: src/components/status.jsx:1190 809 - #: src/components/status.jsx:1976 808 + #: src/components/status.jsx:1191 810 809 #: src/components/status.jsx:1977 811 - #: src/components/status.jsx:2671 810 + #: src/components/status.jsx:1978 811 + #: src/components/status.jsx:2674 812 812 msgid "Reply" 813 813 msgstr "" 814 814 ··· 997 997 998 998 #: src/components/compose.jsx:3830 999 999 #: src/components/media-modal.jsx:469 1000 - #: src/components/timeline.jsx:927 1000 + #: src/components/timeline.jsx:928 1001 1001 msgid "Previous" 1002 1002 msgstr "" 1003 1003 1004 1004 #: src/components/compose.jsx:3848 1005 1005 #: src/components/media-modal.jsx:488 1006 - #: src/components/timeline.jsx:944 1006 + #: src/components/timeline.jsx:945 1007 1007 msgid "Next" 1008 1008 msgstr "" 1009 1009 ··· 1030 1030 1031 1031 #: src/components/drafts.jsx:128 1032 1032 #: src/components/list-add-edit.jsx:188 1033 - #: src/components/status.jsx:1593 1033 + #: src/components/status.jsx:1594 1034 1034 #: src/pages/filters.jsx:603 1035 1035 #: src/pages/scheduled-posts.jsx:369 1036 1036 msgid "Delete…" ··· 1097 1097 msgstr "" 1098 1098 1099 1099 #: src/components/generic-accounts.jsx:214 1100 - #: src/components/timeline.jsx:551 1100 + #: src/components/timeline.jsx:552 1101 1101 #: src/pages/list.jsx:321 1102 1102 #: src/pages/notifications.jsx:922 1103 1103 #: src/pages/search.jsx:562 1104 - #: src/pages/status.jsx:1426 1104 + #: src/pages/status.jsx:1443 1105 1105 msgid "Show more…" 1106 1106 msgstr "" 1107 1107 1108 1108 #: src/components/generic-accounts.jsx:219 1109 - #: src/components/timeline.jsx:556 1109 + #: src/components/timeline.jsx:557 1110 1110 #: src/pages/search.jsx:567 1111 1111 msgid "The end." 1112 1112 msgstr "" ··· 1239 1239 msgstr "" 1240 1240 1241 1241 #: src/components/keyboard-shortcuts-help.jsx:176 1242 - #: src/components/status.jsx:1198 1243 - #: src/components/status.jsx:2698 1244 - #: src/components/status.jsx:2721 1245 - #: src/components/status.jsx:2722 1242 + #: src/components/status.jsx:1199 1243 + #: src/components/status.jsx:2701 1244 + #: src/components/status.jsx:2724 1245 + #: src/components/status.jsx:2725 1246 1246 msgid "Boost" 1247 1247 msgstr "" 1248 1248 ··· 1251 1251 msgstr "" 1252 1252 1253 1253 #: src/components/keyboard-shortcuts-help.jsx:184 1254 - #: src/components/status.jsx:1261 1255 - #: src/components/status.jsx:2746 1256 - #: src/components/status.jsx:2747 1254 + #: src/components/status.jsx:1262 1255 + #: src/components/status.jsx:2749 1256 + #: src/components/status.jsx:2750 1257 1257 msgid "Bookmark" 1258 1258 msgstr "" 1259 1259 ··· 1318 1318 msgstr "" 1319 1319 1320 1320 #: src/components/media-alt-modal.jsx:67 1321 - #: src/components/status.jsx:1304 1322 - #: src/components/status.jsx:1313 1321 + #: src/components/status.jsx:1305 1322 + #: src/components/status.jsx:1314 1323 1323 #: src/components/translation-block.jsx:239 1324 1324 msgid "Translate" 1325 1325 msgstr "" 1326 1326 1327 1327 #: src/components/media-alt-modal.jsx:78 1328 - #: src/components/status.jsx:1332 1328 + #: src/components/status.jsx:1333 1329 1329 msgid "Speak" 1330 1330 msgstr "" 1331 1331 ··· 1362 1362 msgstr "" 1363 1363 1364 1364 #: src/components/media-post.jsx:133 1365 - #: src/components/status.jsx:3848 1366 - #: src/components/status.jsx:3944 1367 - #: src/components/status.jsx:4022 1368 - #: src/components/timeline.jsx:1012 1365 + #: src/components/status.jsx:3851 1366 + #: src/components/status.jsx:3947 1367 + #: src/components/status.jsx:4025 1368 + #: src/components/timeline.jsx:1004 1369 1369 #: src/pages/catchup.jsx:75 1370 1370 #: src/pages/catchup.jsx:1880 1371 1371 msgid "Filtered" ··· 1506 1506 #: src/components/nav-menu.jsx:326 1507 1507 #: src/pages/login.jsx:32 1508 1508 #: src/pages/login.jsx:199 1509 - #: src/pages/status.jsx:925 1509 + #: src/pages/status.jsx:940 1510 1510 #: src/pages/welcome.jsx:65 1511 1511 msgid "Log in" 1512 1512 msgstr "" ··· 1676 1676 msgstr "" 1677 1677 1678 1678 #: src/components/notification.jsx:451 1679 - #: src/components/status.jsx:1275 1680 - #: src/components/status.jsx:1285 1679 + #: src/components/status.jsx:1276 1680 + #: src/components/status.jsx:1286 1681 1681 msgid "Boosted/Liked by…" 1682 1682 msgstr "" 1683 1683 ··· 1703 1703 msgstr "View #Wrapstodon" 1704 1704 1705 1705 #: src/components/notification.jsx:801 1706 - #: src/components/status.jsx:486 1706 + #: src/components/status.jsx:487 1707 1707 msgid "Read more →" 1708 1708 msgstr "" 1709 1709 ··· 1728 1728 #: src/components/poll.jsx:208 1729 1729 #: src/components/poll.jsx:210 1730 1730 #: src/pages/scheduled-posts.jsx:100 1731 - #: src/pages/status.jsx:1295 1732 - #: src/pages/status.jsx:1318 1731 + #: src/pages/status.jsx:1312 1732 + #: src/pages/status.jsx:1335 1733 1733 msgid "Refresh" 1734 1734 msgstr "" 1735 1735 ··· 2030 2030 msgstr "" 2031 2031 2032 2032 #: src/components/shortcuts-settings.jsx:379 2033 - #: src/components/status.jsx:1555 2033 + #: src/components/status.jsx:1556 2034 2034 #: src/pages/list.jsx:195 2035 2035 msgid "Edit" 2036 2036 msgstr "" ··· 2229 2229 msgid "Import/export settings from/to instance server (Very experimental)" 2230 2230 msgstr "" 2231 2231 2232 - #: src/components/status.jsx:351 2232 + #: src/components/status.jsx:352 2233 2233 msgid "Unable to format math" 2234 2234 msgstr "Unable to format math" 2235 2235 2236 - #: src/components/status.jsx:365 2236 + #: src/components/status.jsx:366 2237 2237 msgid "Math expressions found." 2238 2238 msgstr "Math expressions found." 2239 2239 2240 2240 #. Action to switch from rendered math back to raw (LaTeX) markup 2241 - #: src/components/status.jsx:368 2241 + #: src/components/status.jsx:369 2242 2242 msgid "Show markup" 2243 2243 msgstr "Show markup" 2244 2244 2245 2245 #. Action to render math expressions from raw (LaTeX) markup 2246 - #: src/components/status.jsx:373 2246 + #: src/components/status.jsx:374 2247 2247 msgid "Format math" 2248 2248 msgstr "Format math" 2249 2249 2250 - #: src/components/status.jsx:772 2250 + #: src/components/status.jsx:773 2251 2251 msgid "<0/> <1>boosted</1>" 2252 2252 msgstr "<0/> <1>boosted</1>" 2253 2253 2254 - #: src/components/status.jsx:875 2254 + #: src/components/status.jsx:876 2255 2255 msgid "Sorry, your current logged-in instance can't interact with this post from another instance." 2256 2256 msgstr "" 2257 2257 2258 2258 #. placeholder {0}: username || acct 2259 - #: src/components/status.jsx:1029 2259 + #: src/components/status.jsx:1030 2260 2260 msgid "Unliked @{0}'s post" 2261 2261 msgstr "" 2262 2262 2263 2263 #. placeholder {0}: username || acct 2264 - #: src/components/status.jsx:1030 2264 + #: src/components/status.jsx:1031 2265 2265 msgid "Liked @{0}'s post" 2266 2266 msgstr "Liked @{0}'s post" 2267 2267 2268 2268 #. placeholder {0}: username || acct 2269 - #: src/components/status.jsx:1069 2269 + #: src/components/status.jsx:1070 2270 2270 msgid "Unbookmarked @{0}'s post" 2271 2271 msgstr "Unbookmarked @{0}'s post" 2272 2272 2273 2273 #. placeholder {0}: username || acct 2274 - #: src/components/status.jsx:1070 2274 + #: src/components/status.jsx:1071 2275 2275 msgid "Bookmarked @{0}'s post" 2276 2276 msgstr "Bookmarked @{0}'s post" 2277 2277 2278 - #: src/components/status.jsx:1167 2278 + #: src/components/status.jsx:1168 2279 2279 msgid "Some media have no descriptions." 2280 2280 msgstr "" 2281 2281 2282 2282 #. placeholder {0}: rtf.format(-statusMonthsAgo, 'month') 2283 - #: src/components/status.jsx:1174 2283 + #: src/components/status.jsx:1175 2284 2284 msgid "Old post (<0>{0}</0>)" 2285 2285 msgstr "" 2286 2286 2287 - #: src/components/status.jsx:1198 2288 - #: src/components/status.jsx:1238 2289 - #: src/components/status.jsx:2698 2290 - #: src/components/status.jsx:2721 2287 + #: src/components/status.jsx:1199 2288 + #: src/components/status.jsx:1239 2289 + #: src/components/status.jsx:2701 2290 + #: src/components/status.jsx:2724 2291 2291 msgid "Unboost" 2292 2292 msgstr "" 2293 2293 2294 - #: src/components/status.jsx:1214 2295 - #: src/components/status.jsx:2713 2294 + #: src/components/status.jsx:1215 2295 + #: src/components/status.jsx:2716 2296 2296 msgid "Quote" 2297 2297 msgstr "" 2298 2298 2299 2299 #. placeholder {0}: username || acct 2300 - #: src/components/status.jsx:1226 2301 - #: src/components/status.jsx:1692 2300 + #: src/components/status.jsx:1227 2301 + #: src/components/status.jsx:1693 2302 2302 msgid "Unboosted @{0}'s post" 2303 2303 msgstr "Unboosted @{0}'s post" 2304 2304 2305 2305 #. placeholder {0}: username || acct 2306 - #: src/components/status.jsx:1227 2307 - #: src/components/status.jsx:1693 2306 + #: src/components/status.jsx:1228 2307 + #: src/components/status.jsx:1694 2308 2308 msgid "Boosted @{0}'s post" 2309 2309 msgstr "Boosted @{0}'s post" 2310 2310 2311 - #: src/components/status.jsx:1239 2311 + #: src/components/status.jsx:1240 2312 2312 msgid "Boost…" 2313 2313 msgstr "" 2314 2314 2315 - #: src/components/status.jsx:1251 2316 - #: src/components/status.jsx:1986 2317 - #: src/components/status.jsx:2734 2315 + #: src/components/status.jsx:1252 2316 + #: src/components/status.jsx:1987 2317 + #: src/components/status.jsx:2737 2318 2318 msgid "Unlike" 2319 2319 msgstr "" 2320 2320 2321 - #: src/components/status.jsx:1252 2322 - #: src/components/status.jsx:1986 2321 + #: src/components/status.jsx:1253 2323 2322 #: src/components/status.jsx:1987 2324 - #: src/components/status.jsx:2734 2325 - #: src/components/status.jsx:2735 2323 + #: src/components/status.jsx:1988 2324 + #: src/components/status.jsx:2737 2325 + #: src/components/status.jsx:2738 2326 2326 msgid "Like" 2327 2327 msgstr "" 2328 2328 2329 - #: src/components/status.jsx:1261 2330 - #: src/components/status.jsx:2746 2329 + #: src/components/status.jsx:1262 2330 + #: src/components/status.jsx:2749 2331 2331 msgid "Unbookmark" 2332 2332 msgstr "" 2333 2333 2334 - #: src/components/status.jsx:1344 2334 + #: src/components/status.jsx:1345 2335 2335 msgid "Post text copied" 2336 2336 msgstr "Post text copied" 2337 2337 2338 - #: src/components/status.jsx:1347 2338 + #: src/components/status.jsx:1348 2339 2339 msgid "Unable to copy post text" 2340 2340 msgstr "Unable to copy post text" 2341 2341 2342 - #: src/components/status.jsx:1353 2342 + #: src/components/status.jsx:1354 2343 2343 msgid "Copy post text" 2344 2344 msgstr "Copy post text" 2345 2345 2346 2346 #. placeholder {0}: username || acct 2347 - #: src/components/status.jsx:1371 2347 + #: src/components/status.jsx:1372 2348 2348 msgid "View post by <0>@{0}</0>" 2349 2349 msgstr "" 2350 2350 2351 - #: src/components/status.jsx:1392 2351 + #: src/components/status.jsx:1393 2352 2352 msgid "Show Edit History" 2353 2353 msgstr "" 2354 2354 2355 - #: src/components/status.jsx:1395 2355 + #: src/components/status.jsx:1396 2356 2356 msgid "Edited: {editedDateText}" 2357 2357 msgstr "" 2358 2358 2359 - #: src/components/status.jsx:1462 2360 - #: src/components/status.jsx:3514 2359 + #: src/components/status.jsx:1463 2360 + #: src/components/status.jsx:3517 2361 2361 msgid "Embed post" 2362 2362 msgstr "" 2363 2363 2364 - #: src/components/status.jsx:1476 2364 + #: src/components/status.jsx:1477 2365 2365 msgid "Conversation unmuted" 2366 2366 msgstr "" 2367 2367 2368 - #: src/components/status.jsx:1476 2368 + #: src/components/status.jsx:1477 2369 2369 msgid "Conversation muted" 2370 2370 msgstr "" 2371 2371 2372 - #: src/components/status.jsx:1482 2372 + #: src/components/status.jsx:1483 2373 2373 msgid "Unable to unmute conversation" 2374 2374 msgstr "" 2375 2375 2376 - #: src/components/status.jsx:1483 2376 + #: src/components/status.jsx:1484 2377 2377 msgid "Unable to mute conversation" 2378 2378 msgstr "" 2379 2379 2380 - #: src/components/status.jsx:1492 2380 + #: src/components/status.jsx:1493 2381 2381 msgid "Unmute conversation" 2382 2382 msgstr "" 2383 2383 2384 - #: src/components/status.jsx:1499 2384 + #: src/components/status.jsx:1500 2385 2385 msgid "Mute conversation" 2386 2386 msgstr "" 2387 2387 2388 - #: src/components/status.jsx:1515 2388 + #: src/components/status.jsx:1516 2389 2389 msgid "Post unpinned from profile" 2390 2390 msgstr "" 2391 2391 2392 - #: src/components/status.jsx:1516 2392 + #: src/components/status.jsx:1517 2393 2393 msgid "Post pinned to profile" 2394 2394 msgstr "" 2395 2395 2396 - #: src/components/status.jsx:1521 2396 + #: src/components/status.jsx:1522 2397 2397 msgid "Unable to unpin post" 2398 2398 msgstr "" 2399 2399 2400 - #: src/components/status.jsx:1521 2400 + #: src/components/status.jsx:1522 2401 2401 msgid "Unable to pin post" 2402 2402 msgstr "" 2403 2403 2404 - #: src/components/status.jsx:1530 2404 + #: src/components/status.jsx:1531 2405 2405 msgid "Unpin from profile" 2406 2406 msgstr "" 2407 2407 2408 - #: src/components/status.jsx:1537 2408 + #: src/components/status.jsx:1538 2409 2409 msgid "Pin to profile" 2410 2410 msgstr "" 2411 2411 2412 - #: src/components/status.jsx:1566 2412 + #: src/components/status.jsx:1567 2413 2413 msgid "Delete this post?" 2414 2414 msgstr "" 2415 2415 2416 - #: src/components/status.jsx:1582 2416 + #: src/components/status.jsx:1583 2417 2417 msgid "Post deleted" 2418 2418 msgstr "" 2419 2419 2420 - #: src/components/status.jsx:1585 2420 + #: src/components/status.jsx:1586 2421 2421 msgid "Unable to delete post" 2422 2422 msgstr "" 2423 2423 2424 - #: src/components/status.jsx:1613 2424 + #: src/components/status.jsx:1614 2425 2425 msgid "Report post…" 2426 2426 msgstr "" 2427 2427 2428 - #: src/components/status.jsx:1987 2429 - #: src/components/status.jsx:2023 2430 - #: src/components/status.jsx:2735 2428 + #: src/components/status.jsx:1988 2429 + #: src/components/status.jsx:2024 2430 + #: src/components/status.jsx:2738 2431 2431 msgid "Liked" 2432 2432 msgstr "" 2433 2433 2434 - #: src/components/status.jsx:2020 2435 - #: src/components/status.jsx:2722 2434 + #: src/components/status.jsx:2021 2435 + #: src/components/status.jsx:2725 2436 2436 msgid "Boosted" 2437 2437 msgstr "" 2438 2438 2439 - #: src/components/status.jsx:2030 2440 - #: src/components/status.jsx:2747 2439 + #: src/components/status.jsx:2031 2440 + #: src/components/status.jsx:2750 2441 2441 msgid "Bookmarked" 2442 2442 msgstr "" 2443 2443 2444 - #: src/components/status.jsx:2034 2444 + #: src/components/status.jsx:2035 2445 2445 msgid "Pinned" 2446 2446 msgstr "" 2447 2447 2448 - #: src/components/status.jsx:2080 2449 - #: src/components/status.jsx:2559 2448 + #: src/components/status.jsx:2087 2449 + #: src/components/status.jsx:2562 2450 2450 msgid "Deleted" 2451 2451 msgstr "" 2452 2452 2453 - #: src/components/status.jsx:2121 2453 + #: src/components/status.jsx:2128 2454 2454 msgid "{repliesCount, plural, one {# reply} other {# replies}}" 2455 2455 msgstr "" 2456 2456 2457 - #. placeholder {0}: snapStates.statusThreadNumber[sKey] ? ` ${snapStates.statusThreadNumber[sKey]}/X` : '' 2458 - #: src/components/status.jsx:2211 2459 - msgid "Thread{0}" 2460 - msgstr "" 2461 - 2462 - #: src/components/status.jsx:2289 2463 - #: src/components/status.jsx:2351 2464 - #: src/components/status.jsx:2455 2457 + #: src/components/status.jsx:2292 2458 + #: src/components/status.jsx:2354 2459 + #: src/components/status.jsx:2458 2465 2460 msgid "Show less" 2466 2461 msgstr "" 2467 2462 2468 - #: src/components/status.jsx:2289 2469 - #: src/components/status.jsx:2351 2463 + #: src/components/status.jsx:2292 2464 + #: src/components/status.jsx:2354 2470 2465 msgid "Show content" 2471 2466 msgstr "" 2472 2467 2473 2468 #. placeholder {0}: filterInfo.titlesStr 2474 2469 #. placeholder {0}: filterInfo?.titlesStr 2475 - #: src/components/status.jsx:2451 2470 + #: src/components/status.jsx:2454 2476 2471 #: src/pages/catchup.jsx:1879 2477 2472 msgid "Filtered: {0}" 2478 2473 msgstr "Filtered: {0}" 2479 2474 2480 - #: src/components/status.jsx:2455 2475 + #: src/components/status.jsx:2458 2481 2476 msgid "Show media" 2482 2477 msgstr "" 2483 2478 2484 - #: src/components/status.jsx:2595 2479 + #: src/components/status.jsx:2598 2485 2480 msgid "Edited" 2486 2481 msgstr "" 2487 2482 2488 - #: src/components/status.jsx:2672 2483 + #: src/components/status.jsx:2675 2489 2484 msgid "Comments" 2490 2485 msgstr "" 2491 2486 2492 2487 #. More from [Author] 2493 - #: src/components/status.jsx:2972 2488 + #: src/components/status.jsx:2975 2494 2489 msgid "More from <0/>" 2495 2490 msgstr "More from <0/>" 2496 2491 2497 - #: src/components/status.jsx:3274 2492 + #: src/components/status.jsx:3277 2498 2493 msgid "Edit History" 2499 2494 msgstr "" 2500 2495 2501 - #: src/components/status.jsx:3278 2496 + #: src/components/status.jsx:3281 2502 2497 msgid "Failed to load history" 2503 2498 msgstr "" 2504 2499 2505 - #: src/components/status.jsx:3283 2500 + #: src/components/status.jsx:3286 2506 2501 #: src/pages/annual-report.jsx:45 2507 2502 msgid "Loading…" 2508 2503 msgstr "" 2509 2504 2510 - #: src/components/status.jsx:3519 2505 + #: src/components/status.jsx:3522 2511 2506 msgid "HTML Code" 2512 2507 msgstr "" 2513 2508 2514 - #: src/components/status.jsx:3536 2509 + #: src/components/status.jsx:3539 2515 2510 msgid "HTML code copied" 2516 2511 msgstr "" 2517 2512 2518 - #: src/components/status.jsx:3539 2513 + #: src/components/status.jsx:3542 2519 2514 msgid "Unable to copy HTML code" 2520 2515 msgstr "" 2521 2516 2522 - #: src/components/status.jsx:3551 2517 + #: src/components/status.jsx:3554 2523 2518 msgid "Media attachments:" 2524 2519 msgstr "" 2525 2520 2526 - #: src/components/status.jsx:3573 2521 + #: src/components/status.jsx:3576 2527 2522 msgid "Account Emojis:" 2528 2523 msgstr "" 2529 2524 2530 - #: src/components/status.jsx:3604 2531 - #: src/components/status.jsx:3649 2525 + #: src/components/status.jsx:3607 2526 + #: src/components/status.jsx:3652 2532 2527 msgid "static URL" 2533 2528 msgstr "" 2534 2529 2535 - #: src/components/status.jsx:3618 2530 + #: src/components/status.jsx:3621 2536 2531 msgid "Emojis:" 2537 2532 msgstr "" 2538 2533 2539 - #: src/components/status.jsx:3663 2534 + #: src/components/status.jsx:3666 2540 2535 msgid "Notes:" 2541 2536 msgstr "" 2542 2537 2543 - #: src/components/status.jsx:3667 2538 + #: src/components/status.jsx:3670 2544 2539 msgid "This is static, unstyled and scriptless. You may need to apply your own styles and edit as needed." 2545 2540 msgstr "" 2546 2541 2547 - #: src/components/status.jsx:3673 2542 + #: src/components/status.jsx:3676 2548 2543 msgid "Polls are not interactive, becomes a list with vote counts." 2549 2544 msgstr "" 2550 2545 2551 - #: src/components/status.jsx:3678 2546 + #: src/components/status.jsx:3681 2552 2547 msgid "Media attachments can be images, videos, audios or any file types." 2553 2548 msgstr "" 2554 2549 2555 - #: src/components/status.jsx:3684 2550 + #: src/components/status.jsx:3687 2556 2551 msgid "Post could be edited or deleted later." 2557 2552 msgstr "" 2558 2553 2559 - #: src/components/status.jsx:3690 2554 + #: src/components/status.jsx:3693 2560 2555 msgid "Preview" 2561 2556 msgstr "" 2562 2557 2563 - #: src/components/status.jsx:3699 2558 + #: src/components/status.jsx:3702 2564 2559 msgid "Note: This preview is lightly styled." 2565 2560 msgstr "" 2566 2561 2567 2562 #. [Name] [Visibility icon] boosted 2568 - #: src/components/status.jsx:3952 2563 + #: src/components/status.jsx:3955 2569 2564 msgid "<0/> <1/> boosted" 2570 2565 msgstr "<0/> <1/> boosted" 2571 2566 2572 - #: src/components/status.jsx:4054 2567 + #: src/components/status.jsx:4057 2573 2568 msgid "Post hidden by your filters" 2574 2569 msgstr "Post hidden by your filters" 2575 2570 2576 - #: src/components/status.jsx:4055 2571 + #: src/components/status.jsx:4058 2577 2572 msgid "Post pending" 2578 2573 msgstr "Post pending" 2579 2574 2580 - #: src/components/status.jsx:4056 2581 - #: src/components/status.jsx:4057 2582 - #: src/components/status.jsx:4058 2583 2575 #: src/components/status.jsx:4059 2576 + #: src/components/status.jsx:4060 2577 + #: src/components/status.jsx:4061 2578 + #: src/components/status.jsx:4062 2584 2579 msgid "Post unavailable" 2585 2580 msgstr "Post unavailable" 2586 2581 2587 - #: src/components/timeline.jsx:485 2582 + #: src/components/thread-badge.jsx:22 2583 + #: src/components/thread-badge.jsx:37 2584 + #: src/components/thread-badge.jsx:52 2585 + #: src/pages/catchup.jsx:1897 2586 + msgid "Thread" 2587 + msgstr "" 2588 + 2589 + #: src/components/thread-badge.jsx:28 2590 + msgid "Thread {index}/{total}" 2591 + msgstr "Thread {index}/{total}" 2592 + 2593 + #. X is the unspecified total number of posts in a thread 2594 + #: src/components/thread-badge.jsx:32 2595 + msgid "Thread {index}/X" 2596 + msgstr "Thread {index}/X" 2597 + 2598 + #. index/total posts in a thread 2599 + #: src/components/thread-badge.jsx:41 2600 + msgid "{index}/{total}" 2601 + msgstr "{index}/{total}" 2602 + 2603 + #. X is the unspecified total number of posts in a thread 2604 + #: src/components/thread-badge.jsx:46 2605 + msgid "{index}/X" 2606 + msgstr "{index}/X" 2607 + 2608 + #: src/components/timeline.jsx:486 2588 2609 #: src/pages/settings.jsx:1218 2589 2610 msgid "New posts" 2590 2611 msgstr "" 2591 2612 2592 - #: src/components/timeline.jsx:586 2613 + #: src/components/timeline.jsx:587 2593 2614 #: src/pages/home.jsx:228 2594 2615 #: src/pages/notifications.jsx:898 2595 - #: src/pages/status.jsx:1078 2596 - #: src/pages/status.jsx:1455 2616 + #: src/pages/status.jsx:1093 2617 + #: src/pages/status.jsx:1472 2597 2618 msgid "Try again" 2598 2619 msgstr "" 2599 2620 2600 2621 #. placeholder {0}: fItems.length 2601 - #: src/components/timeline.jsx:621 2622 + #: src/components/timeline.jsx:622 2602 2623 msgid "{0, plural, one {# Boost} other {# Boosts}}" 2603 2624 msgstr "{0, plural, one {# Boost} other {# Boosts}}" 2604 2625 2605 - #: src/components/timeline.jsx:626 2626 + #: src/components/timeline.jsx:627 2606 2627 msgid "Pinned posts" 2607 2628 msgstr "Pinned posts" 2608 2629 2609 - #: src/components/timeline.jsx:985 2610 - #: src/components/timeline.jsx:992 2611 - #: src/pages/catchup.jsx:1897 2612 - msgid "Thread" 2613 - msgstr "" 2614 - 2615 2630 #. placeholder {0}: filterInfo.titlesStr 2616 - #: src/components/timeline.jsx:1007 2631 + #: src/components/timeline.jsx:999 2617 2632 msgid "<0>Filtered</0>: <1>{0}</1>" 2618 2633 msgstr "" 2619 2634 ··· 3914 3929 msgstr "" 3915 3930 3916 3931 #. js-lingui-explicit-id 3917 - #: src/pages/status.jsx:658 3918 - #: src/pages/status.jsx:1221 3932 + #: src/pages/status.jsx:673 3933 + #: src/pages/status.jsx:1237 3919 3934 msgid "post.title" 3920 3935 msgstr "Post" 3921 3936 3922 - #: src/pages/status.jsx:912 3937 + #: src/pages/status.jsx:927 3923 3938 msgid "You're not logged in. Interactions (reply, boost, etc) are not possible." 3924 3939 msgstr "" 3925 3940 3926 - #: src/pages/status.jsx:932 3941 + #: src/pages/status.jsx:947 3927 3942 msgid "This post is from another instance (<0>{instance}</0>). Interactions (reply, boost, etc) are not possible." 3928 3943 msgstr "" 3929 3944 3930 - #: src/pages/status.jsx:960 3945 + #: src/pages/status.jsx:975 3931 3946 msgid "Error: {e}" 3932 3947 msgstr "" 3933 3948 3934 - #: src/pages/status.jsx:967 3949 + #: src/pages/status.jsx:982 3935 3950 msgid "Switch to my instance to enable interactions" 3936 3951 msgstr "" 3937 3952 3938 - #: src/pages/status.jsx:1069 3953 + #: src/pages/status.jsx:1084 3939 3954 msgid "Unable to load replies." 3940 3955 msgstr "" 3941 3956 3942 - #: src/pages/status.jsx:1181 3957 + #: src/pages/status.jsx:1197 3943 3958 msgid "Back" 3944 3959 msgstr "" 3945 3960 3946 - #: src/pages/status.jsx:1212 3961 + #: src/pages/status.jsx:1228 3947 3962 msgid "Go to main post" 3948 3963 msgstr "" 3949 3964 3950 3965 #. placeholder {0}: ancestors.length 3951 - #: src/pages/status.jsx:1235 3966 + #: src/pages/status.jsx:1251 3952 3967 msgid "{0} posts above ‒ Go to top" 3953 3968 msgstr "" 3954 3969 3955 - #: src/pages/status.jsx:1282 3956 - #: src/pages/status.jsx:1345 3970 + #: src/pages/status.jsx:1299 3971 + #: src/pages/status.jsx:1362 3957 3972 msgid "Switch to Side Peek view" 3958 3973 msgstr "" 3959 3974 3960 - #: src/pages/status.jsx:1346 3975 + #: src/pages/status.jsx:1363 3961 3976 msgid "Switch to Full view" 3962 3977 msgstr "" 3963 3978 3964 - #: src/pages/status.jsx:1364 3979 + #: src/pages/status.jsx:1381 3965 3980 msgid "Show all sensitive content" 3966 3981 msgstr "" 3967 3982 3968 - #: src/pages/status.jsx:1369 3983 + #: src/pages/status.jsx:1386 3969 3984 msgid "Experimental" 3970 3985 msgstr "" 3971 3986 3972 - #: src/pages/status.jsx:1378 3987 + #: src/pages/status.jsx:1395 3973 3988 msgid "Unable to switch" 3974 3989 msgstr "" 3975 3990 3976 3991 #. placeholder {0}: punycode.toUnicode( postInstance, ) 3977 - #: src/pages/status.jsx:1385 3992 + #: src/pages/status.jsx:1402 3978 3993 msgid "Switch to post's instance ({0})" 3979 3994 msgstr "Switch to post's instance ({0})" 3980 3995 3981 - #: src/pages/status.jsx:1388 3996 + #: src/pages/status.jsx:1405 3982 3997 msgid "Switch to post's instance" 3983 3998 msgstr "" 3984 3999 3985 - #: src/pages/status.jsx:1446 4000 + #: src/pages/status.jsx:1463 3986 4001 msgid "Unable to load post" 3987 4002 msgstr "" 3988 4003 3989 4004 #. placeholder {0}: replies.length 3990 4005 #. placeholder {1}: shortenNumber(replies.length) 3991 - #: src/pages/status.jsx:1582 4006 + #: src/pages/status.jsx:1600 3992 4007 msgid "{0, plural, one {# reply} other {<0>{1}</0> replies}}" 3993 4008 msgstr "" 3994 4009 3995 4010 #. placeholder {0}: shortenNumber(totalComments) 3996 - #: src/pages/status.jsx:1600 4011 + #: src/pages/status.jsx:1618 3997 4012 msgid "{totalComments, plural, one {# comment} other {<0>{0}</0> comments}}" 3998 4013 msgstr "" 3999 4014 4000 - #: src/pages/status.jsx:1622 4015 + #: src/pages/status.jsx:1640 4001 4016 msgid "View post with its replies" 4002 4017 msgstr "" 4003 4018
+323 -305
src/pages/status.jsx
··· 72 72 73 73 const STATUS_URL_REGEX = /\/s\//i; 74 74 75 + import { ThreadCountContext } from '../utils/thread-count-context'; 76 + 75 77 function StatusPage(params) { 76 78 const { t } = useLingui(); 77 79 const { id } = params; ··· 327 329 328 330 const scrollOffsets = useRef(); 329 331 const lastInitContextTS = useRef(); 332 + const [threadsCount, setThreadsCount] = useState(0); 330 333 const initContext = ({ reloadHero } = {}) => { 331 334 console.debug('initContext', id); 332 335 setUIState('loading'); ··· 410 413 const nestedDescendants = []; 411 414 descendants.forEach((status) => { 412 415 saveStatus(status, instance, { 413 - skipThreading: true, 416 + // skipThreading: true, 414 417 }); 415 418 416 419 if ( ··· 485 488 })); 486 489 } 487 490 491 + const mappedNestedDescendants = nestedDescendants.map((s) => ({ 492 + id: s.id, 493 + account: s.account, 494 + accountID: s.account.id, 495 + descendant: true, 496 + thread: s.account.id === heroStatus.account.id, 497 + weight: calcStatusWeight(s), 498 + level: 1, 499 + replies: expandReplies(s.__replies, 1), 500 + })); 488 501 const allStatuses = [ 489 502 ...ancestors.map((s) => ({ 490 503 id: s.id, ··· 500 513 accountID: heroStatus.account.id, 501 514 weight: calcStatusWeight(heroStatus), 502 515 }, 503 - ...nestedDescendants.map((s) => ({ 504 - id: s.id, 505 - account: s.account, 506 - accountID: s.account.id, 507 - descendant: true, 508 - thread: s.account.id === heroStatus.account.id, 509 - weight: calcStatusWeight(s), 510 - level: 1, 511 - replies: expandReplies(s.__replies, 1), 512 - })), 516 + ...mappedNestedDescendants, 513 517 ]; 518 + 519 + const descendantsThread = 520 + ancestors.length && !ancestorsIsThread 521 + ? [] 522 + : mappedNestedDescendants.filter((s) => s.thread); 523 + const threadsCount = 524 + (ancestorsIsThread ? ancestors.length : 0) + descendantsThread.length; 525 + if (threadsCount) { 526 + // Include hero as part of thread count 527 + setThreadsCount(threadsCount + 1); 528 + } 514 529 515 530 setUIState('default'); 516 531 scrollOffsets.current = { ··· 1137 1152 }, [id]); 1138 1153 1139 1154 return ( 1140 - <div 1141 - tabIndex="-1" 1142 - ref={scrollableRef} 1143 - class={`status-deck deck contained ${ 1144 - statuses.length > 1 ? 'padded-bottom' : '' 1145 - } ${ 1146 - initialPageState.current === 'status' && !firstLoad.current 1147 - ? 'slide-in' 1148 - : '' 1149 - } ${viewMode ? `deck-view-${viewMode}` : ''}`} 1150 - onAnimationEnd={(e) => { 1151 - // Fix the bounce effect when switching viewMode 1152 - // `slide-in` animation kicks in when switching viewMode 1153 - if (initialPageState.current === 'status') { 1154 - // e.target.classList.remove('slide-in'); 1155 - initialPageState.current = null; 1156 - } 1157 - }} 1158 - > 1159 - <header 1160 - class={`${uiState === 'loading' ? 'loading' : ''}`} 1161 - onDblClick={(e) => { 1162 - // reload statuses 1163 - states.reloadStatusPage++; 1155 + <ThreadCountContext.Provider value={threadsCount}> 1156 + <div 1157 + tabIndex="-1" 1158 + ref={scrollableRef} 1159 + class={`status-deck deck contained ${ 1160 + statuses.length > 1 ? 'padded-bottom' : '' 1161 + } ${ 1162 + initialPageState.current === 'status' && !firstLoad.current 1163 + ? 'slide-in' 1164 + : '' 1165 + } ${viewMode ? `deck-view-${viewMode}` : ''}`} 1166 + onAnimationEnd={(e) => { 1167 + // Fix the bounce effect when switching viewMode 1168 + // `slide-in` animation kicks in when switching viewMode 1169 + if (initialPageState.current === 'status') { 1170 + // e.target.classList.remove('slide-in'); 1171 + initialPageState.current = null; 1172 + } 1164 1173 }} 1165 1174 > 1166 - {/* <div> 1175 + <header 1176 + class={`${uiState === 'loading' ? 'loading' : ''}`} 1177 + onDblClick={(e) => { 1178 + // reload statuses 1179 + states.reloadStatusPage++; 1180 + }} 1181 + > 1182 + {/* <div> 1167 1183 <Link class="button plain deck-close" href={closeLink}> 1168 1184 <Icon icon="chevron-left" size="xl" /> 1169 1185 </Link> 1170 1186 </div> */} 1171 - <div class="header-grid header-grid-2"> 1172 - <h1> 1173 - {prevLocationIsStatusPage && ( 1187 + <div class="header-grid header-grid-2"> 1188 + <h1> 1189 + {prevLocationIsStatusPage && ( 1190 + <button 1191 + type="button" 1192 + class="plain deck-back" 1193 + onClick={() => { 1194 + history.back(); 1195 + }} 1196 + > 1197 + <Icon icon="chevron-left" size="xl" alt={t`Back`} /> 1198 + </button> 1199 + )} 1200 + {!heroInView && heroStatus && uiState !== 'loading' ? ( 1201 + <> 1202 + <span class="hero-heading"> 1203 + <NameText 1204 + account={heroStatus.account} 1205 + instance={instance} 1206 + showAvatar 1207 + short 1208 + />{' '} 1209 + <span class="insignificant"> 1210 + &bull;{' '} 1211 + <RelativeTime 1212 + datetime={heroStatus.createdAt} 1213 + format="micro" 1214 + /> 1215 + </span> 1216 + </span>{' '} 1217 + <button 1218 + type="button" 1219 + class="ancestors-indicator light small" 1220 + onClick={(e) => { 1221 + e.preventDefault(); 1222 + e.stopPropagation(); 1223 + heroStatusRef.current.scrollIntoView({ 1224 + behavior: 'smooth', 1225 + block: 'start', 1226 + }); 1227 + }} 1228 + title={t`Go to main post`} 1229 + > 1230 + <Icon 1231 + icon={heroPointer === 'down' ? 'arrow-down' : 'arrow-up'} 1232 + /> 1233 + </button> 1234 + </> 1235 + ) : ( 1236 + <> 1237 + <Trans id="post.title">Post</Trans>{' '} 1238 + <button 1239 + type="button" 1240 + class="ancestors-indicator light small" 1241 + onClick={(e) => { 1242 + // Scroll to top 1243 + e.preventDefault(); 1244 + e.stopPropagation(); 1245 + scrollableRef.current.scrollTo({ 1246 + top: 0, 1247 + behavior: 'smooth', 1248 + }); 1249 + }} 1250 + hidden={!ancestors.length || reachTopPost} 1251 + title={t`${ancestors.length} posts above ‒ Go to top`} 1252 + > 1253 + <Icon icon="arrow-up" /> 1254 + {ancestors 1255 + .filter( 1256 + (a, i, arr) => 1257 + arr.findIndex((b) => b.accountID === a.accountID) === 1258 + i, 1259 + ) 1260 + .slice(0, 3) 1261 + .map((ancestor) => ( 1262 + <Avatar 1263 + key={ancestor.account.id} 1264 + url={ 1265 + ancestor.account.avatarStatic || 1266 + ancestor.account.avatar 1267 + } 1268 + alt={ancestor.account.displayName} 1269 + squircle={ancestor.account?.bot} 1270 + /> 1271 + ))} 1272 + {/* <Icon icon="comment" />{' '} */} 1273 + {ancestors.length > 3 && ( 1274 + <> 1275 + {' '} 1276 + <span class="insignificant"> 1277 + {shortenNumber(ancestors.length)} 1278 + </span> 1279 + </> 1280 + )} 1281 + </button> 1282 + </> 1283 + )} 1284 + </h1> 1285 + <div class="header-side"> 1174 1286 <button 1175 1287 type="button" 1176 - class="plain deck-back" 1288 + class="plain4 button-switch-view" 1289 + style={{ 1290 + display: viewMode === 'full' ? '' : 'none', 1291 + }} 1177 1292 onClick={() => { 1178 - history.back(); 1293 + setViewMode(null); 1294 + searchParams.delete('media'); 1295 + searchParams.delete('media-only'); 1296 + searchParams.delete('view'); 1297 + setSearchParams(searchParams); 1179 1298 }} 1299 + title={t`Switch to Side Peek view`} 1180 1300 > 1181 - <Icon icon="chevron-left" size="xl" alt={t`Back`} /> 1301 + <Icon icon="layout4" size="l" /> 1182 1302 </button> 1183 - )} 1184 - {!heroInView && heroStatus && uiState !== 'loading' ? ( 1185 - <> 1186 - <span class="hero-heading"> 1187 - <NameText 1188 - account={heroStatus.account} 1189 - instance={instance} 1190 - showAvatar 1191 - short 1192 - />{' '} 1193 - <span class="insignificant"> 1194 - &bull;{' '} 1195 - <RelativeTime 1196 - datetime={heroStatus.createdAt} 1197 - format="micro" 1198 - /> 1199 - </span> 1200 - </span>{' '} 1303 + {showRefresh && ( 1201 1304 <button 1202 1305 type="button" 1203 - class="ancestors-indicator light small" 1204 - onClick={(e) => { 1205 - e.preventDefault(); 1206 - e.stopPropagation(); 1207 - heroStatusRef.current.scrollIntoView({ 1208 - behavior: 'smooth', 1209 - block: 'start', 1210 - }); 1306 + class="plain button-refresh" 1307 + onClick={() => { 1308 + states.reloadStatusPage++; 1309 + setShowRefresh(false); 1310 + }} 1311 + > 1312 + <Icon icon="refresh" size="l" alt={t`Refresh`} /> 1313 + </button> 1314 + )} 1315 + <Menu2 1316 + align="end" 1317 + portal={{ 1318 + // Need this, else the menu click will cause scroll jump 1319 + target: scrollableRef.current, 1320 + }} 1321 + menuButton={ 1322 + <button type="button" class="button plain4"> 1323 + <Icon icon="more" alt={t`More`} size="xl" /> 1324 + </button> 1325 + } 1326 + > 1327 + <MenuItem 1328 + disabled={uiState === 'loading'} 1329 + onClick={() => { 1330 + states.reloadStatusPage++; 1211 1331 }} 1212 - title={t`Go to main post`} 1332 + > 1333 + <Icon icon="refresh" /> 1334 + <span> 1335 + <Trans>Refresh</Trans> 1336 + </span> 1337 + </MenuItem> 1338 + <MenuItem 1339 + className="menu-switch-view" 1340 + onClick={() => { 1341 + setViewMode(viewMode === 'full' ? null : 'full'); 1342 + searchParams.delete('media'); 1343 + searchParams.delete('media-only'); 1344 + if (viewMode === 'full') { 1345 + searchParams.delete('view'); 1346 + } else { 1347 + searchParams.set('view', 'full'); 1348 + } 1349 + setSearchParams(searchParams); 1350 + }} 1213 1351 > 1214 1352 <Icon 1215 - icon={heroPointer === 'down' ? 'arrow-down' : 'arrow-up'} 1353 + icon={ 1354 + { 1355 + '': 'layout5', 1356 + full: 'layout4', 1357 + }[viewMode || ''] 1358 + } 1216 1359 /> 1217 - </button> 1218 - </> 1219 - ) : ( 1220 - <> 1221 - <Trans id="post.title">Post</Trans>{' '} 1222 - <button 1223 - type="button" 1224 - class="ancestors-indicator light small" 1225 - onClick={(e) => { 1226 - // Scroll to top 1227 - e.preventDefault(); 1228 - e.stopPropagation(); 1229 - scrollableRef.current.scrollTo({ 1230 - top: 0, 1231 - behavior: 'smooth', 1360 + <span> 1361 + {viewMode === 'full' 1362 + ? t`Switch to Side Peek view` 1363 + : t`Switch to Full view`} 1364 + </span> 1365 + </MenuItem> 1366 + <MenuItem 1367 + onClick={() => { 1368 + // Click all buttons with class .spoiler but not .spoiling 1369 + const buttons = Array.from( 1370 + scrollableRef.current.querySelectorAll( 1371 + '.spoiler-button:not(.spoiling), .spoiler-media-button:not(.spoiling)', 1372 + ), 1373 + ); 1374 + buttons.forEach((button) => { 1375 + button.click(); 1232 1376 }); 1233 1377 }} 1234 - hidden={!ancestors.length || reachTopPost} 1235 - title={t`${ancestors.length} posts above ‒ Go to top`} 1378 + > 1379 + <Icon icon="eye-open" />{' '} 1380 + <span> 1381 + <Trans>Show all sensitive content</Trans> 1382 + </span> 1383 + </MenuItem> 1384 + <MenuDivider /> 1385 + <MenuHeader className="plain"> 1386 + <Trans>Experimental</Trans> 1387 + </MenuHeader> 1388 + <MenuItem 1389 + disabled={!postInstance || postSameInstance} 1390 + onClick={() => { 1391 + const statusURL = getInstanceStatusURL(heroStatus.url); 1392 + if (statusURL) { 1393 + location.hash = statusURL; 1394 + } else { 1395 + alert(t`Unable to switch`); 1396 + } 1397 + }} 1398 + > 1399 + <Icon icon="transfer" /> 1400 + <small class="menu-double-lines"> 1401 + {postInstance 1402 + ? t`Switch to post's instance (${punycode.toUnicode( 1403 + postInstance, 1404 + )})` 1405 + : t`Switch to post's instance`} 1406 + </small> 1407 + </MenuItem> 1408 + </Menu2> 1409 + <Link class="button plain deck-close" to={closeLink}> 1410 + <Icon icon="x" size="xl" alt={t`Close`} /> 1411 + </Link> 1412 + </div> 1413 + </div> 1414 + </header> 1415 + {!!statuses.length && heroStatus ? ( 1416 + <ul 1417 + class={`timeline flat contextual grow ${ 1418 + uiState === 'loading' ? 'loading' : '' 1419 + }`} 1420 + > 1421 + {statusesList} 1422 + {showMore > 0 && ( 1423 + <li class="descendant descendant-more"> 1424 + <button 1425 + type="button" 1426 + class="plain block show-more" 1427 + disabled={uiState === 'loading'} 1428 + onClick={() => setLimit((l) => l + LIMIT)} 1429 + style={{ marginBlockEnd: '6em' }} 1430 + data-state-post-ids={moreStatusesKeys.join(' ')} 1236 1431 > 1237 - <Icon icon="arrow-up" /> 1238 - {ancestors 1239 - .filter( 1240 - (a, i, arr) => 1241 - arr.findIndex((b) => b.accountID === a.accountID) === i, 1242 - ) 1243 - .slice(0, 3) 1244 - .map((ancestor) => ( 1432 + <div class="ib avatars-bunch"> 1433 + {/* show avatars for first 5 statuses */} 1434 + {statuses.slice(limit, limit + 5).map((status) => ( 1245 1435 <Avatar 1246 - key={ancestor.account.id} 1247 - url={ 1248 - ancestor.account.avatarStatic || 1249 - ancestor.account.avatar 1250 - } 1251 - alt={ancestor.account.displayName} 1252 - squircle={ancestor.account?.bot} 1436 + key={status.id} 1437 + url={status.account.avatarStatic} 1438 + // title={`${status.avatar.displayName} (@${status.avatar.acct})`} 1253 1439 /> 1254 1440 ))} 1255 - {/* <Icon icon="comment" />{' '} */} 1256 - {ancestors.length > 3 && ( 1257 - <> 1258 - {' '} 1259 - <span class="insignificant"> 1260 - {shortenNumber(ancestors.length)} 1261 - </span> 1262 - </> 1263 - )} 1441 + </div>{' '} 1442 + <div class="ib"> 1443 + <Trans>Show more…</Trans>{' '} 1444 + <span class="tag"> 1445 + {showMore > LIMIT ? `${LIMIT}+` : showMore} 1446 + </span> 1447 + </div> 1264 1448 </button> 1265 - </> 1449 + </li> 1266 1450 )} 1267 - </h1> 1268 - <div class="header-side"> 1269 - <button 1270 - type="button" 1271 - class="plain4 button-switch-view" 1272 - style={{ 1273 - display: viewMode === 'full' ? '' : 'none', 1274 - }} 1275 - onClick={() => { 1276 - setViewMode(null); 1277 - searchParams.delete('media'); 1278 - searchParams.delete('media-only'); 1279 - searchParams.delete('view'); 1280 - setSearchParams(searchParams); 1281 - }} 1282 - title={t`Switch to Side Peek view`} 1283 - > 1284 - <Icon icon="layout4" size="l" /> 1285 - </button> 1286 - {showRefresh && ( 1287 - <button 1288 - type="button" 1289 - class="plain button-refresh" 1290 - onClick={() => { 1291 - states.reloadStatusPage++; 1292 - setShowRefresh(false); 1293 - }} 1294 - > 1295 - <Icon icon="refresh" size="l" alt={t`Refresh`} /> 1296 - </button> 1451 + </ul> 1452 + ) : ( 1453 + <> 1454 + {uiState === 'loading' && ( 1455 + <ul class="timeline flat contextual grow loading"> 1456 + <li> 1457 + <Status skeleton size="l" /> 1458 + </li> 1459 + </ul> 1297 1460 )} 1298 - <Menu2 1299 - align="end" 1300 - portal={{ 1301 - // Need this, else the menu click will cause scroll jump 1302 - target: scrollableRef.current, 1303 - }} 1304 - menuButton={ 1305 - <button type="button" class="button plain4"> 1306 - <Icon icon="more" alt={t`More`} size="xl" /> 1461 + {uiState === 'error' && ( 1462 + <p class="ui-state"> 1463 + <Trans>Unable to load post</Trans> 1464 + <br /> 1465 + <br /> 1466 + <button 1467 + type="button" 1468 + onClick={() => { 1469 + states.reloadStatusPage++; 1470 + }} 1471 + > 1472 + <Trans>Try again</Trans> 1307 1473 </button> 1308 - } 1309 - > 1310 - <MenuItem 1311 - disabled={uiState === 'loading'} 1312 - onClick={() => { 1313 - states.reloadStatusPage++; 1314 - }} 1315 - > 1316 - <Icon icon="refresh" /> 1317 - <span> 1318 - <Trans>Refresh</Trans> 1319 - </span> 1320 - </MenuItem> 1321 - <MenuItem 1322 - className="menu-switch-view" 1323 - onClick={() => { 1324 - setViewMode(viewMode === 'full' ? null : 'full'); 1325 - searchParams.delete('media'); 1326 - searchParams.delete('media-only'); 1327 - if (viewMode === 'full') { 1328 - searchParams.delete('view'); 1329 - } else { 1330 - searchParams.set('view', 'full'); 1331 - } 1332 - setSearchParams(searchParams); 1333 - }} 1334 - > 1335 - <Icon 1336 - icon={ 1337 - { 1338 - '': 'layout5', 1339 - full: 'layout4', 1340 - }[viewMode || ''] 1341 - } 1342 - /> 1343 - <span> 1344 - {viewMode === 'full' 1345 - ? t`Switch to Side Peek view` 1346 - : t`Switch to Full view`} 1347 - </span> 1348 - </MenuItem> 1349 - <MenuItem 1350 - onClick={() => { 1351 - // Click all buttons with class .spoiler but not .spoiling 1352 - const buttons = Array.from( 1353 - scrollableRef.current.querySelectorAll( 1354 - '.spoiler-button:not(.spoiling), .spoiler-media-button:not(.spoiling)', 1355 - ), 1356 - ); 1357 - buttons.forEach((button) => { 1358 - button.click(); 1359 - }); 1360 - }} 1361 - > 1362 - <Icon icon="eye-open" />{' '} 1363 - <span> 1364 - <Trans>Show all sensitive content</Trans> 1365 - </span> 1366 - </MenuItem> 1367 - <MenuDivider /> 1368 - <MenuHeader className="plain"> 1369 - <Trans>Experimental</Trans> 1370 - </MenuHeader> 1371 - <MenuItem 1372 - disabled={!postInstance || postSameInstance} 1373 - onClick={() => { 1374 - const statusURL = getInstanceStatusURL(heroStatus.url); 1375 - if (statusURL) { 1376 - location.hash = statusURL; 1377 - } else { 1378 - alert(t`Unable to switch`); 1379 - } 1380 - }} 1381 - > 1382 - <Icon icon="transfer" /> 1383 - <small class="menu-double-lines"> 1384 - {postInstance 1385 - ? t`Switch to post's instance (${punycode.toUnicode( 1386 - postInstance, 1387 - )})` 1388 - : t`Switch to post's instance`} 1389 - </small> 1390 - </MenuItem> 1391 - </Menu2> 1392 - <Link class="button plain deck-close" to={closeLink}> 1393 - <Icon icon="x" size="xl" alt={t`Close`} /> 1394 - </Link> 1395 - </div> 1396 - </div> 1397 - </header> 1398 - {!!statuses.length && heroStatus ? ( 1399 - <ul 1400 - class={`timeline flat contextual grow ${ 1401 - uiState === 'loading' ? 'loading' : '' 1402 - }`} 1403 - > 1404 - {statusesList} 1405 - {showMore > 0 && ( 1406 - <li class="descendant descendant-more"> 1407 - <button 1408 - type="button" 1409 - class="plain block show-more" 1410 - disabled={uiState === 'loading'} 1411 - onClick={() => setLimit((l) => l + LIMIT)} 1412 - style={{ marginBlockEnd: '6em' }} 1413 - data-state-post-ids={moreStatusesKeys.join(' ')} 1414 - > 1415 - <div class="ib avatars-bunch"> 1416 - {/* show avatars for first 5 statuses */} 1417 - {statuses.slice(limit, limit + 5).map((status) => ( 1418 - <Avatar 1419 - key={status.id} 1420 - url={status.account.avatarStatic} 1421 - // title={`${status.avatar.displayName} (@${status.avatar.acct})`} 1422 - /> 1423 - ))} 1424 - </div>{' '} 1425 - <div class="ib"> 1426 - <Trans>Show more…</Trans>{' '} 1427 - <span class="tag"> 1428 - {showMore > LIMIT ? `${LIMIT}+` : showMore} 1429 - </span> 1430 - </div> 1431 - </button> 1432 - </li> 1433 - )} 1434 - </ul> 1435 - ) : ( 1436 - <> 1437 - {uiState === 'loading' && ( 1438 - <ul class="timeline flat contextual grow loading"> 1439 - <li> 1440 - <Status skeleton size="l" /> 1441 - </li> 1442 - </ul> 1443 - )} 1444 - {uiState === 'error' && ( 1445 - <p class="ui-state"> 1446 - <Trans>Unable to load post</Trans> 1447 - <br /> 1448 - <br /> 1449 - <button 1450 - type="button" 1451 - onClick={() => { 1452 - states.reloadStatusPage++; 1453 - }} 1454 - > 1455 - <Trans>Try again</Trans> 1456 - </button> 1457 - </p> 1458 - )} 1459 - </> 1460 - )} 1461 - </div> 1474 + </p> 1475 + )} 1476 + </> 1477 + )} 1478 + </div> 1479 + </ThreadCountContext.Provider> 1462 1480 ); 1463 1481 } 1464 1482
+3
src/utils/thread-count-context.js
··· 1 + import { createContext } from 'preact'; 2 + 3 + export const ThreadCountContext = createContext(0);