From 4581a20260f0b63634ff88a8a5799af2ca426bac Mon Sep 17 00:00:00 2001 From: Beaudan Brown Date: Mon, 25 Nov 2019 15:35:13 +1100 Subject: [PATCH 1/9] Add new string i18n stuff --- _locales/en/messages.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 7050831ae..cb33b4dad 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1999,6 +1999,18 @@ "Button action that the user can click to copy their public keys" }, + "banUser": { + "message": "Ban user", + "description": + "Ban user from public chat by public key." + }, + + "banUserConfirm": { + "message": "Are you sure you want to ban user?", + "description": + "Message shown when confirming user ban." + }, + "copyChatId": { "message": "Copy Chat ID" }, From a3d171884d43aecde827c5067419ef7f6a9f5ccc Mon Sep 17 00:00:00 2001 From: Beaudan Brown Date: Mon, 25 Nov 2019 15:58:25 +1100 Subject: [PATCH 2/9] Added ban user right click functionality --- js/models/messages.js | 2 ++ ts/components/conversation/Message.tsx | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/js/models/messages.js b/js/models/messages.js index cd089398f..6b5314e33 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -655,6 +655,8 @@ !this.get('isPublic') || this.getConversation().isModerator(this.OUR_NUMBER) || this.getSource() === this.OUR_NUMBER, + hasModPerms: + this.getConversation().isModerator(this.OUR_NUMBER), onCopyText: () => this.copyText(), onSelectMessage: () => this.selectMessage(), diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 534374f03..70e1f61ae 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -57,6 +57,7 @@ export interface Props { disableMenu?: boolean; isModerator?: boolean; isDeletable: boolean; + hasModPerms?: boolean; text?: string; textPending?: boolean; id?: string; @@ -112,6 +113,7 @@ export interface Props { onDownload?: (isDangerous: boolean) => void; onDelete?: () => void; onCopyPubKey?: () => void; + onBanUser?: () => void; onShowDetail: () => void; } @@ -861,6 +863,8 @@ export class Message extends React.PureComponent { onCopyPubKey, isPublic, i18n, + hasModPerms, + onBanUser, } = this.props; const showRetry = status === 'error' && direction === 'outgoing'; @@ -960,6 +964,11 @@ export class Message extends React.PureComponent { {i18n('copyPublicKey')} ) : null} + {(hasModPerms && isPublic) ? ( + + {i18n('banUser')} + + ) : null} ); } From 2bbc1ecf63f7f5953956b1d3a60b23b0d46ad951 Mon Sep 17 00:00:00 2001 From: Beaudan Brown Date: Mon, 25 Nov 2019 15:59:13 +1100 Subject: [PATCH 3/9] Make ban user; handle server request --- js/models/messages.js | 15 +++++++++++++++ js/modules/loki_app_dot_net_api.js | 12 ++++++++++++ 2 files changed, 27 insertions(+) diff --git a/js/models/messages.js b/js/models/messages.js index 6b5314e33..89bb29d26 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -12,6 +12,7 @@ Whisper, clipboard, libloki, + lokiPublicChatAPI, */ /* eslint-disable more/no-then */ @@ -662,6 +663,7 @@ onSelectMessage: () => this.selectMessage(), onSelectMessageUnchecked: () => this.selectMessageUnchecked(), onCopyPubKey: () => this.copyPubKey(), + onBanUser: () => this.banUser(), onReply: () => this.trigger('reply', this), onRetrySend: () => this.retrySend(), onShowDetail: () => this.trigger('show-message-detail', this), @@ -970,6 +972,19 @@ }); }, + banUser() { + window.Whisper.events.trigger('showConfirmationDialog', { + message: i18n('banUserConfirm'), + onOk: async () => { + const source = this.get('source'); + const conversation = this.getConversation(); + + const channelAPI = await conversation.getPublicSendData(); + await channelAPI.banUser(source); + } + }); + }, + // Select message even if the context menu is shown selectMessageUnchecked() { this.selected = !this.selected; diff --git a/js/modules/loki_app_dot_net_api.js b/js/modules/loki_app_dot_net_api.js index 23c9711af..ac66db441 100644 --- a/js/modules/loki_app_dot_net_api.js +++ b/js/modules/loki_app_dot_net_api.js @@ -545,6 +545,18 @@ class LokiPublicChannelAPI { // TODO: poll for group members here? } + async banUser(pubkey){ + const res = await this.serverRequest( + `loki/v1/moderation/blacklist/@${pubkey}` + ); + + if (res.err || !res.response || !res.response.data) { + if (res.err) { + log.error(`Error ${res.err}`); + } + } + } + stop() { this.running = false; if (this.timers.channel) { From bee5a89f14d466c2b893375748db447601d2fee5 Mon Sep 17 00:00:00 2001 From: Beaudan Brown Date: Mon, 25 Nov 2019 16:30:34 +1100 Subject: [PATCH 4/9] Show toast on user ban --- _locales/en/messages.json | 12 ++++++++++++ js/models/messages.js | 13 ++++++++++++- js/modules/loki_app_dot_net_api.js | 7 ++++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index cb33b4dad..f05329f1e 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -2011,6 +2011,18 @@ "Message shown when confirming user ban." }, + "userBanned": { + "message": "User successfully banned", + "description": + "Toast on succesful user ban." + }, + + "userBanFailed": { + "message": "User ban failed!", + "description": + "Toast on unsuccesful user ban." + }, + "copyChatId": { "message": "Copy Chat ID" }, diff --git a/js/models/messages.js b/js/models/messages.js index 89bb29d26..efac82d32 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -980,7 +980,18 @@ const conversation = this.getConversation(); const channelAPI = await conversation.getPublicSendData(); - await channelAPI.banUser(source); + const success = await channelAPI.banUser(source); + + if (success) { + window.Whisper.events.trigger('showToast', { + message: i18n('userBanned'), + }); + } + else{ + window.Whisper.events.trigger('showToast', { + message: i18n('userBanFailed'), + }); + } } }); }, diff --git a/js/modules/loki_app_dot_net_api.js b/js/modules/loki_app_dot_net_api.js index ac66db441..44d9ed6a1 100644 --- a/js/modules/loki_app_dot_net_api.js +++ b/js/modules/loki_app_dot_net_api.js @@ -547,14 +547,19 @@ class LokiPublicChannelAPI { async banUser(pubkey){ const res = await this.serverRequest( - `loki/v1/moderation/blacklist/@${pubkey}` + `loki/v1/moderation/blacklist/@${pubkey}`, { + method: 'POST' + } ); if (res.err || !res.response || !res.response.data) { if (res.err) { log.error(`Error ${res.err}`); } + return false; } + + return true; } stop() { From 43a91ab672308d06783e541a73be5287e2f26c4a Mon Sep 17 00:00:00 2001 From: Beaudan Brown Date: Mon, 25 Nov 2019 16:34:52 +1100 Subject: [PATCH 5/9] Linted --- _locales/en/messages.json | 12 ++++-------- js/models/messages.js | 11 ++++------- js/modules/loki_app_dot_net_api.js | 7 ++++--- ts/components/conversation/Message.tsx | 6 ++---- 4 files changed, 14 insertions(+), 22 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index f05329f1e..414c3f783 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -2001,26 +2001,22 @@ "banUser": { "message": "Ban user", - "description": - "Ban user from public chat by public key." + "description": "Ban user from public chat by public key." }, "banUserConfirm": { "message": "Are you sure you want to ban user?", - "description": - "Message shown when confirming user ban." + "description": "Message shown when confirming user ban." }, "userBanned": { "message": "User successfully banned", - "description": - "Toast on succesful user ban." + "description": "Toast on succesful user ban." }, "userBanFailed": { "message": "User ban failed!", - "description": - "Toast on unsuccesful user ban." + "description": "Toast on unsuccesful user ban." }, "copyChatId": { diff --git a/js/models/messages.js b/js/models/messages.js index efac82d32..7867b6975 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -12,7 +12,6 @@ Whisper, clipboard, libloki, - lokiPublicChatAPI, */ /* eslint-disable more/no-then */ @@ -656,8 +655,7 @@ !this.get('isPublic') || this.getConversation().isModerator(this.OUR_NUMBER) || this.getSource() === this.OUR_NUMBER, - hasModPerms: - this.getConversation().isModerator(this.OUR_NUMBER), + hasModPerms: this.getConversation().isModerator(this.OUR_NUMBER), onCopyText: () => this.copyText(), onSelectMessage: () => this.selectMessage(), @@ -981,18 +979,17 @@ const channelAPI = await conversation.getPublicSendData(); const success = await channelAPI.banUser(source); - + if (success) { window.Whisper.events.trigger('showToast', { message: i18n('userBanned'), }); - } - else{ + } else { window.Whisper.events.trigger('showToast', { message: i18n('userBanFailed'), }); } - } + }, }); }, diff --git a/js/modules/loki_app_dot_net_api.js b/js/modules/loki_app_dot_net_api.js index 44d9ed6a1..f8fe6a87c 100644 --- a/js/modules/loki_app_dot_net_api.js +++ b/js/modules/loki_app_dot_net_api.js @@ -545,10 +545,11 @@ class LokiPublicChannelAPI { // TODO: poll for group members here? } - async banUser(pubkey){ + async banUser(pubkey) { const res = await this.serverRequest( - `loki/v1/moderation/blacklist/@${pubkey}`, { - method: 'POST' + `loki/v1/moderation/blacklist/@${pubkey}`, + { + method: 'POST', } ); diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 70e1f61ae..6313d4f38 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -964,10 +964,8 @@ export class Message extends React.PureComponent { {i18n('copyPublicKey')} ) : null} - {(hasModPerms && isPublic) ? ( - - {i18n('banUser')} - + {hasModPerms && isPublic ? ( + {i18n('banUser')} ) : null} ); From e9068d56cee075dfd942d411ddfbd6a07d7ede61 Mon Sep 17 00:00:00 2001 From: Vince Date: Thu, 28 Nov 2019 15:48:07 +1100 Subject: [PATCH 6/9] Updated isModerator to senderIsModerator and fixed logic of isModerator function --- js/models/messages.js | 10 ++++++---- ts/components/conversation/Message.tsx | 14 +++++++++----- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/js/models/messages.js b/js/models/messages.js index 7867b6975..c142403cf 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -648,14 +648,16 @@ isP2p: !!this.get('isP2p'), isPublic: !!this.get('isPublic'), isRss: !!this.get('isRss'), - isModerator: + senderIsModerator: !!this.get('isPublic') && - this.getConversation().isModerator(this.getSource()), + conversation && + conversation.isModerator(phoneNumber), isDeletable: !this.get('isPublic') || - this.getConversation().isModerator(this.OUR_NUMBER) || + conversation && conversation.isModerator(this.OUR_NUMBER) || this.getSource() === this.OUR_NUMBER, - hasModPerms: this.getConversation().isModerator(this.OUR_NUMBER), + hasModPerms: + conversation && !!conversation.isModerator(this.OUR_NUMBER), onCopyText: () => this.copyText(), onSelectMessage: () => this.selectMessage(), diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index 6313d4f38..e9d7bc739 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -55,7 +55,7 @@ interface LinkPreviewType { export interface Props { disableMenu?: boolean; - isModerator?: boolean; + senderIsModerator?: boolean; isDeletable: boolean; hasModPerms?: boolean; text?: string; @@ -212,9 +212,13 @@ export class Message extends React.PureComponent { } public renderMetadataBadges() { - const { direction, isP2p, isPublic, isModerator } = this.props; + const { direction, isP2p, isPublic, senderIsModerator } = this.props; - const badges = [isPublic && 'Public', isP2p && 'P2p', isModerator && 'Mod']; + const badges = [ + isPublic && 'Public', + isP2p && 'P2p', + senderIsModerator && 'Mod', + ]; return badges .map(badgeText => { @@ -657,7 +661,7 @@ export class Message extends React.PureComponent { authorPhoneNumber, authorProfileName, collapseMetadata, - isModerator, + senderIsModerator, authorColor, conversationType, direction, @@ -684,7 +688,7 @@ export class Message extends React.PureComponent { profileName={authorProfileName} size={36} /> - {isModerator && ( + {senderIsModerator && (
From a7a2f9289c71756a6c2822ef89c1a1ebc0d9db87 Mon Sep 17 00:00:00 2001 From: Vince Date: Thu, 28 Nov 2019 16:44:46 +1100 Subject: [PATCH 7/9] Updated references to hasModPerms to isModerator for code consistency --- js/models/messages.js | 2 +- ts/components/conversation/Message.tsx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/js/models/messages.js b/js/models/messages.js index c142403cf..4e1c1ba33 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -656,7 +656,7 @@ !this.get('isPublic') || conversation && conversation.isModerator(this.OUR_NUMBER) || this.getSource() === this.OUR_NUMBER, - hasModPerms: + isModerator: conversation && !!conversation.isModerator(this.OUR_NUMBER), onCopyText: () => this.copyText(), diff --git a/ts/components/conversation/Message.tsx b/ts/components/conversation/Message.tsx index e9d7bc739..dfdc4c322 100644 --- a/ts/components/conversation/Message.tsx +++ b/ts/components/conversation/Message.tsx @@ -57,7 +57,7 @@ export interface Props { disableMenu?: boolean; senderIsModerator?: boolean; isDeletable: boolean; - hasModPerms?: boolean; + isModerator?: boolean; text?: string; textPending?: boolean; id?: string; @@ -867,7 +867,7 @@ export class Message extends React.PureComponent { onCopyPubKey, isPublic, i18n, - hasModPerms, + isModerator, onBanUser, } = this.props; @@ -968,7 +968,7 @@ export class Message extends React.PureComponent { {i18n('copyPublicKey')} ) : null} - {hasModPerms && isPublic ? ( + {isModerator && isPublic ? ( {i18n('banUser')} ) : null} From 0643c6836c637f73cccfd2d311d8380feaef27d1 Mon Sep 17 00:00:00 2001 From: Vince Date: Thu, 28 Nov 2019 16:57:52 +1100 Subject: [PATCH 8/9] Cached constants for readability --- js/models/messages.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/js/models/messages.js b/js/models/messages.js index 4e1c1ba33..86f440ef0 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -614,6 +614,8 @@ // for the public group chat const conversation = this.getConversation(); + const isModerator = conversation && !!conversation.isModerator(this.OUR_NUMBER); + const convoId = conversation ? conversation.id : undefined; const isGroup = !!conversation && !conversation.isPrivate(); @@ -654,10 +656,9 @@ conversation.isModerator(phoneNumber), isDeletable: !this.get('isPublic') || - conversation && conversation.isModerator(this.OUR_NUMBER) || - this.getSource() === this.OUR_NUMBER, - isModerator: - conversation && !!conversation.isModerator(this.OUR_NUMBER), + isModerator || + phoneNumber === this.OUR_NUMBER, + isModerator: isModerator onCopyText: () => this.copyText(), onSelectMessage: () => this.selectMessage(), From 64996844acb4bda7e51955e971755991cd28f49d Mon Sep 17 00:00:00 2001 From: Vince Date: Thu, 28 Nov 2019 16:59:15 +1100 Subject: [PATCH 9/9] Updated references to hasModPerms to isModerator for code consistency --- js/models/messages.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/js/models/messages.js b/js/models/messages.js index 86f440ef0..127bce516 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -614,7 +614,8 @@ // for the public group chat const conversation = this.getConversation(); - const isModerator = conversation && !!conversation.isModerator(this.OUR_NUMBER); + const isModerator = + conversation && !!conversation.isModerator(this.OUR_NUMBER); const convoId = conversation ? conversation.id : undefined; const isGroup = !!conversation && !conversation.isPrivate(); @@ -658,7 +659,7 @@ !this.get('isPublic') || isModerator || phoneNumber === this.OUR_NUMBER, - isModerator: isModerator + isModerator, onCopyText: () => this.copyText(), onSelectMessage: () => this.selectMessage(),