diff --git a/_locales/en/messages.json b/_locales/en/messages.json index c301eb74a..7fcb221a7 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -155,9 +155,6 @@ "oceanLightThemeTitle": "Ocean Light", "pruneSettingTitle": "Trim Communities", "pruneSettingDescription": "Delete messages from Communities older than 6 months, and where there are over 2,000 messages.", - "pruningOpengroupDialogTitle": "Community pruning", - "pruningOpengroupDialogMessage": "Pruning old communities messages improves performance. Enable pruning for communities messages older than 6 months?", - "pruningOpengroupDialogSubMessage": "You can change this setting in the Session settings menu", "enable": "Enable", "keepDisabled": "Keep disabled", "notificationSettingsDialog": "The information shown in notifications.", @@ -165,6 +162,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:", @@ -172,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$", @@ -297,7 +299,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", @@ -367,7 +369,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 admin list", "userRemovedFromModerators": "User removed from admin list", @@ -380,7 +382,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", @@ -420,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/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/stylesheets/_global.scss b/stylesheets/_global.scss index 0ec294990..6fb7b4429 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: var(--color-light-gray-color); } } ::-webkit-scrollbar-track { - background: var(--color-scroll-bar-track); + background: none; } audio { diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss index b7f929e6a..8a7feb81c 100644 --- a/stylesheets/_session.scss +++ b/stylesheets/_session.scss @@ -94,7 +94,7 @@ textarea { background-color: var(--color-transparent-color); &.disabled { - cursor: default; + cursor: not-allowed; } &.default, @@ -106,18 +106,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); @@ -182,10 +170,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)); } } } @@ -823,6 +811,8 @@ input { } .contact-selection-list { + display: flex; + flex-direction: column; width: 20vw; } diff --git a/stylesheets/_session_constants.scss b/stylesheets/_session_constants.scss index 7c3671ed2..0096a4d62 100644 --- a/stylesheets/_session_constants.scss +++ b/stylesheets/_session_constants.scss @@ -152,9 +152,6 @@ $session-subtle-factor: 0.6; // ////////////////// Sizing //////////////////// // ////////////////////////////////////////////// -// Default Components -$session-left-pane-width: 300px; - // Various Components $session-modal-size-sm: 220px; $session-modal-size-md: 400px; diff --git a/stylesheets/_session_conversation.scss b/stylesheets/_session_conversation.scss index dfdfffedd..1164bfb5c 100644 --- a/stylesheets/_session_conversation.scss +++ b/stylesheets/_session_conversation.scss @@ -372,38 +372,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: var(--color-darkest-gray-color); - 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 c76855d6a..4e4e2ca29 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: $session-left-pane-width; position: relative; height: 100vh; flex-shrink: 0; diff --git a/stylesheets/_session_signin.scss b/stylesheets/_session_signin.scss index 653f17836..729a76859 100644 --- a/stylesheets/_session_signin.scss +++ b/stylesheets/_session_signin.scss @@ -162,7 +162,6 @@ white-space: nowrap; font-weight: bold; text-decoration: none; - color: var(--color-text-subtle); transition: var(--default-duration); @@ -179,8 +178,8 @@ &-description-long { padding-top: 0; padding-bottom: 20px; - - color: var(--color-text-subtle); + // TODO Theming needs to be updated + 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 02bba9272..3b06be785 100644 --- a/ts/components/MemberListItem.tsx +++ b/ts/components/MemberListItem.tsx @@ -18,39 +18,44 @@ const AvatarItem = (props: { memberPubkey: string; isAdmin: boolean }) => { ); }; -const StyledSessionMemberItem = styled.div<{ +const StyledSessionMemberItem = styled.button<{ inMentions?: boolean; zombie?: boolean; 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; - justify-content: space-between; - transition: var(--default-duration); + 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` 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` @@ -97,7 +102,6 @@ export const MemberListItem = (props: { } : {} } - role="button" data-testid={dataTestId} zombie={isZombie} inMentions={inMentions} @@ -105,7 +109,6 @@ export const MemberListItem = (props: { > - {memberName} diff --git a/ts/components/basic/PillContainer.tsx b/ts/components/basic/PillContainer.tsx index acb2e908a..cc8766fdf 100644 --- a/ts/components/basic/PillContainer.tsx +++ b/ts/components/basic/PillContainer.tsx @@ -6,13 +6,11 @@ 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; flex-direction: 'row'; flex-shrink: 0; @@ -26,7 +24,6 @@ const StyledPillContainerHoverable = styled.div` `; const StyledPillInner = styled.div` - background: green; background: none; display: flex; @@ -42,18 +39,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/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 12d0ce9b0..03a576dd7 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/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 d5ac43457..f949b9313 100644 --- a/ts/components/basic/YourSessionIDPill.tsx +++ b/ts/components/basic/YourSessionIDPill.tsx @@ -35,23 +35,21 @@ 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: 300; 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/button/MenuButton.tsx b/ts/components/button/MenuButton.tsx index 889c966ca..66762fd1e 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; @@ -20,17 +20,13 @@ const StyledMenuButton = styled.label` height: 33px; cursor: pointer; + transition: var(--default-duration); + :hover { background: var(--hover-bg-color); } `; -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 +50,14 @@ export const MenuButton = () => { '--fg-color': 'white', } as CSSProperties } + onClick={onClickFn} > - ); diff --git a/ts/components/conversation/SessionConversation.tsx b/ts/components/conversation/SessionConversation.tsx index 5e54346f5..97ae138db 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/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/conversation/message/reactions/Reaction.tsx b/ts/components/conversation/message/reactions/Reaction.tsx index a1ba40786..a2f4cc0fb 100644 --- a/ts/components/conversation/message/reactions/Reaction.tsx +++ b/ts/components/conversation/message/reactions/Reaction.tsx @@ -51,6 +51,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/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/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/LeftPane.tsx b/ts/components/leftpane/LeftPane.tsx index bdf93d2b3..9378a5f62 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 styled from 'styled-components'; import { SectionType } from '../../state/ducks/section'; import { SessionTheme } from '../../themes/SessionTheme'; import { getLeftPaneLists } from '../../state/selectors/conversations'; @@ -11,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); @@ -51,9 +57,9 @@ export const LeftPane = () => {
-
+ -
+
); 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/leftpane/overlay/OverlayClosedGroup.tsx b/ts/components/leftpane/overlay/OverlayClosedGroup.tsx index 8df5d3cd2..6c606f603 100644 --- a/ts/components/leftpane/overlay/OverlayClosedGroup.tsx +++ b/ts/components/leftpane/overlay/OverlayClosedGroup.tsx @@ -18,6 +18,7 @@ import styled from 'styled-components'; import { SessionSearchInput } from '../../SessionSearchInput'; import { getSearchResults, isSearching } from '../../../state/selectors/search'; import { useSet } from '../../../hooks/useSet'; +import { VALIDATION } from '../../../session/constants'; const StyledMemberListNoContacts = styled.div` font-family: var(--font-font-mono); @@ -90,6 +91,8 @@ export const OverlayClosedGroup = () => { } const contactsToRender = isSearch ? sharedWithResults : privateContactsPubkeys; + const disableCreateButton = !selectedMemberIds.length && !groupName.length; + return (
@@ -99,7 +102,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" @@ -129,13 +132,13 @@ export const OverlayClosedGroup = () => { )} - + 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')); @@ -31,20 +42,18 @@ export const OverlayCommunity = () => { const [loading, setLoading] = useState(false); const [groupUrl, setGroupUrl] = useState(''); + const overlayModeIsCommunity = useSelector(getOverlayMode) === 'open-group'; + function closeOverlay() { 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 { @@ -52,7 +61,22 @@ export const OverlayCommunity = () => { } } - // FIXME autofocus inputref on mount + 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 + } + } + useKey('Escape', closeOverlay); const title = window.i18n('joinOpenGroup'); @@ -72,20 +96,20 @@ export const OverlayCommunity = () => { isGroup={true} maxLength={300} onChange={setGroupUrl} - onPressEnter={onEnterPressed} + onPressEnter={onTryJoinRoom} />
+ + - - {groupUrl && ( - - )} + ); }; diff --git a/ts/components/leftpane/overlay/OverlayMessage.tsx b/ts/components/leftpane/overlay/OverlayMessage.tsx index 6d494b5a7..93a7ede6d 100644 --- a/ts/components/leftpane/overlay/OverlayMessage.tsx +++ b/ts/components/leftpane/overlay/OverlayMessage.tsx @@ -45,13 +45,15 @@ 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, 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(); @@ -105,6 +107,7 @@ export const OverlayMessage = () => { placeholder={placeholder} onChange={setPubkeyOrOns} dataTestId="new-session-conversation" + onPressEnter={handleMessageButtonClick} /> @@ -118,7 +121,8 @@ export const OverlayMessage = () => { 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 > @@ -127,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/SessionJoinableDefaultRooms.tsx b/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx index 9b757d141..4c782bad1 100644 --- a/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx +++ b/ts/components/leftpane/overlay/SessionJoinableDefaultRooms.tsx @@ -1,17 +1,14 @@ -import React, { useCallback, useEffect } from 'react'; +import React, { useEffect } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import styled from 'styled-components'; -import { - joinOpenGroupV2WithUIEvents, - 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'; 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 +18,7 @@ export type JoinableRoomProps = { name: string; roomId: string; imageId?: string; - onClick: (completeUrl: string) => void; + onClick?: (completeUrl: string) => void; base64Data?: string; }; @@ -77,7 +74,7 @@ const SessionJoinableRoomAvatar = (props: JoinableRoomProps) => { base64Data={props.base64Data} {...props} pubkey="" - onAvatarClick={() => props.onClick(props.completeUrl)} + onAvatarClick={() => props.onClick?.(props.completeUrl)} /> ); }; @@ -94,64 +91,68 @@ 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: { + alreadyJoining: boolean; + onJoinClick?: (completeUrl: string) => void; +}) => { const joinableRooms = useSelector((state: StateType) => state.defaultRooms); - const onRoomClicked = useCallback( - (loading: boolean) => { - if (loading) { - props.onRoomClicked(); - } - }, - [props.onRoomClicked] + return ( + <> + {joinableRooms.rooms.map(r => { + return ( + + ); + })} + ); +}; + +export const SessionJoinableRooms = (props: { + onJoinClick?: (completeUrl: string) => 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/ContactRow.tsx b/ts/components/leftpane/overlay/choose-action/ContactRow.tsx index a1883bc7e..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); @@ -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..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'; @@ -93,11 +94,11 @@ 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} - width={300} // the same as session-left-pane-width + width={leftPaneListWidth} autoHeight={false} /> ); @@ -113,7 +114,9 @@ const ContactsTitle = () => { return null; } - return {window.i18n('contactsHeader')}; + return ( + {window.i18n('contactsHeader')} + ); }; export const ContactsListWithBreaks = () => { 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/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 b0abfad4f..0ca644a60 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/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() && ( void + uiCallback?: (args: JoinSogsRoomUICallbackArgs) => void ): Promise { try { const parsedRoom = parseOpenGroupV2(completeUrl); @@ -142,9 +147,9 @@ 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); const isConvoCreated = getConversationController().get(conversationID); @@ -155,21 +160,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 27a0bc550..99e925faa 100644 --- a/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts +++ b/ts/session/apis/open_group_api/opengroupV2/OpenGroupServerPoller.ts @@ -20,6 +20,10 @@ import { roomHasBlindEnabled, } from '../sogsv3/sogsV3Capabilities'; import { OpenGroupReaction } from '../../../../types/Reaction'; +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 */ @@ -317,6 +321,36 @@ 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); + + 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) { window?.log?.warn('Got error while compact fetch:', e.message); } finally { 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/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/ducks/section.tsx b/ts/state/ducks/section.tsx index 89bc0980b..9c0ffcd7f 100644 --- a/ts/state/ducks/section.tsx +++ b/ts/state/ducks/section.tsx @@ -92,6 +92,7 @@ export const actions = { export const initialSectionState: SectionStateType = { focusedSection: SectionType.Message, + focusedSettingsSection: undefined, isAppFocused: false, overlayMode: undefined, }; 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/themes/SessionTheme.tsx b/ts/themes/SessionTheme.tsx index 786181b56..98c3dba6f 100644 --- a/ts/themes/SessionTheme.tsx +++ b/ts/themes/SessionTheme.tsx @@ -74,7 +74,6 @@ const darkFilterSessionText = 'none'; const darkUnreadBorder = `4px solid ${accentDarkTheme}`; const darkScrollbarThumb = darkGrayColor; -const darkScrollbarTrack = '#1b1b1b'; const darkFakeChatBubbleBg = '#212121'; const darkInboxBackground = '#171717'; @@ -150,7 +149,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 @@ -225,7 +223,6 @@ const lightFilterSessionText = 'brightness(0) saturate(100%)'; const lightUnreadBorder = `4px solid ${accentLightTheme}`; const lightScrollbarThumb = darkGrayColor; -const lightScrollbarTrack = '#fcfcfc'; const lightFakeChatBubbleBg = '#f5f5f5'; const lightInboxBackground = whiteColor; @@ -307,7 +304,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 @@ -445,7 +441,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}; diff --git a/ts/types/LocalizerKeys.ts b/ts/types/LocalizerKeys.ts index e6d317dfb..d004aa636 100644 --- a/ts/types/LocalizerKeys.ts +++ b/ts/types/LocalizerKeys.ts @@ -67,6 +67,7 @@ export type LocalizerKeys = | 'timerOption_1_hour' | 'youGotKickedFromGroup' | 'cannotRemoveCreatorFromGroupDesc' + | 'contactAvatarAlt' | 'incomingError' | 'notificationsSettingsTitle' | 'conversationsSettingsTitle' @@ -75,6 +76,7 @@ export type LocalizerKeys = | 'from' | 'requestsSubtitle' | 'thisMonth' + | 'chooseAnAction' | 'next' | 'addModerators' | 'sessionMessenger' @@ -122,7 +124,6 @@ export type LocalizerKeys = | 'deleteJustForMe' | 'changeAccountPasswordTitle' | 'onionPathIndicatorDescription' - | 'pruningOpengroupDialogSubMessage' | 'mediaPermissionsTitle' | 'replyingToMessage' | 'welcomeToYourSession' @@ -176,6 +177,7 @@ export type LocalizerKeys = | 'copyOpenGroupURL' | 'setPasswordInvalid' | 'timerOption_30_seconds_abbreviated' + | 'createConversationNewContact' | 'removeResidueMembers' | 'areYouSureDeleteEntireAccount' | 'noGivenPassword' @@ -256,7 +258,6 @@ export type LocalizerKeys = | 'goToSupportPage' | 'passwordsDoNotMatch' | 'createClosedGroupNamePrompt' - | 'pruningOpengroupDialogMessage' | 'audioMessageAutoplayDescription' | 'leaveAndRemoveForEveryone' | 'previewThumbnail' @@ -267,6 +268,7 @@ export type LocalizerKeys = | 'reactionPopupOne' | 'imageCaptionIconAlt' | 'sendRecoveryPhraseTitle' + | 'joinACommunity' | 'multipleJoinedTheGroup' | 'messageRequestAcceptedOursNoName' | 'databaseError' @@ -335,8 +337,7 @@ export type LocalizerKeys = | 'respondingToRequestWarning' | 'error' | 'clearAllData' - | 'pruningOpengroupDialogTitle' - | 'contactAvatarAlt' + | 'createConversationNewGroup' | 'disappearingMessages' | 'autoUpdateNewVersionTitle' | 'linkPreviewDescription' @@ -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. diff --git a/ts/window.d.ts b/ts/window.d.ts index 8071c232d..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; @@ -21,11 +22,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; @@ -38,6 +35,7 @@ declare global { sessionFeatureFlags: { useOnionRequests: boolean; useTestNet: boolean; + useSettingsThemeSwitcher: boolean; debug: { debugFileServerRequests: boolean; debugNonSnodeRequests: boolean;