Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Fix widgets re-appearing after being deleted #1958

Merged
merged 4 commits into from
Jun 14, 2018
Merged

Conversation

dbkr
Copy link
Member

@dbkr dbkr commented Jun 13, 2018

Widgets would sometimes briefly re-appear after having been deleted.
This was because of the following race:

  • User presses delete, send POST req, we set deleting. Widget hides.
  • POST request completes, we unset deleting so widget unhides.
  • State event comes down sync so widget hides again.

This fixes this by introducing waitForRoomWidget and using it to
wait until the state event comes down the sync until clearing the
deleting flag.

Since we now have waitForRoomWidget, this also uses it when adding
a widget so the 'widget saved' appears at the same time the widget
does.

The first commit also does a little refactoring and fixing (see commit message).

dbkr added 2 commits June 13, 2018 10:39
 * ScalarMessaging onMessage was getting the current room ID by listening
  for view_and remembering the room id or alias, and so having to look up
  the alias if it was alias. We have RoomViewStore for this.
 * Move waitForUserWidget into WidgetUtils
 * s/require/import/
Widgets would sometimes briefly re-appear after having been deleted.
This was because of the following race:
 * User presses delete, send POST req, we set `deleting`. Widget hides.
 * POST request completes, we unset `deleting` so widget unhides.
 * State event comes down sync so widget hides again.

This fixes this by introducing `waitForRoomWidget` and using it to
wait until the state event comes down the sync until clearing the
`deleting` flag.

Since we now have `waitForRoomWidget`, this also uses it when adding
a widget so the 'widget saved' appears at the same time the widget
does.
Copy link
Contributor

@lukebarnard1 lukebarnard1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good otherwise. Yay for actually using our approximation of Flux as intended and in a useful way!

* false to wait for it to be deleted.
* @returns {Promise} that resolves when the widget is available
*/
static waitForRoomWidget(widgetId, roomId, add) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any chance the shared logic between this and waitForUserWidget could be factored out? They both do very similar things on slightly different inputs..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I considered this but I think all of the bits of these functions are subtly different, plus there's already the fact that both of them wait for either addition or deletion. I think in this case having two less complex functions might be better than having one more complex one.

Copy link
Contributor

@lukebarnard1 lukebarnard1 Jun 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not necessarily suggesting one function; but I notice that

  • eventsInIntendedState is very similar to eventInIntendedState (and not just in name)
  • they both add a listener to matrix client
  • they both set a timeout
    • the timeout is 10 seconds with both
    • the timeout is cleared when the event is received by the matrix client

Actually, I noticed they've already diverged slightly:
https://github.com/matrix-org/matrix-react-sdk/pull/1958/files/36574ca0fb1b0a14a5886a953b3d6dbaad2ea7d2..3e6b3215cfe15532e19fd48288caf9fe23fd465e#diff-18c7dfd796a5f668feeee73e460716f3R125

gets the event from the account data again instead of reusing startingAccountDataEvent, whereas waitForRoomWidget reuses startingWidgetEvents.

If we want to be able to not care about the divergence between them, I think now is the best time to apply paranoia.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean - they both re-fetch the current state:

const startingAccountDataEvent = MatrixClientPeg.get().getAccountData('m.widgets');
and
const currentWidgetEvents = room.currentState.getStateEvents('im.vector.modular.widgets');

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh. I'm a crank apparently.

IRL we discussed and concluded that these two things are indeed subtly different, pretty much by consequence of the underlying API being used subtly differently depending on whether the widget is in account data or whether it is in a room.

* @param {string} widgetId The ID of the widget to wait for
* @param {boolean} add True to wait for the widget to be added,
* false to wait for it to be deleted.
* @returns {Promise} that resolves when the widget is available
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's deleted, presumably this is not true

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah yep

@lukebarnard1 lukebarnard1 assigned dbkr and unassigned lukebarnard1 Jun 14, 2018
@@ -100,7 +100,8 @@ export default class WidgetUtils {
* @param {string} widgetId The ID of the widget to wait for
* @param {boolean} add True to wait for the widget to be added,
* false to wait for it to be deleted.
* @returns {Promise} that resolves when the widget is available
* @returns {Promise} that resolves when the widget is the the
* requested state according to the `add` param
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't make sense. "is in the" maybe?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops.

@@ -146,7 +147,8 @@ export default class WidgetUtils {
* @param {string} roomId The ID of the room to wait for the widget in
* @param {boolean} add True to wait for the widget to be added,
* false to wait for it to be deleted.
* @returns {Promise} that resolves when the widget is available
* @returns {Promise} that resolves when the widget is the the
* requested state according to the `add` param
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least I'm consistent.

Fix fixed comment
@lukebarnard1
Copy link
Contributor

Following discussion on #1958 (comment)

LGTM

@lukebarnard1 lukebarnard1 merged commit 5077e9e into develop Jun 14, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants