You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			151 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			TypeScript
		
	
			
		
		
	
	
			151 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			TypeScript
		
	
| import React, { useState } from 'react';
 | |
| // tslint:disable: use-simple-attributes no-submodule-imports
 | |
| 
 | |
| import { useDispatch } from 'react-redux';
 | |
| import { SessionButton } from '../../basic/SessionButton';
 | |
| import { SessionIdEditable } from '../../basic/SessionIdEditable';
 | |
| import { SessionSpinner } from '../../basic/SessionSpinner';
 | |
| import { OverlayHeader } from './OverlayHeader';
 | |
| import { resetOverlayMode } from '../../../state/ducks/section';
 | |
| import { PubKey } from '../../../session/types';
 | |
| import { ConversationTypeEnum } from '../../../models/conversationAttributes';
 | |
| import { SNodeAPI } from '../../../session/apis/snode_api';
 | |
| import { onsNameRegex } from '../../../session/apis/snode_api/SNodeAPI';
 | |
| import { getConversationController } from '../../../session/conversations';
 | |
| import { ToastUtils, UserUtils } from '../../../session/utils';
 | |
| import { openConversationWithMessages } from '../../../state/ducks/conversations';
 | |
| import useKey from 'react-use/lib/useKey';
 | |
| import { YourSessionIDPill, YourSessionIDSelectable } from '../../basic/YourSessionIDPill';
 | |
| import { Flex } from '../../basic/Flex';
 | |
| import { SessionIconButton } from '../../icon';
 | |
| import { SpacerMD } from '../../basic/Text';
 | |
| import styled from 'styled-components';
 | |
| 
 | |
| const SessionIDDescription = styled.div`
 | |
|   color: var(--text-secondary-color);
 | |
|   font-family: var(--font-default);
 | |
|   font-style: normal;
 | |
|   font-weight: 400;
 | |
|   font-size: 12px;
 | |
|   text-align: center;
 | |
| `;
 | |
| 
 | |
| function copyOurSessionID() {
 | |
|   const ourSessionId = UserUtils.getOurPubKeyStrFromCache();
 | |
|   if (!ourSessionId) {
 | |
|     return;
 | |
|   }
 | |
|   window.clipboard.writeText(ourSessionId);
 | |
|   ToastUtils.pushCopiedToClipBoard();
 | |
| }
 | |
| 
 | |
| export const OverlayMessage = () => {
 | |
|   const dispatch = useDispatch();
 | |
| 
 | |
|   function closeOverlay() {
 | |
|     dispatch(resetOverlayMode());
 | |
|   }
 | |
| 
 | |
|   useKey('Escape', closeOverlay);
 | |
|   const [pubkeyOrOns, setPubkeyOrOns] = useState('');
 | |
|   const [loading, setLoading] = useState(false);
 | |
| 
 | |
|   const title = window.i18n('newMessage');
 | |
|   const buttonText = window.i18n('next');
 | |
|   const subtitle = window.i18n('enterSessionID');
 | |
|   const placeholder = window.i18n('enterSessionIDOrONSName');
 | |
| 
 | |
|   const disableNextButton = !pubkeyOrOns || loading;
 | |
| 
 | |
|   async function openConvoOnceResolved(resolvedSessionID: string) {
 | |
|     const convo = await getConversationController().getOrCreateAndWait(
 | |
|       resolvedSessionID,
 | |
|       ConversationTypeEnum.PRIVATE
 | |
|     );
 | |
| 
 | |
|     // we now want to show a conversation we just started on the leftpane, even if we did not send a message to it yet
 | |
|     if (!convo.isActive() || !convo.isApproved()) {
 | |
|       convo.set({ active_at: Date.now(), isApproved: true });
 | |
|       await convo.commit();
 | |
|     }
 | |
| 
 | |
|     await openConversationWithMessages({ conversationKey: resolvedSessionID, messageId: null });
 | |
| 
 | |
|     closeOverlay();
 | |
|   }
 | |
| 
 | |
|   async function handleMessageButtonClick() {
 | |
|     if ((!pubkeyOrOns && !pubkeyOrOns.length) || !pubkeyOrOns.trim().length) {
 | |
|       ToastUtils.pushToastError('invalidPubKey', window.i18n('invalidNumberError')); // or ons name
 | |
|       return;
 | |
|     }
 | |
|     const pubkeyorOnsTrimmed = pubkeyOrOns.trim();
 | |
| 
 | |
|     if (!PubKey.validateWithErrorNoBlinding(pubkeyorOnsTrimmed)) {
 | |
|       await openConvoOnceResolved(pubkeyOrOns);
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     // this might be an ONS, validate the regex first
 | |
|     const mightBeOnsName = new RegExp(onsNameRegex, 'g').test(pubkeyorOnsTrimmed);
 | |
|     if (!mightBeOnsName) {
 | |
|       ToastUtils.pushToastError('invalidPubKey', window.i18n('invalidNumberError'));
 | |
|       return;
 | |
|     }
 | |
|     setLoading(true);
 | |
|     try {
 | |
|       const resolvedSessionID = await SNodeAPI.getSessionIDForOnsName(pubkeyorOnsTrimmed);
 | |
|       if (PubKey.validateWithErrorNoBlinding(resolvedSessionID)) {
 | |
|         throw new Error('Got a resolved ONS but the returned entry is not a vlaid SessionID');
 | |
|       }
 | |
|       // this is a pubkey
 | |
|       await openConvoOnceResolved(resolvedSessionID);
 | |
|     } catch (e) {
 | |
|       window?.log?.warn('failed to resolve ons name', pubkeyorOnsTrimmed, e);
 | |
|       ToastUtils.pushToastError('invalidPubKey', window.i18n('failedResolveOns'));
 | |
|     } finally {
 | |
|       setLoading(false);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return (
 | |
|     <div className="module-left-pane-overlay">
 | |
|       <OverlayHeader title={title} subtitle={subtitle} />
 | |
| 
 | |
|       <SessionIdEditable
 | |
|         editable={!loading}
 | |
|         placeholder={placeholder}
 | |
|         onChange={setPubkeyOrOns}
 | |
|         dataTestId="new-session-conversation"
 | |
|         onPressEnter={handleMessageButtonClick}
 | |
|       />
 | |
| 
 | |
|       <SessionSpinner loading={loading} />
 | |
| 
 | |
|       <SessionIDDescription>{window.i18n('startNewConversationBy...')}</SessionIDDescription>
 | |
| 
 | |
|       <Flex container={true} width="100%">
 | |
|         <SpacerMD />
 | |
|         <YourSessionIDPill />
 | |
|         <SpacerMD />
 | |
|       </Flex>
 | |
|       <Flex
 | |
|         container={true}
 | |
|         justifyContent="space-between"
 | |
|         alignItems="center"
 | |
|         width="100%"
 | |
|         padding="0 var(--margins-md)" // YourSessionIDSelectable already has a left margin of 15px
 | |
|       >
 | |
|         <YourSessionIDSelectable />
 | |
|         <SessionIconButton iconSize="small" iconType="copy" onClick={copyOurSessionID} />
 | |
|       </Flex>
 | |
|       <SessionButton
 | |
|         text={buttonText}
 | |
|         disabled={disableNextButton}
 | |
|         onClick={handleMessageButtonClick}
 | |
|         dataTestId="next-new-conversation-button"
 | |
|       />
 | |
|     </div>
 | |
|   );
 | |
| };
 |