From 85ac6443e783081832a0226ea8fd5fb1ed732e55 Mon Sep 17 00:00:00 2001 From: Renan Date: Thu, 11 Nov 2021 20:15:10 -0300 Subject: [PATCH 1/4] Fix bulk invite button getting a negative counter Signed-off-by: Renan --- .../tabs/user/SecurityUserSettingsTab.tsx | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index 5e0cdfcbe3f..2403641f8a4 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -29,6 +29,10 @@ import { SettingLevel } from "../../../../../settings/SettingLevel"; import SecureBackupPanel from "../../SecureBackupPanel"; import SettingsStore from "../../../../../settings/SettingsStore"; import { UIFeature } from "../../../../../settings/UIFeature"; +import { ListNotificationState } from '../../../../../stores/notifications/ListNotificationState'; +import { RoomNotificationStateStore } from '../../../../../stores/notifications/RoomNotificationStateStore'; +import { DefaultTagID } from '../../../../../stores/room-list/models'; +import { NOTIFICATION_STATE_UPDATE } from '../../../../../stores/notifications/NotificationState'; import E2eAdvancedPanel, { isE2eAdvancedPanelPossible } from "../../E2eAdvancedPanel"; import CountlyAnalytics from "../../../../../CountlyAnalytics"; import { replaceableComponent } from "../../../../../utils/replaceableComponent"; @@ -82,18 +86,19 @@ interface IState { @replaceableComponent("views.settings.tabs.user.SecurityUserSettingsTab") export default class SecurityUserSettingsTab extends React.Component { private dispatcherRef: string; + private notificationState: ListNotificationState; constructor(props: IProps) { super(props); // Get number of rooms we're invited to - const invitedRooms = this.getInvitedRooms(); + this.notificationState = RoomNotificationStateStore.instance.getListState(DefaultTagID.Invite); this.state = { ignoredUserIds: MatrixClientPeg.get().getIgnoredUsers(), waitingUnignored: [], managingInvites: false, - invitedRoomAmt: invitedRooms.length, + invitedRoomAmt: this.notificationState.count, }; } @@ -107,10 +112,12 @@ export default class SecurityUserSettingsTab extends React.Component { @@ -119,6 +126,10 @@ export default class SecurityUserSettingsTab extends React.Component { + this.setState({ invitedRoomAmt: this.notificationState.count }); + }; + private onGoToUserProfileClick = (): void => { dis.dispatch({ action: 'view_user_info', @@ -162,10 +173,7 @@ export default class SecurityUserSettingsTab extends React.Component { - // No error, update invited rooms button - this.setState({ invitedRoomAmt: this.state.invitedRoomAmt - 1 }); - }, async (e) => { + await action(roomId).catch(async (e) => { // Action failure if (e.errcode === "M_LIMIT_EXCEEDED") { // Add a delay between each invite change in order to avoid rate @@ -225,9 +233,8 @@ export default class SecurityUserSettingsTab extends React.Component { _t('Bulk options') } From c270b929f9077c72687960424ed898629d194159 Mon Sep 17 00:00:00 2001 From: Renan Date: Tue, 16 Nov 2021 12:16:28 -0300 Subject: [PATCH 2/4] Change invites to be count on membership events Signed-off-by: Renan --- .../tabs/user/SecurityUserSettingsTab.tsx | 58 +++++++++++++------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index 2403641f8a4..68f811f78cc 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -29,10 +29,6 @@ import { SettingLevel } from "../../../../../settings/SettingLevel"; import SecureBackupPanel from "../../SecureBackupPanel"; import SettingsStore from "../../../../../settings/SettingsStore"; import { UIFeature } from "../../../../../settings/UIFeature"; -import { ListNotificationState } from '../../../../../stores/notifications/ListNotificationState'; -import { RoomNotificationStateStore } from '../../../../../stores/notifications/RoomNotificationStateStore'; -import { DefaultTagID } from '../../../../../stores/room-list/models'; -import { NOTIFICATION_STATE_UPDATE } from '../../../../../stores/notifications/NotificationState'; import E2eAdvancedPanel, { isE2eAdvancedPanelPossible } from "../../E2eAdvancedPanel"; import CountlyAnalytics from "../../../../../CountlyAnalytics"; import { replaceableComponent } from "../../../../../utils/replaceableComponent"; @@ -80,25 +76,24 @@ interface IState { ignoredUserIds: string[]; waitingUnignored: string[]; managingInvites: boolean; - invitedRoomAmt: number; + invitedRooms: Room[]; } @replaceableComponent("views.settings.tabs.user.SecurityUserSettingsTab") export default class SecurityUserSettingsTab extends React.Component { private dispatcherRef: string; - private notificationState: ListNotificationState; constructor(props: IProps) { super(props); - // Get number of rooms we're invited to - this.notificationState = RoomNotificationStateStore.instance.getListState(DefaultTagID.Invite); + // Get rooms we're invited to + const invitedRooms = this.getInvitedRooms(); this.state = { ignoredUserIds: MatrixClientPeg.get().getIgnoredUsers(), waitingUnignored: [], managingInvites: false, - invitedRoomAmt: this.notificationState.count, + invitedRooms, }; } @@ -112,12 +107,12 @@ export default class SecurityUserSettingsTab extends React.Component { @@ -126,8 +121,29 @@ export default class SecurityUserSettingsTab extends React.Component { - this.setState({ invitedRoomAmt: this.notificationState.count }); + private onMyMembership = (room: Room, membership: string): void => { + const { invitedRooms } = this.state; + + if (room.isSpaceRoom()) { + return; + } + + if (membership === "invite") { + this.addInvitedRoom(room); + } else if (invitedRooms.some(invitedRoom => invitedRoom.roomId === room.roomId)) { + // The user isn't invited anymore + this.removeInvitedRoom(room.roomId); + } + }; + + private addInvitedRoom = (room: Room): void => { + this.setState(({ invitedRooms }) => ({ invitedRooms: [...invitedRooms, room] })); + }; + + private removeInvitedRoom = (roomId: string): void => { + this.setState((prevState) => ({ + invitedRooms: prevState.invitedRooms.filter(room => room.roomId !== roomId), + })); }; private onGoToUserProfileClick = (): void => { @@ -162,7 +178,7 @@ export default class SecurityUserSettingsTab extends React.Component { + const invitedRoomIds = this.state.invitedRooms.map((room) => { return room.roomId; }); @@ -173,7 +189,10 @@ export default class SecurityUserSettingsTab extends React.Component { + await action(roomId).then(() => { + // No error, update invited rooms button + this.removeInvitedRoom(roomId); + }, async (e) => { // Action failure if (e.errcode === "M_LIMIT_EXCEEDED") { // Add a delay between each invite change in order to avoid rate @@ -229,20 +248,23 @@ export default class SecurityUserSettingsTab extends React.Component { _t('Bulk options') } - { _t("Accept all %(invitedRooms)s invites", { invitedRooms: this.state.invitedRoomAmt }) } + { _t("Accept all %(invitedRooms)s invites", { invitedRooms: invitedRooms.length }) } - { _t("Reject all %(invitedRooms)s invites", { invitedRooms: this.state.invitedRoomAmt }) } + { _t("Reject all %(invitedRooms)s invites", { invitedRooms: invitedRooms.length }) } { this.state.managingInvites ? :
}
From cafd88e765b487a23448d8de489c1baea9d3c942 Mon Sep 17 00:00:00 2001 From: Renan Date: Tue, 16 Nov 2021 12:31:12 -0300 Subject: [PATCH 3/4] Remove unnecessary bind --- .../views/settings/tabs/user/SecurityUserSettingsTab.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index 68f811f78cc..21eb3d30d05 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -254,16 +254,13 @@ export default class SecurityUserSettingsTab extends React.Component { _t('Bulk options') } - + { _t("Accept all %(invitedRooms)s invites", { invitedRooms: invitedRooms.length }) } - + { _t("Reject all %(invitedRooms)s invites", { invitedRooms: invitedRooms.length }) } { this.state.managingInvites ? :
} From ca3944bc7e3edfda5d27f0130745c57ed731d907 Mon Sep 17 00:00:00 2001 From: Renan Date: Tue, 16 Nov 2021 16:10:44 -0300 Subject: [PATCH 4/4] Change invitedRooms state to a set of ids Signed-off-by: Renan --- .../tabs/user/SecurityUserSettingsTab.tsx | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index 21eb3d30d05..ed560b8929f 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -76,7 +76,7 @@ interface IState { ignoredUserIds: string[]; waitingUnignored: string[]; managingInvites: boolean; - invitedRooms: Room[]; + invitedRoomIds: Set; } @replaceableComponent("views.settings.tabs.user.SecurityUserSettingsTab") @@ -87,13 +87,13 @@ export default class SecurityUserSettingsTab extends React.Component room.roomId)); this.state = { ignoredUserIds: MatrixClientPeg.get().getIgnoredUsers(), waitingUnignored: [], managingInvites: false, - invitedRooms, + invitedRoomIds, }; } @@ -122,28 +122,33 @@ export default class SecurityUserSettingsTab extends React.Component { - const { invitedRooms } = this.state; - if (room.isSpaceRoom()) { return; } if (membership === "invite") { this.addInvitedRoom(room); - } else if (invitedRooms.some(invitedRoom => invitedRoom.roomId === room.roomId)) { + } else if (this.state.invitedRoomIds.has(room.roomId)) { // The user isn't invited anymore this.removeInvitedRoom(room.roomId); } }; private addInvitedRoom = (room: Room): void => { - this.setState(({ invitedRooms }) => ({ invitedRooms: [...invitedRooms, room] })); + this.setState(({ invitedRoomIds }) => ({ + invitedRoomIds: new Set(invitedRoomIds).add(room.roomId), + })); }; private removeInvitedRoom = (roomId: string): void => { - this.setState((prevState) => ({ - invitedRooms: prevState.invitedRooms.filter(room => room.roomId !== roomId), - })); + this.setState(({ invitedRoomIds }) => { + const newInvitedRoomIds = new Set(invitedRoomIds); + newInvitedRoomIds.delete(roomId); + + return { + invitedRoomIds: newInvitedRoomIds, + }; + }); }; private onGoToUserProfileClick = (): void => { @@ -177,16 +182,14 @@ export default class SecurityUserSettingsTab extends React.Component { - return room.roomId; - }); + // iterate with a normal for loop in order to retry on action failure + const invitedRoomIdsValues = Array.from(this.state.invitedRoomIds); // Execute all acceptances/rejections sequentially const cli = MatrixClientPeg.get(); const action = accept ? cli.joinRoom.bind(cli) : cli.leave.bind(cli); - for (let i = 0; i < invitedRoomIds.length; i++) { - const roomId = invitedRoomIds[i]; + for (let i = 0; i < invitedRoomIdsValues.length; i++) { + const roomId = invitedRoomIdsValues[i]; // Accept/reject invite await action(roomId).then(() => { @@ -248,9 +251,9 @@ export default class SecurityUserSettingsTab extends React.Component { _t('Bulk options') } - { _t("Accept all %(invitedRooms)s invites", { invitedRooms: invitedRooms.length }) } + { _t("Accept all %(invitedRooms)s invites", { invitedRooms: invitedRoomIds.size }) } - { _t("Reject all %(invitedRooms)s invites", { invitedRooms: invitedRooms.length }) } + { _t("Reject all %(invitedRooms)s invites", { invitedRooms: invitedRoomIds.size }) } { this.state.managingInvites ? :
}