mirror of
https://github.com/oxen-io/session-desktop.git
synced 2023-12-14 02:12:57 +01:00
Merge pull request #1229 from Bilb/fix-open-groups-ui
* fix sync of closed groups * fix showing of contacts and closed groups after sync * create closed group: only show direct conversations * handle message sending events for open groups
This commit is contained in:
commit
d92bf6febf
15 changed files with 112 additions and 44 deletions
|
@ -1359,6 +1359,7 @@
|
|||
attachments: uploads.attachments,
|
||||
preview: uploads.preview,
|
||||
quote: uploads.quote,
|
||||
identifier: id,
|
||||
};
|
||||
const openGroupMessage = new libsession.Messages.Outgoing.OpenGroupMessage(
|
||||
openGroupParams
|
||||
|
|
|
@ -1209,15 +1209,37 @@
|
|||
return errors[0][0];
|
||||
},
|
||||
|
||||
/**
|
||||
* This function is called by inbox_view.js when a message was successfully sent for one device.
|
||||
* So it might be called several times for the same message
|
||||
*/
|
||||
async handleMessageSentSuccess(sentMessage) {
|
||||
const sentTo = this.get('sent_to') || [];
|
||||
let sentTo = this.get('sent_to') || [];
|
||||
|
||||
const isOurDevice = await window.libsession.Protocols.MultiDeviceProtocol.isOurDevice(
|
||||
sentMessage.device
|
||||
);
|
||||
|
||||
const isOpenGroupMessage =
|
||||
sentMessage.group &&
|
||||
sentMessage.group instanceof libsession.Types.OpenGroup;
|
||||
|
||||
// We trigger a sync message only when the message is not to one of our devices, AND
|
||||
// the message is not for an open group (there is no sync for opengroups, each device pulls all messages), AND
|
||||
// if we did not sync or trigger a sync message for this specific message already
|
||||
const shouldTriggerSyncMessage =
|
||||
!isOurDevice &&
|
||||
!isOpenGroupMessage &&
|
||||
!this.get('synced') &&
|
||||
!this.get('sentSync');
|
||||
|
||||
// A message is synced if we triggered a sync message (sentSync)
|
||||
// and the current message was sent to our device (so a sync message)
|
||||
const shouldMarkMessageAsSynced =
|
||||
isOurDevice && !isOpenGroupMessage && this.get('sentSync');
|
||||
|
||||
// Handle the sync logic here
|
||||
if (!isOurDevice && !this.get('synced') && !this.get('sentSync')) {
|
||||
if (shouldTriggerSyncMessage) {
|
||||
const contentDecoded = textsecure.protobuf.Content.decode(
|
||||
sentMessage.plainTextBuffer
|
||||
);
|
||||
|
@ -1225,14 +1247,18 @@
|
|||
if (dataMessage) {
|
||||
this.sendSyncMessage(dataMessage);
|
||||
}
|
||||
} else if (isOurDevice && this.get('sentSync')) {
|
||||
} else if (shouldMarkMessageAsSynced) {
|
||||
this.set({ synced: true });
|
||||
}
|
||||
const primaryPubKey = await libsession.Protocols.MultiDeviceProtocol.getPrimaryDevice(
|
||||
sentMessage.device
|
||||
);
|
||||
if (!isOpenGroupMessage) {
|
||||
const primaryPubKey = await libsession.Protocols.MultiDeviceProtocol.getPrimaryDevice(
|
||||
sentMessage.device
|
||||
);
|
||||
sentTo = _.union(sentTo, [primaryPubKey.key]);
|
||||
}
|
||||
|
||||
this.set({
|
||||
sent_to: _.union(sentTo, [primaryPubKey.key]),
|
||||
sent_to: sentTo,
|
||||
sent: true,
|
||||
expirationStartTimestamp: Date.now(),
|
||||
// unidentifiedDeliveries: result.unidentifiedDeliveries,
|
||||
|
|
|
@ -15,7 +15,12 @@
|
|||
const convos = window.getConversations().models;
|
||||
|
||||
this.contacts = convos.filter(
|
||||
d => !!d && !d.isBlocked() && d.isPrivate() && !d.isMe()
|
||||
d =>
|
||||
!!d &&
|
||||
!d.isBlocked() &&
|
||||
d.isPrivate() &&
|
||||
!d.isMe() &&
|
||||
!!d.get('active_at')
|
||||
);
|
||||
if (!convo.isPublic()) {
|
||||
const members = convo.get('members') || [];
|
||||
|
|
|
@ -55,5 +55,7 @@ GroupBuffer.prototype.constructor = GroupBuffer;
|
|||
const ContactBuffer = function Constructor(arrayBuffer) {
|
||||
ProtoParser.call(this, arrayBuffer, textsecure.protobuf.ContactDetails);
|
||||
};
|
||||
|
||||
window.GroupBuffer = GroupBuffer;
|
||||
ContactBuffer.prototype = Object.create(ProtoParser.prototype);
|
||||
ContactBuffer.prototype.constructor = ContactBuffer;
|
||||
|
|
|
@ -98,6 +98,7 @@ export class DevicePairingDialog extends React.Component<Props, State> {
|
|||
text={window.i18n('ok')}
|
||||
onClick={this.validateSecondaryDevice}
|
||||
disabled={!deviceAlias}
|
||||
buttonColor={SessionButtonColor.Green}
|
||||
/>
|
||||
</div>
|
||||
<SessionSpinner loading={this.state.loading} />
|
||||
|
|
|
@ -31,7 +31,9 @@ export class InviteContactsDialog extends React.Component<Props, State> {
|
|||
|
||||
contacts = contacts.map(d => {
|
||||
const lokiProfile = d.getLokiProfile();
|
||||
const name = lokiProfile ? lokiProfile.displayName : 'Anonymous';
|
||||
const name = lokiProfile
|
||||
? lokiProfile.displayName
|
||||
: window.i18n('anonymous');
|
||||
|
||||
// TODO: should take existing members into account
|
||||
const existingMember = false;
|
||||
|
|
|
@ -456,7 +456,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
if (!OpenGroup.validate(serverUrl)) {
|
||||
window.pushToast({
|
||||
title: window.i18n('noServerURL'),
|
||||
id: 'connectToServerFail',
|
||||
id: 'connectToServer',
|
||||
type: 'error',
|
||||
});
|
||||
|
||||
|
@ -480,7 +480,7 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
if (await OpenGroup.serverExists(serverUrl)) {
|
||||
window.pushToast({
|
||||
title: window.i18n('connectingToServer'),
|
||||
id: 'connectToServerSuccess',
|
||||
id: 'connectToServer',
|
||||
type: 'success',
|
||||
});
|
||||
|
||||
|
@ -488,9 +488,10 @@ export class LeftPaneMessageSection extends React.Component<Props, State> {
|
|||
}
|
||||
});
|
||||
} catch (e) {
|
||||
window.console.error('Failed to connect to server:', e);
|
||||
window.pushToast({
|
||||
title: window.i18n('connectToServerFail'),
|
||||
id: 'connectToServerFail',
|
||||
id: 'connectToServer',
|
||||
type: 'error',
|
||||
});
|
||||
} finally {
|
||||
|
|
|
@ -66,18 +66,34 @@ export class SessionClosableOverlay extends React.Component<Props, State> {
|
|||
}
|
||||
|
||||
public getContacts() {
|
||||
const { overlayMode } = this.props;
|
||||
const contactsList = this.props.contacts ?? [];
|
||||
// Depending on the rendered overlay type we have to filter the contact list.
|
||||
let filteredContactsList = contactsList;
|
||||
const isClosedGroupView =
|
||||
overlayMode === SessionClosableOverlayType.ClosedGroup;
|
||||
if (isClosedGroupView) {
|
||||
filteredContactsList = filteredContactsList.filter(
|
||||
c => c.type === 'direct'
|
||||
);
|
||||
}
|
||||
|
||||
return contactsList.map((d: any) => {
|
||||
const name = d.name ?? window.i18n('anonymous');
|
||||
|
||||
return filteredContactsList.map((d: any) => {
|
||||
// TODO: should take existing members into account
|
||||
const existingMember = false;
|
||||
// if it has a profilename, use it and the shortened pubkey will be added automatically
|
||||
// if no profile name, Anonymous and the shortened pubkey will be added automatically
|
||||
let title;
|
||||
if (d.profileName) {
|
||||
title = `${d.profileName}`;
|
||||
} else {
|
||||
title = `${window.i18n('anonymous')}`;
|
||||
}
|
||||
|
||||
return {
|
||||
id: d.id,
|
||||
authorPhoneNumber: d.id,
|
||||
authorProfileName: name,
|
||||
authorProfileName: title,
|
||||
selected: false,
|
||||
authorName: name,
|
||||
authorColor: d.color,
|
||||
|
|
|
@ -599,7 +599,27 @@ export async function handleMessageEvent(event: MessageEvent): Promise<void> {
|
|||
sendDeliveryReceipt(source, data.timestamp);
|
||||
}
|
||||
|
||||
await window.ConversationController.getOrCreateAndWait(id, type);
|
||||
// Conversation Id is:
|
||||
// - primarySource if it is an incoming DM message,
|
||||
// - destination if it is an outgoing message,
|
||||
// - group.id if it is a group message
|
||||
let conversationId = id;
|
||||
if (isGroupMessage) {
|
||||
/* handle one part of the group logic here:
|
||||
handle requesting info of a new group,
|
||||
dropping an admin only update from a non admin, ...
|
||||
*/
|
||||
conversationId = message.group.id;
|
||||
}
|
||||
|
||||
if (!conversationId) {
|
||||
window.console.warn(
|
||||
'Invalid conversation id for incoming message',
|
||||
conversationId
|
||||
);
|
||||
}
|
||||
|
||||
await window.ConversationController.getOrCreateAndWait(conversationId, type);
|
||||
|
||||
// =========== Process flags =============
|
||||
|
||||
|
@ -613,20 +633,12 @@ export async function handleMessageEvent(event: MessageEvent): Promise<void> {
|
|||
|
||||
// =========================================
|
||||
|
||||
// Conversation Id is:
|
||||
// - primarySource if it is an incoming DM message,
|
||||
// - destination if it is an outgoing message,
|
||||
// - group.id if it is a group message
|
||||
let conversationId = id;
|
||||
|
||||
const primarySource = await MultiDeviceProtocol.getPrimaryDevice(source);
|
||||
if (isGroupMessage) {
|
||||
/* handle one part of the group logic here:
|
||||
handle requesting info of a new group,
|
||||
dropping an admin only update from a non admin, ...
|
||||
*/
|
||||
conversationId = message.group.id;
|
||||
|
||||
const shouldReturn = await preprocessGroupMessage(
|
||||
source,
|
||||
message.group,
|
||||
|
|
|
@ -334,6 +334,7 @@ async function onContactReceived(details: any) {
|
|||
// activeAt is null, then this contact has been purposefully hidden.
|
||||
if (activeAt !== null) {
|
||||
activeAt = activeAt || Date.now();
|
||||
conversation.set('active_at', activeAt);
|
||||
}
|
||||
const ourPrimaryKey = window.storage.get('primaryDevicePubKey');
|
||||
if (ourPrimaryKey) {
|
||||
|
@ -375,7 +376,6 @@ async function onContactReceived(details: any) {
|
|||
conversation.set({
|
||||
// name: details.name,
|
||||
color: details.color,
|
||||
active_at: activeAt,
|
||||
});
|
||||
|
||||
await conversation.setLokiProfile({ displayName: details.name });
|
||||
|
@ -427,6 +427,7 @@ async function onContactReceived(details: any) {
|
|||
verifiedEvent.viaContactSync = true;
|
||||
await onVerified(verifiedEvent);
|
||||
}
|
||||
await conversation.trigger('change');
|
||||
} catch (error) {
|
||||
window.log.error('onContactReceived error:', Errors.toLogFormat(error));
|
||||
}
|
||||
|
|
|
@ -98,7 +98,9 @@ export class MultiDeviceProtocol {
|
|||
primaryDevicePubKey,
|
||||
secondaryDevicePubKey,
|
||||
requestSignature: StringUtils.encode(requestSignature, 'base64'),
|
||||
grantSignature: StringUtils.encode(grantSignature, 'base64'),
|
||||
grantSignature: grantSignature
|
||||
? StringUtils.encode(grantSignature, 'base64')
|
||||
: undefined,
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
@ -152,17 +152,14 @@ export class OpenGroup {
|
|||
if (!OpenGroup.validate(server)) {
|
||||
return;
|
||||
}
|
||||
const rawServerURL = server
|
||||
.replace(/^https?:\/\//i, '')
|
||||
.replace(/[/\\]+$/i, '');
|
||||
const channelId = 1;
|
||||
const conversationId = `publicChat:${channelId}@${rawServerURL}`;
|
||||
|
||||
const prefixedServer = this.prefixify(server);
|
||||
const serverInfo = (await window.lokiPublicChatAPI.findOrCreateServer(
|
||||
prefixedServer
|
||||
)) as any;
|
||||
|
||||
if (!serverInfo?.channels?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
return serverInfo.channels[0].conversation;
|
||||
// Quickly peak to make sure we don't already have it
|
||||
return window.ConversationController.get(conversationId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -50,7 +50,8 @@ export async function getSyncContacts(): Promise<Array<any> | undefined> {
|
|||
c.isPrivate() &&
|
||||
!c.isOurLocalDevice() &&
|
||||
!c.isBlocked() &&
|
||||
!c.attributes.secondaryStatus
|
||||
!c.attributes.secondaryStatus &&
|
||||
!!c.get('active_at')
|
||||
) || [];
|
||||
|
||||
const secondaryContactsPartial = conversations.filter(
|
||||
|
@ -58,7 +59,8 @@ export async function getSyncContacts(): Promise<Array<any> | undefined> {
|
|||
c.isPrivate() &&
|
||||
!c.isOurLocalDevice() &&
|
||||
!c.isBlocked() &&
|
||||
c.attributes.secondaryStatus
|
||||
c.attributes.secondaryStatus &&
|
||||
!!c.get('active_at')
|
||||
);
|
||||
|
||||
const secondaryContactsPromise = secondaryContactsPartial.map(async c =>
|
||||
|
|
|
@ -139,7 +139,7 @@ export const _getLeftPaneLists = (
|
|||
|
||||
// Remove all invalid conversations and conversatons of devices associated
|
||||
// with cancelled attempted links
|
||||
if (!conversation.isPublic && !conversation.timestamp) {
|
||||
if (!conversation.isPublic && !conversation.activeAt) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -151,10 +151,6 @@ export const _getLeftPaneLists = (
|
|||
unreadCount += conversation.unreadCount;
|
||||
}
|
||||
|
||||
if (!conversation.isPublic && !conversation.activeAt) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (conversation.isArchived) {
|
||||
archivedConversations.push(conversation);
|
||||
} else {
|
||||
|
|
|
@ -111,4 +111,8 @@ export class MockConversation {
|
|||
|
||||
return this.isPrimary ? this.id : generateFakePubKey().key;
|
||||
}
|
||||
|
||||
public get(obj: string) {
|
||||
return (this.attributes as any)[obj];
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue