From 85219d3827be722223f8c109dd08f38e731cefe0 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 24 Aug 2022 13:33:02 +1000 Subject: [PATCH 01/12] fix: scrollbar colors and some UI issues found by QA --- stylesheets/_global.scss | 8 ++++---- stylesheets/_session_left_pane.scss | 1 + ts/components/MemberListItem.tsx | 4 ++++ ts/components/basic/Text.tsx | 19 ++++++++++--------- ts/components/basic/YourSessionIDPill.tsx | 9 ++++----- .../leftpane/overlay/OverlayClosedGroup.tsx | 2 +- .../leftpane/overlay/OverlayMessage.tsx | 3 ++- .../overlay/choose-action/ContactRow.tsx | 2 +- .../choose-action/ContactsListWithBreaks.tsx | 2 +- ts/state/ducks/SessionTheme.tsx | 9 ++------- 10 files changed, 30 insertions(+), 29 deletions(-) diff --git a/stylesheets/_global.scss b/stylesheets/_global.scss index 6e39e09cc..9cb556664 100644 --- a/stylesheets/_global.scss +++ b/stylesheets/_global.scss @@ -19,20 +19,20 @@ body { // scrollbars ::-webkit-scrollbar { - width: 9px; - height: 9px; + width: 6px; + height: 6px; } ::-webkit-scrollbar-thumb { background: var(--color-scroll-bar-thumb); - border: solid 2px var(--color-text-opposite); + border-radius: 20px; &:hover { background: $color-light-45; } } ::-webkit-scrollbar-track { - background: var(--color-scroll-bar-track); + background: none; } audio { diff --git a/stylesheets/_session_left_pane.scss b/stylesheets/_session_left_pane.scss index 652e74d23..8eaa0cb36 100644 --- a/stylesheets/_session_left_pane.scss +++ b/stylesheets/_session_left_pane.scss @@ -89,6 +89,7 @@ $session-compose-margin: 20px; height: $main-view-header-height; padding-inline-end: 7px; transition: $session-transition-duration; + margin-bottom: var(--margins-md); .session-button { margin-inline-start: auto; diff --git a/ts/components/MemberListItem.tsx b/ts/components/MemberListItem.tsx index 46a5bf949..bf54d7eab 100644 --- a/ts/components/MemberListItem.tsx +++ b/ts/components/MemberListItem.tsx @@ -45,12 +45,16 @@ const StyledSessionMemberItem = styled.div<{ const StyledInfo = styled.div` display: flex; align-items: center; + min-width: 0; `; const StyledName = styled.span` font-weight: bold; margin-inline-start: var(--margins-md); margin-inline-end: var(--margins-md); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; `; const StyledCheckContainer = styled.div` diff --git a/ts/components/basic/Text.tsx b/ts/components/basic/Text.tsx index c7a4d9634..3dafd86cf 100644 --- a/ts/components/basic/Text.tsx +++ b/ts/components/basic/Text.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import styled from 'styled-components'; +import styled, { CSSProperties } from 'styled-components'; type TextProps = { text: string; @@ -28,6 +28,7 @@ export const Text = (props: TextProps) => { type SpacerProps = { size: 'lg' | 'md' | 'sm' | 'xs'; + style?: CSSProperties; }; const SpacerStyled = styled.div` @@ -54,19 +55,19 @@ const Spacer = (props: SpacerProps) => { return ; }; -export const SpacerLG = () => { - return ; +export const SpacerLG = (props: { style?: CSSProperties }) => { + return ; }; -export const SpacerMD = () => { - return ; +export const SpacerMD = (props: { style?: CSSProperties }) => { + return ; }; -export const SpacerSM = () => { - return ; +export const SpacerSM = (props: { style?: CSSProperties }) => { + return ; }; -export const SpacerXS = () => { - return ; +export const SpacerXS = (props: { style?: CSSProperties }) => { + return ; }; type H3Props = { diff --git a/ts/components/basic/YourSessionIDPill.tsx b/ts/components/basic/YourSessionIDPill.tsx index e5013a711..e1677f3b5 100644 --- a/ts/components/basic/YourSessionIDPill.tsx +++ b/ts/components/basic/YourSessionIDPill.tsx @@ -35,23 +35,22 @@ export const YourSessionIDPill = () => { }; const StyledYourSessionIDSelectable = styled.p` - user-select: text; + user-select: none; text-align: center; word-break: break-all; - padding: 0px var(--margins-lg); font-weight: 100; color: var(--color-text); - font-size: var(--font-size-sm); - padding: 0px var(--margins-md); `; export const YourSessionIDSelectable = () => { const ourSessionID = UserUtils.getOurPubKeyStrFromCache(); return ( - {ourSessionID} + {ourSessionID.slice(0, 33)} +
+ {ourSessionID.slice(33)}
); }; diff --git a/ts/components/leftpane/overlay/OverlayClosedGroup.tsx b/ts/components/leftpane/overlay/OverlayClosedGroup.tsx index 8936baf30..c07acfd3d 100644 --- a/ts/components/leftpane/overlay/OverlayClosedGroup.tsx +++ b/ts/components/leftpane/overlay/OverlayClosedGroup.tsx @@ -144,7 +144,7 @@ export const OverlayClosedGroup = () => { )} - + { container={true} justifyContent="space-between" alignItems="center" - padding="0 15px 0 0 " // YourSessionIDSelectable already has a left margin of 15px + width="100%" + padding="0 var(--margins-md) " // YourSessionIDSelectable already has a left margin of 15px > diff --git a/ts/components/leftpane/overlay/choose-action/ContactRow.tsx b/ts/components/leftpane/overlay/choose-action/ContactRow.tsx index a1883bc7e..853d235c1 100644 --- a/ts/components/leftpane/overlay/choose-action/ContactRow.tsx +++ b/ts/components/leftpane/overlay/choose-action/ContactRow.tsx @@ -64,7 +64,7 @@ const StyledBreak = styled.div` padding: 0 var(--margins-lg); color: var(--color-text-subtle); font-size: var(--font-size-md); - height: 25px; // should also be changed in rowHeight + height: 30px; // should also be changed in rowHeight border-bottom: 1px var(--color-session-border) solid; `; diff --git a/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx b/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx index ea3aa6eb1..1f8969cd0 100644 --- a/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx +++ b/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx @@ -93,7 +93,7 @@ const ContactListItemSection = () => { rowCount={length} rowHeight={ (params: Index) => - isString(directContactsByNameWithBreaks[params.index]) ? 25 : 64 // should also be changed in `ContactRowBreak` + isString(directContactsByNameWithBreaks[params.index]) ? 30 : 64 // should also be changed in `ContactRowBreak` } directContactsByNameWithBreaks={directContactsByNameWithBreaks} rowRenderer={renderRow} diff --git a/ts/state/ducks/SessionTheme.tsx b/ts/state/ducks/SessionTheme.tsx index 3abe5241c..0de913d81 100644 --- a/ts/state/ducks/SessionTheme.tsx +++ b/ts/state/ducks/SessionTheme.tsx @@ -41,8 +41,7 @@ const darkInputBackground = darkColorCellBackground; const darkFilterSessionText = 'none'; const darkUnreadBorder = `4px solid ${accentDarkTheme}`; -const darkScrollbarThumb = '#474646'; -const darkScrollbarTrack = '#1b1b1b'; +const darkScrollbarThumb = '#767676'; const darkFakeChatBubbleBg = '#212121'; const darkInboxBackground = '#171717'; @@ -116,7 +115,6 @@ export const switchHtmlToDarkTheme = () => { document.documentElement.style.setProperty('--border-unread', darkUnreadBorder); document.documentElement.style.setProperty('--color-scroll-bar-thumb', darkScrollbarThumb); - document.documentElement.style.setProperty('--color-scroll-bar-track', darkScrollbarTrack); document.documentElement.style.setProperty( '--color-fake-chat-bubble-background', darkFakeChatBubbleBg @@ -188,8 +186,7 @@ const lightInputBackground = '#efefef'; const lightFilterSessionText = 'brightness(0) saturate(100%)'; const lightUnreadBorder = `4px solid ${accentLightTheme}`; -const lightScrollbarThumb = '#474646'; -const lightScrollbarTrack = '#fcfcfc'; +const lightScrollbarThumb = '#6D6D6D'; const lightFakeChatBubbleBg = '#f5f5f5'; const lightInboxBackground = white; @@ -269,7 +266,6 @@ export const switchHtmlToLightTheme = () => { document.documentElement.style.setProperty('--border-unread', lightUnreadBorder); document.documentElement.style.setProperty('--color-scroll-bar-thumb', lightScrollbarThumb); - document.documentElement.style.setProperty('--color-scroll-bar-track', lightScrollbarTrack); document.documentElement.style.setProperty( '--color-fake-chat-bubble-background', lightFakeChatBubbleBg @@ -374,7 +370,6 @@ export const SessionGlobalStyles = createGlobalStyle` --color-pill-divider-text: ${lightColorPillDividerText}; --color-input-background: ${lightInputBackground}; --color-scroll-bar-thumb: ${lightScrollbarThumb}; - --color-scroll-bar-track: ${lightScrollbarTrack}; --color-fake-chat-bubble-background: ${lightFakeChatBubbleBg}; --color-inbox-background: ${lightInboxBackground}; --color-left-pane-overlay-background: ${lightLeftPaneOverlayBg}; From 997cedc42bf04a24c7d54fd57981d579d58a62c9 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 25 Aug 2022 14:44:04 +1000 Subject: [PATCH 02/12] fix: signin screen design colors --- stylesheets/_session_signin.scss | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stylesheets/_session_signin.scss b/stylesheets/_session_signin.scss index 8343f2f4b..957d199d5 100644 --- a/stylesheets/_session_signin.scss +++ b/stylesheets/_session_signin.scss @@ -162,7 +162,7 @@ font-weight: bold; text-decoration: none; - color: var(--color-text-subtle); + color: rgba(var(--color-text), 0.6); transition: $session-transition-duration; &:visited &:link { @@ -175,11 +175,11 @@ } } - session-description-long { + &-description-long { padding-top: 0; padding-bottom: 20px; - color: var(--color-text-subtle); + color: rgba(var(--color-text), 0.6); text-align: center; font-size: 12px; line-height: 20px; From c54a438f7c06d7f611bad2d8f788d9f592d1d851 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 25 Aug 2022 15:50:28 +1000 Subject: [PATCH 03/12] fix: add some aria labels and match QA test --- _locales/en/messages.json | 6 +++++- stylesheets/_session.scss | 2 +- ts/components/MemberListItem.tsx | 6 ++++-- ts/components/button/MenuButton.tsx | 11 +++-------- .../leftpane/overlay/OverlayClosedGroup.tsx | 7 +++++-- .../leftpane/overlay/OverlayCommunity.tsx | 15 +++++++-------- .../leftpane/overlay/OverlayMessage.tsx | 5 ++++- .../overlay/choose-action/ContactRow.tsx | 2 +- .../choose-action/OverlayChooseAction.tsx | 18 +++++++++++++++--- ts/session/constants.ts | 2 +- ts/types/LocalizerKeys.ts | 13 ++++++++----- 11 files changed, 54 insertions(+), 33 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index ed182279d..66698ad49 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -152,6 +152,10 @@ "noNameOrMessage": "No name or content", "nameOnly": "Name Only", "newMessage": "New Message", + "createConversationNewContact": "Create a conversation with a new contact", + "createConversationNewGroup": "Create a group with existing contacts", + "joinACommunity": "Join a community", + "chooseAnAction": "Choose an action to start a conversation", "newMessages": "New Messages", "notificationMostRecentFrom": "Most recent from: $name$", "notificationFrom": "From:", @@ -283,7 +287,7 @@ "changePasswordToastDescription": "Your password has been changed. Please keep it safe.", "removePasswordToastDescription": "You have removed your password.", "publicChatExists": "You are already connected to this community", - "connectToServerFail": "Couldn't join group", + "connectToServerFail": "Couldn't join community", "connectingToServer": "Connecting...", "connectToServerSuccess": "Successfully connected to community", "setPasswordFail": "Failed to set password", diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index f5be5ca56..29131282f 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -96,7 +96,7 @@ textarea { background-color: rgba(0, 0, 0, 0); &.disabled { - cursor: default; + cursor: not-allowed; } &.default, diff --git a/ts/components/MemberListItem.tsx b/ts/components/MemberListItem.tsx index bf54d7eab..8470224b1 100644 --- a/ts/components/MemberListItem.tsx +++ b/ts/components/MemberListItem.tsx @@ -18,7 +18,7 @@ const AvatarItem = (props: { memberPubkey: string; isAdmin: boolean }) => { ); }; -const StyledSessionMemberItem = styled.div<{ +const StyledSessionMemberItem = styled.button<{ inMentions?: boolean; zombie?: boolean; selected?: boolean; @@ -29,6 +29,9 @@ const StyledSessionMemberItem = styled.div<{ padding: 0px var(--margins-sm); height: ${props => (props.inMentions ? '40px' : '50px')}; display: flex; + + align-items: center; + justify-content: space-between; transition: var(--default-duration); @@ -99,7 +102,6 @@ export const MemberListItem = (props: { } : {} } - role="button" data-testid={dataTestId} zombie={isZombie} inMentions={inMentions} diff --git a/ts/components/button/MenuButton.tsx b/ts/components/button/MenuButton.tsx index 889c966ca..c1626f30a 100644 --- a/ts/components/button/MenuButton.tsx +++ b/ts/components/button/MenuButton.tsx @@ -6,7 +6,7 @@ import { getOverlayMode } from '../../state/selectors/section'; import { SessionIcon } from '../icon'; // tslint:disable: use-simple-attributes -const StyledMenuButton = styled.label` +const StyledMenuButton = styled.button` position: relative; display: inline-block; @@ -25,12 +25,6 @@ const StyledMenuButton = styled.label` } `; -const StyledMenuInput = styled.input` - opacity: 0; - width: 0; - height: 0; -`; - /** * This is the Session Menu Botton. i.e. the button on top of the conversation list to start a new conversation. * It has two state: selected or not and so we use an checkbox input to keep the state in sync. @@ -54,13 +48,14 @@ export const MenuButton = () => { '--fg-color': 'white', } as CSSProperties } + onClick={onClickFn} > - ); diff --git a/ts/components/leftpane/overlay/OverlayClosedGroup.tsx b/ts/components/leftpane/overlay/OverlayClosedGroup.tsx index c07acfd3d..ffd0eb72e 100644 --- a/ts/components/leftpane/overlay/OverlayClosedGroup.tsx +++ b/ts/components/leftpane/overlay/OverlayClosedGroup.tsx @@ -17,6 +17,7 @@ import useKey from 'react-use/lib/useKey'; import styled from 'styled-components'; import { SessionSearchInput } from '../../SessionSearchInput'; import { getSearchResults, isSearching } from '../../../state/selectors/search'; +import { VALIDATION } from '../../../session/constants'; const StyledMemberListNoContacts = styled.div` font-family: var(--font-font-mono); @@ -101,6 +102,8 @@ export const OverlayClosedGroup = () => { } const contactsToRender = isSearch ? sharedWithResults : privateContactsPubkeys; + const disableCreateButton = !selectedMemberIds.length && !groupName.length; + return (
@@ -110,7 +113,7 @@ export const OverlayClosedGroup = () => { placeholder={placeholder} value={groupName} isGroup={true} - maxLength={100} + maxLength={VALIDATION.MAX_GROUP_NAME_LENGTH} onChange={setGroupName} onPressEnter={onEnterPressed} dataTestId="new-closed-group-name" @@ -150,7 +153,7 @@ export const OverlayClosedGroup = () => { buttonColor={SessionButtonColor.Green} buttonType={SessionButtonType.BrandOutline} text={buttonText} - disabled={noContactsForClosedGroup} + disabled={disableCreateButton} onClick={onEnterPressed} dataTestId="next-button" margin="auto 0 var(--margins-lg) 0 " // just to keep that button at the bottom of the overlay (even with an empty list) diff --git a/ts/components/leftpane/overlay/OverlayCommunity.tsx b/ts/components/leftpane/overlay/OverlayCommunity.tsx index 8fac9962f..666dac439 100644 --- a/ts/components/leftpane/overlay/OverlayCommunity.tsx +++ b/ts/components/leftpane/overlay/OverlayCommunity.tsx @@ -78,14 +78,13 @@ export const OverlayCommunity = () => { - {groupUrl && ( - - )} +
); }; diff --git a/ts/components/leftpane/overlay/OverlayMessage.tsx b/ts/components/leftpane/overlay/OverlayMessage.tsx index a19836c37..781ec820b 100644 --- a/ts/components/leftpane/overlay/OverlayMessage.tsx +++ b/ts/components/leftpane/overlay/OverlayMessage.tsx @@ -45,6 +45,8 @@ export const OverlayMessage = () => { const subtitle = window.i18n('enterSessionIDOrONSName'); const placeholder = window.i18n('enterSessionIDOfRecipient'); + const disableNextButton = !pubkeyOrOns || loading; + async function openConvoOnceResolved(resolvedSessionID: string) { const convo = await getConversationController().getOrCreateAndWait( resolvedSessionID, @@ -105,6 +107,7 @@ export const OverlayMessage = () => { placeholder={placeholder} onChange={setPubkeyOrOns} dataTestId="new-session-conversation" + onPressEnter={handleMessageButtonClick} /> @@ -128,7 +131,7 @@ export const OverlayMessage = () => { buttonColor={SessionButtonColor.Green} buttonType={SessionButtonType.BrandOutline} text={buttonText} - disabled={false} + disabled={disableNextButton} onClick={handleMessageButtonClick} dataTestId="next-new-conversation-button" /> diff --git a/ts/components/leftpane/overlay/choose-action/ContactRow.tsx b/ts/components/leftpane/overlay/choose-action/ContactRow.tsx index 853d235c1..06ae33b37 100644 --- a/ts/components/leftpane/overlay/choose-action/ContactRow.tsx +++ b/ts/components/leftpane/overlay/choose-action/ContactRow.tsx @@ -41,7 +41,7 @@ const StyledContactRowName = styled.div` font-size: var(--font-size-lg); `; -const StyledRowContainer = styled.div` +const StyledRowContainer = styled.button` display: flex; align-items: center; padding: 0 var(--margins-lg); diff --git a/ts/components/leftpane/overlay/choose-action/OverlayChooseAction.tsx b/ts/components/leftpane/overlay/choose-action/OverlayChooseAction.tsx index d662f5a78..4b1571e67 100644 --- a/ts/components/leftpane/overlay/choose-action/OverlayChooseAction.tsx +++ b/ts/components/leftpane/overlay/choose-action/OverlayChooseAction.tsx @@ -66,15 +66,27 @@ export const OverlayChooseAction = () => { return (
- + {window.i18n('newMessage')} - + {window.i18n('createGroup')} - + {window.i18n('joinOpenGroup')} diff --git a/ts/session/constants.ts b/ts/session/constants.ts index 44d64a627..9517c6a29 100644 --- a/ts/session/constants.ts +++ b/ts/session/constants.ts @@ -45,7 +45,7 @@ export const CONVERSATION = { export const MAX_ATTACHMENT_FILESIZE_BYTES = 6 * 1000 * 1000; // 6MB export const VALIDATION = { - MAX_GROUP_NAME_LENGTH: 64, + MAX_GROUP_NAME_LENGTH: 30, CLOSED_GROUP_SIZE_LIMIT: 100, }; diff --git a/ts/types/LocalizerKeys.ts b/ts/types/LocalizerKeys.ts index 7d504ef7c..0c9a2889b 100644 --- a/ts/types/LocalizerKeys.ts +++ b/ts/types/LocalizerKeys.ts @@ -62,12 +62,14 @@ export type LocalizerKeys = | 'timerOption_1_hour' | 'youGotKickedFromGroup' | 'cannotRemoveCreatorFromGroupDesc' + | 'contactAvatarAlt' | 'incomingError' | 'notificationsSettingsTitle' | 'ringing' | 'tookAScreenshot' | 'from' | 'thisMonth' + | 'chooseAnAction' | 'next' | 'addModerators' | 'sessionMessenger' @@ -79,6 +81,7 @@ export type LocalizerKeys = | 'openMessageRequestInbox' | 'enterPassword' | 'enterSessionIDOfRecipient' + | 'join' | 'dialogClearAllDataDeletionFailedMultiple' | 'clearAllReactions' | 'pinConversationLimitToastDescription' @@ -166,6 +169,7 @@ export type LocalizerKeys = | 'copyOpenGroupURL' | 'setPasswordInvalid' | 'timerOption_30_seconds_abbreviated' + | 'createConversationNewContact' | 'removeResidueMembers' | 'areYouSureDeleteEntireAccount' | 'noGivenPassword' @@ -194,6 +198,7 @@ export type LocalizerKeys = | 'incomingCallFrom' | 'timerSetOnSync' | 'deleteMessages' + | 'searchForContactsOnly' | 'spellCheckTitle' | 'translation' | 'editMenuSelectAll' @@ -236,7 +241,6 @@ export type LocalizerKeys = | 'invalidSessionId' | 'audioPermissionNeeded' | 'createGroup' - | 'create' | 'add' | 'messageRequests' | 'show' @@ -255,6 +259,7 @@ export type LocalizerKeys = | 'hideMenuBarTitle' | 'imageCaptionIconAlt' | 'sendRecoveryPhraseTitle' + | 'joinACommunity' | 'multipleJoinedTheGroup' | 'messageRequestAcceptedOursNoName' | 'databaseError' @@ -291,6 +296,7 @@ export type LocalizerKeys = | 'cancel' | 'decline' | 'originalMessageNotFound' + | 'create' | 'autoUpdateRestartButtonLabel' | 'deleteConversationConfirmation' | 'timerOption_6_hours_abbreviated' @@ -313,7 +319,7 @@ export type LocalizerKeys = | 'error' | 'clearAllData' | 'pruningOpengroupDialogTitle' - | 'contactAvatarAlt' + | 'createConversationNewGroup' | 'disappearingMessages' | 'autoUpdateNewVersionTitle' | 'linkPreviewDescription' @@ -371,7 +377,6 @@ export type LocalizerKeys = | 'audioMessageAutoplayTitle' | 'removePasswordInvalid' | 'password' - | 'usersCanShareTheir...' | 'nicknamePlaceholder' | 'linkPreviewsTitle' | 'continue' @@ -399,7 +404,6 @@ export type LocalizerKeys = | 'closedGroupMaxSize' | 'messagesHeader' | 'joinOpenGroup' - | 'join' | 'callMediaPermissionsDialogContent' | 'timerOption_1_day_abbreviated' | 'about' @@ -457,7 +461,6 @@ export type LocalizerKeys = | 'trustThisContactDialogDescription' | 'unknownCountry' | 'searchFor...' - | 'searchForContactsOnly' | 'joinedTheGroup' | 'editGroupName' | 'reportIssue'; From 444282e2eca80c38c758926170568dafad5cdf48 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Mon, 29 Aug 2022 16:28:37 +1000 Subject: [PATCH 04/12] fix: position of join button and style of disable buttons also add a little animation to the menu button rotation --- _locales/en/messages.json | 4 ++-- stylesheets/_session.scss | 16 ++-------------- ts/components/button/MenuButton.tsx | 2 ++ ts/components/icon/SessionIcon.tsx | 1 + .../leftpane/overlay/OverlayCommunity.tsx | 6 +++--- 5 files changed, 10 insertions(+), 19 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 66698ad49..05faf8aac 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -355,7 +355,7 @@ "invalidGroupNameTooShort": "Please enter a group name", "invalidGroupNameTooLong": "Please enter a shorter group name", "pickClosedGroupMember": "Please pick at least 1 group member", - "closedGroupMaxSize": "A closed group cannot have more than 100 members", + "closedGroupMaxSize": "A group cannot have more than 100 members", "noBlockedContacts": "No blocked contacts", "userAddedToModerators": "User added to moderator list", "userRemovedFromModerators": "User removed from moderator list", @@ -369,7 +369,7 @@ "closedGroupInviteOkText": "Retry invitations", "closedGroupInviteSuccessTitlePlural": "Group Invitations Completed", "closedGroupInviteSuccessTitle": "Group Invitation Succeeded", - "closedGroupInviteSuccessMessage": "Successfully invited closed group members", + "closedGroupInviteSuccessMessage": "Successfully invited group members", "notificationForConvo": "Notifications", "notificationForConvo_all": "All", "notificationForConvo_disabled": "Disabled", diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index 29131282f..261ab006b 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -108,18 +108,6 @@ textarea { background: var(--color-clickable-hovered); } - &.green, - &.white, - &.primary, - &.secondary, - &.success, - &.danger, - &.warning { - &.disabled { - filter: brightness(60%); - } - } - &.green { background-color: var(--color-accent-button); color: var(--color-text-opposite); @@ -183,10 +171,10 @@ textarea { &.white, &.green { &.disabled { - filter: brightness(60%); + @include transparent-background(var(--color-text-subtle)); &:hover { - filter: brightness(60%); + @include transparent-background(var(--color-text-subtle)); } } } diff --git a/ts/components/button/MenuButton.tsx b/ts/components/button/MenuButton.tsx index c1626f30a..66762fd1e 100644 --- a/ts/components/button/MenuButton.tsx +++ b/ts/components/button/MenuButton.tsx @@ -20,6 +20,8 @@ const StyledMenuButton = styled.button` height: 33px; cursor: pointer; + transition: var(--default-duration); + :hover { background: var(--hover-bg-color); } diff --git a/ts/components/icon/SessionIcon.tsx b/ts/components/icon/SessionIcon.tsx index bbebe5ab5..bb52ac0fd 100644 --- a/ts/components/icon/SessionIcon.tsx +++ b/ts/components/icon/SessionIcon.tsx @@ -131,6 +131,7 @@ const Svg = React.memo(styled.svg` border-radius: ${props => (props.borderRadius ? props.borderRadius : '')}; filter: ${props => (props.noScale ? `drop-shadow(0px 0px 4px ${props.iconColor})` : '')}; padding: ${props => (props.iconPadding ? props.iconPadding : '')}; + transition: inherit; `); //tslint:enable no-unnecessary-callback-wrapper diff --git a/ts/components/leftpane/overlay/OverlayCommunity.tsx b/ts/components/leftpane/overlay/OverlayCommunity.tsx index 666dac439..0a0f68cc8 100644 --- a/ts/components/leftpane/overlay/OverlayCommunity.tsx +++ b/ts/components/leftpane/overlay/OverlayCommunity.tsx @@ -52,7 +52,6 @@ export const OverlayCommunity = () => { } } - // FIXME autofocus inputref on mount useKey('Escape', closeOverlay); const title = window.i18n('joinOpenGroup'); @@ -76,8 +75,6 @@ export const OverlayCommunity = () => { />
- - { disabled={!groupUrl} onClick={onEnterPressed} /> + + + ); }; From b9cccfc2a8418355c85982bb7a205cd29c656643 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 30 Aug 2022 13:23:38 +1000 Subject: [PATCH 05/12] feat: open convo a session sogs when joined from the UI --- stylesheets/_session.scss | 2 + ts/components/MemberListItem.tsx | 1 + ts/components/basic/PillContainer.tsx | 22 ++--- .../message/reactions/Reaction.tsx | 1 + .../leftpane/overlay/OverlayCommunity.tsx | 25 ++++- .../overlay/SessionJoinableDefaultRooms.tsx | 95 +++++++++++-------- .../choose-action/ContactsListWithBreaks.tsx | 4 +- .../open_group_api/opengroupV2/ApiUtil.ts | 2 +- .../opengroupV2/JoinOpenGroupV2.ts | 35 +++++-- .../opengroupV2/OpenGroupServerPoller.ts | 11 ++- ts/session/utils/GlobalEvents.ts | 3 + ts/window.d.ts | 4 - 12 files changed, 133 insertions(+), 72 deletions(-) create mode 100644 ts/session/utils/GlobalEvents.ts diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index 261ab006b..63c29f78d 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -999,6 +999,8 @@ input { } .contact-selection-list { + display: flex; + flex-direction: column; width: 20vw; } diff --git a/ts/components/MemberListItem.tsx b/ts/components/MemberListItem.tsx index 8470224b1..333a23370 100644 --- a/ts/components/MemberListItem.tsx +++ b/ts/components/MemberListItem.tsx @@ -25,6 +25,7 @@ const StyledSessionMemberItem = styled.button<{ }>` cursor: pointer; flex-shrink: 0; + flex-grow: 1; font-family: var(--font-default); padding: 0px var(--margins-sm); height: ${props => (props.inMentions ? '40px' : '50px')}; diff --git a/ts/components/basic/PillContainer.tsx b/ts/components/basic/PillContainer.tsx index acb2e908a..aa32465d0 100644 --- a/ts/components/basic/PillContainer.tsx +++ b/ts/components/basic/PillContainer.tsx @@ -6,11 +6,10 @@ type PillContainerProps = { margin?: string; padding?: string; onClick?: () => void; - onMouseEnter?: () => void; - onMouseLeave?: () => void; + disableHover?: boolean; }; -const StyledPillContainerHoverable = styled.div` +export const StyledPillContainerHoverable = styled.div` background: none; position: relative; @@ -26,7 +25,6 @@ const StyledPillContainerHoverable = styled.div` `; const StyledPillInner = styled.div` - background: green; background: none; display: flex; @@ -42,18 +40,18 @@ const StyledPillInner = styled.div` padding: ${props => props.padding || ''}; margin: ${props => props.margin || ''}; border-radius: 300px; - cursor: pointer; + cursor: ${props => (props.disableHover ? 'unset' : 'pointer')}; border: 1px solid var(--color-pill-divider); transition: var(--default-duration); &:hover { - background: var(--color-clickable-hovered); + background: ${props => (props.disableHover ? 'none' : 'var(--color-clickable-hovered)')}; } `; -export const PillTooltipWrapper = (props: PillContainerProps) => { - return {props.children}; -}; - -export const PillContainerHoverable = (props: PillContainerProps) => { - return {props.children}; +export const PillContainerHoverable = (props: Omit) => { + return ( + + {props.children} + + ); }; diff --git a/ts/components/conversation/message/reactions/Reaction.tsx b/ts/components/conversation/message/reactions/Reaction.tsx index d0d6af1a7..9f2e1c38c 100644 --- a/ts/components/conversation/message/reactions/Reaction.tsx +++ b/ts/components/conversation/message/reactions/Reaction.tsx @@ -52,6 +52,7 @@ export type ReactionProps = { handlePopupReaction?: (emoji: string) => void; handlePopupClick?: () => void; }; +// tslint:disable-next-line: use-simple-attributes export const Reaction = (props: ReactionProps): ReactElement => { const { diff --git a/ts/components/leftpane/overlay/OverlayCommunity.tsx b/ts/components/leftpane/overlay/OverlayCommunity.tsx index 0a0f68cc8..527618515 100644 --- a/ts/components/leftpane/overlay/OverlayCommunity.tsx +++ b/ts/components/leftpane/overlay/OverlayCommunity.tsx @@ -7,12 +7,17 @@ import { SessionButton, SessionButtonColor, SessionButtonType } from '../../basi import { SessionIdEditable } from '../../basic/SessionIdEditable'; import { SessionSpinner } from '../../basic/SessionSpinner'; import { OverlayHeader } from './OverlayHeader'; -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; import { resetOverlayMode } from '../../../state/ducks/section'; -import { joinOpenGroupV2WithUIEvents } from '../../../session/apis/open_group_api/opengroupV2/JoinOpenGroupV2'; +import { + joinOpenGroupV2WithUIEvents, + JoinSogsRoomUICallbackArgs, +} from '../../../session/apis/open_group_api/opengroupV2/JoinOpenGroupV2'; import { openGroupV2CompleteURLRegex } from '../../../session/apis/open_group_api/utils/OpenGroupUtils'; import { ToastUtils } from '../../../session/utils'; import useKey from 'react-use/lib/useKey'; +import { getOverlayMode } from '../../../state/selectors/section'; +import { openConversationWithMessages } from '../../../state/ducks/conversations'; async function joinOpenGroup(serverUrl: string) { // guess if this is an open @@ -31,6 +36,8 @@ export const OverlayCommunity = () => { const [loading, setLoading] = useState(false); const [groupUrl, setGroupUrl] = useState(''); + const overlayModeIsCommunity = useSelector(getOverlayMode) === 'open-group'; + function closeOverlay() { dispatch(resetOverlayMode()); } @@ -52,6 +59,15 @@ export const OverlayCommunity = () => { } } + function onJoinSessionSogsRoom(args: JoinSogsRoomUICallbackArgs) { + setLoading(args.loadingState === 'started'); + + if (args.loadingState === 'finished' && overlayModeIsCommunity && args.conversationKey) { + closeOverlay(); + void openConversationWithMessages({ conversationKey: args.conversationKey, messageId: null }); // open to last unread for a session run sogs + } + } + useKey('Escape', closeOverlay); const title = window.i18n('joinOpenGroup'); @@ -84,7 +100,10 @@ export const OverlayCommunity = () => { /> - + ); }; diff --git a/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx b/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx index 9b757d141..e0ad0a916 100644 --- a/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx +++ b/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx @@ -1,9 +1,10 @@ -import React, { useCallback, useEffect } from 'react'; +import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import styled from 'styled-components'; import { joinOpenGroupV2WithUIEvents, + JoinSogsRoomUICallbackArgs, parseOpenGroupV2, } from '../../../session/apis/open_group_api/opengroupV2/JoinOpenGroupV2'; import { sogsV3FetchPreviewBase64 } from '../../../session/apis/open_group_api/sogsv3/sogsV3FetchFile'; @@ -11,7 +12,7 @@ import { updateDefaultBase64RoomData } from '../../../state/ducks/defaultRooms'; import { StateType } from '../../../state/reducer'; import { Avatar, AvatarSize } from '../../avatar/Avatar'; import { Flex } from '../../basic/Flex'; -import { PillContainerHoverable, PillTooltipWrapper } from '../../basic/PillContainer'; +import { PillContainerHoverable, StyledPillContainerHoverable } from '../../basic/PillContainer'; import { SessionSpinner } from '../../basic/SessionSpinner'; import { H3 } from '../../basic/Text'; // tslint:disable: no-void-expression @@ -21,7 +22,7 @@ export type JoinableRoomProps = { name: string; roomId: string; imageId?: string; - onClick: (completeUrl: string) => void; + onClick?: (completeUrl: string) => void; base64Data?: string; }; @@ -77,7 +78,7 @@ const SessionJoinableRoomAvatar = (props: JoinableRoomProps) => { base64Data={props.base64Data} {...props} pubkey="" - onAvatarClick={() => props.onClick(props.completeUrl)} + onAvatarClick={() => props.onClick?.(props.completeUrl)} /> ); }; @@ -94,64 +95,74 @@ const SessionJoinableRoomName = (props: JoinableRoomProps) => { }; const SessionJoinableRoomRow = (props: JoinableRoomProps) => { + const { onClick, completeUrl } = props; + const onClickWithUrl = onClick + ? () => { + onClick?.(completeUrl); + } + : undefined; + return ( - - { - props.onClick(props.completeUrl); - }} - margin="5px" - padding="5px" - > + + - + ); }; -export const SessionJoinableRooms = (props: { onRoomClicked: () => void }) => { +const JoinableRooms = (props: { + onJoinSessionSogsRoom: (args: JoinSogsRoomUICallbackArgs) => void; + alreadyJoining: boolean; +}) => { const joinableRooms = useSelector((state: StateType) => state.defaultRooms); - const onRoomClicked = useCallback( - (loading: boolean) => { - if (loading) { - props.onRoomClicked(); - } - }, - [props.onRoomClicked] + const onClick = props.alreadyJoining + ? undefined + : (completeUrl: string) => { + void joinOpenGroupV2WithUIEvents(completeUrl, true, false, props.onJoinSessionSogsRoom); + }; + + return ( + <> + {joinableRooms.rooms.map(r => { + return ( + + ); + })} + ); +}; + +export const SessionJoinableRooms = (props: { + onJoinSessionSogsRoom: (args: JoinSogsRoomUICallbackArgs) => void; + alreadyJoining: boolean; +}) => { + const joinableRooms = useSelector((state: StateType) => state.defaultRooms); if (!joinableRooms.inProgress && !joinableRooms.rooms?.length) { window?.log?.info('no default joinable rooms yet and not in progress'); return null; } - const componentToRender = joinableRooms.inProgress ? ( - - ) : ( - joinableRooms.rooms.map(r => { - return ( - { - void joinOpenGroupV2WithUIEvents(completeUrl, true, false, onRoomClicked); - }} - /> - ); - }) - ); - return (

- {componentToRender} + {joinableRooms.inProgress ? ( + + ) : ( + + )} ); diff --git a/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx b/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx index 1f8969cd0..40d011d81 100644 --- a/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx +++ b/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx @@ -113,7 +113,9 @@ const ContactsTitle = () => { return null; } - return {window.i18n('contactsHeader')}; + return ( + {window.i18n('contactsHeader')} + ); }; export const ContactsListWithBreaks = () => { diff --git a/ts/session/apis/open_group_api/opengroupV2/ApiUtil.ts b/ts/session/apis/open_group_api/opengroupV2/ApiUtil.ts index e47e2151f..145339079 100644 --- a/ts/session/apis/open_group_api/opengroupV2/ApiUtil.ts +++ b/ts/session/apis/open_group_api/opengroupV2/ApiUtil.ts @@ -39,7 +39,7 @@ export type OpenGroupV2InfoJoinable = OpenGroupV2Info & { // tslint:disable: no-http-string const legacyDefaultServerIP = '116.203.70.33'; -const defaultServer = 'https://open.getsession.org'; +export const defaultServer = 'https://open.getsession.org'; const defaultServerHost = new window.URL(defaultServer).host; /** diff --git a/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts b/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts index 7b0365f35..706df0bd1 100644 --- a/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts +++ b/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts @@ -2,6 +2,8 @@ import _ from 'lodash'; import { OpenGroupV2Room } from '../../../../data/opengroups'; import { getConversationController } from '../../../conversations'; import { PromiseUtils, ToastUtils } from '../../../utils'; +import { getEventSessionSogsFirstPoll } from '../../../utils/GlobalEvents'; +import { sleepFor, waitForTask } from '../../../utils/Promise'; import { forceSyncConfigurationNowIfNeeded } from '../../../utils/syncUtils'; import { @@ -103,6 +105,11 @@ async function joinOpenGroupV2(room: OpenGroupV2Room, fromConfigMessage: boolean } } +export type JoinSogsRoomUICallbackArgs = { + loadingState: 'started' | 'finished' | 'failed'; + conversationKey: string | null; +}; + /** * This function does not throw * This function can be used to join an opengroupv2 server, from a user initiated click or from a syncMessage. @@ -121,7 +128,7 @@ export async function joinOpenGroupV2WithUIEvents( completeUrl: string, showToasts: boolean, fromConfigMessage: boolean, - uiCallback?: (loading: boolean) => void + uiCallback?: (args: JoinSogsRoomUICallbackArgs) => void ): Promise { try { const parsedRoom = parseOpenGroupV2(completeUrl); @@ -142,11 +149,23 @@ export async function joinOpenGroupV2WithUIEvents( if (showToasts) { ToastUtils.pushToastInfo('connectingToServer', window.i18n('connectingToServer')); } - if (uiCallback) { - uiCallback(true); - } + + uiCallback?.({ loadingState: 'started', conversationKey: conversationID }); + await joinOpenGroupV2(parsedRoom, fromConfigMessage); + // this is very hacky but is made so we wait for the poller to receive the first messages related to that room. + // once the poller added all the messages to the queue of jobs to be run, we still wait a bit for them to be processed. + // This won't age well, but I am not too sure how we can design better. + await waitForTask(done => { + const eventToWait = getEventSessionSogsFirstPoll(parsedRoom.roomId); + window.Whisper.events.on(eventToWait, async () => { + window.Whisper.events.off(eventToWait); + await sleepFor(5000); + done(0); + }); + }, 25000); + const isConvoCreated = getConversationController().get(conversationID); if (isConvoCreated) { if (showToasts) { @@ -155,21 +174,21 @@ export async function joinOpenGroupV2WithUIEvents( window.i18n('connectToServerSuccess') ); } + uiCallback?.({ loadingState: 'finished', conversationKey: conversationID }); + return true; } else { if (showToasts) { ToastUtils.pushToastError('connectToServerFail', window.i18n('connectToServerFail')); } } + uiCallback?.({ loadingState: 'failed', conversationKey: conversationID }); } catch (error) { window?.log?.warn('got error while joining open group:', error.message); if (showToasts) { ToastUtils.pushToastError('connectToServerFail', window.i18n('connectToServerFail')); } - } finally { - if (uiCallback) { - uiCallback(false); - } + uiCallback?.({ loadingState: 'failed', conversationKey: null }); } return false; } diff --git a/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts b/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts index 1f34bb390..439ebec60 100644 --- a/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts +++ b/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts @@ -1,6 +1,6 @@ import { AbortController } from 'abort-controller'; import { getOpenGroupV2ConversationId } from '../utils/OpenGroupUtils'; -import { OpenGroupRequestCommonType } from './ApiUtil'; +import { defaultServer, OpenGroupRequestCommonType } from './ApiUtil'; import _, { isNumber, isObject } from 'lodash'; import { OpenGroupData } from '../../../../data/opengroups'; @@ -20,6 +20,7 @@ import { roomHasBlindEnabled, } from '../sogsv3/sogsV3Capabilities'; import { OpenGroupReaction } from '../../../../types/Reaction'; +import { getEventSessionSogsFirstPoll } from '../../../utils/GlobalEvents'; export type OpenGroupMessageV4 = { /** AFAIK: indicates the number of the message in the group. e.g. 2nd message will be 1 or 2 */ @@ -317,6 +318,14 @@ export class OpenGroupServerPoller { subrequestOptions, this.roomIdsToPoll ); + + if (this.serverUrl === defaultServer) { + for (const room of subrequestOptions) { + if (room.type === 'messages' && !room.messages?.sinceSeqNo && room.messages?.roomId) { + window.Whisper.events.trigger(getEventSessionSogsFirstPoll(room.messages.roomId)); + } + } + } } catch (e) { window?.log?.warn('Got error while compact fetch:', e.message); } finally { diff --git a/ts/session/utils/GlobalEvents.ts b/ts/session/utils/GlobalEvents.ts new file mode 100644 index 000000000..e73c62bbf --- /dev/null +++ b/ts/session/utils/GlobalEvents.ts @@ -0,0 +1,3 @@ +export function getEventSessionSogsFirstPoll(roomId: string) { + return `first-poll-session-sogs:${roomId}`; +} diff --git a/ts/window.d.ts b/ts/window.d.ts index c07742648..ad4e8ad81 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -21,11 +21,7 @@ declare global { CONSTANTS: any; Events: any; Lodash: any; - SessionSnodeAPI: any; Session: any; - StubAppDotNetApi: any; - StringView: any; - StubMessageAPI: any; Whisper: any; clearLocalData: any; clipboard: any; From 6f0d223eb94e43769709a051cbecddb9c40f3f1a Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 6 Sep 2022 17:48:00 +1000 Subject: [PATCH 06/12] fix: address PR reviews --- stylesheets/_session_constants.scss | 1 - stylesheets/_session_left_pane.scss | 2 +- stylesheets/_session_signin.scss | 4 ++-- ts/components/MemberListItem.tsx | 14 +++++--------- ts/components/basic/PillContainer.tsx | 1 - ts/components/leftpane/LeftPane.tsx | 8 +++++++- ts/components/leftpane/overlay/OverlayMessage.tsx | 4 ++-- .../choose-action/ContactsListWithBreaks.tsx | 3 ++- 8 files changed, 19 insertions(+), 18 deletions(-) diff --git a/stylesheets/_session_constants.scss b/stylesheets/_session_constants.scss index a98df48b5..d990b1a3c 100644 --- a/stylesheets/_session_constants.scss +++ b/stylesheets/_session_constants.scss @@ -204,7 +204,6 @@ $session-subtle-factor: 0.6; // Default Components $main-view-header-height: 63px; -$session-left-pane-width: 300px; // Various Components $session-modal-size-sm: 220px; diff --git a/stylesheets/_session_left_pane.scss b/stylesheets/_session_left_pane.scss index 8eaa0cb36..6c98fa679 100644 --- a/stylesheets/_session_left_pane.scss +++ b/stylesheets/_session_left_pane.scss @@ -71,7 +71,7 @@ $session-compose-margin: 20px; } .module-left-pane { - width: $session-left-pane-width; + width: var(--left-pane-list-width); position: relative; height: 100vh; flex-shrink: 0; diff --git a/stylesheets/_session_signin.scss b/stylesheets/_session_signin.scss index 957d199d5..5ae6994b1 100644 --- a/stylesheets/_session_signin.scss +++ b/stylesheets/_session_signin.scss @@ -162,7 +162,7 @@ font-weight: bold; text-decoration: none; - color: rgba(var(--color-text), 0.6); + color: rgba(black, 0.6); transition: $session-transition-duration; &:visited &:link { @@ -179,7 +179,7 @@ padding-top: 0; padding-bottom: 20px; - color: rgba(var(--color-text), 0.6); + color: rgba(black, 0.6); text-align: center; font-size: 12px; line-height: 20px; diff --git a/ts/components/MemberListItem.tsx b/ts/components/MemberListItem.tsx index 333a23370..75f19d695 100644 --- a/ts/components/MemberListItem.tsx +++ b/ts/components/MemberListItem.tsx @@ -24,26 +24,23 @@ const StyledSessionMemberItem = styled.button<{ selected?: boolean; }>` cursor: pointer; + display: flex; + align-items: center; + justify-content: space-between; flex-shrink: 0; flex-grow: 1; font-family: var(--font-default); padding: 0px var(--margins-sm); height: ${props => (props.inMentions ? '40px' : '50px')}; - display: flex; - - align-items: center; - justify-content: space-between; transition: var(--default-duration); - opacity: ${props => (props.zombie ? 0.5 : 1)}; + background-color: ${props => + props.selected && 'var(--color-conversation-item-selected) !important'}; :not(:last-child) { border-bottom: var(--border-session); } - - background-color: ${props => - props.selected ? 'var(--color-conversation-item-selected) !important' : null}; `; const StyledInfo = styled.div` @@ -110,7 +107,6 @@ export const MemberListItem = (props: { > - {memberName} diff --git a/ts/components/basic/PillContainer.tsx b/ts/components/basic/PillContainer.tsx index aa32465d0..cc8766fdf 100644 --- a/ts/components/basic/PillContainer.tsx +++ b/ts/components/basic/PillContainer.tsx @@ -11,7 +11,6 @@ type PillContainerProps = { export const StyledPillContainerHoverable = styled.div` background: none; - position: relative; flex-direction: 'row'; flex-shrink: 0; diff --git a/ts/components/leftpane/LeftPane.tsx b/ts/components/leftpane/LeftPane.tsx index 0dd609fbf..4e9be07ce 100644 --- a/ts/components/leftpane/LeftPane.tsx +++ b/ts/components/leftpane/LeftPane.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { useSelector } from 'react-redux'; +import { CSSProperties } from 'styled-components'; import { SectionType } from '../../state/ducks/section'; import { SessionTheme } from '../../state/ducks/SessionTheme'; import { getLeftPaneLists } from '../../state/selectors/conversations'; @@ -45,13 +46,18 @@ const LeftPaneSection = () => { return null; }; +export const leftPaneListWidth = 300; + export const LeftPane = () => { return (
-
+
diff --git a/ts/components/leftpane/overlay/OverlayMessage.tsx b/ts/components/leftpane/overlay/OverlayMessage.tsx index 781ec820b..93a7ede6d 100644 --- a/ts/components/leftpane/overlay/OverlayMessage.tsx +++ b/ts/components/leftpane/overlay/OverlayMessage.tsx @@ -53,7 +53,7 @@ export const OverlayMessage = () => { ConversationTypeEnum.PRIVATE ); - // we now want to show a conversation we just started on the leftpane, even if we did not sent a message to it yet + // 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(); @@ -122,7 +122,7 @@ export const OverlayMessage = () => { justifyContent="space-between" alignItems="center" width="100%" - padding="0 var(--margins-md) " // YourSessionIDSelectable already has a left margin of 15px + padding="0 var(--margins-md)" // YourSessionIDSelectable already has a left margin of 15px > diff --git a/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx b/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx index 40d011d81..1fd71411c 100644 --- a/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx +++ b/ts/components/leftpane/overlay/choose-action/ContactsListWithBreaks.tsx @@ -8,6 +8,7 @@ import { getDirectContactsByName, getDirectContactsCount, } from '../../../../state/selectors/conversations'; +import { leftPaneListWidth } from '../../LeftPane'; import { StyledLeftPaneList } from '../../LeftPaneList'; import { ContactRow, ContactRowBreak } from './ContactRow'; import { StyledChooseActionTitle } from './OverlayChooseAction'; @@ -97,7 +98,7 @@ const ContactListItemSection = () => { } directContactsByNameWithBreaks={directContactsByNameWithBreaks} rowRenderer={renderRow} - width={300} // the same as session-left-pane-width + width={leftPaneListWidth} autoHeight={false} /> ); From efd249f094785a9dc0cf2552bc6ca7f33d06dcfe Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 7 Sep 2022 16:20:07 +1000 Subject: [PATCH 07/12] fix: add featureflag to hide ThemeSwitcher until ThemeSwitcher is fully done with theming --- preload.js | 1 + ts/components/settings/section/CategoryAppearance.tsx | 2 +- ts/window.d.ts | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/preload.js b/preload.js index d9072725b..eb964c2c3 100644 --- a/preload.js +++ b/preload.js @@ -29,6 +29,7 @@ window.sessionFeatureFlags = { useTestNet: Boolean( process.env.NODE_APP_INSTANCE && process.env.NODE_APP_INSTANCE.includes('testnet') ), + useSettingsThemeSwitcher: false, debug: { debugFileServerRequests: false, debugNonSnodeRequests: false, diff --git a/ts/components/settings/section/CategoryAppearance.tsx b/ts/components/settings/section/CategoryAppearance.tsx index d665b607a..c593fe806 100644 --- a/ts/components/settings/section/CategoryAppearance.tsx +++ b/ts/components/settings/section/CategoryAppearance.tsx @@ -19,7 +19,7 @@ export const SettingsCategoryAppearance = (props: { hasPassword: boolean | null return ( <> - + {window.sessionFeatureFlags.useSettingsThemeSwitcher && } {isHideMenuBarSupported() && ( Date: Wed, 7 Sep 2022 16:20:32 +1000 Subject: [PATCH 08/12] fix: do not autofocus settings section by default but Message --- ts/state/ducks/section.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ts/state/ducks/section.tsx b/ts/state/ducks/section.tsx index 435cc67a2..9c0ffcd7f 100644 --- a/ts/state/ducks/section.tsx +++ b/ts/state/ducks/section.tsx @@ -91,8 +91,8 @@ export const actions = { }; export const initialSectionState: SectionStateType = { - focusedSection: SectionType.Settings, - focusedSettingsSection: SessionSettingCategory.Appearance, + focusedSection: SectionType.Message, + focusedSettingsSection: undefined, isAppFocused: false, overlayMode: undefined, }; From 38d85a653a701f5243df7f1050c665b5ff33cb3b Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Wed, 7 Sep 2022 17:16:27 +1000 Subject: [PATCH 09/12] fix: do not wait for sogs messages on join of unofficial sogs --- .../opengroupV2/JoinOpenGroupV2.ts | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts b/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts index 706df0bd1..9d01af839 100644 --- a/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts +++ b/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts @@ -12,7 +12,7 @@ import { prefixify, publicKeyParam, } from '../utils/OpenGroupUtils'; -import { hasExistingOpenGroup } from './ApiUtil'; +import { defaultServer, hasExistingOpenGroup } from './ApiUtil'; import { getOpenGroupManager } from './OpenGroupManagerV2'; // tslint:disable: variable-name @@ -154,17 +154,19 @@ export async function joinOpenGroupV2WithUIEvents( await joinOpenGroupV2(parsedRoom, fromConfigMessage); - // this is very hacky but is made so we wait for the poller to receive the first messages related to that room. - // once the poller added all the messages to the queue of jobs to be run, we still wait a bit for them to be processed. - // This won't age well, but I am not too sure how we can design better. - await waitForTask(done => { - const eventToWait = getEventSessionSogsFirstPoll(parsedRoom.roomId); - window.Whisper.events.on(eventToWait, async () => { - window.Whisper.events.off(eventToWait); - await sleepFor(5000); - done(0); - }); - }, 25000); + if (parsedRoom.serverUrl === defaultServer) { + // this is very hacky but is made so we wait for the poller to receive the first messages related to that room. + // once the poller added all the messages to the queue of jobs to be run, we still wait a bit for them to be processed. + // This won't age well, but I am not too sure how we can design better. + await waitForTask(done => { + const eventToWait = getEventSessionSogsFirstPoll(parsedRoom.roomId); + window.Whisper.events.on(eventToWait, async () => { + window.Whisper.events.off(eventToWait); + await sleepFor(5000); + done(0); + }); + }, 25000); + } const isConvoCreated = getConversationController().get(conversationID); if (isConvoCreated) { From d9621f79c380ef88144f6f9a939cc7b87cfab685 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 8 Sep 2022 10:28:36 +1000 Subject: [PATCH 10/12] fix: allow any sogs to be awaited until messages are fetched --- .../leftpane/overlay/OverlayCommunity.tsx | 26 ++++++++----------- .../overlay/SessionJoinableDefaultRooms.tsx | 18 +++---------- ts/mains/main_renderer.tsx | 2 -- .../opengroupV2/JoinOpenGroupV2.ts | 8 +++--- .../opengroupV2/OpenGroupServerPoller.ts | 11 +++++--- ts/session/utils/GlobalEvents.ts | 4 +-- 6 files changed, 28 insertions(+), 41 deletions(-) diff --git a/ts/components/leftpane/overlay/OverlayCommunity.tsx b/ts/components/leftpane/overlay/OverlayCommunity.tsx index 527618515..23cad11c3 100644 --- a/ts/components/leftpane/overlay/OverlayCommunity.tsx +++ b/ts/components/leftpane/overlay/OverlayCommunity.tsx @@ -19,10 +19,13 @@ import useKey from 'react-use/lib/useKey'; import { getOverlayMode } from '../../../state/selectors/section'; import { openConversationWithMessages } from '../../../state/ducks/conversations'; -async function joinOpenGroup(serverUrl: string) { +async function joinOpenGroup( + serverUrl: string, + uiCallback?: (args: JoinSogsRoomUICallbackArgs) => void +) { // guess if this is an open if (serverUrl.match(openGroupV2CompleteURLRegex)) { - const groupCreated = await joinOpenGroupV2WithUIEvents(serverUrl, true, false); + const groupCreated = await joinOpenGroupV2WithUIEvents(serverUrl, true, false, uiCallback); return groupCreated; } else { ToastUtils.pushToastError('invalidOpenGroupUrl', window.i18n('invalidOpenGroupUrl')); @@ -42,16 +45,12 @@ export const OverlayCommunity = () => { dispatch(resetOverlayMode()); } - async function onEnterPressed() { + async function onTryJoinRoom(completeUrl?: string) { try { if (loading) { return; } - setLoading(true); - const groupCreated = await joinOpenGroup(groupUrl); - if (groupCreated) { - closeOverlay(); - } + await joinOpenGroup(completeUrl || groupUrl, joinSogsUICallback); } catch (e) { window.log.warn(e); } finally { @@ -59,7 +58,7 @@ export const OverlayCommunity = () => { } } - function onJoinSessionSogsRoom(args: JoinSogsRoomUICallbackArgs) { + function joinSogsUICallback(args: JoinSogsRoomUICallbackArgs) { setLoading(args.loadingState === 'started'); if (args.loadingState === 'finished' && overlayModeIsCommunity && args.conversationKey) { @@ -87,7 +86,7 @@ export const OverlayCommunity = () => { isGroup={true} maxLength={300} onChange={setGroupUrl} - onPressEnter={onEnterPressed} + onPressEnter={onTryJoinRoom} />
@@ -96,14 +95,11 @@ export const OverlayCommunity = () => { buttonType={SessionButtonType.BrandOutline} text={buttonText} disabled={!groupUrl} - onClick={onEnterPressed} + onClick={onTryJoinRoom} /> - + ); }; diff --git a/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx b/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx index e0ad0a916..4c782bad1 100644 --- a/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx +++ b/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx @@ -2,11 +2,7 @@ import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import styled from 'styled-components'; -import { - joinOpenGroupV2WithUIEvents, - JoinSogsRoomUICallbackArgs, - parseOpenGroupV2, -} from '../../../session/apis/open_group_api/opengroupV2/JoinOpenGroupV2'; +import { parseOpenGroupV2 } from '../../../session/apis/open_group_api/opengroupV2/JoinOpenGroupV2'; import { sogsV3FetchPreviewBase64 } from '../../../session/apis/open_group_api/sogsv3/sogsV3FetchFile'; import { updateDefaultBase64RoomData } from '../../../state/ducks/defaultRooms'; import { StateType } from '../../../state/reducer'; @@ -113,17 +109,11 @@ const SessionJoinableRoomRow = (props: JoinableRoomProps) => { }; const JoinableRooms = (props: { - onJoinSessionSogsRoom: (args: JoinSogsRoomUICallbackArgs) => void; alreadyJoining: boolean; + onJoinClick?: (completeUrl: string) => void; }) => { const joinableRooms = useSelector((state: StateType) => state.defaultRooms); - const onClick = props.alreadyJoining - ? undefined - : (completeUrl: string) => { - void joinOpenGroupV2WithUIEvents(completeUrl, true, false, props.onJoinSessionSogsRoom); - }; - return ( <> {joinableRooms.rooms.map(r => { @@ -135,7 +125,7 @@ const JoinableRooms = (props: { roomId={r.id} imageId={r.imageId} base64Data={r.base64Data} - onClick={onClick} + onClick={props.onJoinClick} /> ); })} @@ -144,7 +134,7 @@ const JoinableRooms = (props: { }; export const SessionJoinableRooms = (props: { - onJoinSessionSogsRoom: (args: JoinSogsRoomUICallbackArgs) => void; + onJoinClick?: (completeUrl: string) => void; alreadyJoining: boolean; }) => { const joinableRooms = useSelector((state: StateType) => state.defaultRooms); diff --git a/ts/mains/main_renderer.tsx b/ts/mains/main_renderer.tsx index 27501e386..812261d25 100644 --- a/ts/mains/main_renderer.tsx +++ b/ts/mains/main_renderer.tsx @@ -84,8 +84,6 @@ let newVersion = false; window.document.title = window.getTitle(); -// Whisper.events = -// window.Whisper.events = WhisperEvents ? const WhisperEvents = _.clone(Backbone.Events); window.Whisper = window.Whisper || {}; window.Whisper.events = WhisperEvents; diff --git a/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts b/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts index 9d01af839..9dba3a83d 100644 --- a/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts +++ b/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts @@ -2,7 +2,7 @@ import _ from 'lodash'; import { OpenGroupV2Room } from '../../../../data/opengroups'; import { getConversationController } from '../../../conversations'; import { PromiseUtils, ToastUtils } from '../../../utils'; -import { getEventSessionSogsFirstPoll } from '../../../utils/GlobalEvents'; +import { getEventSogsFirstPoll } from '../../../utils/GlobalEvents'; import { sleepFor, waitForTask } from '../../../utils/Promise'; import { forceSyncConfigurationNowIfNeeded } from '../../../utils/syncUtils'; @@ -12,7 +12,7 @@ import { prefixify, publicKeyParam, } from '../utils/OpenGroupUtils'; -import { defaultServer, hasExistingOpenGroup } from './ApiUtil'; +import { hasExistingOpenGroup } from './ApiUtil'; import { getOpenGroupManager } from './OpenGroupManagerV2'; // tslint:disable: variable-name @@ -154,12 +154,12 @@ export async function joinOpenGroupV2WithUIEvents( await joinOpenGroupV2(parsedRoom, fromConfigMessage); - if (parsedRoom.serverUrl === defaultServer) { + if (!fromConfigMessage && showToasts) { // this is very hacky but is made so we wait for the poller to receive the first messages related to that room. // once the poller added all the messages to the queue of jobs to be run, we still wait a bit for them to be processed. // This won't age well, but I am not too sure how we can design better. await waitForTask(done => { - const eventToWait = getEventSessionSogsFirstPoll(parsedRoom.roomId); + const eventToWait = getEventSogsFirstPoll(parsedRoom.serverPublicKey, parsedRoom.roomId); window.Whisper.events.on(eventToWait, async () => { window.Whisper.events.off(eventToWait); await sleepFor(5000); diff --git a/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts b/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts index 1578cfaf3..1e8592173 100644 --- a/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts +++ b/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts @@ -1,6 +1,6 @@ import { AbortController } from 'abort-controller'; import { getOpenGroupV2ConversationId } from '../utils/OpenGroupUtils'; -import { defaultServer, OpenGroupRequestCommonType } from './ApiUtil'; +import { OpenGroupRequestCommonType } from './ApiUtil'; import _, { isNumber, isObject } from 'lodash'; import { OpenGroupData } from '../../../../data/opengroups'; @@ -20,7 +20,7 @@ import { roomHasBlindEnabled, } from '../sogsv3/sogsV3Capabilities'; import { OpenGroupReaction } from '../../../../types/Reaction'; -import { getEventSessionSogsFirstPoll } from '../../../utils/GlobalEvents'; +import { getEventSogsFirstPoll } from '../../../utils/GlobalEvents'; export type OpenGroupMessageV4 = { /** AFAIK: indicates the number of the message in the group. e.g. 2nd message will be 1 or 2 */ @@ -319,10 +319,13 @@ export class OpenGroupServerPoller { // ==> At this point all those results need to trigger conversation updates, so update what we have to update await handleBatchPollResults(this.serverUrl, batchPollResults, subrequestOptions); - if (this.serverUrl === defaultServer) { + const roomsInDb = OpenGroupData.getV2OpenGroupRoomsByServerUrl(this.serverUrl); + if (roomsInDb?.[0]?.serverPublicKey) { for (const room of subrequestOptions) { if (room.type === 'messages' && !room.messages?.sinceSeqNo && room.messages?.roomId) { - window.Whisper.events.trigger(getEventSessionSogsFirstPoll(room.messages.roomId)); + window.Whisper.events.trigger( + getEventSogsFirstPoll(roomsInDb[0].serverPublicKey, room.messages.roomId) + ); } } } diff --git a/ts/session/utils/GlobalEvents.ts b/ts/session/utils/GlobalEvents.ts index e73c62bbf..52d16b8cb 100644 --- a/ts/session/utils/GlobalEvents.ts +++ b/ts/session/utils/GlobalEvents.ts @@ -1,3 +1,3 @@ -export function getEventSessionSogsFirstPoll(roomId: string) { - return `first-poll-session-sogs:${roomId}`; +export function getEventSogsFirstPoll(serverpubkey: string, roomId: string) { + return `first-poll-sogs:${roomId}-${serverpubkey}`; } From 1d45aa6f459818a492a89334d4c52e90b0d4651d Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 8 Sep 2022 16:26:43 +1000 Subject: [PATCH 11/12] fix: show loading spinner while sogs is fetching initial messages --- ts/components/basic/YourSessionIDPill.tsx | 1 - .../conversation/SessionConversation.tsx | 107 +++++++++++------- .../leftpane/overlay/OverlayCommunity.tsx | 14 ++- .../opengroupV2/JoinOpenGroupV2.ts | 16 --- .../opengroupV2/OpenGroupServerPoller.ts | 40 +++++-- ts/session/utils/GlobalEvents.ts | 3 - ts/state/ducks/conversations.ts | 22 +++- ts/state/selectors/conversations.ts | 5 + ts/state/smart/SessionConversation.ts | 2 + ts/window.d.ts | 1 + 10 files changed, 136 insertions(+), 75 deletions(-) delete mode 100644 ts/session/utils/GlobalEvents.ts diff --git a/ts/components/basic/YourSessionIDPill.tsx b/ts/components/basic/YourSessionIDPill.tsx index 7bf8eecb8..f949b9313 100644 --- a/ts/components/basic/YourSessionIDPill.tsx +++ b/ts/components/basic/YourSessionIDPill.tsx @@ -38,7 +38,6 @@ const StyledYourSessionIDSelectable = styled.p` user-select: none; text-align: center; word-break: break-all; - padding: 0px var(--margins-lg); font-weight: 300; color: var(--color-text); font-size: var(--font-size-sm); diff --git a/ts/components/conversation/SessionConversation.tsx b/ts/components/conversation/SessionConversation.tsx index a7a836565..65bc21e4b 100644 --- a/ts/components/conversation/SessionConversation.tsx +++ b/ts/components/conversation/SessionConversation.tsx @@ -54,6 +54,8 @@ import { ConversationMessageRequestButtons } from './ConversationRequestButtons' import { ConversationRequestinfo } from './ConversationRequestInfo'; import { getCurrentRecoveryPhrase } from '../../util/storage'; import loadImage from 'blueimp-load-image'; +import { SessionSpinner } from '../basic/SessionSpinner'; +import styled from 'styled-components'; // tslint:disable: jsx-curly-spacing interface State { @@ -78,8 +80,25 @@ interface Props { lightBoxOptions?: LightBoxOptions; stagedAttachments: Array; + isSelectedConvoInitialLoadingInProgress: boolean; } +const StyledSpinnerContainer = styled.div` + display: flex; + justify-content: center; + width: 100%; + height: 100%; + align-items: center; +`; + +const ConvoLoadingSpinner = () => { + return ( + + + + ); +}; + export class SessionConversation extends React.Component { private readonly messageContainerRef: React.RefObject; private dragCounter: number; @@ -219,6 +238,7 @@ export class SessionConversation extends React.Component { selectedMessages, isRightPanelShowing, lightBoxOptions, + isSelectedConvoInitialLoadingInProgress, } = this.props; if (!selectedConversation || !messagesProps) { @@ -233,46 +253,55 @@ export class SessionConversation extends React.Component {
-
-
- -
- {lightBoxOptions?.media && this.renderLightBox(lightBoxOptions)} - -
- - } - bottom={ - + ) : ( + <> +
+
+ +
+ {lightBoxOptions?.media && this.renderLightBox(lightBoxOptions)} + +
+ + } + bottom={ + + } + disableTop={!this.props.hasOngoingCallWithFocusedConvo} /> - } - disableTop={!this.props.hasOngoingCallWithFocusedConvo} - /> - - {isDraggingFile && } -
- - - -
-
- -
+ + {isDraggingFile && } +
+ + + +
+
+ +
+ + )}
); } diff --git a/ts/components/leftpane/overlay/OverlayCommunity.tsx b/ts/components/leftpane/overlay/OverlayCommunity.tsx index 23cad11c3..4a8d3b665 100644 --- a/ts/components/leftpane/overlay/OverlayCommunity.tsx +++ b/ts/components/leftpane/overlay/OverlayCommunity.tsx @@ -17,7 +17,10 @@ import { openGroupV2CompleteURLRegex } from '../../../session/apis/open_group_ap import { ToastUtils } from '../../../session/utils'; import useKey from 'react-use/lib/useKey'; import { getOverlayMode } from '../../../state/selectors/section'; -import { openConversationWithMessages } from '../../../state/ducks/conversations'; +import { + markConversationInitialLoadingInProgress, + openConversationWithMessages, +} from '../../../state/ducks/conversations'; async function joinOpenGroup( serverUrl: string, @@ -60,7 +63,14 @@ export const OverlayCommunity = () => { function joinSogsUICallback(args: JoinSogsRoomUICallbackArgs) { setLoading(args.loadingState === 'started'); - + if (args.conversationKey) { + dispatch( + markConversationInitialLoadingInProgress({ + conversationKey: args.conversationKey, + isInitialFetchingInProgress: true, + }) + ); + } if (args.loadingState === 'finished' && overlayModeIsCommunity && args.conversationKey) { closeOverlay(); void openConversationWithMessages({ conversationKey: args.conversationKey, messageId: null }); // open to last unread for a session run sogs diff --git a/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts b/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts index 9dba3a83d..54382a9c8 100644 --- a/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts +++ b/ts/session/apis/open_group_api/opengroupV2/JoinOpenGroupV2.ts @@ -2,8 +2,6 @@ import _ from 'lodash'; import { OpenGroupV2Room } from '../../../../data/opengroups'; import { getConversationController } from '../../../conversations'; import { PromiseUtils, ToastUtils } from '../../../utils'; -import { getEventSogsFirstPoll } from '../../../utils/GlobalEvents'; -import { sleepFor, waitForTask } from '../../../utils/Promise'; import { forceSyncConfigurationNowIfNeeded } from '../../../utils/syncUtils'; import { @@ -154,20 +152,6 @@ export async function joinOpenGroupV2WithUIEvents( await joinOpenGroupV2(parsedRoom, fromConfigMessage); - if (!fromConfigMessage && showToasts) { - // this is very hacky but is made so we wait for the poller to receive the first messages related to that room. - // once the poller added all the messages to the queue of jobs to be run, we still wait a bit for them to be processed. - // This won't age well, but I am not too sure how we can design better. - await waitForTask(done => { - const eventToWait = getEventSogsFirstPoll(parsedRoom.serverPublicKey, parsedRoom.roomId); - window.Whisper.events.on(eventToWait, async () => { - window.Whisper.events.off(eventToWait); - await sleepFor(5000); - done(0); - }); - }, 25000); - } - const isConvoCreated = getConversationController().get(conversationID); if (isConvoCreated) { if (showToasts) { diff --git a/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts b/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts index 1e8592173..99e925faa 100644 --- a/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts +++ b/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts @@ -20,7 +20,10 @@ import { roomHasBlindEnabled, } from '../sogsv3/sogsV3Capabilities'; import { OpenGroupReaction } from '../../../../types/Reaction'; -import { getEventSogsFirstPoll } from '../../../utils/GlobalEvents'; +import { + markConversationInitialLoadingInProgress, + openConversationWithMessages, +} from '../../../../state/ducks/conversations'; export type OpenGroupMessageV4 = { /** AFAIK: indicates the number of the message in the group. e.g. 2nd message will be 1 or 2 */ @@ -319,14 +322,33 @@ export class OpenGroupServerPoller { // ==> At this point all those results need to trigger conversation updates, so update what we have to update await handleBatchPollResults(this.serverUrl, batchPollResults, subrequestOptions); - const roomsInDb = OpenGroupData.getV2OpenGroupRoomsByServerUrl(this.serverUrl); - if (roomsInDb?.[0]?.serverPublicKey) { - for (const room of subrequestOptions) { - if (room.type === 'messages' && !room.messages?.sinceSeqNo && room.messages?.roomId) { - window.Whisper.events.trigger( - getEventSogsFirstPoll(roomsInDb[0].serverPublicKey, room.messages.roomId) - ); - } + for (const room of subrequestOptions) { + if (room.type === 'messages' && !room.messages?.sinceSeqNo && room.messages?.roomId) { + const conversationKey = getOpenGroupV2ConversationId( + this.serverUrl, + room.messages.roomId + ); + + global.setTimeout(() => { + const stateConversations = window.inboxStore?.getState().conversations; + if ( + stateConversations.conversationLookup?.[conversationKey]?.isInitialFetchingInProgress + ) { + if ( + stateConversations.selectedConversation && + conversationKey === stateConversations.selectedConversation + ) { + void openConversationWithMessages({ conversationKey, messageId: null }).then(() => { + window.inboxStore?.dispatch( + markConversationInitialLoadingInProgress({ + conversationKey, + isInitialFetchingInProgress: false, + }) + ); + }); + } + } + }, 5000); } } } catch (e) { diff --git a/ts/session/utils/GlobalEvents.ts b/ts/session/utils/GlobalEvents.ts deleted file mode 100644 index 52d16b8cb..000000000 --- a/ts/session/utils/GlobalEvents.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function getEventSogsFirstPoll(serverpubkey: string, roomId: string) { - return `first-poll-sogs:${roomId}-${serverpubkey}`; -} diff --git a/ts/state/ducks/conversations.ts b/ts/state/ducks/conversations.ts index 178fe8618..0ff54b94d 100644 --- a/ts/state/ducks/conversations.ts +++ b/ts/state/ducks/conversations.ts @@ -264,6 +264,7 @@ export interface ReduxConversationType { currentNotificationSetting?: ConversationNotificationSettingType; isPinned?: boolean; + isInitialFetchingInProgress?: boolean; isApproved?: boolean; didApproveMe?: boolean; @@ -717,10 +718,6 @@ const conversationsSlice = createSlice({ initialMessages: Array; }> ) { - if (state.selectedConversation === action.payload.conversationKey) { - return state; - } - // this is quite hacky, but we don't want to show the showScrollButton if we have only a small amount of messages, // or if the first unread message is not far from the most recent one. // this is because when a new message get added, we do not add it to redux depending on the showScrollButton state. @@ -835,6 +832,20 @@ const conversationsSlice = createSlice({ state.mentionMembers = action.payload; return state; }, + markConversationInitialLoadingInProgress( + state: ConversationsStateType, + action: PayloadAction<{ conversationKey: string; isInitialFetchingInProgress: boolean }> + ) { + window?.log?.info( + `mark conversation initialLoading ${action.payload.conversationKey}: ${action.payload.isInitialFetchingInProgress}` + ); + if (state.conversationLookup[action.payload.conversationKey]) { + state.conversationLookup[action.payload.conversationKey].isInitialFetchingInProgress = + action.payload.isInitialFetchingInProgress; + } + + return state; + }, }, extraReducers: (builder: any) => { // Add reducers for additional action types here, and handle loading state as needed @@ -945,7 +956,7 @@ function applyConversationChanged( selectedConversation, conversationLookup: { ...conversationLookup, - [id]: data, + [id]: { ...data, isInitialFetchingInProgress: existing.isInitialFetchingInProgress }, }, }; } @@ -981,6 +992,7 @@ export const { setNextMessageToPlayId, updateMentionsMembers, resetConversationExternal, + markConversationInitialLoadingInProgress, } = actions; export async function openConversationWithMessages(args: { diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index 247380d89..f3b1c0b3c 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -1172,3 +1172,8 @@ export const getOldBottomMessageId = createSelector( getConversations, (state: ConversationsStateType): string | null => state.oldBottomMessageId || null ); + +export const getIsSelectedConvoInitialLoadingInProgress = createSelector( + getSelectedConversation, + (convo: ReduxConversationType | undefined): boolean => Boolean(convo?.isInitialFetchingInProgress) +); diff --git a/ts/state/smart/SessionConversation.ts b/ts/state/smart/SessionConversation.ts index f38cf803b..ca9692a6c 100644 --- a/ts/state/smart/SessionConversation.ts +++ b/ts/state/smart/SessionConversation.ts @@ -3,6 +3,7 @@ import { mapDispatchToProps } from '../actions'; import { StateType } from '../reducer'; import { getTheme } from '../selectors/theme'; import { + getIsSelectedConvoInitialLoadingInProgress, getLightBoxOptions, getSelectedConversation, getSelectedConversationKey, @@ -29,6 +30,7 @@ const mapStateToProps = (state: StateType) => { lightBoxOptions: getLightBoxOptions(state), stagedAttachments: getStagedAttachmentsForCurrentConversation(state), hasOngoingCallWithFocusedConvo: getHasOngoingCallWithFocusedConvo(state), + isSelectedConvoInitialLoadingInProgress: getIsSelectedConvoInitialLoadingInProgress(state), }; }; diff --git a/ts/window.d.ts b/ts/window.d.ts index aabfae723..6e55cbb27 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -6,6 +6,7 @@ import { Store } from 'redux'; import { ConversationCollection, ConversationModel } from './models/conversation'; import { ConversationType } from './state/ducks/conversations'; +import { StateType } from './state/reducer'; export interface LibTextsecure { messaging: boolean; From 3ffc470c40a5f5694defbc621ce192229b8a8b94 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 8 Sep 2022 16:59:53 +1000 Subject: [PATCH 12/12] fix: address reviews comment --- _locales/en/messages.json | 3 +- stylesheets/_session_conversation.scss | 32 ---------------- stylesheets/_session_left_pane.scss | 1 - stylesheets/_session_signin.scss | 2 +- ts/components/basic/SessionRadio.tsx | 6 ++- ts/components/basic/SessionToggle.tsx | 5 ++- .../conversation/TypingAnimation.tsx | 2 +- .../dialog/OnionStatusPathDialog.tsx | 38 +++++++++---------- ts/components/leftpane/LeftPane.tsx | 16 ++++---- .../leftpane/LeftPaneMessageSection.tsx | 14 +++---- ts/components/settings/BlockedList.tsx | 10 ++--- .../SessionNotificationGroupSettings.tsx | 5 ++- ts/components/settings/SessionSettings.tsx | 2 +- .../settings/SessionSettingsHeader.tsx | 17 ++++----- .../settings/SettingsThemeSwitcher.tsx | 2 +- ts/state/ducks/SessionTheme.tsx | 4 +- ts/types/LocalizerKeys.ts | 2 + ts/util/blockedNumberController.ts | 2 +- 18 files changed, 67 insertions(+), 96 deletions(-) diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 38cdb3e42..7fcb221a7 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -173,6 +173,7 @@ "sendFailed": "Send Failed", "mediaMessage": "Media message", "messageBodyMissing": "Please enter a message body.", + "messageBody": "Message body", "unblockToSend": "Unblock this contact to send a message.", "unblockGroupToSend": "This group is blocked. Unlock it if you would like to send a message.", "youChangedTheTimer": "You set the disappearing message timer to $time$", @@ -421,7 +422,7 @@ "recoveryPhraseRevealMessage": "Secure your account by saving your recovery phrase. Reveal your recovery phrase then store it safely to secure it.", "recoveryPhraseRevealButtonText": "Reveal Recovery Phrase", "notificationSubtitle": "Notifications - $setting$", - "surveyTitle": "We'd love your Feedback", + "surveyTitle": "We'd Love Your Feedback", "faq": "FAQ", "support": "Support", "clearAll": "Clear All", diff --git a/stylesheets/_session_conversation.scss b/stylesheets/_session_conversation.scss index 4ca66d6b7..b19a04746 100644 --- a/stylesheets/_session_conversation.scss +++ b/stylesheets/_session_conversation.scss @@ -393,38 +393,6 @@ } } - &--status { - display: flex; - justify-content: center; - position: absolute; - left: 0; - z-index: 2; - right: 0; - bottom: $composition-container-height + var(--margins-md); - - .session-button { - display: flex; - justify-content: center; - align-items: center; - width: 173px; - font-weight: 300; - font-family: $session-font-default; - - &.primary { - cursor: default; - user-select: none; - - &:hover { - filter: brightness(100%); - border: 2px solid #161819; - } - - background-color: $session-shade-1-alt; - border: 2px solid #161819; - } - } - } - &--timer { display: inline-flex; align-items: center; diff --git a/stylesheets/_session_left_pane.scss b/stylesheets/_session_left_pane.scss index f67445644..e51ec93f2 100644 --- a/stylesheets/_session_left_pane.scss +++ b/stylesheets/_session_left_pane.scss @@ -71,7 +71,6 @@ $session-compose-margin: 20px; } .module-left-pane { - width: var(--left-pane-list-width); position: relative; height: 100vh; flex-shrink: 0; diff --git a/stylesheets/_session_signin.scss b/stylesheets/_session_signin.scss index 4307b3566..374a1a1ec 100644 --- a/stylesheets/_session_signin.scss +++ b/stylesheets/_session_signin.scss @@ -178,7 +178,7 @@ &-description-long { padding-top: 0; padding-bottom: 20px; - + // TODO Theming needs to be updated color: rgba(black, 0.6); text-align: center; font-size: 12px; diff --git a/ts/components/basic/SessionRadio.tsx b/ts/components/basic/SessionRadio.tsx index 44f6379d4..6db7d945a 100644 --- a/ts/components/basic/SessionRadio.tsx +++ b/ts/components/basic/SessionRadio.tsx @@ -1,5 +1,6 @@ import React, { ChangeEvent } from 'react'; import styled from 'styled-components'; +import { black } from '../../state/ducks/SessionTheme'; import { Flex } from '../basic/Flex'; // tslint:disable: react-unused-props-and-state @@ -46,7 +47,7 @@ const StyledLabel = styled.label<{ outline: var(--color-text) solid 1px; border: none; outline-offset: ${props => props.outlineOffset}px; - margin: ${props => props.beforeMargins || ''}; + ${props => props.beforeMargins && `margin: ${props.beforeMargins};`}; } `; @@ -86,6 +87,7 @@ export const SessionRadio = (props: Props) => { filledSize={filledSize} outlineOffset={outlineOffset} beforeMargins={beforeMargins} + aria-label={label} > {label} @@ -105,7 +107,7 @@ const StyledInputOutlineSelected = styled(StyledInput)` const StyledLabelOutlineSelected = styled(StyledLabel)<{ selectedColor: string }>` :before { background: ${props => props.selectedColor}; - outline: #0000 solid 1px; + outline: ${black} solid 1px; } `; diff --git a/ts/components/basic/SessionToggle.tsx b/ts/components/basic/SessionToggle.tsx index 47f98ed96..4e3c246f3 100644 --- a/ts/components/basic/SessionToggle.tsx +++ b/ts/components/basic/SessionToggle.tsx @@ -2,6 +2,7 @@ import React from 'react'; import { updateConfirmModal } from '../../state/ducks/modalDialog'; import { useDispatch } from 'react-redux'; import styled from 'styled-components'; +import { white } from '../../state/ducks/SessionTheme'; const StyledKnob = styled.div<{ active: boolean }>` position: absolute; @@ -10,7 +11,7 @@ const StyledKnob = styled.div<{ active: boolean }>` height: 21px; width: 21px; border-radius: 28px; - background-color: white; + background-color: ${white}; box-shadow: ${props => props.active ? '-2px 1px 3px rgba(0, 0, 0, 0.15)' : '2px 1px 3px rgba(0, 0, 0, 0.15);'}; @@ -22,7 +23,7 @@ const StyledKnob = styled.div<{ active: boolean }>` const StyledSessionToggle = styled.div<{ active: boolean }>` width: 51px; height: 25px; - border: 1px solid #e5e5ea; + border: 1px solid #e5e5ea; // TODO Theming update border-radius: 16px; position: relative; diff --git a/ts/components/conversation/TypingAnimation.tsx b/ts/components/conversation/TypingAnimation.tsx index 0094acbea..79c1384bc 100644 --- a/ts/components/conversation/TypingAnimation.tsx +++ b/ts/components/conversation/TypingAnimation.tsx @@ -14,7 +14,7 @@ const StyledTypingContainer = styled.div` const StyledTypingDot = styled.div<{ index: number }>` border-radius: 50%; - background-color: var(--color-text-subtle); + background-color: var(--color-text-subtle); // TODO Theming update height: 6px; width: 6px; diff --git a/ts/components/dialog/OnionStatusPathDialog.tsx b/ts/components/dialog/OnionStatusPathDialog.tsx index d598f08df..30a64f9ad 100644 --- a/ts/components/dialog/OnionStatusPathDialog.tsx +++ b/ts/components/dialog/OnionStatusPathDialog.tsx @@ -47,6 +47,25 @@ const StyledOnionDescription = styled.p` width: 0; `; +const StyledVerticalLine = styled.div` + background: rgba(#7a7a7a, 0.6); + position: absolute; + height: calc(100% - 2 * 15px); + margin: 15px calc(100% / 2 - 1px); + + width: 1px; +`; + +const StyledLightsContainer = styled.div` + position: relative; +`; + +const StyledGrowingIcon = styled.div` + flex-grow: 1; + display: flex; + align-items: center; +`; + const OnionCountryDisplay = ({ labelText, snodeIp }: { snodeIp?: string; labelText: string }) => { const element = (hovered: boolean) => ( {hovered && snodeIp ? snodeIp : labelText} @@ -120,25 +139,6 @@ const OnionPathModalInner = () => { ); }; -const StyledVerticalLine = styled.div` - background: rgba(#7a7a7a, 0.6); - position: absolute; - height: calc(100% - 2 * 15px); - margin: 15px calc(100% / 2 - 1px); - - width: 1px; -`; - -const StyledLightsContainer = styled.div` - position: relative; -`; - -const StyledGrowingIcon = styled.div` - flex-grow: 1; - display: flex; - align-items: center; -`; - export type OnionNodeStatusLightType = { glowStartDelay: number; glowDuration: number; diff --git a/ts/components/leftpane/LeftPane.tsx b/ts/components/leftpane/LeftPane.tsx index 4e9be07ce..8bfbe1784 100644 --- a/ts/components/leftpane/LeftPane.tsx +++ b/ts/components/leftpane/LeftPane.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { useSelector } from 'react-redux'; -import { CSSProperties } from 'styled-components'; +import styled from 'styled-components'; import { SectionType } from '../../state/ducks/section'; import { SessionTheme } from '../../state/ducks/SessionTheme'; import { getLeftPaneLists } from '../../state/selectors/conversations'; @@ -12,6 +12,11 @@ import { ActionsPanel } from './ActionsPanel'; import { LeftPaneMessageSection } from './LeftPaneMessageSection'; import { LeftPaneSettingSection } from './LeftPaneSettingSection'; +export const leftPaneListWidth = 300; +const StyledLeftPane = styled.div` + width: ${leftPaneListWidth}px; +`; + const InnerLeftPaneMessageSection = () => { const showSearch = useSelector(isSearching); @@ -46,20 +51,15 @@ const LeftPaneSection = () => { return null; }; -export const leftPaneListWidth = 300; - export const LeftPane = () => { return (
-
+ -
+
); diff --git a/ts/components/leftpane/LeftPaneMessageSection.tsx b/ts/components/leftpane/LeftPaneMessageSection.tsx index 50200990b..49bbaee8e 100644 --- a/ts/components/leftpane/LeftPaneMessageSection.tsx +++ b/ts/components/leftpane/LeftPaneMessageSection.tsx @@ -42,6 +42,13 @@ const StyledConversationListContent = styled.div` background: var(--color-conversation-list); `; +const StyledLeftPaneContent = styled.div` + display: flex; + flex-direction: column; + flex: 1; + overflow: hidden; +`; + const ClosableOverlay = () => { const overlayMode = useSelector(getOverlayMode); @@ -146,10 +153,3 @@ export class LeftPaneMessageSection extends React.Component { ); } } - -const StyledLeftPaneContent = styled.div` - display: flex; - flex-direction: column; - flex: 1; - overflow: hidden; -`; diff --git a/ts/components/settings/BlockedList.tsx b/ts/components/settings/BlockedList.tsx index 9021f1554..e32c80ace 100644 --- a/ts/components/settings/BlockedList.tsx +++ b/ts/components/settings/BlockedList.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; // tslint:disable-next-line: no-submodule-imports import useUpdate from 'react-use/lib/useUpdate'; -import styled, { CSSProperties } from 'styled-components'; +import styled from 'styled-components'; import { useSet } from '../../hooks/useSet'; import { ToastUtils } from '../../session/utils'; import { BlockedNumberController } from '../../util'; @@ -18,14 +18,14 @@ const BlockedEntriesContainer = styled.div` overflow: auto; min-height: 40px; max-height: 100%; - background: var(--blocked-contact-list-bg); + background: var(--color-input-background); // TODO theming update `; const BlockedEntriesRoundedContainer = styled.div` overflow: hidden; border-radius: 16px; padding: var(--margins-lg); - background: var(--blocked-contact-list-bg); + background: var(--color-input-background); // TODO theming update `; const BlockedContactsSection = styled.div` @@ -119,9 +119,7 @@ export const BlockedContactsList = () => { } return ( - + diff --git a/ts/components/settings/SessionNotificationGroupSettings.tsx b/ts/components/settings/SessionNotificationGroupSettings.tsx index 86d2a854f..e5e96256e 100644 --- a/ts/components/settings/SessionNotificationGroupSettings.tsx +++ b/ts/components/settings/SessionNotificationGroupSettings.tsx @@ -57,7 +57,10 @@ export const SessionNotificationGroupSettings = (props: { hasPassword: boolean | Notifications.addNotification( { conversationId: `preview-notification-${Date.now()}`, - message: items.find(m => m.value === initialItem)?.label || 'Message body', + message: + items.find(m => m.value === initialItem)?.label || + window?.i18n?.('messageBody') || + 'Message body', title: window.i18n('notificationPreview'), iconUrl: null, isExpiringMessage: false, diff --git a/ts/components/settings/SessionSettings.tsx b/ts/components/settings/SessionSettings.tsx index 7cc054aba..d991228be 100644 --- a/ts/components/settings/SessionSettings.tsx +++ b/ts/components/settings/SessionSettings.tsx @@ -163,7 +163,7 @@ const SettingInCategory = (props: { case SessionSettingCategory.Permissions: return ; - // those three down there have no options, they are just a button + // these three down there have no options, they are just a button case SessionSettingCategory.ClearData: case SessionSettingCategory.MessageRequests: case SessionSettingCategory.RecoveryPhrase: diff --git a/ts/components/settings/SessionSettingsHeader.tsx b/ts/components/settings/SessionSettingsHeader.tsx index f303a8b1b..42f8f8c01 100644 --- a/ts/components/settings/SessionSettingsHeader.tsx +++ b/ts/components/settings/SessionSettingsHeader.tsx @@ -1,6 +1,5 @@ import React from 'react'; import styled from 'styled-components'; -import { LocalizerKeys } from '../../types/LocalizerKeys'; import { missingCaseError } from '../../util'; import { SessionSettingCategory, SettingsViewProps } from './SessionSettings'; @@ -26,32 +25,30 @@ const StyledHeaderTittle = styled.div` export const SettingsHeader = (props: Props) => { const { category } = props; - let categoryLocalized: LocalizerKeys | null = null; + let categoryTitle: string | null = null; switch (category) { case SessionSettingCategory.Appearance: - categoryLocalized = 'appearanceSettingsTitle'; + categoryTitle = window.i18n('appearanceSettingsTitle'); break; case SessionSettingCategory.Conversations: - categoryLocalized = 'conversationsSettingsTitle'; + categoryTitle = window.i18n('conversationsSettingsTitle'); break; case SessionSettingCategory.Notifications: - categoryLocalized = 'notificationsSettingsTitle'; + categoryTitle = window.i18n('notificationsSettingsTitle'); break; case SessionSettingCategory.Help: - categoryLocalized = 'helpSettingsTitle'; + categoryTitle = window.i18n('helpSettingsTitle'); break; case SessionSettingCategory.Permissions: - categoryLocalized = 'permissionsSettingsTitle'; + categoryTitle = window.i18n('permissionsSettingsTitle'); break; case SessionSettingCategory.Privacy: - categoryLocalized = 'privacySettingsTitle'; + categoryTitle = window.i18n('privacySettingsTitle'); break; default: throw missingCaseError('SettingsHeader' as never); } - const categoryTitle = window.i18n(categoryLocalized); - return ( {categoryTitle} diff --git a/ts/components/settings/SettingsThemeSwitcher.tsx b/ts/components/settings/SettingsThemeSwitcher.tsx index ab7af0f6d..fef3d3bb0 100644 --- a/ts/components/settings/SettingsThemeSwitcher.tsx +++ b/ts/components/settings/SettingsThemeSwitcher.tsx @@ -159,7 +159,7 @@ const Themes = () => { }; export const SettingsThemeSwitcher = () => { - //FIXME store that value somewhere in the theme object + //TODO Theming const [selectedAccent, setSelectedAccent] = useState(undefined); return ( diff --git a/ts/state/ducks/SessionTheme.tsx b/ts/state/ducks/SessionTheme.tsx index 1c42103b7..111a4e918 100644 --- a/ts/state/ducks/SessionTheme.tsx +++ b/ts/state/ducks/SessionTheme.tsx @@ -2,8 +2,8 @@ import React from 'react'; import { createGlobalStyle } from 'styled-components'; -const white = '#ffffff'; -const black = '#000000'; +export const white = '#ffffff'; +export const black = '#000000'; const warning = '#e7b100'; const destructive = '#ff453a'; const accentLightTheme = '#00e97b'; diff --git a/ts/types/LocalizerKeys.ts b/ts/types/LocalizerKeys.ts index 1817fe859..d004aa636 100644 --- a/ts/types/LocalizerKeys.ts +++ b/ts/types/LocalizerKeys.ts @@ -7,6 +7,7 @@ export type LocalizerKeys = | 'startedACall' | 'mainMenuWindow' | 'unblocked' + | 'keepDisabled' | 'userAddedToModerators' | 'otherSingular' | 'to' @@ -390,6 +391,7 @@ export type LocalizerKeys = | 'changeAccountPasswordDescription' | 'notificationSettingsDialog' | 'invalidOldPassword' + | 'messageBody' | 'audioMessageAutoplayTitle' | 'removePasswordInvalid' | 'password' diff --git a/ts/util/blockedNumberController.ts b/ts/util/blockedNumberController.ts index e49a1424e..17616ae95 100644 --- a/ts/util/blockedNumberController.ts +++ b/ts/util/blockedNumberController.ts @@ -88,7 +88,7 @@ export class BlockedNumberController { } /** - * Unblock all thope users. + * Unblock all these users. * This will only unblock the primary device of the user. * * @param user The user to unblock.