From 711112d07644108694f127cd0f3c30ecf1339f56 Mon Sep 17 00:00:00 2001 From: Vincent Date: Thu, 7 May 2020 13:46:36 +1000 Subject: [PATCH 1/6] Remove channels --- _locales/en/messages.json | 2 +- stylesheets/_session.scss | 1 + ts/components/LeftPane.tsx | 3 +++ ts/components/session/ActionsPanel.tsx | 6 ----- .../session/LeftPaneContactSection.tsx | 5 +++- .../session/LeftPaneMessageSection.tsx | 3 ++- .../session/LeftPaneSectionHeader.tsx | 26 +++++++++++++------ .../session/LeftPaneSettingSection.tsx | 1 + ts/components/session/icon/Icons.tsx | 6 +++++ 9 files changed, 36 insertions(+), 17 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 94a1fede4..89f448abc 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -784,7 +784,7 @@ "description": "Shown to separate the types of search results" }, "messagesHeader": { - "message": "Session", + "message": "Conversations", "description": "Shown to separate the types of search results" }, "settingsHeader": { diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index ac39ea49c..9dbdf4df1 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -91,6 +91,7 @@ textarea { width: auto; display: flex; justify-content: center; + align-items: center; font-weight: 700; user-select: none; white-space: nowrap; diff --git a/ts/components/LeftPane.tsx b/ts/components/LeftPane.tsx index babd60a8e..21d0a94f3 100644 --- a/ts/components/LeftPane.tsx +++ b/ts/components/LeftPane.tsx @@ -12,6 +12,7 @@ import { ConversationType } from '../state/ducks/conversations'; import { LeftPaneContactSection } from './session/LeftPaneContactSection'; import { LeftPaneSettingSection } from './session/LeftPaneSettingSection'; import { LeftPaneChannelSection } from './session/LeftPaneChannelSection'; +import { SessionIconType } from './session/icon'; // from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5 export type RowRendererParamsType = { @@ -59,6 +60,7 @@ export class LeftPane extends React.Component { labels: Array, onTabSelected?: any, buttonLabel?: string, + buttonIcon?: SessionIconType, buttonClicked?: any, notificationCount?: number ): JSX.Element { @@ -68,6 +70,7 @@ export class LeftPane extends React.Component { selectedTab={0} labels={labels} buttonLabel={buttonLabel} + buttonIcon={buttonIcon} buttonClicked={buttonClicked} notificationCount={notificationCount} /> diff --git a/ts/components/session/ActionsPanel.tsx b/ts/components/session/ActionsPanel.tsx index 2f8f9c10d..215560583 100644 --- a/ts/components/session/ActionsPanel.tsx +++ b/ts/components/session/ActionsPanel.tsx @@ -136,7 +136,6 @@ export class ActionsPanel extends React.Component { const isProfilePageSelected = selectedSection === SectionType.Profile; const isMessagePageSelected = selectedSection === SectionType.Message; const isContactPageSelected = selectedSection === SectionType.Contact; - const isChannelPageSelected = selectedSection === SectionType.Channel; const isSettingsPageSelected = selectedSection === SectionType.Settings; const isMoonPageSelected = selectedSection === SectionType.Moon; @@ -154,11 +153,6 @@ export class ActionsPanel extends React.Component { onSelect={this.handleSectionSelect} notificationCount={unreadMessageCount} /> - { labels, this.handleTabSelected, undefined, + undefined, this.handleToggleFriendRequestPopup, receivedFriendRequestCount ); @@ -321,7 +322,9 @@ export class LeftPaneContactSection extends React.Component { private renderList() { const { sentFriendsRequest } = this.props; - const friends = window.getFriendsFromContacts(this.props.friends); + + const contacts = this.props.friends.filter(f => f.type === 'direct'); + const friends = window.getFriendsFromContacts(contacts); const length = Number(sentFriendsRequest.length) + Number(friends.length); const combined = [...sentFriendsRequest, ...friends]; diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index e29b942b1..275acebe7 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -197,7 +197,8 @@ export class LeftPaneMessageSection extends React.Component { return LeftPane.RENDER_HEADER( labels, null, - window.i18n('newSession'), + undefined, + SessionIconType.Plus, this.handleToggleOverlay ); } diff --git a/ts/components/session/LeftPaneSectionHeader.tsx b/ts/components/session/LeftPaneSectionHeader.tsx index 6a8d60bd6..4c9f1d737 100644 --- a/ts/components/session/LeftPaneSectionHeader.tsx +++ b/ts/components/session/LeftPaneSectionHeader.tsx @@ -1,6 +1,7 @@ import React from 'react'; import classNames from 'classnames'; import { SessionButton } from './SessionButton'; +import { SessionIcon, SessionIconSize, SessionIconType } from './icon'; import { NotificationCountSize, SessionNotificationCount, @@ -43,6 +44,7 @@ interface Props { labels: Array; notificationCount?: number; buttonLabel?: string; + buttonIcon?: SessionIconType; buttonClicked?: any; } @@ -65,10 +67,13 @@ export class LeftPaneSectionHeader extends React.Component { const { labels, buttonLabel, + buttonIcon, buttonClicked, notificationCount, } = this.props; + const hasButton = buttonLabel || buttonIcon; + const children = []; //loop to create children for (let i = 0; i < labels.length; i++) { @@ -83,15 +88,20 @@ export class LeftPaneSectionHeader extends React.Component { ); } - if (buttonLabel && !notificationCount) { - children.push( - + if (hasButton && !notificationCount) { + const buttonContent = buttonIcon ? ( + + ) : ( + buttonLabel ); + + const button = ( + + {buttonContent} + + ); + + children.push(button); } else if (buttonLabel && notificationCount && notificationCount > 0) { children.push(
diff --git a/ts/components/session/LeftPaneSettingSection.tsx b/ts/components/session/LeftPaneSettingSection.tsx index b540e9afd..db3976ea5 100644 --- a/ts/components/session/LeftPaneSettingSection.tsx +++ b/ts/components/session/LeftPaneSettingSection.tsx @@ -57,6 +57,7 @@ export class LeftPaneSettingSection extends React.Component { null, undefined, undefined, + undefined, undefined ); } diff --git a/ts/components/session/icon/Icons.tsx b/ts/components/session/icon/Icons.tsx index f5d447890..0a95571db 100644 --- a/ts/components/session/icon/Icons.tsx +++ b/ts/components/session/icon/Icons.tsx @@ -23,6 +23,7 @@ export enum SessionIconType { Microphone = 'microphone', Moon = 'moon', Pencil = 'pencil', + Plus = 'plus', Reply = 'reply', Search = 'search', Send = 'send', @@ -160,6 +161,11 @@ export const icons = { 'M4,16.4142136 L4,20 L7.58578644,20 L19.5857864,8 L16,4.41421356 L4,16.4142136 Z M16.7071068,2.29289322 L21.7071068,7.29289322 C22.0976311,7.68341751 22.0976311,8.31658249 21.7071068,8.70710678 L8.70710678,21.7071068 C8.5195704,21.8946432 8.26521649,22 8,22 L3,22 C2.44771525,22 2,21.5522847 2,21 L2,16 C2,15.7347835 2.10535684,15.4804296 2.29289322,15.2928932 L15.2928932,2.29289322 C15.6834175,1.90236893 16.3165825,1.90236893 16.7071068,2.29289322 Z', viewBox: '1 1 21 21', }, + [SessionIconType.Plus]: { + path: + 'm405.332031 192h-170.664062v-170.667969c0-11.773437-9.558594-21.332031-21.335938-21.332031-11.773437 0-21.332031 9.558594-21.332031 21.332031v170.667969h-170.667969c-11.773437 0-21.332031 9.558594-21.332031 21.332031 0 11.777344 9.558594 21.335938 21.332031 21.335938h170.667969v170.664062c0 11.777344 9.558594 21.335938 21.332031 21.335938 11.777344 0 21.335938-9.558594 21.335938-21.335938v-170.664062h170.664062c11.777344 0 21.335938-9.558594 21.335938-21.335938 0-11.773437-9.558594-21.332031-21.335938-21.332031zm0 0', + viewBox: '0 0 427 427', + }, [SessionIconType.Reply]: { path: 'M4,3 C4.55228475,3 5,3.44771525 5,4 L5,4 L5,11 C5,12.6568542 6.34314575,14 8,14 L8,14 L17.585,14 L14.2928932,10.7071068 C13.9324093,10.3466228 13.9046797,9.77939176 14.2097046,9.38710056 L14.2928932,9.29289322 C14.6834175,8.90236893 15.3165825,8.90236893 15.7071068,9.29289322 L15.7071068,9.29289322 L20.7071068,14.2928932 C20.7355731,14.3213595 20.7623312,14.3515341 20.787214,14.3832499 C20.788658,14.3849951 20.7902348,14.3870172 20.7918027,14.389044 C20.8140715,14.4179625 20.8348358,14.4480862 20.8539326,14.4793398 C20.8613931,14.4913869 20.8685012,14.5036056 20.8753288,14.5159379 C20.8862061,14.5357061 20.8966234,14.5561086 20.9063462,14.5769009 C20.914321,14.5939015 20.9218036,14.6112044 20.9287745,14.628664 C20.9366843,14.6484208 20.9438775,14.6682023 20.9504533,14.6882636 C20.9552713,14.7031487 20.9599023,14.7185367 20.9641549,14.734007 C20.9701664,14.7555635 20.9753602,14.7772539 20.9798348,14.7992059 C20.9832978,14.8166247 20.9863719,14.834051 20.9889822,14.8515331 C20.9962388,14.8996379 21,14.9493797 21,15 L20.9962979,14.9137692 C20.9978436,14.9317345 20.9989053,14.9497336 20.9994829,14.9677454 L21,15 C21,15.0112225 20.9998151,15.0224019 20.9994483,15.0335352 C20.9988772,15.050591 20.997855,15.0679231 20.996384,15.0852242 C20.994564,15.1070574 20.9920941,15.1281144 20.9889807,15.1489612 C20.9863719,15.165949 20.9832978,15.1833753 20.9797599,15.2007258 C20.9753602,15.2227461 20.9701664,15.2444365 20.964279,15.2658396 C20.9599023,15.2814633 20.9552713,15.2968513 20.9502619,15.3121425 C20.9438775,15.3317977 20.9366843,15.3515792 20.928896,15.3710585 C20.9218036,15.3887956 20.914321,15.4060985 20.9063266,15.4232215 C20.8974314,15.4421635 20.8879327,15.4609002 20.8778732,15.4792864 C20.8703855,15.4931447 20.862375,15.5070057 20.8540045,15.5207088 C20.8382813,15.546275 20.8215099,15.5711307 20.8036865,15.5951593 C20.774687,15.6343256 20.7425008,15.6717127 20.7071068,15.7071068 L20.787214,15.6167501 C20.7849289,15.6196628 20.7826279,15.6225624 20.7803112,15.625449 L20.7071068,15.7071068 L15.7071068,20.7071068 C15.3165825,21.0976311 14.6834175,21.0976311 14.2928932,20.7071068 C13.9023689,20.3165825 13.9023689,19.6834175 14.2928932,19.2928932 L14.2928932,19.2928932 L17.585,16 L8,16 C5.3112453,16 3.11818189,13.8776933 3.00461951,11.2168896 L3,11 L3,4 C3,3.44771525 3.44771525,3 4,3', From 5c02dc9371811f9b4c47f4ac0eeb87da31633530 Mon Sep 17 00:00:00 2001 From: Vincent Date: Mon, 11 May 2020 10:37:40 +1000 Subject: [PATCH 2/6] sorting-tinkers --- js/background.js | 4 - ts/components/LeftPane.tsx | 29 - ts/components/MainViewController.tsx | 174 +++++- .../session/LeftPaneChannelSection.tsx | 508 ------------------ .../session/LeftPaneContactSection.tsx | 6 +- .../session/LeftPaneMessageSection.tsx | 341 +++++++----- .../session/LeftPaneSectionHeader.tsx | 4 +- .../session/SessionClosableOverlay.tsx | 35 +- ts/components/session/SessionIdEditable.tsx | 1 + 9 files changed, 401 insertions(+), 701 deletions(-) delete mode 100644 ts/components/session/LeftPaneChannelSection.tsx diff --git a/js/background.js b/js/background.js index e9f43c901..30d4d268c 100644 --- a/js/background.js +++ b/js/background.js @@ -904,10 +904,6 @@ window.setSettingValue('link-preview-setting', false); } - // Render onboarding message from LeftPaneMessageSection - // unless user turns it off during their session - window.setSettingValue('render-message-onboarding', true); - // Generates useful random ID for various purposes window.generateID = () => Math.random() diff --git a/ts/components/LeftPane.tsx b/ts/components/LeftPane.tsx index 67c300b00..88fe9b5da 100644 --- a/ts/components/LeftPane.tsx +++ b/ts/components/LeftPane.tsx @@ -11,7 +11,6 @@ import { LeftPaneSectionHeader } from './session/LeftPaneSectionHeader'; import { ConversationType } from '../state/ducks/conversations'; import { LeftPaneContactSection } from './session/LeftPaneContactSection'; import { LeftPaneSettingSection } from './session/LeftPaneSettingSection'; -import { LeftPaneChannelSection } from './session/LeftPaneChannelSection'; import { SessionIconType } from './session/icon'; // from https://github.com/bvaughn/react-virtualized/blob/fb3484ed5dcc41bffae8eab029126c0fb8f7abc0/source/List/types.js#L5 @@ -103,8 +102,6 @@ export class LeftPane extends React.Component { return this.renderMessageSection(); case SectionType.Contact: return this.renderContactSection(); - case SectionType.Channel: - return this.renderChannelSection(); case SectionType.Settings: return this.renderSettingSection(); case SectionType.Moon: @@ -179,30 +176,4 @@ export class LeftPane extends React.Component { return ; } - - private renderChannelSection() { - const { - openConversationInternal, - conversations, - searchResults, - searchTerm, - isSecondaryDevice, - updateSearchTerm, - search, - clearSearch, - } = this.props; - - return ( - - ); - } } diff --git a/ts/components/MainViewController.tsx b/ts/components/MainViewController.tsx index e344920c2..c43950ebf 100644 --- a/ts/components/MainViewController.tsx +++ b/ts/components/MainViewController.tsx @@ -7,29 +7,14 @@ import { } from './session/settings/SessionSettings'; export const MainViewController = { - renderMessageView: () => { - if (document.getElementById('main-view')) { - ReactDOM.render(, document.getElementById('main-view')); - } - }, - - renderSettingsView: (category: SessionSettingCategory) => { - // tslint:disable-next-line: no-backbone-get-set-outside-model - const isSecondaryDevice = !!window.textsecure.storage.get( - 'isSecondaryDevice' - ); - if (document.getElementById('main-view')) { - ReactDOM.render( - , - document.getElementById('main-view') - ); - } - }, + joinChannelStateManager, + onCreateClosedGroup, + renderMessageView, + renderSettingsView, }; +import { ContactType } from './session/SessionMemberListItem'; + export class MessageView extends React.Component { public render() { return ( @@ -50,3 +35,150 @@ export class MessageView extends React.Component { ); } } + + +// ///////////////////////////////////// +// //////////// Management ///////////// +// ///////////////////////////////////// + +function joinChannelStateManager( + thisRef: any, + serverURL: string, + onSuccess?: any +) { + // Any component that uses this function MUST have the keys [loading, connectSuccess] + // in their State + + // TODO: Make this not hard coded + const channelId = 1; + thisRef.setState({ loading: true }); + const connectionResult = window.attemptConnection(serverURL, channelId); + + // Give 5s maximum for promise to revole. Else, throw error. + const connectionTimeout = setTimeout(() => { + if (!thisRef.state.connectSuccess) { + thisRef.setState({ loading: false }); + window.pushToast({ + title: window.i18n('connectToServerFail'), + type: 'error', + id: 'connectToServerFail', + }); + + return; + } + }, window.CONSTANTS.MAX_CONNECTION_DURATION); + + connectionResult + .then(() => { + clearTimeout(connectionTimeout); + + if (thisRef.state.loading) { + thisRef.setState({ + connectSuccess: true, + loading: false, + }); + window.pushToast({ + title: window.i18n('connectToServerSuccess'), + id: 'connectToServerSuccess', + type: 'success', + }); + + if (onSuccess) { + onSuccess(); + } + } + }) + .catch((connectionError: string) => { + clearTimeout(connectionTimeout); + thisRef.setState({ + connectSuccess: true, + loading: false, + }); + window.pushToast({ + title: connectionError, + id: 'connectToServerFail', + type: 'error', + }); + + return false; + }); + + return true; +} + +async function onCreateClosedGroup( + groupName: string, + groupMembers: Array, + onSuccess: any +) { + // Validate groupName and groupMembers length + if ( + groupName.length === 0 || + groupName.length > window.CONSTANTS.MAX_GROUP_NAME_LENGTH + ) { + window.pushToast({ + title: window.i18n( + 'invalidGroupName', + window.CONSTANTS.MAX_GROUP_NAME_LENGTH + ), + type: 'error', + id: 'invalidGroupName', + }); + + return; + } + + // >= because we add ourself as a member after this. so a 10 group is already invalid as it will be 11 with ourself + if ( + groupMembers.length === 0 || + groupMembers.length >= window.CONSTANTS.SMALL_GROUP_SIZE_LIMIT + ) { + window.pushToast({ + title: window.i18n( + 'invalidGroupSize', + window.CONSTANTS.SMALL_GROUP_SIZE_LIMIT + ), + type: 'error', + id: 'invalidGroupSize', + }); + + return; + } + + const groupMemberIds = groupMembers.map(m => m.id); + await window.doCreateGroup(groupName, groupMemberIds); + + if (onSuccess) { + onSuccess(); + } + + return true; +} + +// ///////////////////////////////////// +// ///////////// Rendering ///////////// +// ///////////////////////////////////// + +function renderMessageView() { + if (document.getElementById('main-view')) { + ReactDOM.render(, document.getElementById('main-view')); + } +} + +function renderSettingsView(category: SessionSettingCategory) { + // tslint:disable-next-line: no-backbone-get-set-outside-model + const isSecondaryDevice = !!window.textsecure.storage.get( + 'isSecondaryDevice' + ); + if (document.getElementById('main-view')) { + ReactDOM.render( + ( + + ), + document.getElementById('main-view') + ); + } +} diff --git a/ts/components/session/LeftPaneChannelSection.tsx b/ts/components/session/LeftPaneChannelSection.tsx deleted file mode 100644 index 0ae41254b..000000000 --- a/ts/components/session/LeftPaneChannelSection.tsx +++ /dev/null @@ -1,508 +0,0 @@ -import React from 'react'; -import { AutoSizer, List } from 'react-virtualized'; - -import { - ConversationListItem, - PropsData as ConversationListItemPropsType, -} from '../ConversationListItem'; - -import { LeftPane, RowRendererParamsType } from '../LeftPane'; -import { - SessionButton, - SessionButtonColor, - SessionButtonType, -} from './SessionButton'; -import { - PropsData as SearchResultsProps, - SearchResults, -} from '../SearchResults'; -import { SearchOptions } from '../../types/Search'; -import { debounce } from 'lodash'; -import { cleanSearchTerm } from '../../util/cleanSearchTerm'; -import { SessionSearchInput } from './SessionSearchInput'; -import { SessionClosableOverlay } from './SessionClosableOverlay'; -import { MainViewController } from '../MainViewController'; -import { ContactType } from './SessionMemberListItem'; - -export interface Props { - searchTerm: string; - isSecondaryDevice: boolean; - - conversations?: Array; - - searchResults?: SearchResultsProps; - - updateSearchTerm: (searchTerm: string) => void; - search: (query: string, options: SearchOptions) => void; - openConversationInternal: (id: string, messageId?: string) => void; - clearSearch: () => void; -} - -export enum SessionGroupType { - Open = 'open-group', - Closed = 'closed-group', -} - -interface State { - channelUrlPasted: string; - loading: boolean; - connectSuccess: boolean; - // The type of group that is being added. Undefined in default view. - groupAddType: SessionGroupType | undefined; -} - -export class LeftPaneChannelSection extends React.Component { - private readonly updateSearchBound: (searchedString: string) => void; - private readonly debouncedSearch: (searchTerm: string) => void; - - public constructor(props: Props) { - super(props); - this.state = { - channelUrlPasted: '', - loading: false, - connectSuccess: false, - groupAddType: undefined, - }; - - this.handleOnPasteUrl = this.handleOnPasteUrl.bind(this); - this.handleJoinChannelButtonClick = this.handleJoinChannelButtonClick.bind( - this - ); - this.handleToggleOverlay = this.handleToggleOverlay.bind(this); - this.updateSearchBound = this.updateSearch.bind(this); - this.debouncedSearch = debounce(this.search.bind(this), 20); - } - - public componentWillUnmount() { - this.updateSearch(''); - } - - public getCurrentConversations(): - | Array - | undefined { - const { conversations } = this.props; - - let conversationList = conversations; - if (conversationList !== undefined) { - conversationList = conversationList.filter( - // a channel is either a public group or a rss group - conversation => conversation && conversation.type === 'group' - ); - } - - return conversationList; - } - - public renderRow = ({ - index, - key, - style, - }: RowRendererParamsType): JSX.Element => { - const { openConversationInternal } = this.props; - - const conversations = this.getCurrentConversations(); - - if (!conversations) { - throw new Error('renderRow: Tried to render without conversations'); - } - - const conversation = conversations[index]; - - return ( - - ); - }; - - public renderList(): JSX.Element | Array { - const { openConversationInternal, searchResults } = this.props; - - if (searchResults) { - return ( - - ); - } - - const conversations = this.getCurrentConversations(); - - if (!conversations) { - throw new Error( - 'render: must provided conversations if no search results are provided' - ); - } - - const length = conversations.length; - - // Note: conversations is not a known prop for List, but it is required to ensure that - // it re-renders when our conversation data changes. Otherwise it would just render - // on startup and scroll. - const list = ( -
- - {({ height, width }) => ( - - )} - -
- ); - - return [list]; - } - - public renderHeader(): JSX.Element { - const labels = [window.i18n('groups')]; - - return LeftPane.RENDER_HEADER(labels, null); - } - - public componentDidMount() { - MainViewController.renderMessageView(); - } - - public componentDidUpdate() { - MainViewController.renderMessageView(); - } - - public render(): JSX.Element { - return ( -
- {this.renderHeader()} - {this.state.groupAddType - ? this.renderClosableOverlay(this.state.groupAddType) - : this.renderGroups()} -
- ); - } - - public renderGroups() { - return ( -
- - {this.renderList()} - {this.renderBottomButtons()} -
- ); - } - - public updateSearch(searchTerm: string) { - const { updateSearchTerm, clearSearch } = this.props; - - if (!searchTerm) { - clearSearch(); - - return; - } - - this.setState({ channelUrlPasted: '' }); - - if (updateSearchTerm) { - updateSearchTerm(searchTerm); - } - - if (searchTerm.length < 2) { - return; - } - - const cleanedTerm = cleanSearchTerm(searchTerm); - if (!cleanedTerm) { - return; - } - - this.debouncedSearch(cleanedTerm); - } - - public clearSearch() { - this.props.clearSearch(); - } - - public search() { - const { search } = this.props; - const { searchTerm, isSecondaryDevice } = this.props; - - if (search) { - search(searchTerm, { - noteToSelf: window.i18n('noteToSelf').toLowerCase(), - ourNumber: window.textsecure.storage.user.getNumber(), - regionCode: '', - isSecondaryDevice, - }); - } - } - - private handleToggleOverlay(groupType?: SessionGroupType) { - // If no groupType, return to default view. - // Close the overlay with handleToggleOverlay(undefined) - - switch (groupType) { - case SessionGroupType.Open: - this.setState({ - groupAddType: SessionGroupType.Open, - }); - break; - case SessionGroupType.Closed: - this.setState({ - groupAddType: SessionGroupType.Closed, - }); - break; - default: - // Exit overlay - this.setState({ - groupAddType: undefined, - }); - } - } - - private renderClosableOverlay(groupType: SessionGroupType) { - const { searchTerm } = this.props; - const { loading } = this.state; - - const openGroupElement = ( - { - this.handleToggleOverlay(undefined); - }} - onButtonClick={this.handleJoinChannelButtonClick} - searchTerm={searchTerm} - updateSearch={this.updateSearchBound} - showSpinner={loading} - /> - ); - - const closedGroupElement = ( - { - this.handleToggleOverlay(undefined); - }} - onButtonClick={async ( - groupName: string, - groupMembers: Array - ) => this.onCreateClosedGroup(groupName, groupMembers)} - searchTerm={searchTerm} - updateSearch={this.updateSearchBound} - showSpinner={loading} - /> - ); - - return groupType === SessionGroupType.Open - ? openGroupElement - : closedGroupElement; - } - - private renderBottomButtons(): JSX.Element { - const edit = window.i18n('edit'); - const joinOpenGroup = window.i18n('joinOpenGroup'); - const createClosedGroup = window.i18n('createClosedGroup'); - const showEditButton = false; - - return ( -
- {showEditButton && ( - - )} - - { - this.handleToggleOverlay(SessionGroupType.Open); - }} - /> - { - this.handleToggleOverlay(SessionGroupType.Closed); - }} - /> -
- ); - } - - private handleOnPasteUrl(value: string) { - this.setState({ channelUrlPasted: value }); - } - - private handleJoinChannelButtonClick(groupUrl: string) { - const { loading } = this.state; - - if (loading) { - return false; - } - - // longest TLD is now (20/02/06) 24 characters per https://jasontucker.blog/8945/what-is-the-longest-tld-you-can-get-for-a-domain-name - const regexURL = /(http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,24}(:[0-9]{1,5})?(\/.*)?/; - - if (groupUrl.length <= 0) { - window.pushToast({ - title: window.i18n('noServerURL'), - type: 'error', - id: 'connectToServerFail', - }); - - return false; - } - - if (!regexURL.test(groupUrl)) { - window.pushToast({ - title: window.i18n('noServerURL'), - type: 'error', - id: 'connectToServerFail', - }); - - return false; - } - - joinChannelStateManager(this, groupUrl, () => { - this.handleToggleOverlay(undefined); - }); - - return true; - } - - private async onCreateClosedGroup( - groupName: string, - groupMembers: Array - ) { - // Validate groupName and groupMembers length - if ( - groupName.length === 0 || - groupName.length > window.CONSTANTS.MAX_GROUP_NAME_LENGTH - ) { - window.pushToast({ - title: window.i18n( - 'invalidGroupName', - window.CONSTANTS.MAX_GROUP_NAME_LENGTH - ), - type: 'error', - id: 'invalidGroupName', - }); - - return; - } - - // >= because we add ourself as a member after this. so a 10 group is already invalid as it will be 11 with ourself - if ( - groupMembers.length === 0 || - groupMembers.length >= window.CONSTANTS.SMALL_GROUP_SIZE_LIMIT - ) { - window.pushToast({ - title: window.i18n( - 'invalidGroupSize', - window.CONSTANTS.SMALL_GROUP_SIZE_LIMIT - ), - type: 'error', - id: 'invalidGroupSize', - }); - - return; - } - - const groupMemberIds = groupMembers.map(m => m.id); - await window.doCreateGroup(groupName, groupMemberIds); - this.handleToggleOverlay(undefined); - - window.pushToast({ - title: window.i18n('closedGroupCreatedToastTitle'), - type: 'success', - }); - - return true; - } -} - -export function joinChannelStateManager( - thisRef: any, - serverURL: string, - onSuccess?: any -) { - // Any component that uses this function MUST have the keys [loading, connectSuccess] - // in their State - - // TODO: Make this not hard coded - const channelId = 1; - thisRef.setState({ loading: true }); - const connectionResult = window.attemptConnection(serverURL, channelId); - - // Give 5s maximum for promise to revole. Else, throw error. - const connectionTimeout = setTimeout(() => { - if (!thisRef.state.connectSuccess) { - thisRef.setState({ loading: false }); - window.pushToast({ - title: window.i18n('connectToServerFail'), - type: 'error', - id: 'connectToServerFail', - }); - - return; - } - }, window.CONSTANTS.MAX_CONNECTION_DURATION); - - connectionResult - .then(() => { - clearTimeout(connectionTimeout); - - if (thisRef.state.loading) { - thisRef.setState({ - connectSuccess: true, - loading: false, - }); - window.pushToast({ - title: window.i18n('connectToServerSuccess'), - id: 'connectToServerSuccess', - type: 'success', - }); - - if (onSuccess) { - onSuccess(); - } - } - }) - .catch((connectionError: string) => { - clearTimeout(connectionTimeout); - thisRef.setState({ - connectSuccess: true, - loading: false, - }); - window.pushToast({ - title: connectionError, - id: 'connectToServerFail', - type: 'error', - }); - - return false; - }); - - return true; -} diff --git a/ts/components/session/LeftPaneContactSection.tsx b/ts/components/session/LeftPaneContactSection.tsx index 4a9e0704a..84705236d 100644 --- a/ts/components/session/LeftPaneContactSection.tsx +++ b/ts/components/session/LeftPaneContactSection.tsx @@ -17,9 +17,11 @@ import { import { AutoSizer, List } from 'react-virtualized'; import { validateNumber } from '../../types/PhoneNumber'; import { ConversationType } from '../../state/ducks/conversations'; -import { SessionClosableOverlay } from './SessionClosableOverlay'; +import { SessionClosableOverlay, SessionClosableOverlayType } from './SessionClosableOverlay'; import { MainViewController } from '../MainViewController'; +export enum SessionClosableOverlayTypeContact { Contact = 'contact'} + export interface Props { searchTerm: string; isSecondaryDevice: boolean; @@ -204,7 +206,7 @@ export class LeftPaneContactSection extends React.Component { private renderClosableOverlay() { return ( ; - searchResults?: SearchResultsProps; updateSearchTerm: (searchTerm: string) => void; @@ -41,17 +39,40 @@ export interface Props { clearSearch: () => void; } -export class LeftPaneMessageSection extends React.Component { +export enum SessionComposeToType { + Message = 'message', + OpenGroup = 'open-group', + ClosedGroup = 'closed-group', +} + +export const SessionGroupType = { + OpenGroup: SessionComposeToType.OpenGroup, + ClosedGroup: SessionComposeToType.ClosedGroup, +}; +export type SessionGroupType = SessionComposeToType; + +interface State { + loading: boolean; + overlay: false | SessionComposeToType; + valuePasted: string; + connectSuccess: boolean; +} + +export class LeftPaneMessageSection extends React.Component { private readonly updateSearchBound: (searchedString: string) => void; private readonly debouncedSearch: (searchTerm: string) => void; public constructor(props: Props) { super(props); + this.state = { + loading: false, + overlay: false, + valuePasted: '', + connectSuccess: false, + }; + const conversations = this.getCurrentConversations(); - const renderOnboardingSetting = window.getSettingValue( - 'render-message-onboarding' - ); const realConversations: Array = []; if (conversations) { @@ -64,23 +85,20 @@ export class LeftPaneMessageSection extends React.Component { }); } - const length = realConversations.length; - - this.state = { - showComposeView: false, - pubKeyPasted: '', - shouldRenderMessageOnboarding: - length === 0 && renderOnboardingSetting && false, - connectSuccess: false, - loading: false, - }; - this.updateSearchBound = this.updateSearch.bind(this); + + this.handleOnPaste = this.handleOnPaste.bind(this); this.handleToggleOverlay = this.handleToggleOverlay.bind(this); - this.handleCloseOnboarding = this.handleCloseOnboarding.bind(this); - this.handleJoinPublicChat = this.handleJoinPublicChat.bind(this); - this.handleOnPasteSessionID = this.handleOnPasteSessionID.bind(this); this.handleMessageButtonClick = this.handleMessageButtonClick.bind(this); + + this.handleNewSessionButtonClick = this.handleNewSessionButtonClick.bind(this); + this.handleJoinChannelButtonClick = this.handleJoinChannelButtonClick.bind( + this + ); + this.handleCreateClosedGroupButtonClick = this.handleCreateClosedGroupButtonClick.bind(this); + + this.renderClosableOverlay = this.renderClosableOverlay.bind(this); + this.debouncedSearch = debounce(this.search.bind(this), 20); } @@ -199,16 +217,18 @@ export class LeftPaneMessageSection extends React.Component { null, undefined, SessionIconType.Plus, - this.handleToggleOverlay + this.handleNewSessionButtonClick ); } public render(): JSX.Element { + const { overlay } = this.state; + return (
{this.renderHeader()} - {this.state.showComposeView - ? this.renderClosableOverlay() + {overlay + ? this.renderClosableOverlay(overlay) : this.renderConversations()}
); @@ -217,90 +237,17 @@ export class LeftPaneMessageSection extends React.Component { public renderConversations() { return (
- {this.state.shouldRenderMessageOnboarding ? ( - <>{this.renderMessageOnboarding()} - ) : ( - <> - - {this.renderList()} - - )} -
- ); - } - - public renderMessageOnboarding() { - return ( -
-
- -
- -
-
-

{window.i18n('welcomeToSession')}

-
- -
- -
- -
-
- {window.i18n('noMessagesTitle')} -
-
- {window.i18n('noMessagesSubtitle')} -
-
- - <> - {this.state.loading ? ( -
- -
- ) : ( -
- - -
- )} - -
+ + {this.renderList()} + {this.renderBottomButtons()}
); } - public handleCloseOnboarding() { - window.setSettingValue('render-message-onboarding', false); - - this.setState({ - shouldRenderMessageOnboarding: false, - }); - } - public updateSearch(searchTerm: string) { const { updateSearchTerm, clearSearch } = this.props; @@ -309,8 +256,10 @@ export class LeftPaneMessageSection extends React.Component { return; } + // reset our pubKeyPasted, we can either have a pasted sessionID or a sessionID got from a search - this.setState({ pubKeyPasted: '' }); + this.setState({ valuePasted: '' }); + if (updateSearchTerm) { updateSearchTerm(searchTerm); @@ -346,41 +295,127 @@ export class LeftPaneMessageSection extends React.Component { } } - private renderClosableOverlay() { + private renderClosableOverlay(overlay: SessionComposeToType) { const { searchTerm, searchResults } = this.props; + const { loading } = this.state; - return ( + const openGroupElement = ( + { + this.handleToggleOverlay(undefined); + }} + onButtonClick={this.handleJoinChannelButtonClick} + searchTerm={searchTerm} + updateSearch={this.updateSearchBound} + showSpinner={loading} + /> + ); + + const closedGroupElement = ( + { + this.handleToggleOverlay(undefined); + }} + onButtonClick={async ( + groupName: string, + groupMembers: Array + ) => this.handleCreateClosedGroupButtonClick(groupName, groupMembers)} + searchTerm={searchTerm} + updateSearch={this.updateSearchBound} + showSpinner={loading} + /> + ); + + const messageElement = ( { + this.handleToggleOverlay(undefined); + }} onButtonClick={this.handleMessageButtonClick} searchTerm={searchTerm} searchResults={searchResults} updateSearch={this.updateSearchBound} /> ); + + let overlayElement; + switch (overlay) { + case SessionComposeToType.OpenGroup: + overlayElement = openGroupElement; + break; + case SessionComposeToType.ClosedGroup: + overlayElement = closedGroupElement; + break; + default: + overlayElement = messageElement; + } + + return overlayElement; } - private handleToggleOverlay() { - this.setState((state: any) => { - return { showComposeView: !state.showComposeView }; - }); - // empty our generalized searchedString (one for the whole app) - this.updateSearch(''); + private renderBottomButtons(): JSX.Element { + const edit = window.i18n('edit'); + const joinOpenGroup = window.i18n('joinOpenGroup'); + const createClosedGroup = window.i18n('createClosedGroup'); + const showEditButton = false; + + return ( +
+ {showEditButton && ( + + )} + + { + this.handleToggleOverlay(SessionComposeToType.OpenGroup); + }} + /> + { + this.handleToggleOverlay(SessionComposeToType.ClosedGroup); + }} + /> +
+ ); } - private handleOnPasteSessionID(value: string) { - // reset our search, we can either have a pasted sessionID or a sessionID got from a search + private handleToggleOverlay(conversationType?: SessionComposeToType) { + const { overlay } = this.state; + + const overlayState = overlay + ? false + : conversationType || false; + + this.setState({ overlay: overlayState}); + + // empty our generalized searchedString (one for the whole app) this.updateSearch(''); + } - this.setState({ pubKeyPasted: value }); + private handleOnPaste(value: string) { + this.setState({ valuePasted: value }); } private handleMessageButtonClick() { const { openConversationInternal } = this.props; - if (!this.state.pubKeyPasted && !this.props.searchTerm) { + if (!this.state.valuePasted && !this.props.searchTerm) { window.pushToast({ title: window.i18n('invalidNumberError'), type: 'error', @@ -390,7 +425,7 @@ export class LeftPaneMessageSection extends React.Component { return; } let pubkey: string; - pubkey = this.state.pubKeyPasted || this.props.searchTerm; + pubkey = this.state.valuePasted || this.props.searchTerm; pubkey = pubkey.trim(); const error = validateNumber(pubkey); @@ -405,8 +440,64 @@ export class LeftPaneMessageSection extends React.Component { } } - private handleJoinPublicChat() { - const serverURL = window.CONSTANTS.DEFAULT_PUBLIC_CHAT_URL; - joinChannelStateManager(this, serverURL, this.handleCloseOnboarding); + + private handleJoinChannelButtonClick(groupUrl: string) { + const { loading } = this.state; + + if (loading) { + return false; + } + + // longest TLD is now (20/02/06) 24 characters per https://jasontucker.blog/8945/what-is-the-longest-tld-you-can-get-for-a-domain-name + const regexURL = /(http:\/\/|https:\/\/)?[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,24}(:[0-9]{1,5})?(\/.*)?/; + + if (groupUrl.length <= 0) { + window.pushToast({ + title: window.i18n('noServerURL'), + type: 'error', + id: 'connectToServerFail', + }); + + return false; + } + + if (!regexURL.test(groupUrl)) { + window.pushToast({ + title: window.i18n('noServerURL'), + type: 'error', + id: 'connectToServerFail', + }); + + return false; + } + + MainViewController.joinChannelStateManager(this, groupUrl, () => { + this.handleToggleOverlay(undefined); + }); + + return true; + } + + private async handleCreateClosedGroupButtonClick ( + groupName: string, + groupMembers: Array + ) { + // console.log('[vince] groupName:', groupName); + // console.log('[vince] groupMembers:', groupMembers); + + await MainViewController.onCreateClosedGroup(groupName, groupMembers, () => { + this.handleToggleOverlay(undefined); + + window.pushToast({ + title: window.i18n('closedGroupCreatedToastTitle'), + type: 'success', + }); + }); + } + + private handleNewSessionButtonClick() { + this.handleToggleOverlay(SessionComposeToType.Message); } + } + diff --git a/ts/components/session/LeftPaneSectionHeader.tsx b/ts/components/session/LeftPaneSectionHeader.tsx index 4c9f1d737..4a01cceb6 100644 --- a/ts/components/session/LeftPaneSectionHeader.tsx +++ b/ts/components/session/LeftPaneSectionHeader.tsx @@ -94,7 +94,7 @@ export class LeftPaneSectionHeader extends React.Component { ) : ( buttonLabel ); - +; const button = ( {buttonContent} @@ -128,7 +128,7 @@ export class LeftPaneSectionHeader extends React.Component { ); } - //Create the parent and add the children + // Create the parent and add the children return
{children}
; } diff --git a/ts/components/session/SessionClosableOverlay.tsx b/ts/components/session/SessionClosableOverlay.tsx index 6a8b34a77..b585bcb04 100644 --- a/ts/components/session/SessionClosableOverlay.tsx +++ b/ts/components/session/SessionClosableOverlay.tsx @@ -11,11 +11,18 @@ import { SessionButtonType, } from './SessionButton'; import { SessionSpinner } from './SessionSpinner'; -import { SessionGroupType } from './LeftPaneChannelSection'; +import { SessionClosableOverlayTypeContact } from './LeftPaneContactSection'; +import { SessionComposeToType } from './LeftPaneMessageSection'; import { PillDivider } from './PillDivider'; +export const SessionClosableOverlayType = { + ...SessionComposeToType, + ...SessionClosableOverlayTypeContact, +}; +export type SessionClosableOverlayType = SessionComposeToType | SessionClosableOverlayTypeContact; + interface Props { - overlayMode: 'message' | 'contact' | SessionGroupType; + overlayMode: SessionClosableOverlayType; onChangeSessionID: any; onCloseClick: any; onButtonClick: any; @@ -97,11 +104,11 @@ export class SessionClosableOverlay extends React.Component { onButtonClick, } = this.props; - const isAddContactView = overlayMode === 'contact'; - const isMessageView = overlayMode === 'message'; + const isAddContactView = overlayMode === SessionClosableOverlayType.Contact; + const isMessageView = overlayMode === SessionClosableOverlayType.Message; - const isOpenGroupView = overlayMode === SessionGroupType.Open; - const isClosedGroupView = overlayMode === SessionGroupType.Closed; + const isOpenGroupView = overlayMode === SessionClosableOverlayType.OpenGroup; + const isClosedGroupView = overlayMode === SessionClosableOverlayType.ClosedGroup; let title; let buttonText; @@ -144,8 +151,10 @@ export class SessionClosableOverlay extends React.Component { const ourSessionID = window.textsecure.storage.user.getNumber(); const contacts = this.getContacts(); + const noContactsForClosedGroup = - overlayMode === SessionGroupType.Closed && contacts.length === 0; + overlayMode === SessionClosableOverlayType.ClosedGroup && contacts.length === 0; + return (
@@ -201,7 +210,7 @@ export class SessionClosableOverlay extends React.Component {
) : (
- {this.renderMemberList()} + {this.renderMemberList(contacts)}
)}
@@ -245,8 +254,10 @@ export class SessionClosableOverlay extends React.Component { ); } - private renderMemberList() { - const members = this.getContacts(); + private renderMemberList(members: any) { + + console.log('[vince] sdsdf:'); + console.log('[vince] members:', members); return members.map((member: ContactType) => ( { } private onGroupNameChanged(event: any) { + + console.log('[vince] event:', event); + this.setState({ groupName: event, }); + } } diff --git a/ts/components/session/SessionIdEditable.tsx b/ts/components/session/SessionIdEditable.tsx index 6fca9f63e..e2d43024c 100644 --- a/ts/components/session/SessionIdEditable.tsx +++ b/ts/components/session/SessionIdEditable.tsx @@ -55,6 +55,7 @@ export class SessionIdEditable extends React.PureComponent { private handleChange(e: any) { const { editable, onChange } = this.props; + if (editable) { onChange(e.target.value); } From 21a95ce587de69f361021a08fefd0e0060bd3571 Mon Sep 17 00:00:00 2001 From: Vincent Date: Wed, 13 May 2020 12:57:46 +1000 Subject: [PATCH 3/6] Closable overlay finished --- ts/components/MainViewController.tsx | 15 +++---- .../session/LeftPaneContactSection.tsx | 7 ++-- .../session/LeftPaneMessageSection.tsx | 36 ++++++++-------- .../session/LeftPaneSectionHeader.tsx | 1 - .../session/SessionClosableOverlay.tsx | 41 ++++++++++--------- 5 files changed, 48 insertions(+), 52 deletions(-) diff --git a/ts/components/MainViewController.tsx b/ts/components/MainViewController.tsx index c43950ebf..fccd0e85a 100644 --- a/ts/components/MainViewController.tsx +++ b/ts/components/MainViewController.tsx @@ -8,7 +8,7 @@ import { export const MainViewController = { joinChannelStateManager, - onCreateClosedGroup, + createClosedGroup, renderMessageView, renderSettingsView, }; @@ -36,7 +36,6 @@ export class MessageView extends React.Component { } } - // ///////////////////////////////////// // //////////// Management ///////////// // ///////////////////////////////////// @@ -106,7 +105,7 @@ function joinChannelStateManager( return true; } -async function onCreateClosedGroup( +async function createClosedGroup( groupName: string, groupMembers: Array, onSuccess: any @@ -172,12 +171,10 @@ function renderSettingsView(category: SessionSettingCategory) { ); if (document.getElementById('main-view')) { ReactDOM.render( - ( - - ), + , document.getElementById('main-view') ); } diff --git a/ts/components/session/LeftPaneContactSection.tsx b/ts/components/session/LeftPaneContactSection.tsx index 84705236d..dd884a8f7 100644 --- a/ts/components/session/LeftPaneContactSection.tsx +++ b/ts/components/session/LeftPaneContactSection.tsx @@ -17,11 +17,12 @@ import { import { AutoSizer, List } from 'react-virtualized'; import { validateNumber } from '../../types/PhoneNumber'; import { ConversationType } from '../../state/ducks/conversations'; -import { SessionClosableOverlay, SessionClosableOverlayType } from './SessionClosableOverlay'; +import { + SessionClosableOverlay, + SessionClosableOverlayType, +} from './SessionClosableOverlay'; import { MainViewController } from '../MainViewController'; -export enum SessionClosableOverlayTypeContact { Contact = 'contact'} - export interface Props { searchTerm: string; isSecondaryDevice: boolean; diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index 0ed6ccf73..954b624c0 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -17,7 +17,10 @@ import { cleanSearchTerm } from '../../util/cleanSearchTerm'; import { SearchOptions } from '../../types/Search'; import { validateNumber } from '../../types/PhoneNumber'; import { LeftPane, RowRendererParamsType } from '../LeftPane'; -import { SessionClosableOverlay } from './SessionClosableOverlay'; +import { + SessionClosableOverlay, + SessionClosableOverlayType, +} from './SessionClosableOverlay'; import { SessionIconType } from './icon'; import { ContactType } from './SessionMemberListItem'; import { @@ -91,14 +94,15 @@ export class LeftPaneMessageSection extends React.Component { this.handleToggleOverlay = this.handleToggleOverlay.bind(this); this.handleMessageButtonClick = this.handleMessageButtonClick.bind(this); - this.handleNewSessionButtonClick = this.handleNewSessionButtonClick.bind(this); + this.handleNewSessionButtonClick = this.handleNewSessionButtonClick.bind( + this + ); this.handleJoinChannelButtonClick = this.handleJoinChannelButtonClick.bind( this ); - this.handleCreateClosedGroupButtonClick = this.handleCreateClosedGroupButtonClick.bind(this); + this.onCreateClosedGroup = this.onCreateClosedGroup.bind(this); this.renderClosableOverlay = this.renderClosableOverlay.bind(this); - this.debouncedSearch = debounce(this.search.bind(this), 20); } @@ -258,8 +262,7 @@ export class LeftPaneMessageSection extends React.Component { } // reset our pubKeyPasted, we can either have a pasted sessionID or a sessionID got from a search - this.setState({ valuePasted: '' }); - + this.setState({ valuePasted: '' }); if (updateSearchTerm) { updateSearchTerm(searchTerm); @@ -301,7 +304,7 @@ export class LeftPaneMessageSection extends React.Component { const openGroupElement = ( { this.handleToggleOverlay(undefined); @@ -315,7 +318,7 @@ export class LeftPaneMessageSection extends React.Component { const closedGroupElement = ( { this.handleToggleOverlay(undefined); @@ -323,7 +326,7 @@ export class LeftPaneMessageSection extends React.Component { onButtonClick={async ( groupName: string, groupMembers: Array - ) => this.handleCreateClosedGroupButtonClick(groupName, groupMembers)} + ) => this.onCreateClosedGroup(groupName, groupMembers)} searchTerm={searchTerm} updateSearch={this.updateSearchBound} showSpinner={loading} @@ -332,7 +335,7 @@ export class LeftPaneMessageSection extends React.Component { const messageElement = ( { this.handleToggleOverlay(undefined); @@ -398,11 +401,9 @@ export class LeftPaneMessageSection extends React.Component { private handleToggleOverlay(conversationType?: SessionComposeToType) { const { overlay } = this.state; - const overlayState = overlay - ? false - : conversationType || false; + const overlayState = overlay ? false : conversationType || false; - this.setState({ overlay: overlayState}); + this.setState({ overlay: overlayState }); // empty our generalized searchedString (one for the whole app) this.updateSearch(''); @@ -440,7 +441,6 @@ export class LeftPaneMessageSection extends React.Component { } } - private handleJoinChannelButtonClick(groupUrl: string) { const { loading } = this.state; @@ -478,14 +478,14 @@ export class LeftPaneMessageSection extends React.Component { return true; } - private async handleCreateClosedGroupButtonClick ( + private async onCreateClosedGroup( groupName: string, groupMembers: Array ) { // console.log('[vince] groupName:', groupName); // console.log('[vince] groupMembers:', groupMembers); - await MainViewController.onCreateClosedGroup(groupName, groupMembers, () => { + await MainViewController.createClosedGroup(groupName, groupMembers, () => { this.handleToggleOverlay(undefined); window.pushToast({ @@ -498,6 +498,4 @@ export class LeftPaneMessageSection extends React.Component { private handleNewSessionButtonClick() { this.handleToggleOverlay(SessionComposeToType.Message); } - } - diff --git a/ts/components/session/LeftPaneSectionHeader.tsx b/ts/components/session/LeftPaneSectionHeader.tsx index 4a01cceb6..c9ed53aeb 100644 --- a/ts/components/session/LeftPaneSectionHeader.tsx +++ b/ts/components/session/LeftPaneSectionHeader.tsx @@ -94,7 +94,6 @@ export class LeftPaneSectionHeader extends React.Component { ) : ( buttonLabel ); -; const button = ( {buttonContent} diff --git a/ts/components/session/SessionClosableOverlay.tsx b/ts/components/session/SessionClosableOverlay.tsx index b585bcb04..d748c72ee 100644 --- a/ts/components/session/SessionClosableOverlay.tsx +++ b/ts/components/session/SessionClosableOverlay.tsx @@ -11,15 +11,14 @@ import { SessionButtonType, } from './SessionButton'; import { SessionSpinner } from './SessionSpinner'; -import { SessionClosableOverlayTypeContact } from './LeftPaneContactSection'; -import { SessionComposeToType } from './LeftPaneMessageSection'; import { PillDivider } from './PillDivider'; -export const SessionClosableOverlayType = { - ...SessionComposeToType, - ...SessionClosableOverlayTypeContact, -}; -export type SessionClosableOverlayType = SessionComposeToType | SessionClosableOverlayTypeContact; +export enum SessionClosableOverlayType { + Contact = 'contact', + Message = 'message', + OpenGroup = 'open-group', + ClosedGroup = 'closed-group', +} interface Props { overlayMode: SessionClosableOverlayType; @@ -50,7 +49,10 @@ export class SessionClosableOverlay extends React.Component { }; this.inputRef = React.createRef(); + this.onKeyUp = this.onKeyUp.bind(this); this.onGroupNameChanged = this.onGroupNameChanged.bind(this); + + window.addEventListener('keyup', this.onKeyUp); } public componentDidMount() { @@ -106,9 +108,10 @@ export class SessionClosableOverlay extends React.Component { const isAddContactView = overlayMode === SessionClosableOverlayType.Contact; const isMessageView = overlayMode === SessionClosableOverlayType.Message; - - const isOpenGroupView = overlayMode === SessionClosableOverlayType.OpenGroup; - const isClosedGroupView = overlayMode === SessionClosableOverlayType.ClosedGroup; + const isOpenGroupView = + overlayMode === SessionClosableOverlayType.OpenGroup; + const isClosedGroupView = + overlayMode === SessionClosableOverlayType.ClosedGroup; let title; let buttonText; @@ -153,8 +156,8 @@ export class SessionClosableOverlay extends React.Component { const contacts = this.getContacts(); const noContactsForClosedGroup = - overlayMode === SessionClosableOverlayType.ClosedGroup && contacts.length === 0; - + overlayMode === SessionClosableOverlayType.ClosedGroup && + contacts.length === 0; return (
@@ -202,7 +205,6 @@ export class SessionClosableOverlay extends React.Component { {isClosedGroupView && ( <>
-
{noContactsForClosedGroup ? (
@@ -255,10 +257,6 @@ export class SessionClosableOverlay extends React.Component { } private renderMemberList(members: any) { - - console.log('[vince] sdsdf:'); - console.log('[vince] members:', members); - return members.map((member: ContactType) => ( { } private onGroupNameChanged(event: any) { - - console.log('[vince] event:', event); - this.setState({ groupName: event, }); + } + private onKeyUp(event: any) { + if (event.key === 'Escape') { + window.removeEventListener('keyup', this.onKeyUp); + this.props.onCloseClick(); + } } } From 9778d8f7935b0770d1f6bacc8a21fd65118ba7dc Mon Sep 17 00:00:00 2001 From: Vincent Date: Wed, 13 May 2020 13:03:56 +1000 Subject: [PATCH 4/6] remove-comments --- ts/components/session/LeftPaneMessageSection.tsx | 3 --- 1 file changed, 3 deletions(-) diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index 954b624c0..cccc3f340 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -482,9 +482,6 @@ export class LeftPaneMessageSection extends React.Component { groupName: string, groupMembers: Array ) { - // console.log('[vince] groupName:', groupName); - // console.log('[vince] groupMembers:', groupMembers); - await MainViewController.createClosedGroup(groupName, groupMembers, () => { this.handleToggleOverlay(undefined); From 3cb38de29cd7b04fd7de4d2e8d0c7e18816168cd Mon Sep 17 00:00:00 2001 From: Vincent Date: Wed, 13 May 2020 15:26:41 +1000 Subject: [PATCH 5/6] renderRow filter --- ts/components/session/LeftPaneContactSection.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ts/components/session/LeftPaneContactSection.tsx b/ts/components/session/LeftPaneContactSection.tsx index dd884a8f7..7081c2d4d 100644 --- a/ts/components/session/LeftPaneContactSection.tsx +++ b/ts/components/session/LeftPaneContactSection.tsx @@ -144,7 +144,8 @@ export class LeftPaneContactSection extends React.Component { style, }: RowRendererParamsType): JSX.Element | undefined => { const { sentFriendsRequest } = this.props; - const friends = window.getFriendsFromContacts(this.props.friends); + const contacts = this.props.friends.filter(f => f.type === 'direct'); + const friends = window.getFriendsFromContacts(contacts); const combined = [...sentFriendsRequest, ...friends]; const item = combined[index]; From de2654b914b99cfe9bc6e38deb66c2415db27581 Mon Sep 17 00:00:00 2001 From: Vincent Date: Thu, 28 May 2020 16:51:12 +1000 Subject: [PATCH 6/6] rm multi1 from scripts --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index d89caa1ba..ea074269f 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,6 @@ "start-multi2": "cross-env NODE_APP_INSTANCE=2 electron .", "start-prod": "cross-env NODE_ENV=production NODE_APP_INSTANCE=devprod electron .", "start-prod-multi": "cross-env NODE_ENV=production NODE_APP_INSTANCE=devprod1 electron .", - "start-prod-multi1": "cross-env NODE_ENV=production NODE_APP_INSTANCE=devprod2 electron .", "start-swarm-test": "cross-env NODE_ENV=swarm-testing NODE_APP_INSTANCE=1 electron .", "start-swarm-test-2": "cross-env NODE_ENV=swarm-testing NODE_APP_INSTANCE=2 electron .", "grunt": "grunt",