From 4f8e455b38a47b17c819b9edb13fb51708fe08e8 Mon Sep 17 00:00:00 2001 From: Warrick Corfe-Tan Date: Fri, 18 Jun 2021 15:02:55 +1000 Subject: [PATCH 1/6] WIP. Adding confirmation to show link preview on pasting into composition box. --- ts/components/session/SessionToggle.tsx | 9 --- .../conversation/SessionCompositionBox.tsx | 55 +++++++++++++++---- 2 files changed, 45 insertions(+), 19 deletions(-) diff --git a/ts/components/session/SessionToggle.tsx b/ts/components/session/SessionToggle.tsx index 3e35076b7..eb7ed2de4 100644 --- a/ts/components/session/SessionToggle.tsx +++ b/ts/components/session/SessionToggle.tsx @@ -5,15 +5,6 @@ import { updateConfirmModal } from '../../state/ducks/modalDialog'; interface Props { active: boolean; onClick: any; - // If you require the toggle to be confirmed, use - // a confirmation dialog. The parameters needed in the - // setting item in SessionSettings.tsx are like such: - // confirmationDialogParams: { - // shouldShowConfirm: false, - // title: window.i18n('linkPreviewsTitle'), - // message: window.i18n('linkPreviewsConfirmMessage'), - // okTheme: 'danger', - // } confirmationDialogParams?: any | undefined; updateConfirmModal?: any; diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx index 3161c1e70..edc74f66b 100644 --- a/ts/components/session/conversation/SessionCompositionBox.tsx +++ b/ts/components/session/conversation/SessionCompositionBox.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import _, { debounce } from 'lodash'; +import _, { debounce, update } from 'lodash'; import { Attachment, AttachmentType } from '../../../types/Attachment'; import * as MIME from '../../../types/MIME'; @@ -38,6 +38,9 @@ import { updateMentionsMembers, } from '../../../state/ducks/mentionsInput'; import { getMentionsInput } from '../../../state/selectors/mentionsInput'; +import { useDispatch } from 'react-redux'; +import { updateConfirmModal } from '../../../state/ducks/modalDialog'; +import { SessionButtonColor } from '../SessionButton'; export interface ReplyingToMessageProps { convoId: string; @@ -209,9 +212,32 @@ export class SessionCompositionBox extends React.Component { const { items } = e.clipboardData; let imgBlob = null; for (const item of items) { - if (item.type.split('/')[0] === 'image') { + const pasteType = item.type.split('/')[0] + if (pasteType === 'image') { imgBlob = item.getAsFile(); } + + switch (pasteType) { + case ('image'): + imgBlob = item.getAsFile(); + break; + case ('text'): + // check for links + console.log('is a text'); + let x = e.clipboardData.getData('text'); + console.log({ x }); + if (this.isURL(x)) { + console.log('IS A URL!'); + // const dispatch = useDispatch(); + // dispatch(updateConfirmModal({ + // shouldShowConfirm: () => !window.getSettingValue('link-preview-setting'), + // title: window.i18n('linkPreviewsTitle'), + // message: window.i18n('linkPreviewsConfirmMessage'), + // okTheme: SessionButtonColor.Danger, + // })) + } + + } } if (imgBlob !== null) { const file = imgBlob; @@ -223,6 +249,17 @@ export class SessionCompositionBox extends React.Component { } } + /** + * + * @param str String to evaluate + * @returns boolean if the string is true or false + */ + private isURL(str: string) { + var urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$'; + var url = new RegExp(urlRegex, 'i'); + return str.length < 2083 && url.test(str); + } + private showEmojiPanel() { document.addEventListener('mousedown', this.handleClick, false); @@ -344,12 +381,12 @@ export class SessionCompositionBox extends React.Component { const messagePlaceHolder = isKickedFromGroup ? i18n('youGotKickedFromGroup') : left - ? i18n('youLeftTheGroup') - : isBlocked && isPrivate - ? i18n('unblockToSend') - : isBlocked && !isPrivate - ? i18n('unblockGroupToSend') - : i18n('sendMessage'); + ? i18n('youLeftTheGroup') + : isBlocked && isPrivate + ? i18n('unblockToSend') + : isBlocked && !isPrivate + ? i18n('unblockGroupToSend') + : i18n('sendMessage'); const typingEnabled = this.isTypingEnabled(); let index = 0; @@ -516,8 +553,6 @@ export class SessionCompositionBox extends React.Component { }} /> ); - - return <>; } private fetchLinkPreview(firstLink: string) { From 6393a4ff273f7fcc45c25d108eb2b2a975950fc0 Mon Sep 17 00:00:00 2001 From: Warrick Corfe-Tan Date: Fri, 18 Jun 2021 15:44:11 +1000 Subject: [PATCH 2/6] Confirmation box appearing on link paste but no functionality is changed yet. --- ts/components/session/SessionConfirm.tsx | 2 -- .../session/conversation/SessionCompositionBox.tsx | 9 +++++++++ .../session/conversation/SessionConversation.tsx | 3 +-- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/ts/components/session/SessionConfirm.tsx b/ts/components/session/SessionConfirm.tsx index 9296475ab..bd51938ea 100644 --- a/ts/components/session/SessionConfirm.tsx +++ b/ts/components/session/SessionConfirm.tsx @@ -115,11 +115,9 @@ const SessionConfirmInner = (props: SessionConfirmDialogProps) => {
- {/* */} {!hideCancel && ( - // void; showSettingsSection: (category: SessionSettingCategory) => void; theme: DefaultTheme; + updateConfirmModal: (props: SessionConfirmDialogProps) => any; } interface State { @@ -235,6 +238,12 @@ export class SessionCompositionBox extends React.Component { // message: window.i18n('linkPreviewsConfirmMessage'), // okTheme: SessionButtonColor.Danger, // })) + this.props.updateConfirmModal({ + shouldShowConfirm: () => !window.getSettingValue('link-preview-setting'), + title: window.i18n('linkPreviewsTitle'), + message: window.i18n('linkPreviewsConfirmMessage'), + okTheme: SessionButtonColor.Danger, + }) } } diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx index c17cf2b93..702e062f7 100644 --- a/ts/components/session/conversation/SessionConversation.tsx +++ b/ts/components/session/conversation/SessionConversation.tsx @@ -43,8 +43,6 @@ import { AddModeratorsDialog } from '../../conversation/ModeratorsAddDialog'; import { RemoveModeratorsDialog } from '../../conversation/ModeratorsRemoveDialog'; import { UpdateGroupNameDialog } from '../../conversation/UpdateGroupNameDialog'; import { UpdateGroupMembersDialog } from '../../conversation/UpdateGroupMembersDialog'; -import { getOurNumber } from '../../../state/selectors/user'; -import { useSelector } from 'react-redux'; import { InviteContactsDialog } from '../../conversation/InviteContactsDialog'; interface State { @@ -314,6 +312,7 @@ export class SessionConversation extends React.Component { removeAttachment={this.removeAttachment} onChoseAttachments={this.onChoseAttachments} theme={this.props.theme} + updateConfirmModal={actions.updateConfirmModal} />
From e27e299f14fc0777c09c6d18d74e61b17dd61850 Mon Sep 17 00:00:00 2001 From: Warrick Corfe-Tan Date: Fri, 18 Jun 2021 16:18:51 +1000 Subject: [PATCH 3/6] minor refactor. --- .../conversation/SessionCompositionBox.tsx | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx index 88aec4ff2..ce315adcd 100644 --- a/ts/components/session/conversation/SessionCompositionBox.tsx +++ b/ts/components/session/conversation/SessionCompositionBox.tsx @@ -225,27 +225,7 @@ export class SessionCompositionBox extends React.Component { imgBlob = item.getAsFile(); break; case ('text'): - // check for links - console.log('is a text'); - let x = e.clipboardData.getData('text'); - console.log({ x }); - if (this.isURL(x)) { - console.log('IS A URL!'); - // const dispatch = useDispatch(); - // dispatch(updateConfirmModal({ - // shouldShowConfirm: () => !window.getSettingValue('link-preview-setting'), - // title: window.i18n('linkPreviewsTitle'), - // message: window.i18n('linkPreviewsConfirmMessage'), - // okTheme: SessionButtonColor.Danger, - // })) - this.props.updateConfirmModal({ - shouldShowConfirm: () => !window.getSettingValue('link-preview-setting'), - title: window.i18n('linkPreviewsTitle'), - message: window.i18n('linkPreviewsConfirmMessage'), - okTheme: SessionButtonColor.Danger, - }) - } - + this.showLinkSharingConfirmationModalDialog(e); } } if (imgBlob !== null) { @@ -258,6 +238,22 @@ export class SessionCompositionBox extends React.Component { } } + /** + * Check if what is pasted is a URL and prompt confirmation for a setting change + * @param e paste event + */ + private showLinkSharingConfirmationModalDialog(e: any) { + let pastedText = e.clipboardData.getData('text'); + if (this.isURL(pastedText)) { + this.props.updateConfirmModal({ + shouldShowConfirm: () => !window.getSettingValue('link-preview-setting'), + title: window.i18n('linkPreviewsTitle'), + message: window.i18n('linkPreviewsConfirmMessage'), + okTheme: SessionButtonColor.Danger, + }); + } + } + /** * * @param str String to evaluate From 15afdbfa7d716d61acfa993af7fa7e0e7a3b7137 Mon Sep 17 00:00:00 2001 From: Warrick Corfe-Tan Date: Fri, 18 Jun 2021 16:28:24 +1000 Subject: [PATCH 4/6] Link preview confirmation dialog working. --- ts/components/session/SessionConfirm.tsx | 18 +++--------------- .../conversation/SessionCompositionBox.tsx | 3 +++ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/ts/components/session/SessionConfirm.tsx b/ts/components/session/SessionConfirm.tsx index 62f55c0d9..606a26f05 100644 --- a/ts/components/session/SessionConfirm.tsx +++ b/ts/components/session/SessionConfirm.tsx @@ -39,12 +39,10 @@ const SessionConfirmInner = (props: SessionConfirmDialogProps) => { closeTheme = SessionButtonColor.Primary, onClickOk, onClickClose, - closeAfterClickOk = true, hideCancel = false, sessionIcon, iconSize, shouldShowConfirm, - // updateConfirmModal } = props; const okText = props.okText || window.i18n('ok'); @@ -55,19 +53,6 @@ const SessionConfirmInner = (props: SessionConfirmDialogProps) => { const messageSubText = messageSub ? 'session-confirm-main-message' : 'subtle'; - /** - * Calls close function after the ok button is clicked. If no close method specified, closes the modal - */ - const onClickOkWithClose = () => { - if (onClickOk) { - onClickOk(); - } - - if (onClickClose) { - onClickClose(); - } - }; - const onClickOkHandler = () => { if (onClickOk) { onClickOk(); @@ -80,6 +65,9 @@ const SessionConfirmInner = (props: SessionConfirmDialogProps) => { return null; } + /** + * Performs specified on close action then removes the modal. + */ const onClickCancelHandler = () => { if (onClickClose) { onClickClose(); diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx index ce315adcd..c5341e22a 100644 --- a/ts/components/session/conversation/SessionCompositionBox.tsx +++ b/ts/components/session/conversation/SessionCompositionBox.tsx @@ -250,6 +250,9 @@ export class SessionCompositionBox extends React.Component { title: window.i18n('linkPreviewsTitle'), message: window.i18n('linkPreviewsConfirmMessage'), okTheme: SessionButtonColor.Danger, + onClickOk: () => { + window.setSettingValue('link-preview-setting', true); + } }); } } From f356c9b843e4e342b31d38c59f17db1cf77d0682 Mon Sep 17 00:00:00 2001 From: Warrick Corfe-Tan Date: Fri, 18 Jun 2021 16:30:42 +1000 Subject: [PATCH 5/6] Yarn formatting. --- ts/components/session/SessionWrapperModal.tsx | 4 +-- .../conversation/SessionCompositionBox.tsx | 25 ++++++++++--------- ts/components/session/icon/SessionIcon.tsx | 2 +- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/ts/components/session/SessionWrapperModal.tsx b/ts/components/session/SessionWrapperModal.tsx index b8b150965..8227cd980 100644 --- a/ts/components/session/SessionWrapperModal.tsx +++ b/ts/components/session/SessionWrapperModal.tsx @@ -53,7 +53,7 @@ export const SessionWrapperModal = (props: SessionWrapperModalType) => { showExitIcon, headerIconButtons, headerReverse, - additionalClassName + additionalClassName, } = props; const theme = useTheme(); @@ -75,7 +75,7 @@ export const SessionWrapperModal = (props: SessionWrapperModalType) => { }; return ( -
+
{showHeader ? ( diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx index c5341e22a..4a4be5add 100644 --- a/ts/components/session/conversation/SessionCompositionBox.tsx +++ b/ts/components/session/conversation/SessionCompositionBox.tsx @@ -215,16 +215,16 @@ export class SessionCompositionBox extends React.Component { const { items } = e.clipboardData; let imgBlob = null; for (const item of items) { - const pasteType = item.type.split('/')[0] + const pasteType = item.type.split('/')[0]; if (pasteType === 'image') { imgBlob = item.getAsFile(); } switch (pasteType) { - case ('image'): + case 'image': imgBlob = item.getAsFile(); break; - case ('text'): + case 'text': this.showLinkSharingConfirmationModalDialog(e); } } @@ -252,18 +252,19 @@ export class SessionCompositionBox extends React.Component { okTheme: SessionButtonColor.Danger, onClickOk: () => { window.setSettingValue('link-preview-setting', true); - } + }, }); } } /** - * + * * @param str String to evaluate * @returns boolean if the string is true or false */ private isURL(str: string) { - var urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$'; + var urlRegex = + '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$'; var url = new RegExp(urlRegex, 'i'); return str.length < 2083 && url.test(str); } @@ -389,12 +390,12 @@ export class SessionCompositionBox extends React.Component { const messagePlaceHolder = isKickedFromGroup ? i18n('youGotKickedFromGroup') : left - ? i18n('youLeftTheGroup') - : isBlocked && isPrivate - ? i18n('unblockToSend') - : isBlocked && !isPrivate - ? i18n('unblockGroupToSend') - : i18n('sendMessage'); + ? i18n('youLeftTheGroup') + : isBlocked && isPrivate + ? i18n('unblockToSend') + : isBlocked && !isPrivate + ? i18n('unblockGroupToSend') + : i18n('sendMessage'); const typingEnabled = this.isTypingEnabled(); let index = 0; diff --git a/ts/components/session/icon/SessionIcon.tsx b/ts/components/session/icon/SessionIcon.tsx index c8cf79ab7..dc5d5e1cc 100644 --- a/ts/components/session/icon/SessionIcon.tsx +++ b/ts/components/session/icon/SessionIcon.tsx @@ -131,7 +131,7 @@ const SessionSvg = (props: { viewBox: props.viewBox, glowDuration: props.glowDuration, glowStartDelay: props.glowStartDelay, - iconColor: props.iconColor + iconColor: props.iconColor, }; return ( From 6affca034da39617fcfa7cd8037bbc57b40c4ee2 Mon Sep 17 00:00:00 2001 From: Warrick Corfe-Tan Date: Fri, 18 Jun 2021 16:36:43 +1000 Subject: [PATCH 6/6] yarn linting fixes. --- ts/components/session/SessionWrapperModal.tsx | 2 +- .../session/conversation/SessionCompositionBox.tsx | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ts/components/session/SessionWrapperModal.tsx b/ts/components/session/SessionWrapperModal.tsx index 8227cd980..5f7d4537a 100644 --- a/ts/components/session/SessionWrapperModal.tsx +++ b/ts/components/session/SessionWrapperModal.tsx @@ -75,7 +75,7 @@ export const SessionWrapperModal = (props: SessionWrapperModalType) => { }; return ( -
+
{showHeader ? ( diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx index 4a4be5add..40c431a6b 100644 --- a/ts/components/session/conversation/SessionCompositionBox.tsx +++ b/ts/components/session/conversation/SessionCompositionBox.tsx @@ -226,6 +226,8 @@ export class SessionCompositionBox extends React.Component { break; case 'text': this.showLinkSharingConfirmationModalDialog(e); + break; + default: } } if (imgBlob !== null) { @@ -243,7 +245,7 @@ export class SessionCompositionBox extends React.Component { * @param e paste event */ private showLinkSharingConfirmationModalDialog(e: any) { - let pastedText = e.clipboardData.getData('text'); + const pastedText = e.clipboardData.getData('text'); if (this.isURL(pastedText)) { this.props.updateConfirmModal({ shouldShowConfirm: () => !window.getSettingValue('link-preview-setting'), @@ -263,9 +265,9 @@ export class SessionCompositionBox extends React.Component { * @returns boolean if the string is true or false */ private isURL(str: string) { - var urlRegex = + const urlRegex = '^(?!mailto:)(?:(?:http|https|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[0-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))|localhost)(?::\\d{2,5})?(?:(/|\\?|#)[^\\s]*)?$'; - var url = new RegExp(urlRegex, 'i'); + const url = new RegExp(urlRegex, 'i'); return str.length < 2083 && url.test(str); }