v4: the notifications page restores its list and scroll on Back, and shows what it missed — it now saves its loaded pages and scroll position as it is left and restores them on Back, through useFeedCache, useScrollSave and useScrollRestore like the feeds and the profile's tabs; the saved list keeps the ones the server confirmed read as read, so coming back doesn't highlight them again. The page never refetched after a reconnect, so notifications sent while the socket was down never showed, and the next read-all marked them read unseen; a reconnect, and every restored list (after a reload the socket hasn't said yet whether anything is new), now fetch the first page again, and what is new goes on top with the socket's arrivals, those alone sorted newest first so the server's order stays. Marking read now follows the unread notifications shown, each sent once, instead of each socket message, and a list with none unread sends nothing. The arrivals shift the server's offset pages, so a next page could repeat the last one's tail: each notification shows once. The next page loads as the end scrolls into view, with FeedFooter, as every other page list does, and the loading and error states go through ListState. The "N new" pill was a number before a separately translated "new", which French made "3 nouveau"; it is one plural message, "3 nouvelles". Dates past a week and the tooltip use the app's locale rather than the browser's. The mention, comment and like icons had no colored circle; they have one now, and the decorative emoji are hidden from screen readers. 670 frontend tests pass (new: loading on scroll, the save on leaving, the restore with what came meanwhile, the reconnect backfill), and tsc, deno fmt, deno lint, doc:lint and i18n:compile --strict are clean; the restore was checked in the running app at phone width.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
khannurien
2026-10-08 19:54:31 +00:00
parent 0a16d3c96c
commit 58c95dc4f3
8 changed files with 393 additions and 220 deletions

View File

@@ -407,6 +407,10 @@ msgstr "{0}–{1} caractères : lettres, chiffres ou tirets bas"
msgid "{label} ({count})"
msgstr "{label} ({count})"
#: src/pages/Notifications.tsx:502
msgid "{totalUnread, plural, one {# new} other {# new}}"
msgstr "{totalUnread, plural, one {# nouvelle} other {# nouvelles}}"
#: src/components/chat/ChatModal.tsx:756
msgid "{unseenCount} new messages"
msgstr "{unseenCount} nouveaux messages"
@@ -441,47 +445,47 @@ msgstr "+ Collection"
#. placeholder {0}: d.commenterUsername
#. placeholder {1}: d.dumpTitle
#: src/pages/Notifications.tsx:225
#: src/pages/Notifications.tsx:235
msgid "<0>{0}</0> commented on <1>{1}</1>"
msgstr "<0>{0}</0> a commenté sur <1>{1}</1>"
#. placeholder {0}: d.followerUsername
#. placeholder {1}: d.playlistTitle
#: src/pages/Notifications.tsx:185
#: src/pages/Notifications.tsx:195
msgid "<0>{0}</0> followed your playlist <1>{1}</1>"
msgstr "<0>{0}</0> a suivi votre collection <1>{1}</1>"
#. placeholder {0}: d.likerUsername
#. placeholder {1}: d.dumpTitle
#: src/pages/Notifications.tsx:235
#: src/pages/Notifications.tsx:245
msgid "<0>{0}</0> liked your comment on <1>{1}</1>"
msgstr "<0>{0}</0> a aimé votre commentaire sur <1>{1}</1>"
#. placeholder {0}: d.mentionerUsername
#: src/pages/Notifications.tsx:251
#: src/pages/Notifications.tsx:261
msgid "<0>{0}</0> mentioned you in <1>{where}</1>"
msgstr "<0>{0}</0> vous a mentionné dans <1>{where}</1>"
#. placeholder {0}: d.dumperUsername
#. placeholder {1}: d.dumpTitle
#: src/pages/Notifications.tsx:195
#: src/pages/Notifications.tsx:205
msgid "<0>{0}</0> posted <1>{1}</1>"
msgstr "<0>{0}</0> a publié <1>{1}</1>"
#. placeholder {0}: d.followerUsername
#: src/pages/Notifications.tsx:176
#: src/pages/Notifications.tsx:186
msgid "<0>{0}</0> started following you"
msgstr "<0>{0}</0> a commencé à vous suivre"
#. placeholder {0}: d.voterUsername
#. placeholder {1}: d.dumpTitle
#: src/pages/Notifications.tsx:215
#: src/pages/Notifications.tsx:225
msgid "<0>{0}</0> upvoted <1>{1}</1>"
msgstr "<0>{0}</0> a voté pour <1>{1}</1>"
#. placeholder {0}: d.dumpTitle
#. placeholder {1}: d.playlistTitle
#: src/pages/Notifications.tsx:205
#: src/pages/Notifications.tsx:215
msgid "<0>{0}</0> was added to <1>{1}</1>"
msgstr "<0>{0}</0> a été ajouté à <1>{1}</1>"
@@ -489,7 +493,7 @@ msgstr "<0>{0}</0> a été ajouté à <1>{1}</1>"
msgid "1 new message"
msgstr "1 nouveau message"
#: src/pages/Notifications.tsx:246
#: src/pages/Notifications.tsx:256
msgid "a comment"
msgstr "un commentaire"
@@ -497,7 +501,7 @@ msgstr "un commentaire"
msgid "A link is required"
msgstr "Il faut un lien"
#: src/pages/Notifications.tsx:249
#: src/pages/Notifications.tsx:259
msgid "a post"
msgstr "une publication"
@@ -871,7 +875,7 @@ msgstr "Recommandé !"
#: src/components/profile/ProfileDumpsTab.tsx:45
#: src/pages/Search.tsx:120
#: src/pages/UserPublicProfile.tsx:154
#: src/pages/UserPublicProfile.tsx:158
msgid "Dumps"
msgstr "Recos"
@@ -880,7 +884,7 @@ msgstr "Recos"
msgid "Dumps ({0})"
msgstr "Recos ({0})"
#: src/pages/Notifications.tsx:405
#: src/pages/Notifications.tsx:301
msgid "Earlier"
msgstr "Plus tôt"
@@ -979,7 +983,6 @@ msgid "Failed to generate invite"
msgstr "Impossible de générer une invitation"
#: src/components/shared/ListState.tsx:43
#: src/pages/Notifications.tsx:379
msgid "Failed to load"
msgstr "Chargement échoué"
@@ -1053,7 +1056,7 @@ msgstr "Suivez des utilisateurs pour voir leurs recos ici."
#: src/components/feed/FeedTabBar.tsx:43
#: src/components/profile/ProfileFollowTab.tsx:163
#: src/pages/Settings.tsx:53
#: src/pages/UserPublicProfile.tsx:157
#: src/pages/UserPublicProfile.tsx:161
msgid "Followed"
msgstr "Suivi"
@@ -1127,7 +1130,7 @@ msgid "invited by"
msgstr "invité par"
#: src/components/profile/ProfileInviteesTab.tsx:77
#: src/pages/UserPublicProfile.tsx:158
#: src/pages/UserPublicProfile.tsx:162
msgid "Invitees"
msgstr "Invités"
@@ -1209,7 +1212,6 @@ msgstr "Chargement du profil…"
#: src/components/shared/ListState.tsx:38
#: src/components/shared/LoadMoreButton.tsx:32
#: src/components/social/UserListPopover.tsx:151
#: src/pages/Notifications.tsx:375
msgid "Loading…"
msgstr "Chargement…"
@@ -1228,8 +1230,8 @@ msgstr "Se connecter pour aimer"
msgid "Log in to vote"
msgstr "Se connecter pour voter"
#: src/components/profile/ProfileHeader.tsx:185
#: src/pages/UserPublicProfile.tsx:127
#: src/components/profile/ProfileHeader.tsx:189
#: src/pages/UserPublicProfile.tsx:131
msgid "Log out"
msgstr "Se déconnecter"
@@ -1249,7 +1251,7 @@ msgstr "Minuscules, chiffres et tirets simples seulement"
#: src/components/profile/ProfileHeader.tsx:181
#: src/pages/Manage.tsx:23
#: src/pages/Manage.tsx:30
#: src/pages/UserPublicProfile.tsx:160
#: src/pages/UserPublicProfile.tsx:164
msgid "Manage"
msgstr "Administration"
@@ -1270,10 +1272,6 @@ msgstr "Couper le son"
msgid "Name"
msgstr "Nom"
#: src/pages/Notifications.tsx:368
msgid "new"
msgstr "nouveau"
#: src/components/chat/ChatModal.tsx:669
#: src/components/feed/FeedTabBar.tsx:40
#: src/pages/Settings.tsx:51
@@ -1361,13 +1359,13 @@ msgstr "Aucun abonnement pour le moment."
#: src/components/profile/ProfileDumpsTab.tsx:53
#: src/components/profile/ProfileOverviewTab.tsx:47
#: src/pages/Notifications.tsx:386
#: src/pages/Notifications.tsx:516
msgid "Nothing here yet."
msgstr "Rien ici pour l'instant."
#: src/components/layout/NotificationBell.tsx:54
#: src/pages/Notifications.tsx:308
#: src/pages/Notifications.tsx:364
#: src/pages/Notifications.tsx:374
#: src/pages/Notifications.tsx:498
#: src/pages/Settings.tsx:131
msgid "Notifications"
msgstr "Notifications"
@@ -1405,7 +1403,7 @@ msgstr "Ouvrir la source"
msgid "or <0>browse files</0>"
msgstr "ou <0>parcourir les fichiers</0>"
#: src/pages/UserPublicProfile.tsx:153
#: src/pages/UserPublicProfile.tsx:157
msgid "Overview"
msgstr "Aperçu"
@@ -1471,7 +1469,7 @@ msgstr "Titre de la collection"
#: src/components/profile/ProfileFollowTab.tsx:167
#: src/components/profile/ProfilePlaylistsTab.tsx:118
#: src/pages/Search.tsx:123
#: src/pages/UserPublicProfile.tsx:156
#: src/pages/UserPublicProfile.tsx:160
msgid "Playlists"
msgstr "Collections"
@@ -1738,7 +1736,7 @@ msgstr "Lancer la recherche"
msgid "That file is over {limit}."
msgstr "Ce fichier dépasse {limit}."
#: src/pages/Notifications.tsx:248
#: src/pages/Notifications.tsx:258
msgid "the chat"
msgstr "la tribune"
@@ -1800,7 +1798,7 @@ msgstr "Titre"
msgid "Title is required."
msgstr "Un titre est requis."
#: src/pages/Notifications.tsx:402
#: src/pages/Notifications.tsx:299
#: src/utils/chat/time.ts:24
msgid "Today"
msgstr "Aujourd'hui"
@@ -1880,7 +1878,7 @@ msgid "Upvote"
msgstr "Voter"
#: src/components/profile/ProfileDumpsTab.tsx:45
#: src/pages/UserPublicProfile.tsx:155
#: src/pages/UserPublicProfile.tsx:159
msgid "Upvoted"
msgstr "Voté"
@@ -1965,7 +1963,7 @@ msgstr "Pourquoi ?"
msgid "Write a reply…"
msgstr "Écrire une réponse…"
#: src/pages/Notifications.tsx:404
#: src/pages/Notifications.tsx:300
#: src/utils/chat/time.ts:27
msgid "Yesterday"
msgstr "Hier"
@@ -1982,7 +1980,7 @@ msgstr "Vous ne recevrez plus le récap mensuel. Vous pouvez le réactiver dans
msgid "You won't get the weekly digest any more. You can turn it back on in your settings."
msgstr "Vous ne recevrez plus le résumé hebdomadaire. Vous pouvez le réactiver dans vos paramètres."
#: src/pages/Notifications.tsx:389
#: src/pages/Notifications.tsx:519
msgid "You'll be notified when someone follows your playlists, upvotes your dumps, or posts new content."
msgstr "Vous serez notifié lorsque quelqu'un suit vos collections, vote pour vos recos ou publie du nouveau contenu."