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

Commit 9b8b1d1

Browse files
Disable redacting reactions if we don't have sufficient permissions (#8767)
1 parent 3f99f59 commit 9b8b1d1

File tree

11 files changed

+37
-9
lines changed

11 files changed

+37
-9
lines changed

res/css/views/elements/_AccessibleButton.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ limitations under the License.
1818
cursor: pointer;
1919

2020
&.mx_AccessibleButton_disabled {
21-
cursor: default;
21+
cursor: not-allowed;
2222

2323
&.mx_AccessibleButton_kind_primary,
2424
&.mx_AccessibleButton_kind_primary_outline,

src/components/structures/RoomView.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ export interface IRoomState {
169169
searchInProgress?: boolean;
170170
callState?: CallState;
171171
canPeek: boolean;
172+
canSelfRedact: boolean;
172173
showApps: boolean;
173174
isPeeking: boolean;
174175
showRightPanel: boolean;
@@ -252,6 +253,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
252253
searchResults: null,
253254
callState: null,
254255
canPeek: false,
256+
canSelfRedact: false,
255257
showApps: false,
256258
isPeeking: false,
257259
showRightPanel: false,
@@ -1173,10 +1175,14 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
11731175
private updatePermissions(room: Room) {
11741176
if (room) {
11751177
const me = this.context.getUserId();
1176-
const canReact = room.getMyMembership() === "join" && room.currentState.maySendEvent("m.reaction", me);
1178+
const canReact = (
1179+
room.getMyMembership() === "join" &&
1180+
room.currentState.maySendEvent(EventType.Reaction, me)
1181+
);
11771182
const canSendMessages = room.maySendMessage();
1183+
const canSelfRedact = room.currentState.maySendEvent(EventType.RoomRedaction, me);
11781184

1179-
this.setState({ canReact, canSendMessages });
1185+
this.setState({ canReact, canSendMessages, canSelfRedact });
11801186
}
11811187
}
11821188

src/components/views/emojipicker/Category.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ interface IProps {
4545
onClick(emoji: IEmoji): void;
4646
onMouseEnter(emoji: IEmoji): void;
4747
onMouseLeave(emoji: IEmoji): void;
48+
isEmojiDisabled?: (unicode: string) => boolean;
4849
}
4950

5051
class Category extends React.PureComponent<IProps> {
@@ -60,6 +61,7 @@ class Category extends React.PureComponent<IProps> {
6061
onClick={onClick}
6162
onMouseEnter={onMouseEnter}
6263
onMouseLeave={onMouseLeave}
64+
disabled={this.props.isEmojiDisabled?.(emoji.unicode)}
6365
/>
6466
))
6567
}</div>);

src/components/views/emojipicker/Emoji.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ interface IProps {
2626
onClick(emoji: IEmoji): void;
2727
onMouseEnter(emoji: IEmoji): void;
2828
onMouseLeave(emoji: IEmoji): void;
29+
disabled?: boolean;
2930
}
3031

3132
class Emoji extends React.PureComponent<IProps> {
@@ -40,6 +41,7 @@ class Emoji extends React.PureComponent<IProps> {
4041
onMouseLeave={() => onMouseLeave(emoji)}
4142
className="mx_EmojiPicker_item_wrapper"
4243
label={emoji.unicode}
44+
disabled={this.props.disabled}
4345
>
4446
<div className={`mx_EmojiPicker_item ${isSelected ? 'mx_EmojiPicker_item_selected' : ''}`}>
4547
{ emoji.unicode }

src/components/views/emojipicker/EmojiPicker.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ interface IProps {
3737
selectedEmojis?: Set<string>;
3838
showQuickReactions?: boolean;
3939
onChoose(unicode: string): boolean;
40+
isEmojiDisabled?: (unicode: string) => boolean;
4041
}
4142

4243
interface IState {
@@ -261,6 +262,7 @@ class EmojiPicker extends React.Component<IProps, IState> {
261262
onClick={this.onClickEmoji}
262263
onMouseEnter={this.onHoverEmoji}
263264
onMouseLeave={this.onHoverEmojiEnd}
265+
isEmojiDisabled={this.props.isEmojiDisabled}
264266
selectedEmojis={this.props.selectedEmojis}
265267
/>
266268
);

src/components/views/emojipicker/ReactionPicker.tsx

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class ReactionPicker extends React.Component<IProps, IState> {
7373
}
7474
}
7575

76-
private getReactions() {
76+
private getReactions(): Record<string, string> {
7777
if (!this.props.reactions) {
7878
return {};
7979
}
@@ -95,6 +95,8 @@ class ReactionPicker extends React.Component<IProps, IState> {
9595
this.props.onFinished();
9696
const myReactions = this.getReactions();
9797
if (myReactions.hasOwnProperty(reaction)) {
98+
if (this.props.mxEvent.isRedacted() || !this.context.canSelfRedact) return;
99+
98100
MatrixClientPeg.get().redactEvent(this.props.mxEvent.getRoomId(), myReactions[reaction]);
99101
dis.dispatch<FocusComposerPayload>({
100102
action: Action.FocusAComposer,
@@ -119,9 +121,17 @@ class ReactionPicker extends React.Component<IProps, IState> {
119121
}
120122
};
121123

124+
private isEmojiDisabled = (unicode: string): boolean => {
125+
if (!this.getReactions()[unicode]) return false;
126+
if (this.context.canSelfRedact) return false;
127+
128+
return true;
129+
};
130+
122131
render() {
123132
return <EmojiPicker
124133
onChoose={this.onChoose}
134+
isEmojiDisabled={this.isEmojiDisabled}
125135
selectedEmojis={this.state.selectedEmojis}
126136
showQuickReactions={true}
127137
data-testid='mx_ReactionPicker'

src/components/views/messages/ReactionsRow.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,10 @@ export default class ReactionsRow extends React.PureComponent<IProps, IState> {
183183
mxEvent={mxEvent}
184184
reactionEvents={events}
185185
myReactionEvent={myReactionEvent}
186-
disabled={!this.context.canReact}
186+
disabled={
187+
!this.context.canReact ||
188+
(myReactionEvent && !myReactionEvent.isRedacted() && !this.context.canSelfRedact)
189+
}
187190
/>;
188191
}).filter(item => !!item);
189192

src/components/views/messages/ReactionsRowButton.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ interface IState {
4747

4848
export default class ReactionsRowButton extends React.PureComponent<IProps, IState> {
4949
static contextType = MatrixClientContext;
50+
public context!: React.ContextType<typeof MatrixClientContext>;
5051

5152
state = {
5253
tooltipRendered: false,

src/contexts/RoomContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const RoomContext = createContext<IRoomState>({
4343
showTopUnreadMessagesBar: false,
4444
statusBarVisible: false,
4545
canReact: false,
46+
canSelfRedact: false,
4647
canSendMessages: false,
4748
resizing: false,
4849
layout: Layout.Group,

test/components/views/rooms/MessageComposerButtons-test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ function createRoomState(room: Room, narrow: boolean): IRoomState {
209209
shouldPeek: true,
210210
membersLoaded: false,
211211
numUnreadMessages: 0,
212+
canSelfRedact: false,
212213
canPeek: false,
213214
showApps: false,
214215
isPeeking: false,

0 commit comments

Comments
 (0)