From 248494f15bcb6b289c3c1c77a53e96ace1bc7cb5 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 7 May 2021 14:49:38 +1000 Subject: [PATCH 1/4] redesign group invitation message type --- _locales/en/messages.json | 3 + stylesheets/_conversation.scss | 30 +++++---- .../conversation/GroupInvitation.tsx | 62 ++++++++++--------- ts/models/message.ts | 13 ++-- .../opengroupV2/OpenGroupServerPoller.ts | 1 - ts/receiver/closedGroups.ts | 1 - ts/session/snode_api/onions.ts | 1 - ts/session/utils/syncUtils.ts | 4 -- 8 files changed, 58 insertions(+), 57 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index c53111f4e..02ffdaa57 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -289,6 +289,9 @@ "incomingError": { "message": "Error handling incoming message" }, + "openGroupInvitation": { + "message": "Open group invitation" + }, "media": { "message": "Media", "description": "Header of the default pane in the media gallery, showing images and videos", diff --git a/stylesheets/_conversation.scss b/stylesheets/_conversation.scss index f4665b540..cbffe6901 100644 --- a/stylesheets/_conversation.scss +++ b/stylesheets/_conversation.scss @@ -87,11 +87,11 @@ display: inline-flex; flex-direction: column; - padding: 8px; + padding: 0px 12px; .group-name { - font-weight: lighter; - padding-bottom: 4px; + font-weight: bold; + font-size: 18px; } .group-address { @@ -99,19 +99,17 @@ } } - .join-btn { - background-color: #00f782; - color: white; - padding: 6px 10px; - margin-inline-start: 6px; - border-radius: 2px; - box-shadow: none; - user-select: none; - cursor: pointer; - transition: $session-transition-duration; - - &:hover { - background-color: #00d672; + .session-icon-button { + @include themify($themes) { + background-color: themed('accent'); + box-shadow: none; + } + svg path { + transition: $session-transition-duration; + opacity: 0.6; + @include themify($themes) { + fill: themed('textColorOpposite'); + } } } } diff --git a/ts/components/conversation/GroupInvitation.tsx b/ts/components/conversation/GroupInvitation.tsx index 0faa862a3..7e4246bce 100644 --- a/ts/components/conversation/GroupInvitation.tsx +++ b/ts/components/conversation/GroupInvitation.tsx @@ -1,41 +1,43 @@ import React from 'react'; import classNames from 'classnames'; +import { SessionButton, SessionButtonType } from '../session/SessionButton'; +import { SessionIconButton, SessionIconSize, SessionIconType } from '../session/icon'; +import { useTheme } from 'styled-components'; -interface Props { +type Props = { serverName: string; serverAddress: string; direction: string; - onClick: any; -} + onJoinClick: () => void; +}; -export class GroupInvitation extends React.Component { - public render() { - const classes = ['group-invitation']; +export const GroupInvitation = (props: Props) => { + const theme = useTheme(); + const classes = ['group-invitation']; - if (this.props.direction === 'outgoing') { - classes.push('invitation-outgoing'); - } + if (props.direction === 'outgoing') { + classes.push('invitation-outgoing'); + } + const openGroupInvitation = window.i18n('openGroupInvitation'); - return ( -
-
-
Group invitation
-
- group-avatar - - {this.props.serverName} - {this.props.serverAddress} - - - Join - -
+ return ( +
+
+
+ + + {props.serverName} + {openGroupInvitation} + {props.serverAddress} +
- ); - } -} +
+ ); +}; diff --git a/ts/models/message.ts b/ts/models/message.ts index 84324a536..dbcdc4239 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -281,15 +281,20 @@ export class MessageModel extends Backbone.Model { if (!direction) { direction = this.get('type') === 'outgoing' ? 'outgoing' : 'incoming'; } - const serverAddress = invitation.serverAddress?.length - ? `${invitation.serverAddress.slice(0, 30)}...` - : ''; + + let serverAddress = ''; + try { + const url = new URL(invitation.serverAddress); + serverAddress = url.origin; + } catch (e) { + window.log.warn('failed to get hostname from opengroupv2 invitation', invitation); + } return { serverName: invitation.serverName, serverAddress, direction, - onClick: () => { + onJoinClick: () => { void acceptOpenGroupInvitation(invitation.serverAddress); }, }; diff --git a/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts b/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts index 912671ea4..04d4aade9 100644 --- a/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts +++ b/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts @@ -409,7 +409,6 @@ const handleCompactPollResults = async ( serverUrl: string, results: Array ) => { - // console.warn('compoll res', results); await Promise.all( results.map(async res => { const convoId = getOpenGroupV2ConversationId(serverUrl, res.roomId); diff --git a/ts/receiver/closedGroups.ts b/ts/receiver/closedGroups.ts index 2e146c304..8c8eb08c9 100644 --- a/ts/receiver/closedGroups.ts +++ b/ts/receiver/closedGroups.ts @@ -643,7 +643,6 @@ function addMemberToZombies( if (isAlreadyZombie) { return false; } - // console.warn('Marking user ', userToAdd.key, ' as a zombie'); convo.set('zombies', [...zombies, userToAdd.key]); return true; } diff --git a/ts/session/snode_api/onions.ts b/ts/session/snode_api/onions.ts index 030a89bca..944a38e3f 100644 --- a/ts/session/snode_api/onions.ts +++ b/ts/session/snode_api/onions.ts @@ -443,7 +443,6 @@ const sendOnionRequest = async ( const guardUrl = `https://${nodePath[0].ip}:${nodePath[0].port}${target}`; // no logs for that one as we do need to call insecureNodeFetch to our guardNode // window.log.info('insecureNodeFetch => plaintext for sendOnionRequest'); - // console.warn('sendViaOnion payload: ', payload.length); const response = await insecureNodeFetch(guardUrl, guardFetchOptions); return processOnionResponse(reqIdx, response, destCtx.symmetricKey, false, abortSignal); diff --git a/ts/session/utils/syncUtils.ts b/ts/session/utils/syncUtils.ts index 9d69a4181..a5d1674be 100644 --- a/ts/session/utils/syncUtils.ts +++ b/ts/session/utils/syncUtils.ts @@ -67,8 +67,6 @@ export const forceSyncConfigurationNowIfNeeded = async (waitForMessageSent = fal void getCurrentConfigurationMessage(allConvos) .then(configMessage => { - // console.warn('forceSyncConfigurationNowIfNeeded with', configMessage); - // this just adds the message to the sending queue. // if waitForMessageSent is set, we need to effectively wait until then // tslint:disable-next-line: no-void-expression @@ -195,8 +193,6 @@ export const getCurrentConfigurationMessage = async (convos: Array Date: Fri, 7 May 2021 14:54:34 +1000 Subject: [PATCH 2/4] ask confirmation before joining opengroup invitation --- _locales/en/messages.json | 3 +++ ts/interactions/message.ts | 9 ++++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 02ffdaa57..833526459 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -292,6 +292,9 @@ "openGroupInvitation": { "message": "Open group invitation" }, + "joinOpenGroupAfterInvitationConfirmation": { + "message": "Do you want to join this open group?" + }, "media": { "message": "Media", "description": "Header of the default pane in the media gallery, showing images and videos", diff --git a/ts/interactions/message.ts b/ts/interactions/message.ts index f3bc37476..105c60d40 100644 --- a/ts/interactions/message.ts +++ b/ts/interactions/message.ts @@ -241,9 +241,12 @@ async function acceptOpenGroupInvitationV1(serverAddress: string) { } } -const acceptOpenGroupInvitationV2 = async (completeUrl: string) => { +const acceptOpenGroupInvitationV2 = (completeUrl: string) => { + window.confirmationDialog({ + message: window.i18n('joinOpenGroupAfterInvitationConfirmation'), + resolve: () => joinOpenGroupV2WithUIEvents(completeUrl, true), + }); // this function does not throw, and will showToasts if anything happens - await joinOpenGroupV2WithUIEvents(completeUrl, true); }; /** @@ -251,7 +254,7 @@ const acceptOpenGroupInvitationV2 = async (completeUrl: string) => { */ export const acceptOpenGroupInvitation = async (completeUrl: string) => { if (completeUrl.match(openGroupV2CompleteURLRegex)) { - await acceptOpenGroupInvitationV2(completeUrl); + acceptOpenGroupInvitationV2(completeUrl); } else { await acceptOpenGroupInvitationV1(completeUrl); } From e10a3cd4a94975e4013da65b1e182a554e1a9e1d Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 7 May 2021 15:01:15 +1000 Subject: [PATCH 3/4] remove the channelId from groupInvitation --- protos/SignalService.proto | 1 - ts/models/conversation.ts | 1 - .../outgoing/visibleMessage/GroupInvitationMessage.ts | 4 ---- ts/test/session/unit/messages/GroupInvitationMessage_test.ts | 3 --- 4 files changed, 9 deletions(-) diff --git a/protos/SignalService.proto b/protos/SignalService.proto index 513097cce..87560cb83 100644 --- a/protos/SignalService.proto +++ b/protos/SignalService.proto @@ -187,7 +187,6 @@ message DataMessage { message GroupInvitation { optional string serverAddress = 1; - optional uint32 channelId = 2; optional string serverName = 3; } diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index ad1965522..31691e856 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -670,7 +670,6 @@ export class ConversationModel extends Backbone.Model { identifier: id, timestamp: sentAt, serverName: groupInvitation.serverName, - channelId: 1, serverAddress: groupInvitation.serverAddress, expireTimer: this.get('expireTimer'), }); diff --git a/ts/session/messages/outgoing/visibleMessage/GroupInvitationMessage.ts b/ts/session/messages/outgoing/visibleMessage/GroupInvitationMessage.ts index 48685ac12..2ff3bef36 100644 --- a/ts/session/messages/outgoing/visibleMessage/GroupInvitationMessage.ts +++ b/ts/session/messages/outgoing/visibleMessage/GroupInvitationMessage.ts @@ -5,7 +5,6 @@ import { MessageParams } from '../Message'; interface GroupInvitationMessageParams extends MessageParams { serverAddress: string; - channelId: number; serverName: string; // if there is an expire timer set for the conversation, we need to set it. // otherwise, it will disable the expire timer on the receiving side. @@ -14,14 +13,12 @@ interface GroupInvitationMessageParams extends MessageParams { export class GroupInvitationMessage extends DataMessage { private readonly serverAddress: string; - private readonly channelId: number; private readonly serverName: string; private readonly expireTimer?: number; constructor(params: GroupInvitationMessageParams) { super({ timestamp: params.timestamp, identifier: params.identifier }); this.serverAddress = params.serverAddress; - this.channelId = params.channelId; this.serverName = params.serverName; this.expireTimer = params.expireTimer; } @@ -29,7 +26,6 @@ export class GroupInvitationMessage extends DataMessage { public dataProto(): SignalService.DataMessage { const groupInvitation = new SignalService.DataMessage.GroupInvitation({ serverAddress: this.serverAddress, - channelId: this.channelId, serverName: this.serverName, }); diff --git a/ts/test/session/unit/messages/GroupInvitationMessage_test.ts b/ts/test/session/unit/messages/GroupInvitationMessage_test.ts index e50f94841..6b55d0122 100644 --- a/ts/test/session/unit/messages/GroupInvitationMessage_test.ts +++ b/ts/test/session/unit/messages/GroupInvitationMessage_test.ts @@ -9,14 +9,12 @@ describe('GroupInvitationMessage', () => { let message: GroupInvitationMessage; const timestamp = Date.now(); const serverAddress = 'http://localhost'; - const channelId = 1; const serverName = 'test'; beforeEach(() => { message = new GroupInvitationMessage({ timestamp, serverAddress, - channelId, serverName, }); }); @@ -26,7 +24,6 @@ describe('GroupInvitationMessage', () => { const decoded = SignalService.Content.decode(plainText); expect(decoded.dataMessage?.groupInvitation).to.have.property('serverAddress', serverAddress); - expect(decoded.dataMessage?.groupInvitation).to.have.property('channelId', channelId); expect(decoded.dataMessage?.groupInvitation).to.have.property('serverName', serverName); }); From b574fd731df57dadd55bd689c106cdf947d094c4 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 7 May 2021 16:52:10 +1000 Subject: [PATCH 4/4] match group invitation design with ios --- _locales/en/messages.json | 22 ++++++++++++++----- stylesheets/_conversation.scss | 16 +++++++++----- ts/interactions/message.ts | 9 ++++---- ts/models/message.ts | 4 ++-- .../opengroupV2/OpenGroupServerPoller.ts | 2 +- 5 files changed, 35 insertions(+), 18 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 833526459..d63759ba6 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -292,8 +292,23 @@ "openGroupInvitation": { "message": "Open group invitation" }, - "joinOpenGroupAfterInvitationConfirmation": { - "message": "Do you want to join this open group?" + "joinOpenGroupAfterInvitationConfirmationTitle": { + "message": "Join $roomName$?", + "placeholders": { + "count": { + "roomName": "$1", + "example": "Main" + } + } + }, + "joinOpenGroupAfterInvitationConfirmationDesc": { + "message": "Are you sure you wan to join the $roomName$ open group?", + "placeholders": { + "count": { + "roomName": "$1", + "example": "Main" + } + } }, "media": { "message": "Media", @@ -1593,9 +1608,6 @@ "message": "Add", "androidKey": "fragment_add_public_chat_add_button_title_1" }, - "groupInvitation": { - "message": "Group Invitation" - }, "addingContacts": { "message": "Adding contacts to" }, diff --git a/stylesheets/_conversation.scss b/stylesheets/_conversation.scss index cbffe6901..43b1dd0bd 100644 --- a/stylesheets/_conversation.scss +++ b/stylesheets/_conversation.scss @@ -31,7 +31,6 @@ } .check-box-container { - // background-color: blue; align-items: center; flex-direction: row; display: inline-flex; @@ -52,15 +51,19 @@ } .group-invitation { - background-color: #f4f4f0; + @include themify($themes) { + background: themed('receivedMessageBackground'); + } + &.invitation-outgoing { + @include themify($themes) { + background: themed('sentMessageBackground'); + } + } display: inline-block; margin: 4px 16px; padding: 4px; - border: solid; - border-width: 0.5px; - border-radius: 4px; - border-color: #e0e0e0; + border-radius: 15px; align-self: flex-start; @@ -104,6 +107,7 @@ background-color: themed('accent'); box-shadow: none; } + filter: brightness(1.05); svg path { transition: $session-transition-duration; opacity: 0.6; diff --git a/ts/interactions/message.ts b/ts/interactions/message.ts index 105c60d40..bbf7d3f9e 100644 --- a/ts/interactions/message.ts +++ b/ts/interactions/message.ts @@ -241,9 +241,10 @@ async function acceptOpenGroupInvitationV1(serverAddress: string) { } } -const acceptOpenGroupInvitationV2 = (completeUrl: string) => { +const acceptOpenGroupInvitationV2 = (completeUrl: string, roomName?: string) => { window.confirmationDialog({ - message: window.i18n('joinOpenGroupAfterInvitationConfirmation'), + title: window.i18n('joinOpenGroupAfterInvitationConfirmationTitle', roomName), + message: window.i18n('joinOpenGroupAfterInvitationConfirmationDesc', roomName), resolve: () => joinOpenGroupV2WithUIEvents(completeUrl, true), }); // this function does not throw, and will showToasts if anything happens @@ -252,9 +253,9 @@ const acceptOpenGroupInvitationV2 = (completeUrl: string) => { /** * Accepts a v1 (channelid defaults to 1) url or a v2 url (with pubkey) */ -export const acceptOpenGroupInvitation = async (completeUrl: string) => { +export const acceptOpenGroupInvitation = async (completeUrl: string, roomName?: string) => { if (completeUrl.match(openGroupV2CompleteURLRegex)) { - acceptOpenGroupInvitationV2(completeUrl); + acceptOpenGroupInvitationV2(completeUrl, roomName); } else { await acceptOpenGroupInvitationV1(completeUrl); } diff --git a/ts/models/message.ts b/ts/models/message.ts index dbcdc4239..75e3d415f 100644 --- a/ts/models/message.ts +++ b/ts/models/message.ts @@ -186,7 +186,7 @@ export class MessageModel extends Backbone.Model { return window.i18n('incomingError'); } if (this.isGroupInvitation()) { - return `<${window.i18n('groupInvitation')}>`; + return `😎 ${window.i18n('openGroupInvitation')}`; } return this.get('body'); } @@ -295,7 +295,7 @@ export class MessageModel extends Backbone.Model { serverAddress, direction, onJoinClick: () => { - void acceptOpenGroupInvitation(invitation.serverAddress); + void acceptOpenGroupInvitation(invitation.serverAddress, invitation.serverName); }, }; } diff --git a/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts b/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts index 04d4aade9..03c558c90 100644 --- a/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts +++ b/ts/opengroup/opengroupV2/OpenGroupServerPoller.ts @@ -22,7 +22,7 @@ import autoBind from 'auto-bind'; import { sha256 } from '../../session/crypto'; import { fromBase64ToArrayBuffer } from '../../session/utils/String'; -const pollForEverythingInterval = SECONDS * 6; +const pollForEverythingInterval = SECONDS * 4; const pollForRoomAvatarInterval = DAYS * 1; const pollForMemberCountInterval = MINUTES * 10;