From 8abd624c474b7ac04f1c8029352f429f47a04edd Mon Sep 17 00:00:00 2001 From: William Grant Date: Mon, 3 Apr 2023 14:09:04 +0200 Subject: [PATCH] feat: updated right panel in a conversation to use overlay logic in preparation for disappearing messages added panel buttons specific to this UI --- stylesheets/_rtl.scss | 2 +- ...p_panel.scss => _session_right_panel.scss} | 6 +- stylesheets/manifest.scss | 2 +- .../{button => buttons}/MenuButton.tsx | 0 ts/components/buttons/PanelButton.tsx | 76 ++++++++++++++++++ ts/components/buttons/PanelIconButton.tsx | 41 ++++++++++ ts/components/buttons/index.ts | 5 ++ .../conversation/SessionConversation.tsx | 4 +- .../conversation/right-panel/RightPanel.tsx | 25 ++++++ .../overlay/OverlayDisappearingMessages.tsx | 24 ++++++ .../overlay/OverlayRightPanelSettings.tsx} | 78 +++++++++---------- .../leftpane/LeftPaneSectionHeader.tsx | 2 +- ts/state/ducks/section.tsx | 42 ++++++++++ ts/state/selectors/section.ts | 8 +- 14 files changed, 267 insertions(+), 48 deletions(-) rename stylesheets/{_session_group_panel.scss => _session_right_panel.scss} (90%) rename ts/components/{button => buttons}/MenuButton.tsx (100%) create mode 100644 ts/components/buttons/PanelButton.tsx create mode 100644 ts/components/buttons/PanelIconButton.tsx create mode 100644 ts/components/buttons/index.ts create mode 100644 ts/components/conversation/right-panel/RightPanel.tsx create mode 100644 ts/components/conversation/right-panel/overlay/OverlayDisappearingMessages.tsx rename ts/components/conversation/{SessionRightPanel.tsx => right-panel/overlay/OverlayRightPanelSettings.tsx} (85%) diff --git a/stylesheets/_rtl.scss b/stylesheets/_rtl.scss index 264d2fee0..41808e491 100644 --- a/stylesheets/_rtl.scss +++ b/stylesheets/_rtl.scss @@ -3,7 +3,7 @@ body.rtl { textarea, .module-left-pane, .module-conversation-list-item, - .group-settings-item, + .right-panel-item, .contact-selection-list, .group-member-list__selection, .react-contexify__item { diff --git a/stylesheets/_session_group_panel.scss b/stylesheets/_session_right_panel.scss similarity index 90% rename from stylesheets/_session_group_panel.scss rename to stylesheets/_session_right_panel.scss index f2e4e3010..ca4524e42 100644 --- a/stylesheets/_session_group_panel.scss +++ b/stylesheets/_session_right_panel.scss @@ -1,4 +1,4 @@ -.group-settings { +.right-panel { display: flex; flex-direction: column; height: 100vh; @@ -90,10 +90,10 @@ .module-media-grid-item { height: calc( 22vw / 4 - ); //.group-settings is 22vw and we want three rows with some space so divide it by 4 + ); //.right-panel is 22vw and we want three rows with some space so divide it by 4 width: calc( 22vw / 4 - ); //.group-settings is 22vw and we want three rows with some space so divide it by 4 + ); //.right-panel is 22vw and we want three rows with some space so divide it by 4 margin: auto; } } diff --git a/stylesheets/manifest.scss b/stylesheets/manifest.scss index 65e16951a..b4d5d5ae7 100644 --- a/stylesheets/manifest.scss +++ b/stylesheets/manifest.scss @@ -35,7 +35,7 @@ @import 'session_theme'; @import 'session_left_pane'; -@import 'session_group_panel'; +@import 'session_right_panel'; @import 'session_slider'; @import 'session_conversation'; diff --git a/ts/components/button/MenuButton.tsx b/ts/components/buttons/MenuButton.tsx similarity index 100% rename from ts/components/button/MenuButton.tsx rename to ts/components/buttons/MenuButton.tsx diff --git a/ts/components/buttons/PanelButton.tsx b/ts/components/buttons/PanelButton.tsx new file mode 100644 index 000000000..576204f10 --- /dev/null +++ b/ts/components/buttons/PanelButton.tsx @@ -0,0 +1,76 @@ +import React, { ReactNode } from 'react'; +import styled from 'styled-components'; + +const StyledRoundedPanelButtonGroup = styled.div` + overflow: hidden; + background: var(--background-secondary-color); + border: 1px solid var(--border-color); + border-radius: 16px; + padding: var(--margins-lg); + margin: 0 var(--margins-lg); + width: -webkit-fill-available; +`; + +const PanelButtonContainer = styled.div` + overflow: auto; + min-height: 40px; + max-height: 100%; +`; + +export const PanelButtonGroup = ({ children }: { children: ReactNode }) => { + return ( + + {children} + + ); +}; + +const StyledPanelButton = styled.button<{ + disableBg?: 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: '50px'; + width: 100%; + transition: var(--default-duration); + background-color: ${props => + !props.disableBg ? 'var(--conversation-tab-background-selected-color) !important' : null}; + + :not(:last-child) { + border-bottom: 1px solid var(--border-color); + } +`; + +export type PanelButtonProps = { + disableBg?: boolean; + children: ReactNode; + onClick: (...args: any[]) => void; + dataTestId?: string; +}; + +export const PanelButton = (props: PanelButtonProps) => { + const { disableBg, children, onClick, dataTestId } = props; + + return ( + + {children} + + ); +}; diff --git a/ts/components/buttons/PanelIconButton.tsx b/ts/components/buttons/PanelIconButton.tsx new file mode 100644 index 000000000..6ba60c884 --- /dev/null +++ b/ts/components/buttons/PanelIconButton.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import styled from 'styled-components'; +import { SessionIcon, SessionIconType } from '../icon'; +import { PanelButton, PanelButtonProps } from './PanelButton'; + +const StyledContent = styled.div` + display: flex; + align-items: center; + width: 100%; +`; + +const StyledText = styled.span` + font-size: var(--font-size-md); + font-weight: 500; + margin-inline-start: var(--margins-lg); + margin-inline-end: var(--margins-lg); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + width: 100%; + /* TODO needs RTL support */ + text-align: left; +`; + +interface PanelIconButton extends Omit { + iconType: SessionIconType; + text: string; +} + +export const PanelIconButton = (props: PanelIconButton) => { + const { iconType, text, disableBg, onClick, dataTestId } = props; + + return ( + + + + {text} + + + ); +}; diff --git a/ts/components/buttons/index.ts b/ts/components/buttons/index.ts new file mode 100644 index 000000000..063e46fec --- /dev/null +++ b/ts/components/buttons/index.ts @@ -0,0 +1,5 @@ +import { MenuButton } from './MenuButton'; +import { PanelButton, PanelButtonGroup } from './PanelButton'; +import { PanelIconButton } from './PanelIconButton'; + +export { MenuButton, PanelButton, PanelButtonGroup, PanelIconButton }; diff --git a/ts/components/conversation/SessionConversation.tsx b/ts/components/conversation/SessionConversation.tsx index be0c5b4d6..6d8b6bf9c 100644 --- a/ts/components/conversation/SessionConversation.tsx +++ b/ts/components/conversation/SessionConversation.tsx @@ -42,7 +42,6 @@ import { SessionButtonColor } from '../basic/SessionButton'; import { MessageView } from '../MainViewController'; import { ConversationHeaderWithDetails } from './ConversationHeader'; import { MessageDetail } from './message/message-item/MessageDetail'; -import { SessionRightPanelWithDetails } from './SessionRightPanel'; import { makeImageThumbnailBuffer, makeVideoScreenshot, @@ -58,6 +57,7 @@ import { markAllReadByConvoId } from '../../interactions/conversationInteraction import { SessionSpinner } from '../basic/SessionSpinner'; import styled from 'styled-components'; +import { RightPanel } from './right-panel/RightPanel'; // tslint:disable: jsx-curly-spacing interface State { @@ -300,7 +300,7 @@ export class SessionConversation extends React.Component { isRightPanelShowing && 'show' )} > - + )} diff --git a/ts/components/conversation/right-panel/RightPanel.tsx b/ts/components/conversation/right-panel/RightPanel.tsx new file mode 100644 index 000000000..223499b84 --- /dev/null +++ b/ts/components/conversation/right-panel/RightPanel.tsx @@ -0,0 +1,25 @@ +import React from 'react'; + +import { useSelector } from 'react-redux'; +import { getRightOverlayMode } from '../../../state/selectors/section'; +import { OverlayDisappearingMessages } from './overlay/OverlayDisappearingMessages'; +import { OverlayRightPanelSettings } from './overlay/OverlayRightPanelSettings'; + +const ClosableOverlay = () => { + const rightOverlayMode = useSelector(getRightOverlayMode); + switch (rightOverlayMode) { + case 'disappearing-messages': + return ; + case 'panel-settings': + default: + return ; + } +}; + +export const RightPanel = () => { + return ( +
+ +
+ ); +}; diff --git a/ts/components/conversation/right-panel/overlay/OverlayDisappearingMessages.tsx b/ts/components/conversation/right-panel/overlay/OverlayDisappearingMessages.tsx new file mode 100644 index 000000000..b34124ce9 --- /dev/null +++ b/ts/components/conversation/right-panel/overlay/OverlayDisappearingMessages.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { useDispatch } from 'react-redux'; +import { resetRightOverlayMode } from '../../../../state/ducks/section'; + +export const OverlayDisappearingMessages = () => { + const dispatch = useDispatch(); + + function resetOverlay() { + dispatch(resetRightOverlayMode()); + } + + // const timerOptions = useSelector(getTimerOptions).timerOptions; + + // const disappearingMessagesOptions = timerOptions.map(option => { + // return { + // content: option.name, + // onClick: () => { + // void setDisappearingMessagesByConvoId(id, option.value); + // }, + // }; + // }); + + return
TODO
; +}; diff --git a/ts/components/conversation/SessionRightPanel.tsx b/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx similarity index 85% rename from ts/components/conversation/SessionRightPanel.tsx rename to ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx index eefa5970d..b6a3fb040 100644 --- a/ts/components/conversation/SessionRightPanel.tsx +++ b/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx @@ -1,33 +1,35 @@ import React, { useEffect, useState } from 'react'; -import { SessionIconButton } from '../icon'; import _ from 'lodash'; // tslint:disable-next-line: no-submodule-imports import useInterval from 'react-use/lib/useInterval'; import { useDispatch, useSelector } from 'react-redux'; -import { Data } from '../../data/data'; +import { Data } from '../../../../data/data'; import { deleteAllMessagesByConvoIdWithConfirmation, - setDisappearingMessagesByConvoId, showAddModeratorsByConvoId, showInviteContactByConvoId, showLeaveGroupByConvoId, showRemoveModeratorsByConvoId, showUpdateGroupMembersByConvoId, showUpdateGroupNameByConvoId, -} from '../../interactions/conversationInteractions'; -import { Constants } from '../../session'; -import { closeRightPanel } from '../../state/ducks/conversations'; -import { getSelectedConversation, isRightPanelShowing } from '../../state/selectors/conversations'; -import { getTimerOptions } from '../../state/selectors/timerOptions'; -import { AttachmentTypeWithPath } from '../../types/Attachment'; -import { Avatar, AvatarSize } from '../avatar/Avatar'; -import { SessionButton, SessionButtonColor, SessionButtonType } from '../basic/SessionButton'; -import { SessionDropdown } from '../basic/SessionDropdown'; -import { SpacerLG } from '../basic/Text'; -import { MediaItemType } from '../lightbox/LightboxGallery'; -import { MediaGallery } from './media-gallery/MediaGallery'; -import { getAbsoluteAttachmentPath } from '../../types/MessageAttachment'; +} from '../../../../interactions/conversationInteractions'; +import { Constants } from '../../../../session'; +import { + getSelectedConversation, + isRightPanelShowing, +} from '../../../../state/selectors/conversations'; +import { AttachmentTypeWithPath } from '../../../../types/Attachment'; +import { SessionButton, SessionButtonColor, SessionButtonType } from '../../../basic/SessionButton'; +import { SpacerLG } from '../../../basic/Text'; +import { MediaItemType } from '../../../lightbox/LightboxGallery'; +import { MediaGallery } from '../../media-gallery/MediaGallery'; +import { getAbsoluteAttachmentPath } from '../../../../types/MessageAttachment'; import styled from 'styled-components'; +import { SessionIconButton } from '../../../icon'; +import { closeRightPanel } from '../../../../state/ducks/conversations'; +import { Avatar, AvatarSize } from '../../../avatar/Avatar'; +import { setRightOverlayMode } from '../../../../state/ducks/section'; +import { PanelButtonGroup, PanelIconButton } from '../../../buttons'; async function getMediaGalleryProps( conversationId: string @@ -114,7 +116,7 @@ const HeaderItem = () => { const showInviteContacts = isGroup && !isKickedFromGroup && !isBlocked && !left; return ( -
+
{ +export const OverlayRightPanelSettings = () => { const [documents, setDocuments] = useState>([]); const [media, setMedia] = useState>([]); + const dispatch = useDispatch(); const selectedConversation = useSelector(getSelectedConversation); const isShowing = useSelector(isRightPanelShowing); @@ -255,17 +258,6 @@ export const SessionRightPanelWithDetails = () => { ? window.i18n('youLeftTheGroup') : window.i18n('leaveGroup'); - const timerOptions = useSelector(getTimerOptions).timerOptions; - - const disappearingMessagesOptions = timerOptions.map(option => { - return { - content: option.name, - onClick: () => { - void setDisappearingMessagesByConvoId(id, option.value); - }, - }; - }); - const showUpdateGroupNameButton = isGroup && (!isPublic || (isPublic && weAreAdmin)) && !commonNoShow; const showAddRemoveModeratorsButton = weAreAdmin && !commonNoShow && isPublic; @@ -278,8 +270,9 @@ export const SessionRightPanelWithDetails = () => { : () => { showLeaveGroupByConvoId(id); }; + return ( -
+ <> {displayNameInProfile} {showMemberCount && ( @@ -293,7 +286,7 @@ export const SessionRightPanelWithDetails = () => { )} {showUpdateGroupNameButton && ( { await showUpdateGroupNameByConvoId(id); @@ -305,7 +298,7 @@ export const SessionRightPanelWithDetails = () => { {showAddRemoveModeratorsButton && ( <> { showAddModeratorsByConvoId(id); @@ -314,7 +307,7 @@ export const SessionRightPanelWithDetails = () => { {window.i18n('addModerators')} { showRemoveModeratorsByConvoId(id); @@ -327,7 +320,7 @@ export const SessionRightPanelWithDetails = () => { {showUpdateGroupMembersButton && ( { await showUpdateGroupMembersByConvoId(id); @@ -338,10 +331,17 @@ export const SessionRightPanelWithDetails = () => { )} {hasDisappearingMessages && ( - + /* TODO Move ButtonGroup around all settings items */ + + { + dispatch(setRightOverlayMode('disappearing-messages')); + }} + /> + )} @@ -357,6 +357,6 @@ export const SessionRightPanelWithDetails = () => { /> )} -
+ ); }; diff --git a/ts/components/leftpane/LeftPaneSectionHeader.tsx b/ts/components/leftpane/LeftPaneSectionHeader.tsx index 4a9f2b1c9..39ec934f4 100644 --- a/ts/components/leftpane/LeftPaneSectionHeader.tsx +++ b/ts/components/leftpane/LeftPaneSectionHeader.tsx @@ -9,7 +9,7 @@ import { getFocusedSection, getOverlayMode } from '../../state/selectors/section import { SectionType } from '../../state/ducks/section'; import { SessionButton } from '../basic/SessionButton'; import { isSignWithRecoveryPhrase } from '../../util/storage'; -import { MenuButton } from '../button/MenuButton'; +import { MenuButton } from '../buttons'; const SectionTitle = styled.h1` padding-top: var(--margins-xs); diff --git a/ts/state/ducks/section.tsx b/ts/state/ducks/section.tsx index d1e1351e2..09c4bfb97 100644 --- a/ts/state/ducks/section.tsx +++ b/ts/state/ducks/section.tsx @@ -5,6 +5,8 @@ export const FOCUS_SETTINGS_SECTION = 'FOCUS_SETTINGS_SECTION'; export const IS_APP_FOCUSED = 'IS_APP_FOCUSED'; export const OVERLAY_MODE = 'OVERLAY_MODE'; export const RESET_OVERLAY_MODE = 'RESET_OVERLAY_MODE'; +export const RIGHT_OVERLAY_MODE = 'RIGHT_OVERLAY_MODE'; +export const RESET_RIGHT_OVERLAY_MODE = 'RESET_RIGHT_OVERLAY_MODE'; export enum SectionType { Profile, @@ -38,6 +40,15 @@ type ResetOverlayModeActionType = { type: 'RESET_OVERLAY_MODE'; }; +type RightOverlayModeActionType = { + type: 'RIGHT_OVERLAY_MODE'; + payload: RightOverlayMode; +}; + +type ResetRightOverlayModeActionType = { + type: 'RESET_RIGHT_OVERLAY_MODE'; +}; + export function showLeftPaneSection(section: SectionType): FocusSectionActionType { return { type: FOCUS_SECTION, @@ -54,6 +65,7 @@ export function setIsAppFocused(focused: boolean): IsAppFocusedActionType { }; } +// TODO Should be renamed to LeftOverlayMode export type OverlayMode = | 'choose-action' | 'message' @@ -74,6 +86,22 @@ export function resetOverlayMode(): ResetOverlayModeActionType { }; } +// TODO possibly more overlays here +export type RightOverlayMode = 'disappearing-messages' | 'panel-settings'; + +export function setRightOverlayMode(overlayMode: RightOverlayMode): RightOverlayModeActionType { + return { + type: RIGHT_OVERLAY_MODE, + payload: overlayMode, + }; +} + +export function resetRightOverlayMode(): ResetRightOverlayModeActionType { + return { + type: RESET_RIGHT_OVERLAY_MODE, + }; +} + export function showSettingsSection( category: SessionSettingCategory ): FocusSettingsSectionActionType { @@ -88,6 +116,8 @@ export const actions = { showSettingsSection, setOverlayMode, resetOverlayMode, + setRightOverlayMode, + resetRightOverlayMode, }; export const initialSectionState: SectionStateType = { @@ -95,6 +125,7 @@ export const initialSectionState: SectionStateType = { focusedSettingsSection: undefined, isAppFocused: false, overlayMode: undefined, + rightOverlayMode: undefined, }; export type SectionStateType = { @@ -102,6 +133,7 @@ export type SectionStateType = { focusedSettingsSection?: SessionSettingCategory; isAppFocused: boolean; overlayMode: OverlayMode | undefined; + rightOverlayMode: RightOverlayMode | undefined; }; export const reducer = ( @@ -154,6 +186,16 @@ export const reducer = ( ...state, overlayMode: undefined, }; + case RIGHT_OVERLAY_MODE: + return { + ...state, + rightOverlayMode: payload, + }; + case RESET_RIGHT_OVERLAY_MODE: + return { + ...state, + rightOverlayMode: undefined, + }; default: return state; } diff --git a/ts/state/selectors/section.ts b/ts/state/selectors/section.ts index 5c1b1a2bf..3cf72bc7d 100644 --- a/ts/state/selectors/section.ts +++ b/ts/state/selectors/section.ts @@ -1,7 +1,7 @@ import { createSelector } from '@reduxjs/toolkit'; import { StateType } from '../reducer'; -import { OverlayMode, SectionStateType, SectionType } from '../ducks/section'; +import { OverlayMode, RightOverlayMode, SectionStateType, SectionType } from '../ducks/section'; import { SessionSettingCategory } from '../../components/settings/SessionSettings'; export const getSection = (state: StateType): SectionStateType => state.section; @@ -21,7 +21,13 @@ export const getIsAppFocused = createSelector( (state: SectionStateType): boolean => state.isAppFocused ); +// TODO This should probably be renamed to getLeftOverlayMode and the props should be updated. export const getOverlayMode = createSelector( getSection, (state: SectionStateType): OverlayMode | undefined => state.overlayMode ); + +export const getRightOverlayMode = createSelector( + getSection, + (state: SectionStateType): RightOverlayMode | undefined => state.rightOverlayMode +);