Merge pull request #1607 from Bilb/redesign-group-invitation

Redesign group invitation and ask user confirmation before accepting one
pull/1611/head
Audric Ackermann 5 years ago committed by GitHub
commit 1d22c12bf5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -289,6 +289,27 @@
"incomingError": {
"message": "Error handling incoming message"
},
"openGroupInvitation": {
"message": "Open group invitation"
},
"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",
"description": "Header of the default pane in the media gallery, showing images and videos",
@ -1587,9 +1608,6 @@
"message": "Add",
"androidKey": "fragment_add_public_chat_add_button_title_1"
},
"groupInvitation": {
"message": "Group Invitation"
},
"addingContacts": {
"message": "Adding contacts to"
},

@ -187,7 +187,6 @@ message DataMessage {
message GroupInvitation {
optional string serverAddress = 1;
optional uint32 channelId = 2;
optional string serverName = 3;
}

@ -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;
@ -87,11 +90,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 +102,18 @@
}
}
.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;
}
filter: brightness(1.05);
svg path {
transition: $session-transition-duration;
opacity: 0.6;
@include themify($themes) {
fill: themed('textColorOpposite');
}
}
}
}

@ -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<Props> {
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 (
<div className={'group-invitation-container'}>
<div className={classNames(classes)}>
<div className="title">Group invitation</div>
<div className="contents">
<img
alt="group-avatar"
src="images/session/session_chat_icon.png"
className="invite-group-avatar"
/>
<span className="group-details">
<span className="group-name">{this.props.serverName}</span>
<span className="group-address">{this.props.serverAddress}</span>
</span>
<span role="button" className="join-btn" onClick={this.props.onClick}>
Join
</span>
</div>
return (
<div className="group-invitation-container">
<div className={classNames(classes)}>
<div className="contents">
<SessionIconButton
iconType={SessionIconType.Plus}
iconColor={theme.colors.accent}
theme={theme}
iconSize={SessionIconSize.Large}
onClick={props.onJoinClick}
/>
<span className="group-details">
<span className="group-name">{props.serverName}</span>
<span className="group-type">{openGroupInvitation}</span>
<span className="group-address">{props.serverAddress}</span>
</span>
</div>
</div>
);
}
}
</div>
);
};

@ -241,17 +241,21 @@ async function acceptOpenGroupInvitationV1(serverAddress: string) {
}
}
const acceptOpenGroupInvitationV2 = async (completeUrl: string) => {
const acceptOpenGroupInvitationV2 = (completeUrl: string, roomName?: string) => {
window.confirmationDialog({
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
await joinOpenGroupV2WithUIEvents(completeUrl, true);
};
/**
* 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)) {
await acceptOpenGroupInvitationV2(completeUrl);
acceptOpenGroupInvitationV2(completeUrl, roomName);
} else {
await acceptOpenGroupInvitationV1(completeUrl);
}

@ -670,7 +670,6 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
identifier: id,
timestamp: sentAt,
serverName: groupInvitation.serverName,
channelId: 1,
serverAddress: groupInvitation.serverAddress,
expireTimer: this.get('expireTimer'),
});

@ -186,7 +186,7 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
return window.i18n('incomingError');
}
if (this.isGroupInvitation()) {
return `<${window.i18n('groupInvitation')}>`;
return `😎 ${window.i18n('openGroupInvitation')}`;
}
return this.get('body');
}
@ -281,16 +281,21 @@ export class MessageModel extends Backbone.Model<MessageAttributes> {
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: () => {
void acceptOpenGroupInvitation(invitation.serverAddress);
onJoinClick: () => {
void acceptOpenGroupInvitation(invitation.serverAddress, invitation.serverName);
},
};
}

@ -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;
@ -409,7 +409,6 @@ const handleCompactPollResults = async (
serverUrl: string,
results: Array<ParsedRoomCompactPollResults>
) => {
// console.warn('compoll res', results);
await Promise.all(
results.map(async res => {
const convoId = getOpenGroupV2ConversationId(serverUrl, res.roomId);

@ -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;
}

@ -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,
});

@ -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);

@ -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<ConversationM
const activeOpenGroups = [...openGroupsV1Ids, ...opengroupV2CompleteUrls];
// console.warn('SyncConfiguration', activeOpenGroups);
return new ConfigurationMessage({
identifier: uuid(),
timestamp: Date.now(),

@ -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);
});

Loading…
Cancel
Save