From 1bfdbc5c93cd037255983b66ac7386e2b6e9ae18 Mon Sep 17 00:00:00 2001 From: Warrick Corfe-Tan Date: Tue, 8 Jun 2021 14:04:09 +1000 Subject: [PATCH] WIP: Refactoring modals. --- background.html | 5 - js/background.js | 152 ------------------ js/views/app_view.js | 7 - js/views/password_dialog_view.js | 44 ----- js/views/session_confirm_view.js | 80 --------- test/index.html | 1 - ts/components/EditProfileDialog.tsx | 2 +- ts/components/MainViewController.tsx | 5 +- .../session/LeftPaneMessageSection.tsx | 15 +- ts/components/session/SessionConfirm.tsx | 4 +- .../session/settings/SessionSettings.tsx | 1 - ts/models/conversation.ts | 12 -- .../{closedGroups.ts => closedGroups.tsx} | 36 +++-- ts/window.d.ts | 4 - 14 files changed, 47 insertions(+), 321 deletions(-) delete mode 100644 js/views/password_dialog_view.js delete mode 100644 js/views/session_confirm_view.js rename ts/receiver/{closedGroups.ts => closedGroups.tsx} (97%) diff --git a/background.html b/background.html index 86d2b3336..85a217961 100644 --- a/background.html +++ b/background.html @@ -129,7 +129,6 @@ - @@ -140,16 +139,12 @@ - - - - diff --git a/js/background.js b/js/background.js index 7acc305b3..c8bbe3e69 100644 --- a/js/background.js +++ b/js/background.js @@ -363,157 +363,11 @@ window.addEventListener('focus', () => Whisper.Notifications.clear()); window.addEventListener('unload', () => Whisper.Notifications.fastClear()); - window.confirmationDialog = params => { - const confirmDialog = new Whisper.SessionConfirmView({ - el: $('body'), - title: params.title, - message: params.message, - messageSub: params.messageSub || undefined, - resolve: params.resolve || undefined, - reject: params.reject || undefined, - okText: params.okText || undefined, - okTheme: params.okTheme || undefined, - closeTheme: params.closeTheme || undefined, - cancelText: params.cancelText || undefined, - hideCancel: params.hideCancel || false, - sessionIcon: params.sessionIcon || undefined, - iconSize: params.iconSize || undefined, - }); - - confirmDialog.render(); - }; - window.showResetSessionIdDialog = () => { appView.showResetSessionIdDialog(); }; - window.showOnionStatusDialog = () => { - appView.showOnionStatusDialog(); - }; - - window.commitProfileEdits = async (newName, avatar) => { - const ourNumber = window.storage.get('primaryDevicePubKey'); - const conversation = await window - .getConversationController() - .getOrCreateAndWait(ourNumber, 'private'); - - const readFile = attachment => - new Promise((resolve, reject) => { - const fileReader = new FileReader(); - fileReader.onload = e => { - const data = e.target.result; - resolve({ - ...attachment, - data, - size: data.byteLength, - }); - }; - fileReader.onerror = reject; - fileReader.onabort = reject; - fileReader.readAsArrayBuffer(attachment.file); - }); - - // const avatarPath = conversation.getAvatarPath(); - // const profile = conversation.getLokiProfile(); - // const displayName = profile && profile.displayName; - - let newAvatarPath = ''; - let url = null; - let profileKey = null; - if (avatar) { - const data = await readFile({ file: avatar }); - // Ensure that this file is either small enough or is resized to meet our - // requirements for attachments - try { - const withBlob = await window.Signal.Util.AttachmentUtil.autoScale( - { - contentType: avatar.type, - file: new Blob([data.data], { - type: avatar.contentType, - }), - }, - { - maxSide: 640, - maxSize: 1000 * 1024, - } - ); - const dataResized = await window.Signal.Types.Attachment.arrayBufferFromFile( - withBlob.file - ); - - // For simplicity we use the same attachment pointer that would send to - // others, which means we need to wait for the database response. - // To avoid the wait, we create a temporary url for the local image - // and use it until we the the response from the server - const tempUrl = window.URL.createObjectURL(avatar); - conversation.setLokiProfile({ displayName: newName }); - conversation.set('avatar', tempUrl); - - // Encrypt with a new key every time - profileKey = libsignal.crypto.getRandomBytes(32); - const encryptedData = await textsecure.crypto.encryptProfile(dataResized, profileKey); - - const avatarPointer = await libsession.Utils.AttachmentUtils.uploadAvatarV1({ - ...dataResized, - data: encryptedData, - size: encryptedData.byteLength, - }); - - ({ url } = avatarPointer); - - storage.put('profileKey', profileKey); - - conversation.set('avatarPointer', url); - - const upgraded = await Signal.Migrations.processNewAttachment({ - isRaw: true, - data: data.data, - url, - }); - newAvatarPath = upgraded.path; - // Replace our temporary image with the attachment pointer from the server: - conversation.set('avatar', null); - conversation.setLokiProfile({ - displayName: newName, - avatar: newAvatarPath, - }); - await conversation.commit(); - window.libsession.Utils.UserUtils.setLastProfileUpdateTimestamp(Date.now()); - await window.libsession.Utils.SyncUtils.forceSyncConfigurationNowIfNeeded(true); - } catch (error) { - window.log.error( - 'showEditProfileDialog Error ensuring that image is properly sized:', - error && error.stack ? error.stack : error - ); - } - } else { - // do not update the avatar if it did not change - conversation.setLokiProfile({ - displayName: newName, - }); - // might be good to not trigger a sync if the name did not change - await conversation.commit(); - window.libsession.Utils.UserUtils.setLastProfileUpdateTimestamp(Date.now()); - await window.libsession.Utils.SyncUtils.forceSyncConfigurationNowIfNeeded(true); - } - - // inform all your registered public servers - // could put load on all the servers - // if they just keep changing their names without sending messages - // so we could disable this here - // or least it enable for the quickest response - window.lokiPublicChatAPI.setProfileName(newName); - - if (avatar) { - window - .getConversationController() - .getConversations() - .filter(convo => convo.isPublic()) - .forEach(convo => convo.trigger('ourAvatarChanged', { url, profileKey })); - } - }; - // Set user's launch count. const prevLaunchCount = window.getSettingValue('launch-count'); const launchCount = !prevLaunchCount ? 1 : prevLaunchCount + 1; @@ -641,12 +495,6 @@ }); - Whisper.events.on('showPasswordDialog', async options => { - if (appView) { - appView.showPasswordDialog(options); - } - }); - Whisper.events.on('password-updated', () => { if (appView && appView.inboxView) { appView.inboxView.trigger('password-updated'); diff --git a/js/views/app_view.js b/js/views/app_view.js index 5bc964a20..3276f70e7 100644 --- a/js/views/app_view.js +++ b/js/views/app_view.js @@ -16,7 +16,6 @@ this.applyRtl(); this.applyHideMenu(); - this.showPasswordDialog = this.showPasswordDialog.bind(this); }, events: { openInbox: 'openInbox', @@ -124,12 +123,6 @@ const dialog = new Whisper.UserDetailsDialogView(options); this.el.prepend(dialog.el); }, - showPasswordDialog(options) { - // eslint-disable-next-line no-param-reassign - options.theme = this.getThemeObject(); - const dialog = new Whisper.PasswordDialogView(options); - this.el.prepend(dialog.el); - }, getThemeObject() { const themeSettings = storage.get('theme-setting') || 'light'; const theme = themeSettings === 'light' ? window.lightTheme : window.darkTheme; diff --git a/js/views/password_dialog_view.js b/js/views/password_dialog_view.js deleted file mode 100644 index d73f433f2..000000000 --- a/js/views/password_dialog_view.js +++ /dev/null @@ -1,44 +0,0 @@ -/* global Whisper */ - -// eslint-disable-next-line func-names -(function() { - 'use strict'; - - window.Whisper = window.Whisper || {}; - - Whisper.PasswordDialogView = Whisper.View.extend({ - className: 'loki-dialog password-dialog modal', - initialize(options) { - this.close = this.close.bind(this); - this.onOk = this.onOk.bind(this); - this.props = options; - - this.render(); - }, - - render() { - this.dialogView = new Whisper.ReactWrapperView({ - className: 'password-dialog-wrapper', - Component: window.Signal.Components.SessionPasswordModal, - props: { - onClose: this.close, - onOk: this.onOk, - ...this.props, - }, - }); - - this.$el.append(this.dialogView.el); - return this; - }, - - onOk(action) { - if (this.props.onSuccess) { - this.props.onSuccess(action); - } - }, - - close() { - this.remove(); - }, - }); -})(); diff --git a/js/views/session_confirm_view.js b/js/views/session_confirm_view.js deleted file mode 100644 index 8d29a14d2..000000000 --- a/js/views/session_confirm_view.js +++ /dev/null @@ -1,80 +0,0 @@ -/* global Whisper */ - -// eslint-disable-next-line func-names -(function() { - 'use strict'; - - window.Whisper = window.Whisper || {}; - - Whisper.SessionConfirmView = Whisper.View.extend({ - initialize(options) { - this.props = { - title: options.title, - message: options.message, - messageSub: options.messageSub, - onClickOk: this.ok.bind(this), - onClickClose: this.cancel.bind(this), - resolve: options.resolve, - reject: options.reject, - okText: options.okText, - cancelText: options.cancelText, - okTheme: options.okTheme, - closeTheme: options.closeTheme, - hideCancel: options.hideCancel, - sessionIcon: options.sessionIcon, - iconSize: options.iconSize, - }; - }, - - registerEvents() { - this.unregisterEvents(); - document.addEventListener('keyup', this.props.onClickClose, false); - }, - - unregisterEvents() { - document.removeEventListener('keyup', this.props.onClickClose, false); - if (this.confirmView && this.confirmView.el) { - window.ReactDOM.unmountComponentAtNode(this.confirmView.el); - } - - this.$('.session-confirm-wrapper').remove(); - }, - - render() { - this.$('.session-confirm-wrapper').remove(); - this.registerEvents(); - - this.confirmView = new Whisper.ReactWrapperView({ - className: 'loki-dialog modal session-confirm-wrapper', - Component: window.Signal.Components.SessionConfirm, - props: this.props, - }); - - this.$el.prepend(this.confirmView.el); - }, - - ok() { - this.unregisterEvents(); - - this.$('.session-confirm-wrapper').remove(); - if (this.props.resolve) { - this.props.resolve(); - } - }, - cancel() { - this.unregisterEvents(); - - this.$('.session-confirm-wrapper').remove(); - - if (this.props.reject) { - this.props.reject(); - } - }, - onKeyup(event) { - if (event.key === 'Escape' || event.key === 'Esc') { - this.unregisterEvents(); - this.props.onClickClose(); - } - }, - }); -})(); diff --git a/test/index.html b/test/index.html index 2e7bdeebb..b2700f9c9 100644 --- a/test/index.html +++ b/test/index.html @@ -178,7 +178,6 @@ - diff --git a/ts/components/EditProfileDialog.tsx b/ts/components/EditProfileDialog.tsx index cb4053915..7aeb1b8d5 100644 --- a/ts/components/EditProfileDialog.tsx +++ b/ts/components/EditProfileDialog.tsx @@ -327,7 +327,7 @@ export class EditProfileDialog extends React.Component { * @returns */ private onClickOK() { - const newName = this.state.profileName.trim(); + const newName = this.state.profileName ? this.state.profileName.trim() : ''; if (newName.length === 0 || newName.length > MAX_USERNAME_LENGTH) { return; diff --git a/ts/components/MainViewController.tsx b/ts/components/MainViewController.tsx index 9c222c93f..25d898b2b 100644 --- a/ts/components/MainViewController.tsx +++ b/ts/components/MainViewController.tsx @@ -38,7 +38,8 @@ export class MessageView extends React.Component { */ async function createClosedGroup( groupName: string, - groupMembers: Array + groupMembers: Array, + setModal: () => void ): Promise { // Validate groupName and groupMembers length if (groupName.length === 0) { @@ -63,7 +64,7 @@ async function createClosedGroup( const groupMemberIds = groupMembers.map(m => m.id); - await createClosedGroupV2(groupName, groupMemberIds); + await createClosedGroupV2(groupName, groupMemberIds, setModal); return true; } diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index dc46ca959..92b5c7707 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -29,6 +29,8 @@ import { openGroupV2CompleteURLRegex } from '../../opengroup/utils/OpenGroupUtil import { joinOpenGroupV2WithUIEvents } from '../../opengroup/opengroupV2/JoinOpenGroupV2'; import autoBind from 'auto-bind'; +import { createClosedGroup } from "../../receiver/closedGroups"; + export interface Props { searchTerm: string; @@ -59,6 +61,7 @@ interface State { loading: boolean; overlay: false | SessionComposeToType; valuePasted: string; + modal: null | JSX.Element; } export class LeftPaneMessageSection extends React.Component { @@ -71,6 +74,7 @@ export class LeftPaneMessageSection extends React.Component { loading: false, overlay: false, valuePasted: '', + modal: null }; autoBind(this); @@ -166,11 +170,20 @@ export class LeftPaneMessageSection extends React.Component { return (
{this.renderHeader()} + { this.state.modal ? this.state.modal : null } {overlay ? this.renderClosableOverlay(overlay) : this.renderConversations()}
); } + + + public setModal (modal: null | JSX.Element) { + this.setState({ + modal + }); + } + public renderConversations() { return (
@@ -434,7 +447,7 @@ export class LeftPaneMessageSection extends React.Component { return; } this.setState({ loading: true }, async () => { - const groupCreated = await MainViewController.createClosedGroup(groupName, groupMembers); + const groupCreated = await MainViewController.createClosedGroup(groupName, groupMembers, setModal); if (groupCreated) { this.handleToggleOverlay(undefined); diff --git a/ts/components/session/SessionConfirm.tsx b/ts/components/session/SessionConfirm.tsx index 04a68e7e9..03e2496ae 100644 --- a/ts/components/session/SessionConfirm.tsx +++ b/ts/components/session/SessionConfirm.tsx @@ -12,12 +12,12 @@ type Props = { title: string; onOk?: any; onClose?: any; - onClickOk: any; + onClickOk?: any; onClickClose?: any; okText?: string; cancelText?: string; hideCancel?: boolean; - okTheme: SessionButtonColor; + okTheme?: SessionButtonColor; closeTheme?: SessionButtonColor; sessionIcon?: SessionIconType; iconSize?: SessionIconSize; diff --git a/ts/components/session/settings/SessionSettings.tsx b/ts/components/session/settings/SessionSettings.tsx index cc6e8e173..57f3f7561 100644 --- a/ts/components/session/settings/SessionSettings.tsx +++ b/ts/components/session/settings/SessionSettings.tsx @@ -12,7 +12,6 @@ import { getConversationLookup, getConversations } from '../../../state/selector import { connect } from 'react-redux'; import { getPasswordHash } from '../../../../ts/data/data'; import { PasswordAction, SessionPasswordModal } from '../SessionPasswordModal'; -import { ModalStatusLight } from '../../OnionStatusDialog'; export enum SessionSettingCategory { Appearance = 'appearance', diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts index aa92d145a..c8c740efd 100644 --- a/ts/models/conversation.ts +++ b/ts/models/conversation.ts @@ -422,7 +422,6 @@ export class ConversationModel extends Backbone.Model { onUnblockContact: this.unblock, onCopyPublicKey: this.copyPublicKey, onDeleteContact: this.deleteContact, - onChangeNickname: this.changeNickname, onClearNickname: this.clearNickname, onDeleteMessages: this.deleteMessages, onLeaveGroup: () => { @@ -1306,17 +1305,6 @@ export class ConversationModel extends Backbone.Model { void ConversationInteraction.copyPublicKey(this.id); } - public changeNickname() { - if (this.isGroup()) { - throw new Error( - 'Called changeNickname() on a group. This is only supported in 1-on-1 conversation items and 1-on-1 conversation headers' - ); - } - window.showNicknameDialog({ - convoId: this.id, - }); - } - public clearNickname = () => { void this.setNickname(''); }; diff --git a/ts/receiver/closedGroups.ts b/ts/receiver/closedGroups.tsx similarity index 97% rename from ts/receiver/closedGroups.ts rename to ts/receiver/closedGroups.tsx index 6f9fd0039..e757ce684 100644 --- a/ts/receiver/closedGroups.ts +++ b/ts/receiver/closedGroups.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import { SignalService } from '../protobuf'; import { removeFromCache } from './cache'; import { EnvelopePlus } from './types'; @@ -35,6 +36,7 @@ import { queueAllCachedFromSource } from './receiver'; import { actions as conversationActions } from '../state/ducks/conversations'; import { SwarmPolling } from '../session/snode_api/swarmPolling'; import { MessageModel } from '../models/message'; +import { SessionConfirm } from '../components/session/SessionConfirm'; export const distributingClosedGroupEncryptionKeyPairs = new Map(); @@ -45,8 +47,7 @@ export async function handleClosedGroupControlMessage( const { type } = groupUpdate; const { Type } = SignalService.DataMessage.ClosedGroupControlMessage; window.log.info( - ` handle closed group update from ${envelope.senderIdentity || envelope.source} about group ${ - envelope.source + ` handle closed group update from ${envelope.senderIdentity || envelope.source} about group ${envelope.source }` ); @@ -837,7 +838,7 @@ async function handleClosedGroupEncryptionKeyPairRequest( return removeFromCache(envelope); } -export async function createClosedGroup(groupName: string, members: Array) { +export async function createClosedGroup(groupName: string, members: Array, setModal: any) { const setOfMembers = new Set(members); const ourNumber = UserUtils.getOurPubKeyFromCache(); @@ -892,7 +893,8 @@ export async function createClosedGroup(groupName: string, members: Array, encryptionKeyPair: ECKeyPair, dbMessage: MessageModel, - isRetry: boolean = false + setModal: any, + isRetry: boolean = false, ): Promise { const promises = createInvitePromises( listOfMembers, @@ -948,14 +951,28 @@ async function sendToGroupMembers( inviteResults.length > 1 ? window.i18n('closedGroupInviteSuccessTitlePlural') : window.i18n('closedGroupInviteSuccessTitle'); - window.confirmationDialog({ - title: invitesTitle, - message: window.i18n('closedGroupInviteSuccessMessage'), - }); + + // setModal() + + setModal( + ) + ) + + // window.confirmationDialog({ + // title: invitesTitle, + // message: window.i18n('closedGroupInviteSuccessMessage'), + // }); } return allInvitesSent; } else { // Confirmation dialog that recursively calls sendToGroupMembers on resolve + window.confirmationDialog({ title: inviteResults.length > 1 @@ -984,6 +1001,7 @@ async function sendToGroupMembers( admins, encryptionKeyPair, dbMessage, + setModal, isRetrySend ); } diff --git a/ts/window.d.ts b/ts/window.d.ts index 065e1536c..3309f1a17 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -41,7 +41,6 @@ declare global { Whisper: any; clearLocalData: any; clipboard: any; - confirmationDialog: (params: ConfirmationDialogParams) => any; dcodeIO: any; displayNameRegex: any; friends: any; @@ -68,9 +67,6 @@ declare global { seedNodeList: any; setPassword: any; setSettingValue: any; - showEditProfileDialog: any; - showNicknameDialog: (options: { convoId: string }) => void; - showOnionStatusDialog: any; showResetSessionIdDialog: any; storage: any; textsecure: LibTextsecure;