New feature flag with ability to migrate GV1 groups

This commit is contained in:
Scott Nonnenberg 2020-12-01 08:42:35 -08:00 committed by GitHub
parent 089a6fb5a2
commit 2b8ae412e0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 608 additions and 189 deletions

View file

@ -3,9 +3,11 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
// Note: because this file is pulled in directly from background.html, we can't use any
// imports here aside from types. That means everything will have to be references via
// globals right on window.
// This allows us to pull in types despite the fact that this is not a module. We can't
// use normal import syntax, nor can we use 'import type' syntax, or this will be turned
// into a module, and we'll get the dreaded 'exports is not defined' error.
// see https://github.com/microsoft/TypeScript/issues/41562
type GroupV2PendingMemberType = import('../model-types.d').GroupV2PendingMemberType;
interface GetLinkPreviewResult {
title: string;
@ -404,8 +406,6 @@ Whisper.ConversationView = Whisper.View.extend({
},
events: {
'click .composition-area-placeholder': 'onClickPlaceholder',
'click .bottom-bar': 'focusMessageField',
'click .capture-audio .microphone': 'captureAudio',
'change input.file-input': 'onChoseAttachment',
@ -647,6 +647,7 @@ Whisper.ConversationView = Whisper.View.extend({
),
});
},
onStartGroupMigration: () => this.startMigrationToGV2(),
};
this.compositionAreaView = new Whisper.ReactWrapperView({
@ -661,13 +662,13 @@ Whisper.ConversationView = Whisper.View.extend({
this.$('.composition-area-placeholder').append(this.compositionAreaView.el);
},
async longRunningTaskWrapper({
async longRunningTaskWrapper<T>({
name,
task,
}: {
name: string;
task: () => Promise<void>;
}): Promise<void> {
task: () => Promise<T>;
}): Promise<T> {
const idLog = `${name}/${this.model.idForLogging()}`;
const ONE_SECOND = 1000;
const TWO_SECONDS = 2000;
@ -690,7 +691,7 @@ Whisper.ConversationView = Whisper.View.extend({
// show a spinner until it's done
try {
window.log.info(`longRunningTaskWrapper/${idLog}: Starting task`);
await task();
const result = await task();
window.log.info(
`longRunningTaskWrapper/${idLog}: Task completed successfully`
);
@ -710,6 +711,8 @@ Whisper.ConversationView = Whisper.View.extend({
progressView.remove();
progressView = undefined;
}
return result;
} catch (error) {
window.log.error(
`longRunningTaskWrapper/${idLog}: Error!`,
@ -736,6 +739,8 @@ Whisper.ConversationView = Whisper.View.extend({
onClose: () => errorView.remove(),
},
});
throw error;
}
},
@ -1170,10 +1175,58 @@ Whisper.ConversationView = Whisper.View.extend({
}
},
// We need this, or clicking the reactified buttons will submit the form and send any
// mid-composition message content.
onClickPlaceholder(e: any) {
e.preventDefault();
async startMigrationToGV2(): Promise<void> {
const logId = this.model.idForLogging();
if (!this.model.isGroupV1()) {
throw new Error(
`startMigrationToGV2/${logId}: Cannot start, not a GroupV1 group`
);
}
const onClose = () => {
if (this.migrationDialog) {
this.migrationDialog.remove();
this.migrationDialog = undefined;
}
};
onClose();
const migrate = () => {
onClose();
this.longRunningTaskWrapper({
name: 'initiateMigrationToGroupV2',
task: () => window.Signal.Groups.initiateMigrationToGroupV2(this.model),
});
};
// Grab the dropped/invited user set
const {
droppedGV2MemberIds,
pendingMembersV2,
} = await this.longRunningTaskWrapper({
name: 'getGroupMigrationMembers',
task: () => window.Signal.Groups.getGroupMigrationMembers(this.model),
});
const invitedMemberIds = pendingMembersV2.map(
(item: GroupV2PendingMemberType) => item.conversationId
);
this.migrationDialog = new Whisper.ReactWrapperView({
className: 'group-v1-migration-wrapper',
JSX: window.Signal.State.Roots.createGroupV1MigrationModal(
window.reduxStore,
{
droppedMemberIds: droppedGV2MemberIds,
hasMigrated: false,
invitedMemberIds,
migrate,
onClose,
}
),
});
},
onChooseAttachment() {