-
-
Notifications
You must be signed in to change notification settings - Fork 670
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove redundant, stringly-typed fields from PmConversationData #4116
Remove redundant, stringly-typed fields from PmConversationData #4116
Conversation
... but also to simplify further refactoring.
Somewhere around my 3.7th [sic] rebase-slash-rewrite of PR #4104, I got frustrated enough to do this first. This may not be the only way to keep the final version of that PR reasonable, but it's probably the best. There is some overlap here with the commits in #4104: the commits for well-typing the relevant test code are taken from it. I believe I have addressed all of @gnprice's feedback for those commits in this version, with one notable exception (the The final five commits (starting at |
export const makeMessagesState = (messages: Message[]): MessagesState => | ||
objectFromEntries(messages.map(m => [m.id, m])); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Feedback at #4104 (comment) resolved by a) stripping the exactness from both MessagesState
itself (until Flow v0.111.0) and its indexer-property's value type, and b) eliminating the $FlowFixMe
entirely.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @ray-kraesig ! Happy to get these data structures cleaned up. Comments below about some of the specifics.
src/types.js
Outdated
/** | ||
* A comma-separated sequence of the emails of the users involved in this | ||
* conversation, sorted by user ID. Does not include the self-user, unless the | ||
* self-user is the only recipient. | ||
*/ | ||
recipients: string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this true?
I don't think it is. See the implementation of normalizeRecipientsSansMe
, and normalizeRecipients
which it invokes. We sort there, by email address.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops! Will fix.
handleGroupNarrow = (email: string) => { | ||
this.props.dispatch(doNarrow(groupNarrow(email.split(',')))); | ||
handleGroupNarrow = (users: UserOrBot[]) => { | ||
this.props.dispatch(doNarrow(groupNarrow(users.map(s => s.email)))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The order here matters, because we use it for the key to look up the narrow in our data structures. So it's important to preserve the order used by the existing code, or else to carefully untangle to make it stop mattering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, doesn't this now see the full set of users? Where previously it saw the set excluding self.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's odd – I specifically remember seeing that issue and fixing it. (The second one, not the first; the first is a carryover of my mistake in describing recipients
.) Will fix again.
/** | ||
* If this is a 1:1 conversation, the other user involved. (For the | ||
* self-conversation, this is the self-user.) | ||
* | ||
* If this is a group PM, null. | ||
*/ | ||
getOtherUser = (users: UserOrBot[]): UserOrBot | null => { | ||
const ownUserId = this.props.ownUser.user_id; | ||
if (users.length <= 2) { | ||
return users.filter(u => u.user_id !== ownUserId)[0]; | ||
} | ||
return null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, does this work in the self-1:1 case? It looks like it'd end up returning [][0]
, which is undefined
.
handleGroupNarrow = (users: UserOrBot[]) => { | ||
this.props.dispatch(doNarrow(groupNarrow(users.map(s => s.email)))); | ||
const { dispatch, ownUser } = this.props; | ||
const emails = users.filter(u => u.user_id !== ownUser.user_id).map(u => u.email); | ||
dispatch(doNarrow(groupNarrow(emails))); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see. This change belongs in the earlier commit where we changed what set of users gets passed here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
– oh, there it is. I must have squashed the fix into the wrong commit. 😓
src/unread/UnreadCards.js
Outdated
const unreadCards: Array<Card> = [ | ||
{ | ||
key: 'private', | ||
data: [{ conversations, ...restProps }], | ||
data: [conversations], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, can this really work with how this data gets used below?
section.key === 'private' ? (
<PmConversationList {...item} />
How does it know to call the prop conversations
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can't possibly have worked. I think when I tested it last night I wasn't actually running the right version of the code. 😓
|}; | ||
// This type cannot be made exact until Flow v0.111.0. | ||
export type MessagesState = { | ||
[id: number]: Message, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of removing exactness here, why not add it on Message
itself? (And remove the then-redundant mention of it here.)
Otherwise we're regressing on how tightly we type-check.
For a quick experiment I made Message
exact. Flow reported only one error -- and in fact it looks like a real one, which would have been caught in 3dc2d8f if we'd had Message
exact then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Message
really isn't exact, though: it's full of unlisted fields from (possibly future versions of) the server. We shouldn't make the claim that it is. (The bug you cite is a good argument that eg.streamMessage
and friends should take $Exact<Message>
, though.)
I assume what we really want to do is to deconstruct the inexact, server-supplied ApiMessage
object (to coin a name) into a fresh LocalMessage
object that really is exact. But not, I think, today.
(I'm pretty sure this has come up before. I know I've documented it in Message
at some point, but I suppose that hasn't made it into a PR yet. I'll try to dig it up and submit it separately. Or just rewrite it.)
As I think you guessed, I am not a fan of these last few changes. 🙂 They make this code significantly more complex, and I don't see a corresponding gain. |
... following a brief archaeological expedition.
MessagesState is exact; until Flow v0.111.0, this is not usefully compatible with indexer properties. This exactness was added in 8370002, as part of a mechanical transformation, before we were aware of this issue. MessagesState also has `$Exact<Message>` as its indexer value type, rather than simply `Message`. This is the only use of `$Exact<...>` directly as the type of a value in our codebase; it was added in commit 01003e6, a professedly experimental commit, where it is the only such change among several less interesting `{ ... }` → `{| ... |}` conversions. Revert both. Add a note about the former and Flow v0.111.0, for grep's sake.
Additionally, make their arguments exact, to raise errors on unrecognized arguments.
... an expansion of `pmMessage` allowing (and requiring) the caller to supply the users involved in the message.
... which assembles a `MessagesState` from the `Message`s that compose it.
Translate existing tests from JavaScript to Flow. (There is no significant functional difference, but there are some minor changes to irrelevant data under the hood.)
PmConversationData has two distinct and terrible ways of passing down the list of users. Add a third way (presumably less terrible), which will replace both of them.
... instead of threading the relevant Redux state through its callers. (Consequently, eliminate the now-unused additional plumbing.)
Add a new function to `recipient.js` which will substitute for `normalizeRecipientsSansMe` in the private conversation UI. The new function is no longer stringly-typed, but is not otherwise an improvement. (Also, `normalize` is a terrible name for what any of these do.)
Remove its dependence on the old stringly-typed fields. The existing code has relied on the selector to munge the data for UI presentation; this now becomes the responsibility of the UI component itself. (The logic to do so is presently inline, but is expected to be unified with existing related logic in `recipient.js` later.)
The key used here doesn't have to be anything in particular, so long as it's consistent. We assemble a nonce-key not used elsewhere. (Or, if it does happen to be used elsewhere, we don't care.)
For the purposes of eliminating all but the latest message per conversation, one uniquely-identifying string-key is as good as another. Since we no longer need to send `recipients` downstream, we might as well just use `ids` -- in which case there's no longer any need for `normalizeRecipientsSansMe` here.
... and, following the previous commit, there are no more uses of `normalizeRecipientsSansMe`. Eliminate it. Convert its tests to be used by the function which has effectively replaced it, instead.
2758052
to
f371f09
Compare
The new version may be politely described as less ambitious. It may be less politely described as "just pushing the junk from one room into another room". The semantic mess that is (But at least we're no longer passing two different stringly-typed values in.) |
Replace the excessively quirky
ids: string
andrecipients: string
fields inPmConversationData
with ausers: Users[]
field, unconditionally containing all participants.Partly in support of #3764 and #4035. Blocks PR #4104 (although see below).