From 93ee2a6ab75c581f6fcf862432932764a81f0452 Mon Sep 17 00:00:00 2001 From: Alex Gleason Date: Fri, 7 Jan 2022 16:57:58 -0600 Subject: [PATCH] Replying-to: fix order of mentions --- .../status-unordered-mentions.json | 122 ++++++++++++++++++ .../reducers/__tests__/statuses-test.js | 18 ++- app/soapbox/reducers/statuses.js | 25 +++- 3 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 app/soapbox/__fixtures__/status-unordered-mentions.json diff --git a/app/soapbox/__fixtures__/status-unordered-mentions.json b/app/soapbox/__fixtures__/status-unordered-mentions.json new file mode 100644 index 000000000..40bdbe8b6 --- /dev/null +++ b/app/soapbox/__fixtures__/status-unordered-mentions.json @@ -0,0 +1,122 @@ +{ + "account": { + "acct": "apropos@freespeechextremist.com", + "avatar": "https://gleasonator.com/proxy/WVdkCbG7AOZ_eqMzskzXQoyjq8o/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9tZWRpYS8zN2I4MDMzZC03OGQ1LTQ0YmMtYmY5NC0xYTI2NzY5NTQwM2YvYmxvYi5wbmc_bmFtZT1ibG9iLnBuZw/blob.png", + "avatar_static": "https://gleasonator.com/proxy/WVdkCbG7AOZ_eqMzskzXQoyjq8o/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9tZWRpYS8zN2I4MDMzZC03OGQ1LTQ0YmMtYmY5NC0xYTI2NzY5NTQwM2YvYmxvYi5wbmc_bmFtZT1ibG9iLnBuZw/blob.png", + "bot": false, + "created_at": "2020-05-21T07:20:46.000Z", + "display_name": "of nothing", + "emojis": [], + "fields": [], + "followers_count": 87, + "following_count": 85, + "fqn": "apropos@freespeechextremist.com", + "header": "https://gleasonator.com/proxy/pIracLGWm_skCfOOgdwcCNqES5s/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9tZWRpYS8yZDEwYmRjZC01NDUwLTRjZjYtYWFhZS1hNTJjMzYwYjk2YjYvdHJhY2tzb25tYXJzLmpwZz9uYW1lPXRyYWNrc29ubWFycy5qcGc/tracksonmars.jpg", + "header_static": "https://gleasonator.com/proxy/pIracLGWm_skCfOOgdwcCNqES5s/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9tZWRpYS8yZDEwYmRjZC01NDUwLTRjZjYtYWFhZS1hNTJjMzYwYjk2YjYvdHJhY2tzb25tYXJzLmpwZz9uYW1lPXRyYWNrc29ubWFycy5qcGc/tracksonmars.jpg", + "id": "9vGR3IWmWVYRkKUZ4i", + "last_status_at": "2022-01-07T21:47:39", + "locked": false, + "note": "If you wait by the river long enough, the bodies of your enemies will float by.

Deo Vindice", + "pleroma": { + "accepts_chat_messages": true, + "also_known_as": [], + "ap_id": "https://freespeechextremist.com/users/apropos", + "background_image": null, + "favicon": "https://gleasonator.com/proxy/EN7BSaEEYTRpmRj4lITIjgWp2sg/aHR0cHM6Ly9mcmVlc3BlZWNoZXh0cmVtaXN0LmNvbS9mYXZpY29uLnBuZw/favicon.png", + "hide_favorites": true, + "hide_followers": false, + "hide_followers_count": false, + "hide_follows": false, + "hide_follows_count": false, + "is_admin": false, + "is_confirmed": true, + "is_moderator": false, + "is_suggested": false, + "relationship": {}, + "skip_thread_containment": false, + "tags": [] + }, + "source": { + "fields": [], + "note": "", + "pleroma": { + "actor_type": "Person", + "discoverable": false + }, + "sensitive": false + }, + "statuses_count": 7087, + "url": "https://freespeechextremist.com/users/apropos", + "username": "apropos" + }, + "application": null, + "bookmarked": false, + "card": null, + "content": "@NEETzsche @alex @Lumeinshin @sneeden
>seething
'posting', just like you.", + "created_at": "2022-01-07T17:29:58.000Z", + "emojis": [], + "favourited": false, + "favourites_count": 1, + "id": "AFChectaqZjmOVkXZ2", + "in_reply_to_account_id": "9v5bw7hEGBPc9nrpzc", + "in_reply_to_id": "AFChbnWqrAZ2VIlPJw", + "language": null, + "media_attachments": [], + "mentions": [ + { + "acct": "alex", + "id": "9v5bmRalQvjOy0ECcC", + "url": "https://gleasonator.com/users/alex", + "username": "alex" + }, + { + "acct": "NEETzsche@iddqd.social", + "id": "9v5bw7hEGBPc9nrpzc", + "url": "https://iddqd.social/users/NEETzsche", + "username": "NEETzsche" + }, + { + "acct": "Lumeinshin@pleroma.skyshanty.xyz", + "id": "A3dFSwTkwgRfd998iG", + "url": "https://pleroma.skyshanty.xyz/users/Lumeinshin", + "username": "Lumeinshin" + }, + { + "acct": "sneeden@social.silkky.cloud", + "id": "ACrsPAbAOPh3GbKZhQ", + "url": "https://social.silkky.cloud/users/sneeden", + "username": "sneeden" + } + ], + "muted": false, + "pinned": false, + "pleroma": { + "content": { + "text/plain": "@NEETzsche @alex @Lumeinshin @sneeden >seething'posting', just like you." + }, + "conversation_id": "AFCYCBFN9SgOwoIWTg", + "direct_conversation_id": null, + "emoji_reactions": [], + "expires_at": null, + "in_reply_to_account_acct": "NEETzsche@iddqd.social", + "local": false, + "parent_visible": true, + "pinned_at": null, + "spoiler_text": { + "text/plain": "" + }, + "thread_muted": false + }, + "poll": null, + "reblog": null, + "reblogged": false, + "reblogs_count": 0, + "replies_count": 0, + "sensitive": false, + "spoiler_text": "", + "tags": [], + "text": null, + "uri": "https://freespeechextremist.com/objects/714b0e04-bec4-4a2a-9514-312814380064", + "url": "https://freespeechextremist.com/objects/714b0e04-bec4-4a2a-9514-312814380064", + "visibility": "public" +} diff --git a/app/soapbox/reducers/__tests__/statuses-test.js b/app/soapbox/reducers/__tests__/statuses-test.js index 7bcc67c9e..525ca50e6 100644 --- a/app/soapbox/reducers/__tests__/statuses-test.js +++ b/app/soapbox/reducers/__tests__/statuses-test.js @@ -4,13 +4,29 @@ import { STATUS_CREATE_REQUEST, STATUS_CREATE_FAIL, } from 'soapbox/actions/statuses'; - +import { STATUS_IMPORT } from 'soapbox/actions/importer'; describe('statuses reducer', () => { it('should return the initial state', () => { expect(reducer(undefined, {})).toEqual(ImmutableMap()); }); + describe('STATUS_IMPORT', () => { + it('fixes the order of mentions', () => { + const status = require('soapbox/__fixtures__/status-unordered-mentions.json'); + const action = { type: STATUS_IMPORT, status }; + + const expected = ['NEETzsche', 'alex', 'Lumeinshin', 'sneeden']; + + const result = reducer(undefined, action) + .getIn(['AFChectaqZjmOVkXZ2', 'mentions']) + .map(mention => mention.get('username')) + .toJS(); + + expect(result).toEqual(expected); + }); + }); + describe('STATUS_CREATE_REQUEST', () => { it('increments the replies_count of its parent', () => { const state = fromJS({ '123': { replies_count: 4 } }); diff --git a/app/soapbox/reducers/statuses.js b/app/soapbox/reducers/statuses.js index 6f9215337..ebf405806 100644 --- a/app/soapbox/reducers/statuses.js +++ b/app/soapbox/reducers/statuses.js @@ -24,7 +24,30 @@ import { STATUS_IMPORT, STATUSES_IMPORT } from '../actions/importer'; import { Map as ImmutableMap, fromJS } from 'immutable'; import { simulateEmojiReact, simulateUnEmojiReact } from 'soapbox/utils/emoji_reacts'; -const importStatus = (state, status) => state.set(status.id, fromJS(status)); +// Fix order of mentions +const fixMentions = status => { + const mentions = status.get('mentions'); + const inReplyToAccountId = status.get('in_reply_to_account_id'); + + // Sort the replied-to mention to the top + const sorted = mentions.sort((a, b) => { + if (a.get('id') === inReplyToAccountId) { + return -1; + } else { + return 0; + } + }); + + return status.set('mentions', sorted); +}; + +const fixStatus = status => { + return status.withMutations(status => { + fixMentions(status); + }); +}; + +const importStatus = (state, status) => state.set(status.id, fixStatus(fromJS(status))); const importStatuses = (state, statuses) => state.withMutations(mutable => statuses.forEach(status => importStatus(mutable, status)));