this repo has no description
0
fork

Configure Feed

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

It's time for keyboard-layout-dependant shortcuts

Let's hope this works!

+721 -606
+16 -7
src/components/background-service.jsx
··· 144 144 }); 145 145 146 146 // Global keyboard shortcuts "service" 147 - useHotkeys('shift+alt+k', () => { 148 - const currentCloakMode = states.settings.cloakMode; 149 - states.settings.cloakMode = !currentCloakMode; 150 - showToast({ 151 - text: currentCloakMode ? t`Cloak mode disabled` : t`Cloak mode enabled`, 152 - }); 153 - }); 147 + useHotkeys( 148 + 'shift+alt+k', 149 + (e) => { 150 + // Need modifers check due to useKey: true 151 + if (!e.shiftKey || !e.altKey) return; 152 + 153 + const currentCloakMode = states.settings.cloakMode; 154 + states.settings.cloakMode = !currentCloakMode; 155 + showToast({ 156 + text: currentCloakMode ? t`Cloak mode disabled` : t`Cloak mode enabled`, 157 + }); 158 + }, 159 + { 160 + useKey: true, 161 + }, 162 + ); 154 163 155 164 return null; 156 165 });
+30 -23
src/components/columns.jsx
··· 68 68 } 69 69 }); 70 70 71 - useHotkeys(['[', ']'], (e, handler) => { 72 - const key = handler.keys[0]; 73 - const currentFocusedColumn = document.activeElement.closest('#columns > *'); 71 + useHotkeys( 72 + ['[', ']'], 73 + (e, handler) => { 74 + const key = handler.keys[0]; 75 + const currentFocusedColumn = 76 + document.activeElement.closest('#columns > *'); 74 77 75 - const rtl = isRTL(); 76 - const prevColKey = rtl ? ']' : '['; 77 - const nextColKey = rtl ? '[' : ']'; 78 - let $column; 78 + const rtl = isRTL(); 79 + const prevColKey = rtl ? ']' : '['; 80 + const nextColKey = rtl ? '[' : ']'; 81 + let $column; 79 82 80 - if (key === prevColKey) { 81 - // If [, focus on left of focused column, else first column 82 - $column = currentFocusedColumn 83 - ? currentFocusedColumn.previousElementSibling 84 - : document.querySelectorAll('#columns > *')[0]; 85 - } else if (key === nextColKey) { 86 - // If ], focus on right of focused column, else 2nd column 87 - $column = currentFocusedColumn 88 - ? currentFocusedColumn.nextElementSibling 89 - : document.querySelectorAll('#columns > *')[1]; 90 - } 91 - if ($column) { 92 - $column.focus(); 93 - $column.scrollIntoView(scrollIntoViewOptions); 94 - } 95 - }); 83 + if (key === prevColKey) { 84 + // If [, focus on left of focused column, else first column 85 + $column = currentFocusedColumn 86 + ? currentFocusedColumn.previousElementSibling 87 + : document.querySelectorAll('#columns > *')[0]; 88 + } else if (key === nextColKey) { 89 + // If ], focus on right of focused column, else 2nd column 90 + $column = currentFocusedColumn 91 + ? currentFocusedColumn.nextElementSibling 92 + : document.querySelectorAll('#columns > *')[1]; 93 + } 94 + if ($column) { 95 + $column.focus(); 96 + $column.scrollIntoView(scrollIntoViewOptions); 97 + } 98 + }, 99 + { 100 + useKey: true, 101 + }, 102 + ); 96 103 97 104 return ( 98 105 <div
+12 -5
src/components/compose-button.jsx
··· 70 70 } 71 71 } 72 72 73 - useHotkeys('c, shift+c', handleButton, { 74 - ignoreEventWhen: (e) => { 75 - const hasModal = !!document.querySelector('#modal-container > *'); 76 - return hasModal; 73 + useHotkeys( 74 + 'c, shift+c', 75 + handleButton, 76 + { 77 + ignoreEventWhen: (e) => { 78 + const hasModal = !!document.querySelector('#modal-container > *'); 79 + return hasModal; 80 + }, 81 + }, 82 + { 83 + useKey: true, 77 84 }, 78 - }); 85 + ); 79 86 80 87 // Setup longpress handler to open context menu 81 88 const bindLongPress = useLongPress(
+3 -2
src/components/keyboard-shortcuts-help.jsx
··· 19 19 } 20 20 21 21 useHotkeys( 22 - '?, shift+?, shift+slash', 23 - (e) => { 22 + '?', 23 + () => { 24 24 console.log('help'); 25 25 states.showKeyboardShortcutsHelp = true; 26 26 }, 27 27 { 28 + useKey: true, 28 29 ignoreEventWhen: (e) => { 29 30 const isCatchUpPage = /\/catchup/i.test(location.hash); 30 31 return isCatchUpPage;
+1
src/components/search-command.jsx
··· 20 20 }, 0); 21 21 }, 22 22 { 23 + useKey: true, 23 24 preventDefault: true, 24 25 ignoreEventWhen: (e) => { 25 26 const isSearchPage = /\/search/.test(location.hash);
+31 -18
src/components/status.jsx
··· 1482 1482 const hotkeysEnabled = !readOnly && !previewMode && !quoted; 1483 1483 const rRef = useHotkeys('r, shift+r', replyStatus, { 1484 1484 enabled: hotkeysEnabled, 1485 + useKey: true, 1485 1486 }); 1486 1487 const fRef = useHotkeys('f, l', favouriteStatusNotify, { 1487 1488 enabled: hotkeysEnabled, 1489 + useKey: true, 1488 1490 }); 1489 1491 const dRef = useHotkeys('d', bookmarkStatusNotify, { 1490 1492 enabled: hotkeysEnabled, 1493 + useKey: true, 1491 1494 }); 1492 1495 const bRef = useHotkeys( 1493 1496 'shift+b', 1494 - () => { 1497 + (e) => { 1498 + // Need shiftKey check due to useKey: true 1499 + if (!e.shiftKey) return; 1500 + 1495 1501 (async () => { 1496 1502 try { 1497 1503 const done = await confirmBoostStatus(); ··· 1507 1513 }, 1508 1514 { 1509 1515 enabled: hotkeysEnabled && canBoost, 1516 + useKey: true, 1510 1517 }, 1511 1518 ); 1512 - const xRef = useHotkeys('x', (e) => { 1513 - const activeStatus = document.activeElement.closest( 1514 - '.status-link, .status-focus', 1515 - ); 1516 - if (activeStatus) { 1517 - const spoilerButton = activeStatus.querySelector( 1518 - '.spoiler-button:not(.spoiling)', 1519 + const xRef = useHotkeys( 1520 + 'x', 1521 + (e) => { 1522 + const activeStatus = document.activeElement.closest( 1523 + '.status-link, .status-focus', 1519 1524 ); 1520 - if (spoilerButton) { 1521 - e.stopPropagation(); 1522 - spoilerButton.click(); 1523 - } else { 1524 - const spoilerMediaButton = activeStatus.querySelector( 1525 - '.spoiler-media-button:not(.spoiling)', 1525 + if (activeStatus) { 1526 + const spoilerButton = activeStatus.querySelector( 1527 + '.spoiler-button:not(.spoiling)', 1526 1528 ); 1527 - if (spoilerMediaButton) { 1529 + if (spoilerButton) { 1528 1530 e.stopPropagation(); 1529 - spoilerMediaButton.click(); 1531 + spoilerButton.click(); 1532 + } else { 1533 + const spoilerMediaButton = activeStatus.querySelector( 1534 + '.spoiler-media-button:not(.spoiling)', 1535 + ); 1536 + if (spoilerMediaButton) { 1537 + e.stopPropagation(); 1538 + spoilerMediaButton.click(); 1539 + } 1530 1540 } 1531 1541 } 1532 - } 1533 - }); 1542 + }, 1543 + { 1544 + useKey: true, 1545 + }, 1546 + ); 1534 1547 1535 1548 const displayedMediaAttachments = mediaAttachments.slice( 1536 1549 0,
+105 -81
src/components/timeline.jsx
··· 143 143 144 144 const itemsSelector = '.timeline-item, .timeline-item-alt'; 145 145 146 - const jRef = useHotkeys('j, shift+j', (_, handler) => { 147 - // focus on next status after active item 148 - const activeItem = document.activeElement.closest(itemsSelector); 149 - const activeItemRect = activeItem?.getBoundingClientRect(); 150 - const allItems = Array.from( 151 - scrollableRef.current.querySelectorAll(itemsSelector), 152 - ).filter((item) => !!item.offsetHeight); 153 - if ( 154 - activeItem && 155 - activeItemRect.top < scrollableRef.current.clientHeight && 156 - activeItemRect.bottom > 0 157 - ) { 158 - const activeItemIndex = allItems.indexOf(activeItem); 159 - let nextItem = allItems[activeItemIndex + 1]; 160 - if (handler.shift) { 161 - // get next status that's not .timeline-item-alt 162 - nextItem = allItems.find( 163 - (item, index) => 164 - index > activeItemIndex && 165 - !item.classList.contains('timeline-item-alt'), 166 - ); 167 - } 168 - if (nextItem) { 169 - nextItem.focus(); 170 - nextItem.scrollIntoView(scrollIntoViewOptions); 171 - } 172 - } else { 173 - // If active status is not in viewport, get the topmost status-link in viewport 174 - const topmostItem = allItems.find((item) => { 175 - const itemRect = item.getBoundingClientRect(); 176 - return itemRect.top >= 44 && itemRect.left >= 0; // 44 is the magic number for header height, not real 177 - }); 178 - if (topmostItem) { 179 - topmostItem.focus(); 180 - topmostItem.scrollIntoView(scrollIntoViewOptions); 181 - } 182 - } 183 - }); 146 + const jRef = useHotkeys( 147 + 'j, shift+j', 148 + (e, handler) => { 149 + // Fix bug: shift+j is fired even when j is pressed due to useKey: true 150 + if (e.shiftKey !== handler.shift) return; 184 151 185 - const kRef = useHotkeys('k, shift+k', (_, handler) => { 186 - // focus on previous status after active item 187 - const activeItem = document.activeElement.closest(itemsSelector); 188 - const activeItemRect = activeItem?.getBoundingClientRect(); 189 - const allItems = Array.from( 190 - scrollableRef.current.querySelectorAll(itemsSelector), 191 - ).filter((item) => !!item.offsetHeight); 192 - if ( 193 - activeItem && 194 - activeItemRect.top < scrollableRef.current.clientHeight && 195 - activeItemRect.bottom > 0 196 - ) { 197 - const activeItemIndex = allItems.indexOf(activeItem); 198 - let prevItem = allItems[activeItemIndex - 1]; 199 - if (handler.shift) { 200 - // get prev status that's not .timeline-item-alt 201 - prevItem = allItems.findLast( 202 - (item, index) => 203 - index < activeItemIndex && 204 - !item.classList.contains('timeline-item-alt'), 205 - ); 206 - } 207 - if (prevItem) { 208 - prevItem.focus(); 209 - prevItem.scrollIntoView(scrollIntoViewOptions); 152 + // focus on next status after active item 153 + const activeItem = document.activeElement.closest(itemsSelector); 154 + const activeItemRect = activeItem?.getBoundingClientRect(); 155 + const allItems = Array.from( 156 + scrollableRef.current.querySelectorAll(itemsSelector), 157 + ).filter((item) => !!item.offsetHeight); 158 + if ( 159 + activeItem && 160 + activeItemRect.top < scrollableRef.current.clientHeight && 161 + activeItemRect.bottom > 0 162 + ) { 163 + const activeItemIndex = allItems.indexOf(activeItem); 164 + let nextItem = allItems[activeItemIndex + 1]; 165 + if (handler.shift) { 166 + // get next status that's not .timeline-item-alt 167 + nextItem = allItems.find( 168 + (item, index) => 169 + index > activeItemIndex && 170 + !item.classList.contains('timeline-item-alt'), 171 + ); 172 + } 173 + if (nextItem) { 174 + nextItem.focus(); 175 + nextItem.scrollIntoView(scrollIntoViewOptions); 176 + } 177 + } else { 178 + // If active status is not in viewport, get the topmost status-link in viewport 179 + const topmostItem = allItems.find((item) => { 180 + const itemRect = item.getBoundingClientRect(); 181 + return itemRect.top >= 44 && itemRect.left >= 0; // 44 is the magic number for header height, not real 182 + }); 183 + if (topmostItem) { 184 + topmostItem.focus(); 185 + topmostItem.scrollIntoView(scrollIntoViewOptions); 186 + } 210 187 } 211 - } else { 212 - // If active status is not in viewport, get the topmost status-link in viewport 213 - const topmostItem = allItems.find((item) => { 214 - const itemRect = item.getBoundingClientRect(); 215 - return itemRect.top >= 44 && itemRect.left >= 0; // 44 is the magic number for header height, not real 216 - }); 217 - if (topmostItem) { 218 - topmostItem.focus(); 219 - topmostItem.scrollIntoView(scrollIntoViewOptions); 188 + }, 189 + { 190 + useKey: true, 191 + }, 192 + ); 193 + 194 + const kRef = useHotkeys( 195 + 'k, shift+k', 196 + (e, handler) => { 197 + // Fix bug: shift+k is fired even when k is pressed due to useKey: true 198 + if (e.shiftKey !== handler.shift) return; 199 + 200 + // focus on previous status after active item 201 + const activeItem = document.activeElement.closest(itemsSelector); 202 + const activeItemRect = activeItem?.getBoundingClientRect(); 203 + const allItems = Array.from( 204 + scrollableRef.current.querySelectorAll(itemsSelector), 205 + ).filter((item) => !!item.offsetHeight); 206 + if ( 207 + activeItem && 208 + activeItemRect.top < scrollableRef.current.clientHeight && 209 + activeItemRect.bottom > 0 210 + ) { 211 + const activeItemIndex = allItems.indexOf(activeItem); 212 + let prevItem = allItems[activeItemIndex - 1]; 213 + if (handler.shift) { 214 + // get prev status that's not .timeline-item-alt 215 + prevItem = allItems.findLast( 216 + (item, index) => 217 + index < activeItemIndex && 218 + !item.classList.contains('timeline-item-alt'), 219 + ); 220 + } 221 + if (prevItem) { 222 + prevItem.focus(); 223 + prevItem.scrollIntoView(scrollIntoViewOptions); 224 + } 225 + } else { 226 + // If active status is not in viewport, get the topmost status-link in viewport 227 + const topmostItem = allItems.find((item) => { 228 + const itemRect = item.getBoundingClientRect(); 229 + return itemRect.top >= 44 && itemRect.left >= 0; // 44 is the magic number for header height, not real 230 + }); 231 + if (topmostItem) { 232 + topmostItem.focus(); 233 + topmostItem.scrollIntoView(scrollIntoViewOptions); 234 + } 220 235 } 221 - } 222 - }); 236 + }, 237 + { 238 + useKey: true, 239 + }, 240 + ); 223 241 224 - const oRef = useHotkeys(['enter', 'o'], () => { 225 - // open active status 226 - const activeItem = document.activeElement; 227 - if (activeItem?.matches(itemsSelector)) { 228 - activeItem.click(); 229 - } 230 - }); 242 + const oRef = useHotkeys( 243 + ['enter', 'o'], 244 + () => { 245 + // open active status 246 + const activeItem = document.activeElement; 247 + if (activeItem?.matches(itemsSelector)) { 248 + activeItem.click(); 249 + } 250 + }, 251 + { 252 + useKey: true, 253 + }, 254 + ); 231 255 232 256 const showNewPostsIndicator = 233 257 items.length > 0 && uiState !== 'loading' && showNew;
+281 -281
src/locales/en.po
··· 101 101 #: src/components/account-info.jsx:436 102 102 #: src/components/account-info.jsx:836 103 103 #: src/pages/account-statuses.jsx:479 104 - #: src/pages/search.jsx:328 105 - #: src/pages/search.jsx:475 104 + #: src/pages/search.jsx:341 105 + #: src/pages/search.jsx:488 106 106 msgid "Posts" 107 107 msgstr "" 108 108 ··· 111 111 #: src/components/compose.jsx:2772 112 112 #: src/components/media-alt-modal.jsx:46 113 113 #: src/components/media-modal.jsx:358 114 - #: src/components/status.jsx:1796 115 - #: src/components/status.jsx:1813 116 - #: src/components/status.jsx:1938 117 - #: src/components/status.jsx:2556 118 - #: src/components/status.jsx:2559 114 + #: src/components/status.jsx:1809 115 + #: src/components/status.jsx:1826 116 + #: src/components/status.jsx:1951 117 + #: src/components/status.jsx:2569 118 + #: src/components/status.jsx:2572 119 119 #: src/pages/account-statuses.jsx:523 120 120 #: src/pages/accounts.jsx:110 121 121 #: src/pages/hashtag.jsx:200 122 122 #: src/pages/list.jsx:158 123 123 #: src/pages/public.jsx:115 124 124 #: src/pages/scheduled-posts.jsx:87 125 - #: src/pages/status.jsx:1214 125 + #: src/pages/status.jsx:1232 126 126 #: src/pages/trending.jsx:469 127 127 msgid "More" 128 128 msgstr "" ··· 203 203 msgstr "" 204 204 205 205 #: src/components/account-info.jsx:926 206 - #: src/components/status.jsx:2340 206 + #: src/components/status.jsx:2353 207 207 #: src/pages/catchup.jsx:72 208 - #: src/pages/catchup.jsx:1442 209 - #: src/pages/catchup.jsx:2057 210 - #: src/pages/status.jsx:937 211 - #: src/pages/status.jsx:1560 208 + #: src/pages/catchup.jsx:1447 209 + #: src/pages/catchup.jsx:2062 210 + #: src/pages/status.jsx:955 211 + #: src/pages/status.jsx:1578 212 212 msgid "Replies" 213 213 msgstr "" 214 214 215 215 #: src/components/account-info.jsx:930 216 216 #: src/pages/catchup.jsx:73 217 - #: src/pages/catchup.jsx:1444 218 - #: src/pages/catchup.jsx:2069 217 + #: src/pages/catchup.jsx:1449 218 + #: src/pages/catchup.jsx:2074 219 219 #: src/pages/settings.jsx:1154 220 220 msgid "Boosts" 221 221 msgstr "" ··· 312 312 #: src/components/account-info.jsx:1393 313 313 #: src/components/shortcuts-settings.jsx:1059 314 314 #: src/components/status.jsx:1245 315 - #: src/components/status.jsx:3327 315 + #: src/components/status.jsx:3340 316 316 msgid "Copy" 317 317 msgstr "" 318 318 ··· 428 428 #: src/components/drafts.jsx:59 429 429 #: src/components/embed-modal.jsx:13 430 430 #: src/components/generic-accounts.jsx:143 431 - #: src/components/keyboard-shortcuts-help.jsx:42 431 + #: src/components/keyboard-shortcuts-help.jsx:43 432 432 #: src/components/list-add-edit.jsx:36 433 433 #: src/components/media-alt-modal.jsx:34 434 434 #: src/components/media-modal.jsx:322 ··· 437 437 #: src/components/shortcuts-settings.jsx:230 438 438 #: src/components/shortcuts-settings.jsx:583 439 439 #: src/components/shortcuts-settings.jsx:783 440 - #: src/components/status.jsx:3051 441 - #: src/components/status.jsx:3291 442 - #: src/components/status.jsx:3800 440 + #: src/components/status.jsx:3064 441 + #: src/components/status.jsx:3304 442 + #: src/components/status.jsx:3813 443 443 #: src/pages/accounts.jsx:37 444 - #: src/pages/catchup.jsx:1578 444 + #: src/pages/catchup.jsx:1583 445 445 #: src/pages/filters.jsx:225 446 446 #: src/pages/list.jsx:276 447 - #: src/pages/notifications.jsx:916 447 + #: src/pages/notifications.jsx:934 448 448 #: src/pages/scheduled-posts.jsx:257 449 449 #: src/pages/settings.jsx:79 450 - #: src/pages/status.jsx:1301 450 + #: src/pages/status.jsx:1319 451 451 msgid "Close" 452 452 msgstr "" 453 453 ··· 533 533 #: src/components/list-add-edit.jsx:150 534 534 #: src/components/shortcuts-settings.jsx:715 535 535 #: src/pages/filters.jsx:570 536 - #: src/pages/notifications.jsx:982 536 + #: src/pages/notifications.jsx:1000 537 537 msgid "Save" 538 538 msgstr "" 539 539 ··· 545 545 msgid "server domain name" 546 546 msgstr "" 547 547 548 - #: src/components/background-service.jsx:151 548 + #: src/components/background-service.jsx:156 549 549 msgid "Cloak mode disabled" 550 550 msgstr "" 551 551 552 - #: src/components/background-service.jsx:151 552 + #: src/components/background-service.jsx:156 553 553 msgid "Cloak mode enabled" 554 554 msgstr "" 555 555 556 556 #: src/components/columns.jsx:27 557 557 #: src/components/nav-menu.jsx:176 558 558 #: src/components/shortcuts-settings.jsx:139 559 - #: src/components/timeline.jsx:439 560 - #: src/pages/catchup.jsx:877 559 + #: src/components/timeline.jsx:463 560 + #: src/pages/catchup.jsx:882 561 561 #: src/pages/filters.jsx:90 562 562 #: src/pages/followed-hashtags.jsx:41 563 563 #: src/pages/home.jsx:54 564 - #: src/pages/notifications.jsx:561 564 + #: src/pages/notifications.jsx:579 565 565 #: src/pages/scheduled-posts.jsx:72 566 566 msgid "Home" 567 567 msgstr "" 568 568 569 - #: src/components/compose-button.jsx:135 569 + #: src/components/compose-button.jsx:142 570 570 #: src/compose.jsx:38 571 571 msgid "Compose" 572 572 msgstr "" 573 573 574 - #: src/components/compose-button.jsx:162 574 + #: src/components/compose-button.jsx:169 575 575 #: src/components/nav-menu.jsx:260 576 576 #: src/pages/scheduled-posts.jsx:31 577 577 #: src/pages/scheduled-posts.jsx:76 578 578 msgid "Scheduled Posts" 579 579 msgstr "Scheduled Posts" 580 580 581 - #: src/components/compose-button.jsx:175 581 + #: src/components/compose-button.jsx:182 582 582 msgid "Add to thread" 583 583 msgstr "Add to thread" 584 584 ··· 680 680 msgstr "Attachment #{i} failed" 681 681 682 682 #: src/components/compose.jsx:1211 683 - #: src/components/status.jsx:2126 684 - #: src/components/timeline.jsx:993 683 + #: src/components/status.jsx:2139 684 + #: src/components/timeline.jsx:1017 685 685 msgid "Content warning" 686 686 msgstr "" 687 687 ··· 716 716 717 717 #: src/components/compose.jsx:1278 718 718 #: src/components/status.jsx:100 719 - #: src/components/status.jsx:2002 719 + #: src/components/status.jsx:2015 720 720 msgid "Private mention" 721 721 msgstr "" 722 722 ··· 752 752 msgstr "Schedule" 753 753 754 754 #: src/components/compose.jsx:1664 755 - #: src/components/keyboard-shortcuts-help.jsx:154 755 + #: src/components/keyboard-shortcuts-help.jsx:155 756 756 #: src/components/status.jsx:1008 757 - #: src/components/status.jsx:1776 758 - #: src/components/status.jsx:1777 759 - #: src/components/status.jsx:2460 757 + #: src/components/status.jsx:1789 758 + #: src/components/status.jsx:1790 759 + #: src/components/status.jsx:2473 760 760 msgid "Reply" 761 761 msgstr "" 762 762 ··· 824 824 #: src/components/compose.jsx:2692 825 825 #: src/components/compose.jsx:2942 826 826 #: src/components/shortcuts-settings.jsx:726 827 - #: src/pages/catchup.jsx:1075 827 + #: src/pages/catchup.jsx:1080 828 828 #: src/pages/filters.jsx:413 829 829 msgid "Remove" 830 830 msgstr "" ··· 945 945 946 946 #: src/components/compose.jsx:3777 947 947 #: src/components/media-modal.jsx:464 948 - #: src/components/timeline.jsx:897 948 + #: src/components/timeline.jsx:921 949 949 msgid "Previous" 950 950 msgstr "" 951 951 952 952 #: src/components/compose.jsx:3795 953 953 #: src/components/media-modal.jsx:483 954 - #: src/components/timeline.jsx:914 954 + #: src/components/timeline.jsx:938 955 955 msgid "Next" 956 956 msgstr "" 957 957 ··· 1005 1005 msgstr "" 1006 1006 1007 1007 #: src/components/drafts.jsx:247 1008 - #: src/pages/catchup.jsx:1928 1008 + #: src/pages/catchup.jsx:1933 1009 1009 msgid "Poll" 1010 1010 msgstr "" 1011 1011 ··· 1019 1019 msgstr "" 1020 1020 1021 1021 #: src/components/follow-request-buttons.jsx:43 1022 - #: src/pages/notifications.jsx:966 1022 + #: src/pages/notifications.jsx:984 1023 1023 msgid "Accept" 1024 1024 msgstr "" 1025 1025 ··· 1028 1028 msgstr "" 1029 1029 1030 1030 #: src/components/follow-request-buttons.jsx:76 1031 - #: src/pages/notifications.jsx:1250 1031 + #: src/pages/notifications.jsx:1268 1032 1032 msgid "Accepted" 1033 1033 msgstr "" 1034 1034 ··· 1039 1039 #: src/components/generic-accounts.jsx:146 1040 1040 #: src/components/notification.jsx:445 1041 1041 #: src/pages/accounts.jsx:42 1042 - #: src/pages/search.jsx:318 1043 - #: src/pages/search.jsx:351 1042 + #: src/pages/search.jsx:331 1043 + #: src/pages/search.jsx:364 1044 1044 msgid "Accounts" 1045 1045 msgstr "" 1046 1046 1047 1047 #: src/components/generic-accounts.jsx:206 1048 - #: src/components/timeline.jsx:521 1048 + #: src/components/timeline.jsx:545 1049 1049 #: src/pages/list.jsx:295 1050 - #: src/pages/notifications.jsx:896 1051 - #: src/pages/search.jsx:545 1052 - #: src/pages/status.jsx:1334 1050 + #: src/pages/notifications.jsx:914 1051 + #: src/pages/search.jsx:558 1052 + #: src/pages/status.jsx:1352 1053 1053 msgid "Show more…" 1054 1054 msgstr "" 1055 1055 1056 1056 #: src/components/generic-accounts.jsx:211 1057 - #: src/components/timeline.jsx:526 1058 - #: src/pages/search.jsx:550 1057 + #: src/components/timeline.jsx:550 1058 + #: src/pages/search.jsx:563 1059 1059 msgid "The end." 1060 1060 msgstr "" 1061 1061 ··· 1063 1063 msgid "Nothing to show" 1064 1064 msgstr "" 1065 1065 1066 - #: src/components/keyboard-shortcuts-help.jsx:46 1066 + #: src/components/keyboard-shortcuts-help.jsx:47 1067 1067 #: src/components/nav-menu.jsx:363 1068 - #: src/pages/catchup.jsx:1616 1068 + #: src/pages/catchup.jsx:1621 1069 1069 msgid "Keyboard shortcuts" 1070 1070 msgstr "" 1071 1071 1072 - #: src/components/keyboard-shortcuts-help.jsx:54 1072 + #: src/components/keyboard-shortcuts-help.jsx:55 1073 1073 msgid "Keyboard shortcuts help" 1074 1074 msgstr "" 1075 1075 1076 - #: src/components/keyboard-shortcuts-help.jsx:58 1077 - #: src/pages/catchup.jsx:1641 1076 + #: src/components/keyboard-shortcuts-help.jsx:59 1077 + #: src/pages/catchup.jsx:1646 1078 1078 msgid "Next post" 1079 1079 msgstr "" 1080 1080 1081 - #: src/components/keyboard-shortcuts-help.jsx:62 1082 - #: src/pages/catchup.jsx:1649 1081 + #: src/components/keyboard-shortcuts-help.jsx:63 1082 + #: src/pages/catchup.jsx:1654 1083 1083 msgid "Previous post" 1084 1084 msgstr "" 1085 1085 1086 - #: src/components/keyboard-shortcuts-help.jsx:66 1086 + #: src/components/keyboard-shortcuts-help.jsx:67 1087 1087 msgid "Skip carousel to next post" 1088 1088 msgstr "" 1089 1089 1090 - #: src/components/keyboard-shortcuts-help.jsx:68 1090 + #: src/components/keyboard-shortcuts-help.jsx:69 1091 1091 msgid "<0>Shift</0> + <1>j</1>" 1092 1092 msgstr "" 1093 1093 1094 - #: src/components/keyboard-shortcuts-help.jsx:74 1094 + #: src/components/keyboard-shortcuts-help.jsx:75 1095 1095 msgid "Skip carousel to previous post" 1096 1096 msgstr "" 1097 1097 1098 - #: src/components/keyboard-shortcuts-help.jsx:76 1098 + #: src/components/keyboard-shortcuts-help.jsx:77 1099 1099 msgid "<0>Shift</0> + <1>k</1>" 1100 1100 msgstr "" 1101 1101 1102 - #: src/components/keyboard-shortcuts-help.jsx:82 1102 + #: src/components/keyboard-shortcuts-help.jsx:83 1103 1103 msgid "Load new posts" 1104 1104 msgstr "" 1105 1105 1106 - #: src/components/keyboard-shortcuts-help.jsx:86 1107 - #: src/pages/catchup.jsx:1673 1106 + #: src/components/keyboard-shortcuts-help.jsx:87 1107 + #: src/pages/catchup.jsx:1678 1108 1108 msgid "Open post details" 1109 1109 msgstr "" 1110 1110 1111 - #: src/components/keyboard-shortcuts-help.jsx:88 1111 + #: src/components/keyboard-shortcuts-help.jsx:89 1112 1112 msgid "<0>Enter</0> or <1>o</1>" 1113 1113 msgstr "" 1114 1114 1115 - #: src/components/keyboard-shortcuts-help.jsx:95 1115 + #: src/components/keyboard-shortcuts-help.jsx:96 1116 1116 msgid "Expand content warning or<0/>toggle expanded/collapsed thread" 1117 1117 msgstr "" 1118 1118 1119 - #: src/components/keyboard-shortcuts-help.jsx:104 1119 + #: src/components/keyboard-shortcuts-help.jsx:105 1120 1120 msgid "Close post or dialogs" 1121 1121 msgstr "" 1122 1122 1123 - #: src/components/keyboard-shortcuts-help.jsx:106 1123 + #: src/components/keyboard-shortcuts-help.jsx:107 1124 1124 msgid "<0>Esc</0> or <1>Backspace</1>" 1125 1125 msgstr "" 1126 1126 1127 - #: src/components/keyboard-shortcuts-help.jsx:112 1127 + #: src/components/keyboard-shortcuts-help.jsx:113 1128 1128 msgid "Focus column in multi-column mode" 1129 1129 msgstr "" 1130 1130 1131 - #: src/components/keyboard-shortcuts-help.jsx:114 1131 + #: src/components/keyboard-shortcuts-help.jsx:115 1132 1132 msgid "<0>1</0> to <1>9</1>" 1133 1133 msgstr "" 1134 1134 1135 - #: src/components/keyboard-shortcuts-help.jsx:120 1135 + #: src/components/keyboard-shortcuts-help.jsx:121 1136 1136 msgid "Focus next column in multi-column mode" 1137 1137 msgstr "Focus next column in multi-column mode" 1138 1138 1139 - #: src/components/keyboard-shortcuts-help.jsx:124 1139 + #: src/components/keyboard-shortcuts-help.jsx:125 1140 1140 msgid "Focus previous column in multi-column mode" 1141 1141 msgstr "Focus previous column in multi-column mode" 1142 1142 1143 - #: src/components/keyboard-shortcuts-help.jsx:128 1143 + #: src/components/keyboard-shortcuts-help.jsx:129 1144 1144 msgid "Compose new post" 1145 1145 msgstr "" 1146 1146 1147 - #: src/components/keyboard-shortcuts-help.jsx:132 1147 + #: src/components/keyboard-shortcuts-help.jsx:133 1148 1148 msgid "Compose new post (new window)" 1149 1149 msgstr "" 1150 1150 1151 - #: src/components/keyboard-shortcuts-help.jsx:135 1151 + #: src/components/keyboard-shortcuts-help.jsx:136 1152 1152 msgid "<0>Shift</0> + <1>c</1>" 1153 1153 msgstr "" 1154 1154 1155 - #: src/components/keyboard-shortcuts-help.jsx:141 1155 + #: src/components/keyboard-shortcuts-help.jsx:142 1156 1156 msgid "Send post" 1157 1157 msgstr "" 1158 1158 1159 - #: src/components/keyboard-shortcuts-help.jsx:143 1159 + #: src/components/keyboard-shortcuts-help.jsx:144 1160 1160 msgid "<0>Ctrl</0> + <1>Enter</1> or <2>⌘</2> + <3>Enter</3>" 1161 1161 msgstr "" 1162 1162 1163 - #: src/components/keyboard-shortcuts-help.jsx:150 1163 + #: src/components/keyboard-shortcuts-help.jsx:151 1164 1164 #: src/components/nav-menu.jsx:332 1165 1165 #: src/components/search-form.jsx:73 1166 1166 #: src/components/shortcuts-settings.jsx:52 1167 1167 #: src/components/shortcuts-settings.jsx:179 1168 1168 #: src/pages/search.jsx:46 1169 - #: src/pages/search.jsx:300 1169 + #: src/pages/search.jsx:313 1170 1170 msgid "Search" 1171 1171 msgstr "" 1172 1172 1173 - #: src/components/keyboard-shortcuts-help.jsx:158 1173 + #: src/components/keyboard-shortcuts-help.jsx:159 1174 1174 msgid "Reply (new window)" 1175 1175 msgstr "" 1176 1176 1177 - #: src/components/keyboard-shortcuts-help.jsx:161 1177 + #: src/components/keyboard-shortcuts-help.jsx:162 1178 1178 msgid "<0>Shift</0> + <1>r</1>" 1179 1179 msgstr "" 1180 1180 1181 - #: src/components/keyboard-shortcuts-help.jsx:167 1181 + #: src/components/keyboard-shortcuts-help.jsx:168 1182 1182 msgid "Like (favourite)" 1183 1183 msgstr "" 1184 1184 1185 - #: src/components/keyboard-shortcuts-help.jsx:169 1185 + #: src/components/keyboard-shortcuts-help.jsx:170 1186 1186 msgid "<0>l</0> or <1>f</1>" 1187 1187 msgstr "" 1188 1188 1189 - #: src/components/keyboard-shortcuts-help.jsx:175 1189 + #: src/components/keyboard-shortcuts-help.jsx:176 1190 1190 #: src/components/status.jsx:1016 1191 - #: src/components/status.jsx:2487 1192 - #: src/components/status.jsx:2510 1193 - #: src/components/status.jsx:2511 1191 + #: src/components/status.jsx:2500 1192 + #: src/components/status.jsx:2523 1193 + #: src/components/status.jsx:2524 1194 1194 msgid "Boost" 1195 1195 msgstr "" 1196 1196 1197 - #: src/components/keyboard-shortcuts-help.jsx:177 1197 + #: src/components/keyboard-shortcuts-help.jsx:178 1198 1198 msgid "<0>Shift</0> + <1>b</1>" 1199 1199 msgstr "" 1200 1200 1201 - #: src/components/keyboard-shortcuts-help.jsx:183 1201 + #: src/components/keyboard-shortcuts-help.jsx:184 1202 1202 #: src/components/status.jsx:1079 1203 - #: src/components/status.jsx:2535 1204 - #: src/components/status.jsx:2536 1203 + #: src/components/status.jsx:2548 1204 + #: src/components/status.jsx:2549 1205 1205 msgid "Bookmark" 1206 1206 msgstr "" 1207 1207 1208 - #: src/components/keyboard-shortcuts-help.jsx:187 1208 + #: src/components/keyboard-shortcuts-help.jsx:188 1209 1209 msgid "Toggle Cloak mode" 1210 1210 msgstr "" 1211 1211 1212 - #: src/components/keyboard-shortcuts-help.jsx:189 1212 + #: src/components/keyboard-shortcuts-help.jsx:190 1213 1213 msgid "<0>Shift</0> + <1>Alt</1> + <2>k</2>" 1214 1214 msgstr "" 1215 1215 ··· 1304 1304 msgstr "" 1305 1305 1306 1306 #: src/components/media-post.jsx:134 1307 - #: src/components/status.jsx:3630 1308 - #: src/components/status.jsx:3726 1309 - #: src/components/status.jsx:3804 1310 - #: src/components/timeline.jsx:982 1307 + #: src/components/status.jsx:3643 1308 + #: src/components/status.jsx:3739 1309 + #: src/components/status.jsx:3817 1310 + #: src/components/timeline.jsx:1006 1311 1311 #: src/pages/catchup.jsx:76 1312 - #: src/pages/catchup.jsx:1876 1312 + #: src/pages/catchup.jsx:1881 1313 1313 msgid "Filtered" 1314 1314 msgstr "" 1315 1315 ··· 1358 1358 msgstr "Following" 1359 1359 1360 1360 #: src/components/nav-menu.jsx:192 1361 - #: src/pages/catchup.jsx:872 1361 + #: src/pages/catchup.jsx:877 1362 1362 msgid "Catch-up" 1363 1363 msgstr "" 1364 1364 ··· 1380 1380 #: src/pages/home.jsx:86 1381 1381 #: src/pages/home.jsx:186 1382 1382 #: src/pages/notifications.jsx:114 1383 - #: src/pages/notifications.jsx:565 1383 + #: src/pages/notifications.jsx:583 1384 1384 msgid "Notifications" 1385 1385 msgstr "" 1386 1386 ··· 1403 1403 #: src/components/nav-menu.jsx:248 1404 1404 #: src/components/shortcuts-settings.jsx:55 1405 1405 #: src/components/shortcuts-settings.jsx:201 1406 - #: src/pages/catchup.jsx:1443 1407 - #: src/pages/catchup.jsx:2063 1406 + #: src/pages/catchup.jsx:1448 1407 + #: src/pages/catchup.jsx:2068 1408 1408 #: src/pages/favourites.jsx:12 1409 1409 #: src/pages/favourites.jsx:24 1410 1410 #: src/pages/settings.jsx:1150 ··· 1448 1448 #: src/components/nav-menu.jsx:321 1449 1449 #: src/pages/login.jsx:27 1450 1450 #: src/pages/login.jsx:190 1451 - #: src/pages/status.jsx:837 1451 + #: src/pages/status.jsx:855 1452 1452 #: src/pages/welcome.jsx:65 1453 1453 msgid "Log in" 1454 1454 msgstr "" ··· 1670 1670 #: src/components/poll.jsx:208 1671 1671 #: src/components/poll.jsx:210 1672 1672 #: src/pages/scheduled-posts.jsx:98 1673 - #: src/pages/status.jsx:1203 1674 - #: src/pages/status.jsx:1226 1673 + #: src/pages/status.jsx:1221 1674 + #: src/pages/status.jsx:1244 1675 1675 msgid "Refresh" 1676 1676 msgstr "" 1677 1677 ··· 2185 2185 2186 2186 #: src/components/status.jsx:1016 2187 2187 #: src/components/status.jsx:1056 2188 - #: src/components/status.jsx:2487 2189 - #: src/components/status.jsx:2510 2188 + #: src/components/status.jsx:2500 2189 + #: src/components/status.jsx:2523 2190 2190 msgid "Unboost" 2191 2191 msgstr "" 2192 2192 2193 2193 #: src/components/status.jsx:1032 2194 - #: src/components/status.jsx:2502 2194 + #: src/components/status.jsx:2515 2195 2195 msgid "Quote" 2196 2196 msgstr "" 2197 2197 2198 2198 #. placeholder {0}: username || acct 2199 2199 #: src/components/status.jsx:1044 2200 - #: src/components/status.jsx:1501 2200 + #: src/components/status.jsx:1507 2201 2201 msgid "Unboosted @{0}'s post" 2202 2202 msgstr "Unboosted @{0}'s post" 2203 2203 2204 2204 #. placeholder {0}: username || acct 2205 2205 #: src/components/status.jsx:1045 2206 - #: src/components/status.jsx:1502 2206 + #: src/components/status.jsx:1508 2207 2207 msgid "Boosted @{0}'s post" 2208 2208 msgstr "Boosted @{0}'s post" 2209 2209 ··· 2212 2212 msgstr "" 2213 2213 2214 2214 #: src/components/status.jsx:1069 2215 - #: src/components/status.jsx:1786 2216 - #: src/components/status.jsx:2523 2215 + #: src/components/status.jsx:1799 2216 + #: src/components/status.jsx:2536 2217 2217 msgid "Unlike" 2218 2218 msgstr "" 2219 2219 2220 2220 #: src/components/status.jsx:1070 2221 - #: src/components/status.jsx:1786 2222 - #: src/components/status.jsx:1787 2223 - #: src/components/status.jsx:2523 2224 - #: src/components/status.jsx:2524 2221 + #: src/components/status.jsx:1799 2222 + #: src/components/status.jsx:1800 2223 + #: src/components/status.jsx:2536 2224 + #: src/components/status.jsx:2537 2225 2225 msgid "Like" 2226 2226 msgstr "" 2227 2227 2228 2228 #: src/components/status.jsx:1079 2229 - #: src/components/status.jsx:2535 2229 + #: src/components/status.jsx:2548 2230 2230 msgid "Unbookmark" 2231 2231 msgstr "" 2232 2232 ··· 2256 2256 msgstr "" 2257 2257 2258 2258 #: src/components/status.jsx:1280 2259 - #: src/components/status.jsx:3296 2259 + #: src/components/status.jsx:3309 2260 2260 msgid "Embed post" 2261 2261 msgstr "" 2262 2262 ··· 2324 2324 msgid "Report post…" 2325 2325 msgstr "" 2326 2326 2327 - #: src/components/status.jsx:1787 2328 - #: src/components/status.jsx:1823 2329 - #: src/components/status.jsx:2524 2327 + #: src/components/status.jsx:1800 2328 + #: src/components/status.jsx:1836 2329 + #: src/components/status.jsx:2537 2330 2330 msgid "Liked" 2331 2331 msgstr "" 2332 2332 2333 - #: src/components/status.jsx:1820 2334 - #: src/components/status.jsx:2511 2333 + #: src/components/status.jsx:1833 2334 + #: src/components/status.jsx:2524 2335 2335 msgid "Boosted" 2336 2336 msgstr "" 2337 2337 2338 - #: src/components/status.jsx:1830 2339 - #: src/components/status.jsx:2536 2338 + #: src/components/status.jsx:1843 2339 + #: src/components/status.jsx:2549 2340 2340 msgid "Bookmarked" 2341 2341 msgstr "" 2342 2342 2343 - #: src/components/status.jsx:1834 2343 + #: src/components/status.jsx:1847 2344 2344 msgid "Pinned" 2345 2345 msgstr "" 2346 2346 2347 - #: src/components/status.jsx:1880 2348 - #: src/components/status.jsx:2348 2347 + #: src/components/status.jsx:1893 2348 + #: src/components/status.jsx:2361 2349 2349 msgid "Deleted" 2350 2350 msgstr "" 2351 2351 2352 - #: src/components/status.jsx:1921 2352 + #: src/components/status.jsx:1934 2353 2353 msgid "{repliesCount, plural, one {# reply} other {# replies}}" 2354 2354 msgstr "" 2355 2355 2356 2356 #. placeholder {0}: snapStates.statusThreadNumber[sKey] ? ` ${snapStates.statusThreadNumber[sKey]}/X` : '' 2357 - #: src/components/status.jsx:2011 2357 + #: src/components/status.jsx:2024 2358 2358 msgid "Thread{0}" 2359 2359 msgstr "" 2360 2360 2361 - #: src/components/status.jsx:2089 2362 - #: src/components/status.jsx:2151 2363 - #: src/components/status.jsx:2244 2361 + #: src/components/status.jsx:2102 2362 + #: src/components/status.jsx:2164 2363 + #: src/components/status.jsx:2257 2364 2364 msgid "Show less" 2365 2365 msgstr "" 2366 2366 2367 - #: src/components/status.jsx:2089 2368 - #: src/components/status.jsx:2151 2367 + #: src/components/status.jsx:2102 2368 + #: src/components/status.jsx:2164 2369 2369 msgid "Show content" 2370 2370 msgstr "" 2371 2371 2372 2372 #. placeholder {0}: filterInfo.titlesStr 2373 2373 #. placeholder {0}: filterInfo?.titlesStr 2374 - #: src/components/status.jsx:2240 2375 - #: src/pages/catchup.jsx:1875 2374 + #: src/components/status.jsx:2253 2375 + #: src/pages/catchup.jsx:1880 2376 2376 msgid "Filtered: {0}" 2377 2377 msgstr "Filtered: {0}" 2378 2378 2379 - #: src/components/status.jsx:2244 2379 + #: src/components/status.jsx:2257 2380 2380 msgid "Show media" 2381 2381 msgstr "" 2382 2382 2383 - #: src/components/status.jsx:2384 2383 + #: src/components/status.jsx:2397 2384 2384 msgid "Edited" 2385 2385 msgstr "" 2386 2386 2387 - #: src/components/status.jsx:2461 2387 + #: src/components/status.jsx:2474 2388 2388 msgid "Comments" 2389 2389 msgstr "" 2390 2390 2391 2391 #. More from [Author] 2392 - #: src/components/status.jsx:2754 2392 + #: src/components/status.jsx:2767 2393 2393 msgid "More from <0/>" 2394 2394 msgstr "More from <0/>" 2395 2395 2396 - #: src/components/status.jsx:3056 2396 + #: src/components/status.jsx:3069 2397 2397 msgid "Edit History" 2398 2398 msgstr "" 2399 2399 2400 - #: src/components/status.jsx:3060 2400 + #: src/components/status.jsx:3073 2401 2401 msgid "Failed to load history" 2402 2402 msgstr "" 2403 2403 2404 - #: src/components/status.jsx:3065 2404 + #: src/components/status.jsx:3078 2405 2405 #: src/pages/annual-report.jsx:45 2406 2406 msgid "Loading…" 2407 2407 msgstr "" 2408 2408 2409 - #: src/components/status.jsx:3301 2409 + #: src/components/status.jsx:3314 2410 2410 msgid "HTML Code" 2411 2411 msgstr "" 2412 2412 2413 - #: src/components/status.jsx:3318 2413 + #: src/components/status.jsx:3331 2414 2414 msgid "HTML code copied" 2415 2415 msgstr "" 2416 2416 2417 - #: src/components/status.jsx:3321 2417 + #: src/components/status.jsx:3334 2418 2418 msgid "Unable to copy HTML code" 2419 2419 msgstr "" 2420 2420 2421 - #: src/components/status.jsx:3333 2421 + #: src/components/status.jsx:3346 2422 2422 msgid "Media attachments:" 2423 2423 msgstr "" 2424 2424 2425 - #: src/components/status.jsx:3355 2425 + #: src/components/status.jsx:3368 2426 2426 msgid "Account Emojis:" 2427 2427 msgstr "" 2428 2428 2429 - #: src/components/status.jsx:3386 2430 - #: src/components/status.jsx:3431 2429 + #: src/components/status.jsx:3399 2430 + #: src/components/status.jsx:3444 2431 2431 msgid "static URL" 2432 2432 msgstr "" 2433 2433 2434 - #: src/components/status.jsx:3400 2434 + #: src/components/status.jsx:3413 2435 2435 msgid "Emojis:" 2436 2436 msgstr "" 2437 2437 2438 - #: src/components/status.jsx:3445 2438 + #: src/components/status.jsx:3458 2439 2439 msgid "Notes:" 2440 2440 msgstr "" 2441 2441 2442 - #: src/components/status.jsx:3449 2442 + #: src/components/status.jsx:3462 2443 2443 msgid "This is static, unstyled and scriptless. You may need to apply your own styles and edit as needed." 2444 2444 msgstr "" 2445 2445 2446 - #: src/components/status.jsx:3455 2446 + #: src/components/status.jsx:3468 2447 2447 msgid "Polls are not interactive, becomes a list with vote counts." 2448 2448 msgstr "" 2449 2449 2450 - #: src/components/status.jsx:3460 2450 + #: src/components/status.jsx:3473 2451 2451 msgid "Media attachments can be images, videos, audios or any file types." 2452 2452 msgstr "" 2453 2453 2454 - #: src/components/status.jsx:3466 2454 + #: src/components/status.jsx:3479 2455 2455 msgid "Post could be edited or deleted later." 2456 2456 msgstr "" 2457 2457 2458 - #: src/components/status.jsx:3472 2458 + #: src/components/status.jsx:3485 2459 2459 msgid "Preview" 2460 2460 msgstr "" 2461 2461 2462 - #: src/components/status.jsx:3481 2462 + #: src/components/status.jsx:3494 2463 2463 msgid "Note: This preview is lightly styled." 2464 2464 msgstr "" 2465 2465 2466 2466 #. [Name] [Visibility icon] boosted 2467 - #: src/components/status.jsx:3734 2467 + #: src/components/status.jsx:3747 2468 2468 msgid "<0/> <1/> boosted" 2469 2469 msgstr "" 2470 2470 2471 - #: src/components/timeline.jsx:455 2471 + #: src/components/timeline.jsx:479 2472 2472 #: src/pages/settings.jsx:1174 2473 2473 msgid "New posts" 2474 2474 msgstr "" 2475 2475 2476 - #: src/components/timeline.jsx:556 2476 + #: src/components/timeline.jsx:580 2477 2477 #: src/pages/home.jsx:216 2478 - #: src/pages/notifications.jsx:872 2479 - #: src/pages/status.jsx:990 2480 - #: src/pages/status.jsx:1363 2478 + #: src/pages/notifications.jsx:890 2479 + #: src/pages/status.jsx:1008 2480 + #: src/pages/status.jsx:1381 2481 2481 msgid "Try again" 2482 2482 msgstr "" 2483 2483 2484 2484 #. placeholder {0}: fItems.length 2485 - #: src/components/timeline.jsx:591 2485 + #: src/components/timeline.jsx:615 2486 2486 msgid "{0, plural, one {# Boost} other {# Boosts}}" 2487 2487 msgstr "{0, plural, one {# Boost} other {# Boosts}}" 2488 2488 2489 - #: src/components/timeline.jsx:596 2489 + #: src/components/timeline.jsx:620 2490 2490 msgid "Pinned posts" 2491 2491 msgstr "Pinned posts" 2492 2492 2493 - #: src/components/timeline.jsx:955 2494 - #: src/components/timeline.jsx:962 2495 - #: src/pages/catchup.jsx:1893 2493 + #: src/components/timeline.jsx:979 2494 + #: src/components/timeline.jsx:986 2495 + #: src/pages/catchup.jsx:1898 2496 2496 msgid "Thread" 2497 2497 msgstr "" 2498 2498 2499 2499 #. placeholder {0}: filterInfo.titlesStr 2500 - #: src/components/timeline.jsx:977 2500 + #: src/components/timeline.jsx:1001 2501 2501 msgid "<0>Filtered</0>: <1>{0}</1>" 2502 2502 msgstr "" 2503 2503 ··· 2757 2757 msgid "Showing {selectedFilterCategory, select, all {all posts} original {original posts} replies {replies} boosts {boosts} followedTags {followed tags} groups {groups} filtered {filtered posts}}, {sortBy, select, createdAt {{sortOrder, select, asc {oldest} desc {latest}}} reblogsCount {{sortOrder, select, asc {fewest boosts} desc {most boosts}}} favouritesCount {{sortOrder, select, asc {fewest likes} desc {most likes}}} repliesCount {{sortOrder, select, asc {fewest replies} desc {most replies}}} density {{sortOrder, select, asc {least dense} desc {most dense}}}} first{groupBy, select, account {, grouped by authors} other {}}" 2758 2758 msgstr "Showing {selectedFilterCategory, select, all {all posts} original {original posts} replies {replies} boosts {boosts} followedTags {followed tags} groups {groups} filtered {filtered posts}}, {sortBy, select, createdAt {{sortOrder, select, asc {oldest} desc {latest}}} reblogsCount {{sortOrder, select, asc {fewest boosts} desc {most boosts}}} favouritesCount {{sortOrder, select, asc {fewest likes} desc {most likes}}} repliesCount {{sortOrder, select, asc {fewest replies} desc {most replies}}} density {{sortOrder, select, asc {least dense} desc {most dense}}}} first{groupBy, select, account {, grouped by authors} other {}}" 2759 2759 2760 - #: src/pages/catchup.jsx:883 2761 - #: src/pages/catchup.jsx:907 2760 + #: src/pages/catchup.jsx:888 2761 + #: src/pages/catchup.jsx:912 2762 2762 msgid "Catch-up <0>beta</0>" 2763 2763 msgstr "" 2764 2764 2765 - #: src/pages/catchup.jsx:897 2766 - #: src/pages/catchup.jsx:1582 2765 + #: src/pages/catchup.jsx:902 2766 + #: src/pages/catchup.jsx:1587 2767 2767 msgid "Help" 2768 2768 msgstr "" 2769 2769 2770 - #: src/pages/catchup.jsx:913 2770 + #: src/pages/catchup.jsx:918 2771 2771 msgid "What is this?" 2772 2772 msgstr "" 2773 2773 2774 - #: src/pages/catchup.jsx:916 2774 + #: src/pages/catchup.jsx:921 2775 2775 msgid "Catch-up is a separate timeline for your followings, offering a high-level view at a glance, with a simple, email-inspired interface to effortlessly sort and filter through posts." 2776 2776 msgstr "" 2777 2777 2778 - #: src/pages/catchup.jsx:927 2778 + #: src/pages/catchup.jsx:932 2779 2779 msgid "Preview of Catch-up UI" 2780 2780 msgstr "Preview of Catch-up UI" 2781 2781 2782 - #: src/pages/catchup.jsx:936 2782 + #: src/pages/catchup.jsx:941 2783 2783 msgid "Let's catch up" 2784 2784 msgstr "" 2785 2785 2786 - #: src/pages/catchup.jsx:941 2786 + #: src/pages/catchup.jsx:946 2787 2787 msgid "Let's catch up on the posts from your followings." 2788 2788 msgstr "" 2789 2789 2790 - #: src/pages/catchup.jsx:945 2790 + #: src/pages/catchup.jsx:950 2791 2791 msgid "Show me all posts from…" 2792 2792 msgstr "" 2793 2793 2794 - #: src/pages/catchup.jsx:968 2794 + #: src/pages/catchup.jsx:973 2795 2795 msgid "until the max" 2796 2796 msgstr "until the max" 2797 2797 2798 - #: src/pages/catchup.jsx:998 2798 + #: src/pages/catchup.jsx:1003 2799 2799 msgid "Catch up" 2800 2800 msgstr "" 2801 2801 2802 - #: src/pages/catchup.jsx:1004 2802 + #: src/pages/catchup.jsx:1009 2803 2803 msgid "Overlaps with your last catch-up" 2804 2804 msgstr "" 2805 2805 2806 2806 #. placeholder {0}: dtf.format(new Date(lastCatchupEndAt)) 2807 - #: src/pages/catchup.jsx:1016 2807 + #: src/pages/catchup.jsx:1021 2808 2808 msgid "Until the last catch-up ({0})" 2809 2809 msgstr "" 2810 2810 2811 - #: src/pages/catchup.jsx:1025 2811 + #: src/pages/catchup.jsx:1030 2812 2812 msgid "Note: your instance might only show a maximum of 800 posts in the Home timeline regardless of the time range. Could be less or more." 2813 2813 msgstr "" 2814 2814 2815 - #: src/pages/catchup.jsx:1035 2815 + #: src/pages/catchup.jsx:1040 2816 2816 msgid "Previously…" 2817 2817 msgstr "" 2818 2818 2819 2819 #. placeholder {0}: pc.count 2820 - #: src/pages/catchup.jsx:1053 2820 + #: src/pages/catchup.jsx:1058 2821 2821 msgid "{0, plural, one {# post} other {# posts}}" 2822 2822 msgstr "" 2823 2823 2824 - #: src/pages/catchup.jsx:1063 2824 + #: src/pages/catchup.jsx:1068 2825 2825 msgid "Remove this catch-up?" 2826 2826 msgstr "Remove this catch-up?" 2827 2827 2828 2828 #. placeholder {0}: pc.id 2829 - #: src/pages/catchup.jsx:1066 2829 + #: src/pages/catchup.jsx:1071 2830 2830 msgid "Removing Catch-up {0}" 2831 2831 msgstr "Removing Catch-up {0}" 2832 2832 2833 2833 #. placeholder {0}: pc.id 2834 - #: src/pages/catchup.jsx:1070 2834 + #: src/pages/catchup.jsx:1075 2835 2835 msgid "Catch-up {0} removed" 2836 2836 msgstr "Catch-up {0} removed" 2837 2837 2838 - #: src/pages/catchup.jsx:1084 2838 + #: src/pages/catchup.jsx:1089 2839 2839 msgid "Note: Only max 3 will be stored. The rest will be automatically removed." 2840 2840 msgstr "" 2841 2841 2842 - #: src/pages/catchup.jsx:1099 2842 + #: src/pages/catchup.jsx:1104 2843 2843 msgid "Fetching posts…" 2844 2844 msgstr "" 2845 2845 2846 - #: src/pages/catchup.jsx:1102 2846 + #: src/pages/catchup.jsx:1107 2847 2847 msgid "This might take a while." 2848 2848 msgstr "" 2849 2849 2850 - #: src/pages/catchup.jsx:1137 2850 + #: src/pages/catchup.jsx:1142 2851 2851 msgid "Reset filters" 2852 2852 msgstr "" 2853 2853 2854 - #: src/pages/catchup.jsx:1145 2855 - #: src/pages/catchup.jsx:1588 2854 + #: src/pages/catchup.jsx:1150 2855 + #: src/pages/catchup.jsx:1593 2856 2856 msgid "Top links" 2857 2857 msgstr "" 2858 2858 2859 2859 #. placeholder {0}: sharers.map((s) => { const { avatarStatic, displayName } = s; return ( <button type="button" class="plain" style={{ padding: 0, }} onClick={(e) => { e.preventDefault(); e.stopPropagation(); // Reset and filter to author const { id } = s; setSelectedAuthor(id); setSelectedFilterCategory('all'); }} > <Avatar url={avatarStatic} size="s" alt={displayName} /> </button> ); }) 2860 - #: src/pages/catchup.jsx:1258 2860 + #: src/pages/catchup.jsx:1263 2861 2861 msgid "Shared by {0}" 2862 2862 msgstr "" 2863 2863 2864 - #: src/pages/catchup.jsx:1313 2864 + #: src/pages/catchup.jsx:1318 2865 2865 #: src/pages/mentions.jsx:148 2866 - #: src/pages/search.jsx:313 2866 + #: src/pages/search.jsx:326 2867 2867 msgid "All" 2868 2868 msgstr "" 2869 2869 2870 2870 #. placeholder {0}: authorCountsList.length 2871 - #: src/pages/catchup.jsx:1398 2871 + #: src/pages/catchup.jsx:1403 2872 2872 msgid "{0, plural, one {# author} other {# authors}}" 2873 2873 msgstr "" 2874 2874 2875 - #: src/pages/catchup.jsx:1410 2875 + #: src/pages/catchup.jsx:1415 2876 2876 msgid "Sort" 2877 2877 msgstr "" 2878 2878 2879 - #: src/pages/catchup.jsx:1441 2879 + #: src/pages/catchup.jsx:1446 2880 2880 msgid "Date" 2881 2881 msgstr "Date" 2882 2882 2883 - #: src/pages/catchup.jsx:1445 2883 + #: src/pages/catchup.jsx:1450 2884 2884 msgid "Density" 2885 2885 msgstr "Density" 2886 2886 2887 2887 #. js-lingui-explicit-id 2888 - #: src/pages/catchup.jsx:1468 2888 + #: src/pages/catchup.jsx:1473 2889 2889 msgid "group.filter" 2890 2890 msgstr "Group" 2891 2891 2892 - #: src/pages/catchup.jsx:1483 2892 + #: src/pages/catchup.jsx:1488 2893 2893 msgid "Authors" 2894 2894 msgstr "Authors" 2895 2895 2896 - #: src/pages/catchup.jsx:1484 2896 + #: src/pages/catchup.jsx:1489 2897 2897 msgid "None" 2898 2898 msgstr "None" 2899 2899 2900 - #: src/pages/catchup.jsx:1500 2900 + #: src/pages/catchup.jsx:1505 2901 2901 msgid "Show all authors" 2902 2902 msgstr "" 2903 2903 2904 - #: src/pages/catchup.jsx:1551 2904 + #: src/pages/catchup.jsx:1556 2905 2905 msgid "You don't have to read everything." 2906 2906 msgstr "You don't have to read everything." 2907 2907 2908 - #: src/pages/catchup.jsx:1552 2908 + #: src/pages/catchup.jsx:1557 2909 2909 msgid "That's all." 2910 2910 msgstr "That's all." 2911 2911 2912 - #: src/pages/catchup.jsx:1560 2912 + #: src/pages/catchup.jsx:1565 2913 2913 msgid "Back to top" 2914 2914 msgstr "" 2915 2915 2916 - #: src/pages/catchup.jsx:1591 2916 + #: src/pages/catchup.jsx:1596 2917 2917 msgid "Links shared by followings, sorted by shared counts, boosts and likes." 2918 2918 msgstr "" 2919 2919 2920 - #: src/pages/catchup.jsx:1597 2920 + #: src/pages/catchup.jsx:1602 2921 2921 msgid "Sort: Density" 2922 2922 msgstr "" 2923 2923 2924 - #: src/pages/catchup.jsx:1600 2924 + #: src/pages/catchup.jsx:1605 2925 2925 msgid "Posts are sorted by information density or depth. Shorter posts are \"lighter\" while longer posts are \"heavier\". Posts with photos are \"heavier\" than posts without photos." 2926 2926 msgstr "" 2927 2927 2928 - #: src/pages/catchup.jsx:1607 2928 + #: src/pages/catchup.jsx:1612 2929 2929 msgid "Group: Authors" 2930 2930 msgstr "" 2931 2931 2932 - #: src/pages/catchup.jsx:1610 2932 + #: src/pages/catchup.jsx:1615 2933 2933 msgid "Posts are grouped by authors, sorted by posts count per author." 2934 2934 msgstr "" 2935 2935 2936 - #: src/pages/catchup.jsx:1657 2936 + #: src/pages/catchup.jsx:1662 2937 2937 msgid "Next author" 2938 2938 msgstr "" 2939 2939 2940 - #: src/pages/catchup.jsx:1665 2940 + #: src/pages/catchup.jsx:1670 2941 2941 msgid "Previous author" 2942 2942 msgstr "" 2943 2943 2944 - #: src/pages/catchup.jsx:1681 2944 + #: src/pages/catchup.jsx:1686 2945 2945 msgid "Scroll to top" 2946 2946 msgstr "" 2947 2947 ··· 3327 3327 msgid "Who are limited by server moderators" 3328 3328 msgstr "" 3329 3329 3330 - #: src/pages/notifications.jsx:579 3331 - #: src/pages/notifications.jsx:920 3330 + #: src/pages/notifications.jsx:597 3331 + #: src/pages/notifications.jsx:938 3332 3332 msgid "Notifications settings" 3333 3333 msgstr "" 3334 3334 3335 - #: src/pages/notifications.jsx:597 3335 + #: src/pages/notifications.jsx:615 3336 3336 msgid "New notifications" 3337 3337 msgstr "" 3338 3338 3339 3339 #. placeholder {0}: announcements.length 3340 - #: src/pages/notifications.jsx:608 3340 + #: src/pages/notifications.jsx:626 3341 3341 msgid "{0, plural, one {Announcement} other {Announcements}}" 3342 3342 msgstr "" 3343 3343 3344 - #: src/pages/notifications.jsx:655 3344 + #: src/pages/notifications.jsx:673 3345 3345 #: src/pages/settings.jsx:1162 3346 3346 msgid "Follow requests" 3347 3347 msgstr "" 3348 3348 3349 3349 #. placeholder {0}: followRequests.length 3350 - #: src/pages/notifications.jsx:660 3350 + #: src/pages/notifications.jsx:678 3351 3351 msgid "{0, plural, one {# follow request} other {# follow requests}}" 3352 3352 msgstr "" 3353 3353 3354 3354 #. placeholder {0}: notificationsPolicy.summary.pendingRequestsCount 3355 - #: src/pages/notifications.jsx:715 3355 + #: src/pages/notifications.jsx:733 3356 3356 msgid "{0, plural, one {Filtered notifications from # person} other {Filtered notifications from # people}}" 3357 3357 msgstr "" 3358 3358 3359 - #: src/pages/notifications.jsx:788 3359 + #: src/pages/notifications.jsx:806 3360 3360 msgid "Only mentions" 3361 3361 msgstr "" 3362 3362 3363 - #: src/pages/notifications.jsx:792 3363 + #: src/pages/notifications.jsx:810 3364 3364 msgid "Today" 3365 3365 msgstr "" 3366 3366 3367 - #: src/pages/notifications.jsx:797 3367 + #: src/pages/notifications.jsx:815 3368 3368 msgid "You're all caught up." 3369 3369 msgstr "" 3370 3370 3371 - #: src/pages/notifications.jsx:820 3371 + #: src/pages/notifications.jsx:838 3372 3372 msgid "Yesterday" 3373 3373 msgstr "" 3374 3374 3375 - #: src/pages/notifications.jsx:868 3375 + #: src/pages/notifications.jsx:886 3376 3376 msgid "Unable to load notifications" 3377 3377 msgstr "" 3378 3378 3379 - #: src/pages/notifications.jsx:947 3379 + #: src/pages/notifications.jsx:965 3380 3380 msgid "Notifications settings updated" 3381 3381 msgstr "" 3382 3382 3383 - #: src/pages/notifications.jsx:955 3383 + #: src/pages/notifications.jsx:973 3384 3384 msgid "Filter out notifications from people:" 3385 3385 msgstr "" 3386 3386 3387 - #: src/pages/notifications.jsx:969 3387 + #: src/pages/notifications.jsx:987 3388 3388 msgid "Filter" 3389 3389 msgstr "" 3390 3390 3391 - #: src/pages/notifications.jsx:972 3391 + #: src/pages/notifications.jsx:990 3392 3392 msgid "Ignore" 3393 3393 msgstr "" 3394 3394 3395 3395 #. placeholder {0}: niceDateTime(updatedAtDate) 3396 - #: src/pages/notifications.jsx:1045 3396 + #: src/pages/notifications.jsx:1063 3397 3397 msgid "Updated <0>{0}</0>" 3398 3398 msgstr "" 3399 3399 3400 3400 #. placeholder {0}: account.username 3401 - #: src/pages/notifications.jsx:1113 3401 + #: src/pages/notifications.jsx:1131 3402 3402 msgid "View notifications from <0>@{0}</0>" 3403 3403 msgstr "" 3404 3404 3405 3405 #. placeholder {0}: account.username 3406 - #: src/pages/notifications.jsx:1134 3406 + #: src/pages/notifications.jsx:1152 3407 3407 msgid "Notifications from <0>@{0}</0>" 3408 3408 msgstr "" 3409 3409 3410 3410 #. placeholder {0}: request.account.username 3411 - #: src/pages/notifications.jsx:1202 3411 + #: src/pages/notifications.jsx:1220 3412 3412 msgid "Notifications from @{0} will not be filtered from now on." 3413 3413 msgstr "" 3414 3414 3415 - #: src/pages/notifications.jsx:1207 3415 + #: src/pages/notifications.jsx:1225 3416 3416 msgid "Unable to accept notification request" 3417 3417 msgstr "" 3418 3418 3419 - #: src/pages/notifications.jsx:1212 3419 + #: src/pages/notifications.jsx:1230 3420 3420 msgid "Allow" 3421 3421 msgstr "" 3422 3422 3423 3423 #. placeholder {0}: request.account.username 3424 - #: src/pages/notifications.jsx:1232 3424 + #: src/pages/notifications.jsx:1250 3425 3425 msgid "Notifications from @{0} will not show up in Filtered notifications from now on." 3426 3426 msgstr "Notifications from @{0} will not show up in Filtered notifications from now on." 3427 3427 3428 - #: src/pages/notifications.jsx:1237 3428 + #: src/pages/notifications.jsx:1255 3429 3429 msgid "Unable to dismiss notification request" 3430 3430 msgstr "" 3431 3431 3432 - #: src/pages/notifications.jsx:1242 3432 + #: src/pages/notifications.jsx:1260 3433 3433 msgid "Dismiss" 3434 3434 msgstr "" 3435 3435 3436 - #: src/pages/notifications.jsx:1257 3436 + #: src/pages/notifications.jsx:1275 3437 3437 msgid "Dismissed" 3438 3438 msgstr "" 3439 3439 ··· 3520 3520 msgid "Search: {q}" 3521 3521 msgstr "" 3522 3522 3523 - #: src/pages/search.jsx:323 3524 - #: src/pages/search.jsx:405 3523 + #: src/pages/search.jsx:336 3524 + #: src/pages/search.jsx:418 3525 3525 msgid "Hashtags" 3526 3526 msgstr "" 3527 3527 3528 - #: src/pages/search.jsx:355 3529 - #: src/pages/search.jsx:409 3530 - #: src/pages/search.jsx:479 3528 + #: src/pages/search.jsx:368 3529 + #: src/pages/search.jsx:422 3530 + #: src/pages/search.jsx:492 3531 3531 msgid "See more" 3532 3532 msgstr "" 3533 3533 3534 - #: src/pages/search.jsx:381 3534 + #: src/pages/search.jsx:394 3535 3535 msgid "See more accounts" 3536 3536 msgstr "" 3537 3537 3538 - #: src/pages/search.jsx:395 3538 + #: src/pages/search.jsx:408 3539 3539 msgid "No accounts found." 3540 3540 msgstr "" 3541 3541 3542 - #: src/pages/search.jsx:451 3542 + #: src/pages/search.jsx:464 3543 3543 msgid "See more hashtags" 3544 3544 msgstr "" 3545 3545 3546 - #: src/pages/search.jsx:465 3546 + #: src/pages/search.jsx:478 3547 3547 msgid "No hashtags found." 3548 3548 msgstr "" 3549 3549 3550 - #: src/pages/search.jsx:509 3550 + #: src/pages/search.jsx:522 3551 3551 msgid "See more posts" 3552 3552 msgstr "" 3553 3553 3554 - #: src/pages/search.jsx:523 3554 + #: src/pages/search.jsx:536 3555 3555 msgid "No posts found." 3556 3556 msgstr "" 3557 3557 3558 - #: src/pages/search.jsx:567 3558 + #: src/pages/search.jsx:580 3559 3559 msgid "Enter your search term or paste a URL above to get started." 3560 3560 msgstr "" 3561 3561 ··· 3802 3802 3803 3803 #. js-lingui-explicit-id 3804 3804 #: src/pages/status.jsx:599 3805 - #: src/pages/status.jsx:1133 3805 + #: src/pages/status.jsx:1151 3806 3806 msgid "post.title" 3807 3807 msgstr "Post" 3808 3808 3809 - #: src/pages/status.jsx:824 3809 + #: src/pages/status.jsx:842 3810 3810 msgid "You're not logged in. Interactions (reply, boost, etc) are not possible." 3811 3811 msgstr "" 3812 3812 3813 - #: src/pages/status.jsx:844 3813 + #: src/pages/status.jsx:862 3814 3814 msgid "This post is from another instance (<0>{instance}</0>). Interactions (reply, boost, etc) are not possible." 3815 3815 msgstr "" 3816 3816 3817 - #: src/pages/status.jsx:872 3817 + #: src/pages/status.jsx:890 3818 3818 msgid "Error: {e}" 3819 3819 msgstr "" 3820 3820 3821 - #: src/pages/status.jsx:879 3821 + #: src/pages/status.jsx:897 3822 3822 msgid "Switch to my instance to enable interactions" 3823 3823 msgstr "" 3824 3824 3825 - #: src/pages/status.jsx:981 3825 + #: src/pages/status.jsx:999 3826 3826 msgid "Unable to load replies." 3827 3827 msgstr "" 3828 3828 3829 - #: src/pages/status.jsx:1093 3829 + #: src/pages/status.jsx:1111 3830 3830 msgid "Back" 3831 3831 msgstr "" 3832 3832 3833 - #: src/pages/status.jsx:1124 3833 + #: src/pages/status.jsx:1142 3834 3834 msgid "Go to main post" 3835 3835 msgstr "" 3836 3836 3837 3837 #. placeholder {0}: ancestors.length 3838 - #: src/pages/status.jsx:1147 3838 + #: src/pages/status.jsx:1165 3839 3839 msgid "{0} posts above ‒ Go to top" 3840 3840 msgstr "" 3841 3841 3842 - #: src/pages/status.jsx:1190 3843 - #: src/pages/status.jsx:1253 3842 + #: src/pages/status.jsx:1208 3843 + #: src/pages/status.jsx:1271 3844 3844 msgid "Switch to Side Peek view" 3845 3845 msgstr "" 3846 3846 3847 - #: src/pages/status.jsx:1254 3847 + #: src/pages/status.jsx:1272 3848 3848 msgid "Switch to Full view" 3849 3849 msgstr "" 3850 3850 3851 - #: src/pages/status.jsx:1272 3851 + #: src/pages/status.jsx:1290 3852 3852 msgid "Show all sensitive content" 3853 3853 msgstr "" 3854 3854 3855 - #: src/pages/status.jsx:1277 3855 + #: src/pages/status.jsx:1295 3856 3856 msgid "Experimental" 3857 3857 msgstr "" 3858 3858 3859 - #: src/pages/status.jsx:1286 3859 + #: src/pages/status.jsx:1304 3860 3860 msgid "Unable to switch" 3861 3861 msgstr "" 3862 3862 3863 3863 #. placeholder {0}: punycode.toUnicode( postInstance, ) 3864 - #: src/pages/status.jsx:1293 3864 + #: src/pages/status.jsx:1311 3865 3865 msgid "Switch to post's instance ({0})" 3866 3866 msgstr "Switch to post's instance ({0})" 3867 3867 3868 - #: src/pages/status.jsx:1296 3868 + #: src/pages/status.jsx:1314 3869 3869 msgid "Switch to post's instance" 3870 3870 msgstr "" 3871 3871 3872 - #: src/pages/status.jsx:1354 3872 + #: src/pages/status.jsx:1372 3873 3873 msgid "Unable to load post" 3874 3874 msgstr "" 3875 3875 3876 3876 #. placeholder {0}: replies.length 3877 3877 #. placeholder {1}: shortenNumber(replies.length) 3878 - #: src/pages/status.jsx:1490 3878 + #: src/pages/status.jsx:1508 3879 3879 msgid "{0, plural, one {# reply} other {<0>{1}</0> replies}}" 3880 3880 msgstr "" 3881 3881 3882 3882 #. placeholder {0}: shortenNumber(totalComments) 3883 - #: src/pages/status.jsx:1508 3883 + #: src/pages/status.jsx:1526 3884 3884 msgid "{totalComments, plural, one {# comment} other {<0>{0}</0> comments}}" 3885 3885 msgstr "" 3886 3886 3887 - #: src/pages/status.jsx:1530 3887 + #: src/pages/status.jsx:1548 3888 3888 msgid "View post with its replies" 3889 3889 msgstr "" 3890 3890
+4
src/pages/catchup.jsx
··· 716 716 } 717 717 }, 718 718 { 719 + useKey: true, 719 720 preventDefault: true, 720 721 ignoreModifiers: true, 721 722 }, ··· 760 761 } 761 762 }, 762 763 { 764 + useKey: true, 763 765 preventDefault: true, 764 766 ignoreModifiers: true, 765 767 }, ··· 789 791 } 790 792 }, 791 793 { 794 + useKey: true, 792 795 preventDefault: true, 793 796 ignoreModifiers: true, 794 797 enableOnFormTags: ['input'], ··· 817 820 }); 818 821 }, 819 822 { 823 + useKey: true, 820 824 preventDefault: true, 821 825 ignoreModifiers: true, 822 826 enableOnFormTags: ['input'],
+80 -62
src/pages/notifications.jsx
··· 451 451 }, []); 452 452 453 453 const itemsSelector = '.notification'; 454 - const jRef = useHotkeys('j', () => { 455 - const activeItem = document.activeElement.closest(itemsSelector); 456 - const activeItemRect = activeItem?.getBoundingClientRect(); 457 - const allItems = Array.from( 458 - scrollableRef.current.querySelectorAll(itemsSelector), 459 - ); 460 - if ( 461 - activeItem && 462 - activeItemRect.top < scrollableRef.current.clientHeight && 463 - activeItemRect.bottom > 0 464 - ) { 465 - const activeItemIndex = allItems.indexOf(activeItem); 466 - let nextItem = allItems[activeItemIndex + 1]; 467 - if (nextItem) { 468 - nextItem.focus(); 469 - nextItem.scrollIntoView(scrollIntoViewOptions); 454 + const jRef = useHotkeys( 455 + 'j', 456 + () => { 457 + const activeItem = document.activeElement.closest(itemsSelector); 458 + const activeItemRect = activeItem?.getBoundingClientRect(); 459 + const allItems = Array.from( 460 + scrollableRef.current.querySelectorAll(itemsSelector), 461 + ); 462 + if ( 463 + activeItem && 464 + activeItemRect.top < scrollableRef.current.clientHeight && 465 + activeItemRect.bottom > 0 466 + ) { 467 + const activeItemIndex = allItems.indexOf(activeItem); 468 + let nextItem = allItems[activeItemIndex + 1]; 469 + if (nextItem) { 470 + nextItem.focus(); 471 + nextItem.scrollIntoView(scrollIntoViewOptions); 472 + } 473 + } else { 474 + const topmostItem = allItems.find((item) => { 475 + const itemRect = item.getBoundingClientRect(); 476 + return itemRect.top >= 44 && itemRect.left >= 0; 477 + }); 478 + if (topmostItem) { 479 + topmostItem.focus(); 480 + topmostItem.scrollIntoView(scrollIntoViewOptions); 481 + } 470 482 } 471 - } else { 472 - const topmostItem = allItems.find((item) => { 473 - const itemRect = item.getBoundingClientRect(); 474 - return itemRect.top >= 44 && itemRect.left >= 0; 475 - }); 476 - if (topmostItem) { 477 - topmostItem.focus(); 478 - topmostItem.scrollIntoView(scrollIntoViewOptions); 479 - } 480 - } 481 - }); 483 + }, 484 + { 485 + useKey: true, 486 + }, 487 + ); 482 488 483 - const kRef = useHotkeys('k', () => { 484 - // focus on previous status after active item 485 - const activeItem = document.activeElement.closest(itemsSelector); 486 - const activeItemRect = activeItem?.getBoundingClientRect(); 487 - const allItems = Array.from( 488 - scrollableRef.current.querySelectorAll(itemsSelector), 489 - ); 490 - if ( 491 - activeItem && 492 - activeItemRect.top < scrollableRef.current.clientHeight && 493 - activeItemRect.bottom > 0 494 - ) { 495 - const activeItemIndex = allItems.indexOf(activeItem); 496 - let prevItem = allItems[activeItemIndex - 1]; 497 - if (prevItem) { 498 - prevItem.focus(); 499 - prevItem.scrollIntoView(scrollIntoViewOptions); 489 + const kRef = useHotkeys( 490 + 'k', 491 + () => { 492 + // focus on previous status after active item 493 + const activeItem = document.activeElement.closest(itemsSelector); 494 + const activeItemRect = activeItem?.getBoundingClientRect(); 495 + const allItems = Array.from( 496 + scrollableRef.current.querySelectorAll(itemsSelector), 497 + ); 498 + if ( 499 + activeItem && 500 + activeItemRect.top < scrollableRef.current.clientHeight && 501 + activeItemRect.bottom > 0 502 + ) { 503 + const activeItemIndex = allItems.indexOf(activeItem); 504 + let prevItem = allItems[activeItemIndex - 1]; 505 + if (prevItem) { 506 + prevItem.focus(); 507 + prevItem.scrollIntoView(scrollIntoViewOptions); 508 + } 509 + } else { 510 + const topmostItem = allItems.find((item) => { 511 + const itemRect = item.getBoundingClientRect(); 512 + return itemRect.top >= 44 && itemRect.left >= 0; 513 + }); 514 + if (topmostItem) { 515 + topmostItem.focus(); 516 + topmostItem.scrollIntoView(scrollIntoViewOptions); 517 + } 500 518 } 501 - } else { 502 - const topmostItem = allItems.find((item) => { 503 - const itemRect = item.getBoundingClientRect(); 504 - return itemRect.top >= 44 && itemRect.left >= 0; 505 - }); 506 - if (topmostItem) { 507 - topmostItem.focus(); 508 - topmostItem.scrollIntoView(scrollIntoViewOptions); 519 + }, 520 + { 521 + useKey: true, 522 + }, 523 + ); 524 + 525 + const oRef = useHotkeys( 526 + ['enter', 'o'], 527 + () => { 528 + const activeItem = document.activeElement.closest(itemsSelector); 529 + const statusLink = activeItem?.querySelector('.status-link'); 530 + if (statusLink) { 531 + statusLink.click(); 509 532 } 510 - } 511 - }); 512 - 513 - const oRef = useHotkeys(['enter', 'o'], () => { 514 - const activeItem = document.activeElement.closest(itemsSelector); 515 - const statusLink = activeItem?.querySelector('.status-link'); 516 - if (statusLink) { 517 - statusLink.click(); 518 - } 519 - }); 533 + }, 534 + { 535 + useKey: true, 536 + }, 537 + ); 520 538 521 539 const today = new Date(); 522 540 const todaySubHeading = useMemo(() => {
+69 -56
src/pages/search.jsx
··· 198 198 }, [q, type, instance]); 199 199 200 200 useHotkeys( 201 - ['/', 'Slash'], 201 + ['Slash', '/'], 202 202 (e) => { 203 203 searchFormRef.current?.focus?.(); 204 204 searchFormRef.current?.select?.(); 205 205 }, 206 206 { 207 + useKey: true, 207 208 preventDefault: true, 208 209 }, 209 210 ); 210 211 211 212 const itemsSelector = '.timeline > li > a, .hashtag-list > li > a'; 212 - const jRef = useHotkeys('j', () => { 213 - const activeItem = document.activeElement.closest(itemsSelector); 214 - const activeItemRect = activeItem?.getBoundingClientRect(); 215 - const allItems = Array.from( 216 - scrollableRef.current.querySelectorAll(itemsSelector), 217 - ); 218 - if ( 219 - activeItem && 220 - activeItemRect.top < scrollableRef.current.clientHeight && 221 - activeItemRect.bottom > 0 222 - ) { 223 - const activeItemIndex = allItems.indexOf(activeItem); 224 - let nextItem = allItems[activeItemIndex + 1]; 225 - if (nextItem) { 226 - nextItem.focus(); 227 - nextItem.scrollIntoView(scrollIntoViewOptions); 213 + const jRef = useHotkeys( 214 + 'j', 215 + () => { 216 + const activeItem = document.activeElement.closest(itemsSelector); 217 + const activeItemRect = activeItem?.getBoundingClientRect(); 218 + const allItems = Array.from( 219 + scrollableRef.current.querySelectorAll(itemsSelector), 220 + ); 221 + if ( 222 + activeItem && 223 + activeItemRect.top < scrollableRef.current.clientHeight && 224 + activeItemRect.bottom > 0 225 + ) { 226 + const activeItemIndex = allItems.indexOf(activeItem); 227 + let nextItem = allItems[activeItemIndex + 1]; 228 + if (nextItem) { 229 + nextItem.focus(); 230 + nextItem.scrollIntoView(scrollIntoViewOptions); 231 + } 232 + } else { 233 + const topmostItem = allItems.find((item) => { 234 + const itemRect = item.getBoundingClientRect(); 235 + return itemRect.top >= 44 && itemRect.left >= 0; 236 + }); 237 + if (topmostItem) { 238 + topmostItem.focus(); 239 + topmostItem.scrollIntoView(scrollIntoViewOptions); 240 + } 228 241 } 229 - } else { 230 - const topmostItem = allItems.find((item) => { 231 - const itemRect = item.getBoundingClientRect(); 232 - return itemRect.top >= 44 && itemRect.left >= 0; 233 - }); 234 - if (topmostItem) { 235 - topmostItem.focus(); 236 - topmostItem.scrollIntoView(scrollIntoViewOptions); 237 - } 238 - } 239 - }); 242 + }, 243 + { 244 + useKey: true, 245 + }, 246 + ); 240 247 241 - const kRef = useHotkeys('k', () => { 242 - // focus on previous status after active item 243 - const activeItem = document.activeElement.closest(itemsSelector); 244 - const activeItemRect = activeItem?.getBoundingClientRect(); 245 - const allItems = Array.from( 246 - scrollableRef.current.querySelectorAll(itemsSelector), 247 - ); 248 - if ( 249 - activeItem && 250 - activeItemRect.top < scrollableRef.current.clientHeight && 251 - activeItemRect.bottom > 0 252 - ) { 253 - const activeItemIndex = allItems.indexOf(activeItem); 254 - let prevItem = allItems[activeItemIndex - 1]; 255 - if (prevItem) { 256 - prevItem.focus(); 257 - prevItem.scrollIntoView(scrollIntoViewOptions); 258 - } 259 - } else { 260 - const topmostItem = allItems.find((item) => { 261 - const itemRect = item.getBoundingClientRect(); 262 - return itemRect.top >= 44 && itemRect.left >= 0; 263 - }); 264 - if (topmostItem) { 265 - topmostItem.focus(); 266 - topmostItem.scrollIntoView(scrollIntoViewOptions); 248 + const kRef = useHotkeys( 249 + 'k', 250 + () => { 251 + // focus on previous status after active item 252 + const activeItem = document.activeElement.closest(itemsSelector); 253 + const activeItemRect = activeItem?.getBoundingClientRect(); 254 + const allItems = Array.from( 255 + scrollableRef.current.querySelectorAll(itemsSelector), 256 + ); 257 + if ( 258 + activeItem && 259 + activeItemRect.top < scrollableRef.current.clientHeight && 260 + activeItemRect.bottom > 0 261 + ) { 262 + const activeItemIndex = allItems.indexOf(activeItem); 263 + let prevItem = allItems[activeItemIndex - 1]; 264 + if (prevItem) { 265 + prevItem.focus(); 266 + prevItem.scrollIntoView(scrollIntoViewOptions); 267 + } 268 + } else { 269 + const topmostItem = allItems.find((item) => { 270 + const itemRect = item.getBoundingClientRect(); 271 + return itemRect.top >= 44 && itemRect.left >= 0; 272 + }); 273 + if (topmostItem) { 274 + topmostItem.focus(); 275 + topmostItem.scrollIntoView(scrollIntoViewOptions); 276 + } 267 277 } 268 - } 269 - }); 278 + }, 279 + { 280 + useKey: true, 281 + }, 282 + ); 270 283 271 284 const [filterBarParent] = useAutoAnimate(); 272 285
+89 -71
src/pages/status.jsx
··· 651 651 location.hash = closeLink; 652 652 }); 653 653 654 - useHotkeys('j', () => { 655 - const activeStatus = document.activeElement.closest( 656 - '.status-link, .status-focus', 657 - ); 658 - const activeStatusRect = activeStatus?.getBoundingClientRect(); 659 - const allStatusLinks = Array.from( 660 - scrollableRef.current.querySelectorAll(STATUSES_SELECTOR), 661 - ); 662 - console.log({ allStatusLinks }); 663 - if ( 664 - activeStatus && 665 - activeStatusRect.top < scrollableRef.current.clientHeight && 666 - activeStatusRect.bottom > 0 667 - ) { 668 - const activeStatusIndex = allStatusLinks.indexOf(activeStatus); 669 - let nextStatus = allStatusLinks[activeStatusIndex + 1]; 670 - if (nextStatus) { 671 - nextStatus.focus(); 672 - nextStatus.scrollIntoView(scrollIntoViewOptions); 673 - } 674 - } else { 675 - // If active status is not in viewport, get the topmost status-link in viewport 676 - const topmostStatusLink = allStatusLinks.find((statusLink) => { 677 - const statusLinkRect = statusLink.getBoundingClientRect(); 678 - return statusLinkRect.top >= 44 && statusLinkRect.left >= 0; // 44 is the magic number for header height, not real 679 - }); 680 - if (topmostStatusLink) { 681 - topmostStatusLink.focus(); 682 - topmostStatusLink.scrollIntoView(scrollIntoViewOptions); 654 + useHotkeys( 655 + 'j', 656 + () => { 657 + const activeStatus = document.activeElement.closest( 658 + '.status-link, .status-focus', 659 + ); 660 + const activeStatusRect = activeStatus?.getBoundingClientRect(); 661 + const allStatusLinks = Array.from( 662 + scrollableRef.current.querySelectorAll(STATUSES_SELECTOR), 663 + ); 664 + console.log({ allStatusLinks }); 665 + if ( 666 + activeStatus && 667 + activeStatusRect.top < scrollableRef.current.clientHeight && 668 + activeStatusRect.bottom > 0 669 + ) { 670 + const activeStatusIndex = allStatusLinks.indexOf(activeStatus); 671 + let nextStatus = allStatusLinks[activeStatusIndex + 1]; 672 + if (nextStatus) { 673 + nextStatus.focus(); 674 + nextStatus.scrollIntoView(scrollIntoViewOptions); 675 + } 676 + } else { 677 + // If active status is not in viewport, get the topmost status-link in viewport 678 + const topmostStatusLink = allStatusLinks.find((statusLink) => { 679 + const statusLinkRect = statusLink.getBoundingClientRect(); 680 + return statusLinkRect.top >= 44 && statusLinkRect.left >= 0; // 44 is the magic number for header height, not real 681 + }); 682 + if (topmostStatusLink) { 683 + topmostStatusLink.focus(); 684 + topmostStatusLink.scrollIntoView(scrollIntoViewOptions); 685 + } 683 686 } 684 - } 685 - }); 687 + }, 688 + { 689 + useKey: true, 690 + }, 691 + ); 686 692 687 - useHotkeys('k', () => { 688 - const activeStatus = document.activeElement.closest( 689 - '.status-link, .status-focus', 690 - ); 691 - const activeStatusRect = activeStatus?.getBoundingClientRect(); 692 - const allStatusLinks = Array.from( 693 - scrollableRef.current.querySelectorAll(STATUSES_SELECTOR), 694 - ); 695 - if ( 696 - activeStatus && 697 - activeStatusRect.top < scrollableRef.current.clientHeight && 698 - activeStatusRect.bottom > 0 699 - ) { 700 - const activeStatusIndex = allStatusLinks.indexOf(activeStatus); 701 - let prevStatus = allStatusLinks[activeStatusIndex - 1]; 702 - if (prevStatus) { 703 - prevStatus.focus(); 704 - prevStatus.scrollIntoView(scrollIntoViewOptions); 705 - } 706 - } else { 707 - // If active status is not in viewport, get the topmost status-link in viewport 708 - const topmostStatusLink = allStatusLinks.find((statusLink) => { 709 - const statusLinkRect = statusLink.getBoundingClientRect(); 710 - return statusLinkRect.top >= 44 && statusLinkRect.left >= 0; // 44 is the magic number for header height, not real 711 - }); 712 - if (topmostStatusLink) { 713 - topmostStatusLink.focus(); 714 - topmostStatusLink.scrollIntoView(scrollIntoViewOptions); 693 + useHotkeys( 694 + 'k', 695 + () => { 696 + const activeStatus = document.activeElement.closest( 697 + '.status-link, .status-focus', 698 + ); 699 + const activeStatusRect = activeStatus?.getBoundingClientRect(); 700 + const allStatusLinks = Array.from( 701 + scrollableRef.current.querySelectorAll(STATUSES_SELECTOR), 702 + ); 703 + if ( 704 + activeStatus && 705 + activeStatusRect.top < scrollableRef.current.clientHeight && 706 + activeStatusRect.bottom > 0 707 + ) { 708 + const activeStatusIndex = allStatusLinks.indexOf(activeStatus); 709 + let prevStatus = allStatusLinks[activeStatusIndex - 1]; 710 + if (prevStatus) { 711 + prevStatus.focus(); 712 + prevStatus.scrollIntoView(scrollIntoViewOptions); 713 + } 714 + } else { 715 + // If active status is not in viewport, get the topmost status-link in viewport 716 + const topmostStatusLink = allStatusLinks.find((statusLink) => { 717 + const statusLinkRect = statusLink.getBoundingClientRect(); 718 + return statusLinkRect.top >= 44 && statusLinkRect.left >= 0; // 44 is the magic number for header height, not real 719 + }); 720 + if (topmostStatusLink) { 721 + topmostStatusLink.focus(); 722 + topmostStatusLink.scrollIntoView(scrollIntoViewOptions); 723 + } 715 724 } 716 - } 717 - }); 725 + }, 726 + { 727 + useKey: true, 728 + }, 729 + ); 718 730 719 731 // NOTE: I'm not sure if 'x' is the best shortcut for this, might change it later 720 732 // IDEA: x is for expand 721 - useHotkeys('x', () => { 722 - const activeStatus = document.activeElement.closest( 723 - '.status-link, .status-focus', 724 - ); 725 - if (activeStatus) { 726 - const details = activeStatus.nextElementSibling; 727 - if (details && details.tagName.toLowerCase() === 'details') { 728 - details.open = !details.open; 733 + useHotkeys( 734 + 'x', 735 + () => { 736 + const activeStatus = document.activeElement.closest( 737 + '.status-link, .status-focus', 738 + ); 739 + if (activeStatus) { 740 + const details = activeStatus.nextElementSibling; 741 + if (details && details.tagName.toLowerCase() === 'details') { 742 + details.open = !details.open; 743 + } 729 744 } 730 - } 731 - }); 745 + }, 746 + { 747 + useKey: true, 748 + }, 749 + ); 732 750 733 751 const [reachTopPost, setReachTopPost] = useState(false); 734 752 // const { nearReachStart } = useScroll({