diff --git a/stylesheets/_session.scss b/stylesheets/_session.scss
index a8759c621..377e6e2b8 100644
--- a/stylesheets/_session.scss
+++ b/stylesheets/_session.scss
@@ -602,12 +602,6 @@ input {
}
}
-.module-message-detail {
- .module-message {
- pointer-events: none;
- }
-}
-
.module-message__text {
white-space: pre-wrap;
}
diff --git a/stylesheets/_session_conversation.scss b/stylesheets/_session_conversation.scss
index 80a70a4f3..dcb3ca23a 100644
--- a/stylesheets/_session_conversation.scss
+++ b/stylesheets/_session_conversation.scss
@@ -18,15 +18,16 @@
}
}
+// TODO move this into the right panel as Styled container component
.conversation-item__options-pane {
position: absolute;
- height: 100%;
+ height: var(--right-panel-height);
right: 0vw;
transition: transform 0.3s ease-in-out;
transform: translateX(100%);
will-change: transform;
- width: 25vw;
+ width: var(--right-panel-width);
z-index: 5;
background-color: var(--background-primary-color);
@@ -91,6 +92,11 @@
flex-direction: column;
position: relative;
outline: none;
+ height: inherit;
+
+ &-left {
+ flex-grow: 1;
+ }
.conversation-messages {
display: flex;
@@ -104,24 +110,6 @@
background-color: var(--background-secondary-color);
border-top: 1px solid var(--border-color);
}
-
- .conversation-info-panel {
- position: absolute;
- justify-content: flex-start;
- flex-direction: column;
- align-items: center;
- height: 100%;
- width: 100%;
- z-index: 5; // to be sure to hide the borders of images in messages
- background-color: inherit;
- display: none;
- padding: 20px;
-
- &.show {
- display: flex;
- background: var(--background-primary-color);
- }
- }
}
.composition-container {
diff --git a/stylesheets/_session_right_panel.scss b/stylesheets/_session_right_panel.scss
index a199edeb7..4a0e3cef5 100644
--- a/stylesheets/_session_right_panel.scss
+++ b/stylesheets/_session_right_panel.scss
@@ -1,106 +1,4 @@
-.right-panel {
- display: flex;
- flex-direction: column;
- height: 100%;
- width: -webkit-fill-available;
-
- align-items: center;
-
- &-header {
- margin-top: var(--margins-lg);
- margin-inline-start: var(--margins-sm);
- margin-inline-end: var(--margins-sm);
- width: -webkit-fill-available;
- display: flex;
- flex-direction: row;
- flex-shrink: 0;
-
- .module-avatar {
- margin: auto;
- }
- }
-
- h2 {
- word-break: break-word;
- }
-
- .description {
- margin: var(--margins-md) 0;
- min-height: 4rem;
- width: inherit;
- color: var(--text-secondary-color);
- text-align: center;
- display: none;
- }
-
- // no double border (top and bottom) between two elements
- &-item + &-item {
- border-top: none;
- }
-
- .module-empty-state {
- text-align: center;
- }
-
- .module-attachment-section__items {
- &-media {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- width: 100%;
- }
-
- &-documents {
- width: 100%;
- }
- }
-
- .module-media {
- &-gallery {
- &__tab-container {
- padding-top: 1rem;
- }
-
- &__tab {
- color: var(--text-primary-color);
- font-weight: bold;
- font-size: 0.9rem;
- padding: 0.6rem;
- opacity: 0.8;
-
- &--active {
- border-bottom: none;
- opacity: 1;
-
- &:after {
- content: ''; /* This is necessary for the pseudo element to work. */
- display: block;
- margin: 0 auto;
- width: 70%;
- padding-top: 0.5rem;
- border-bottom: 4px solid var(--primary-color);
- }
- }
- }
-
- &__content {
- padding: var(--margins-xs);
- margin-bottom: 1vh;
-
- .module-media-grid-item__image,
- .module-media-grid-item {
- height: calc(
- 22vw / 4
- ); //.right-panel is 22vw and we want three rows with some space so divide it by 4
- width: calc(
- 22vw / 4
- ); //.right-panel is 22vw and we want three rows with some space so divide it by 4
- margin: auto;
- }
- }
- }
- }
-}
-
+// TODO is this being used
.conversation-content {
display: flex;
height: inherit;
diff --git a/ts/components/buttons/PanelButton.tsx b/ts/components/buttons/PanelButton.tsx
index d8fd31c81..8743b61d9 100644
--- a/ts/components/buttons/PanelButton.tsx
+++ b/ts/components/buttons/PanelButton.tsx
@@ -1,5 +1,6 @@
import React, { ReactNode } from 'react';
import styled, { CSSProperties } from 'styled-components';
+import { Flex } from '../basic/Flex';
// NOTE Used for descendant components
export const StyledContent = styled.div<{ disabled: boolean }>`
@@ -44,7 +45,9 @@ const StyledRoundedPanelButtonGroup = styled.div`
const PanelButtonContainer = styled.div`
overflow: auto;
- min-height: 50px;
+ // TODO clear
+ /* min-height: 50px; */
+ min-height: 40px;
max-height: 100%;
`;
@@ -108,3 +111,26 @@ export const PanelButton = (props: PanelButtonProps) => {
);
};
+
+const StyledSubtitle = styled.p<{ color?: string }>`
+ font-size: var(--font-size-xs);
+ margin: 0;
+ text-align: initial;
+ ${props => props.color && `color: ${props.color};`}
+`;
+
+export const PanelButtonText = (props: { text: string; subtitle?: string; color?: string }) => {
+ return (
+
+ {props.text}
+ {!!props.subtitle && {props.subtitle}}
+
+ );
+};
diff --git a/ts/components/buttons/PanelIconButton.tsx b/ts/components/buttons/PanelIconButton.tsx
index 9059fac04..f47c6e687 100644
--- a/ts/components/buttons/PanelIconButton.tsx
+++ b/ts/components/buttons/PanelIconButton.tsx
@@ -1,20 +1,30 @@
import React from 'react';
+import styled from 'styled-components';
import { SessionIcon, SessionIconType } from '../icon';
-import { PanelButton, PanelButtonProps, StyledContent, StyledText } from './PanelButton';
+import { PanelButton, PanelButtonProps, PanelButtonText, StyledContent } from './PanelButton';
interface PanelIconButton extends Omit {
iconType: SessionIconType;
text: string;
+ subtitle?: string;
+ color?: string;
}
+const IconContainer = styled.div`
+ flex-shrink: 0;
+ width: var(--toggle-width);
+`;
+
export const PanelIconButton = (props: PanelIconButton) => {
- const { iconType, text, disabled = false, onClick, dataTestId } = props;
+ const { iconType, text, subtitle, color, disabled = false, onClick, dataTestId } = props;
return (
-
- {text}
+
+
+
+
);
diff --git a/ts/components/buttons/PanelRadioButton.tsx b/ts/components/buttons/PanelRadioButton.tsx
index 4b7969a97..af7936bb3 100644
--- a/ts/components/buttons/PanelRadioButton.tsx
+++ b/ts/components/buttons/PanelRadioButton.tsx
@@ -1,8 +1,7 @@
import React from 'react';
import styled from 'styled-components';
-import { Flex } from '../basic/Flex';
import { SessionRadio } from '../basic/SessionRadio';
-import { PanelButton, PanelButtonProps, StyledContent, StyledText } from './PanelButton';
+import { PanelButton, PanelButtonProps, PanelButtonText, StyledContent } from './PanelButton';
const StyledPanelButton = styled(PanelButton)`
padding-top: var(--margins-lg);
@@ -15,19 +14,6 @@ const StyledPanelButton = styled(PanelButton)`
margin-inline-end: 0;
}
}
-
- :first-child {
- padding-top: 0;
- }
-
- :last-child {
- padding-bottom: 0;
- }
-`;
-
-const StyledSubtitle = styled.p`
- font-size: var(--font-size-xs);
- margin: 0;
`;
const StyledCheckContainer = styled.div`
@@ -65,10 +51,7 @@ export const PanelRadioButton = (props: PanelRadioButtonProps) => {
dataTestId={dataTestId}
>
-
- {text}
- {subtitle && {subtitle}}
-
+
{
}
if (visibleSubtitle === 'disappearingMessages') {
- dispatch(setRightOverlayMode('disappearing-messages'));
+ dispatch(setRightOverlayMode({ type: 'disappearing_messages', params: null }));
} else {
dispatch(resetRightOverlayMode());
}
diff --git a/ts/components/conversation/message/message-content/MessageContent.tsx b/ts/components/conversation/message/message-content/MessageContent.tsx
index d6a5249d8..6a4a2470f 100644
--- a/ts/components/conversation/message/message-content/MessageContent.tsx
+++ b/ts/components/conversation/message/message-content/MessageContent.tsx
@@ -13,6 +13,7 @@ import {
getQuotedMessageToAnimate,
getShouldHighlightMessage,
} from '../../../../state/selectors/conversations';
+import { canDisplayImage } from '../../../../types/Attachment';
import { ScrollToLoadedMessageContext } from '../../SessionMessagesListContainer';
import { MessageAttachment } from './MessageAttachment';
import { MessageLinkPreview } from './MessageLinkPreview';
@@ -156,12 +157,23 @@ export const MessageContent = (props: Props) => {
return null;
}
- const { direction, text, timestamp, serverTimestamp, previews, quote } = contentProps;
+ const {
+ direction,
+ text,
+ timestamp,
+ serverTimestamp,
+ previews,
+ quote,
+ attachments,
+ } = contentProps;
const hasContentBeforeAttachment = !isEmpty(previews) || !isEmpty(quote) || !isEmpty(text);
const toolTipTitle = moment(serverTimestamp || timestamp).format('llll');
+ const isDetailViewAndSupportsAttachmentCarousel =
+ props.isDetailView && canDisplayImage(attachments);
+
return (
{
)}
- {!isDeleted && (
+ {!isDeleted && isDetailViewAndSupportsAttachmentCarousel && !imageBroken ? null : (
{
return showRetry ? - {window.i18n('resend')}
: null;
};
+export const showMessageInfoOverlay = async ({
+ messageId,
+ dispatch,
+}: {
+ messageId: string;
+ dispatch: Dispatch;
+}) => {
+ const found = await Data.getMessageById(messageId);
+ if (found) {
+ const messageDetailsProps = await found.getPropsForMessageDetail();
+ dispatch(showMessageDetailsView(messageDetailsProps));
+ dispatch(
+ setRightOverlayMode({
+ type: 'message_info',
+ params: { messageId, visibleAttachmentIndex: 0 },
+ })
+ );
+ dispatch(openRightPanel());
+ } else {
+ window.log.warn(`[showMessageInfoOverlay] Message ${messageId} not found in db`);
+ }
+};
+
export const MessageContextMenu = (props: Props) => {
const { messageId, contextMenuId, enableReactions } = props;
const dispatch = useDispatch();
@@ -214,16 +239,6 @@ export const MessageContextMenu = (props: Props) => {
[showEmojiPanel]
);
- const onShowDetail = async () => {
- const found = await Data.getMessageById(messageId);
- if (found) {
- const messageDetailsProps = await found.getPropsForMessageDetail();
- dispatch(showMessageDetailsView(messageDetailsProps));
- } else {
- window.log.warn(`Message ${messageId} not found in db`);
- }
- };
-
const selectMessageText = window.i18n('selectMessage');
const deleteMessageJustForMeText = window.i18n('deleteJustForMe');
@@ -361,9 +376,13 @@ export const MessageContextMenu = (props: Props) => {
{(isSent || !isOutgoing) && (
- {window.i18n('replyToMessage')}
)}
- {(!isPublic || isOutgoing) && (
- - {window.i18n('moreInformation')}
- )}
+ - {
+ await showMessageInfoOverlay({ messageId, dispatch });
+ }}
+ >
+ {window.i18n('moreInformation')}
+
{isDeletable ? - {selectMessageText}
: null}
{isDeletable && !isPublic ? (
diff --git a/ts/components/conversation/message/message-content/MessageQuote.tsx b/ts/components/conversation/message/message-content/MessageQuote.tsx
index 84ab7e082..9a57d7a64 100644
--- a/ts/components/conversation/message/message-content/MessageQuote.tsx
+++ b/ts/components/conversation/message/message-content/MessageQuote.tsx
@@ -7,10 +7,7 @@ import { ToastUtils } from '../../../../session/utils';
import { openConversationToSpecificMessage } from '../../../../state/ducks/conversations';
import { StateType } from '../../../../state/reducer';
import { useMessageDirection } from '../../../../state/selectors';
-import {
- getMessageQuoteProps,
- isMessageDetailView,
-} from '../../../../state/selectors/conversations';
+import { getMessageQuoteProps } from '../../../../state/selectors/conversations';
import { Quote } from './quote/Quote';
type Props = {
@@ -22,7 +19,6 @@ export type MessageQuoteSelectorProps = Pick {
const selected = useSelector((state: StateType) => getMessageQuoteProps(state, props.messageId));
const direction = useMessageDirection(props.messageId);
- const isMessageDetailViewMode = useSelector(isMessageDetailView);
if (!selected || isEmpty(selected)) {
return null;
@@ -48,11 +44,6 @@ export const MessageQuote = (props: Props) => {
return;
}
- if (isMessageDetailViewMode) {
- // trying to scroll while in the container while the message detail view is shown has unknown effects
- return;
- }
-
let conversationKey = String(quote.convoId);
let messageIdToNavigateTo = String(quote.id);
let quoteNotFoundInDB = false;
diff --git a/ts/components/conversation/right-panel/RightPanel.tsx b/ts/components/conversation/right-panel/RightPanel.tsx
index 56afed854..e636c06e9 100644
--- a/ts/components/conversation/right-panel/RightPanel.tsx
+++ b/ts/components/conversation/right-panel/RightPanel.tsx
@@ -1,15 +1,92 @@
import React from 'react';
+import styled from 'styled-components';
import { useRightOverlayMode } from '../../../hooks/useUI';
+import { Flex } from '../../basic/Flex';
import { OverlayRightPanelSettings } from './overlay/OverlayRightPanelSettings';
import { OverlayDisappearingMessages } from './overlay/disappearing-messages/OverlayDisappearingMessages';
+const StyledRightPanel = styled(Flex)`
+ h2 {
+ word-break: break-word;
+ }
+ .description {
+ margin: var(--margins-md) 0;
+ min-height: 4rem;
+ width: inherit;
+ color: var(--text-secondary-color);
+ text-align: center;
+ display: none;
+ }
+ // no double border (top and bottom) between two elements
+ &-item + &-item {
+ border-top: none;
+ }
+ .module-empty-state {
+ text-align: center;
+ }
+ .module-attachment-section__items {
+ &-media {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ width: 100%;
+ }
+ &-documents {
+ width: 100%;
+ }
+ }
+ .module-media {
+ &-gallery {
+ &__tab-container {
+ padding-top: 1rem;
+ }
+ &__tab {
+ color: var(--text-primary-color);
+ font-weight: bold;
+ font-size: 0.9rem;
+ padding: 0.6rem;
+ opacity: 0.8;
+ &--active {
+ border-bottom: none;
+ opacity: 1;
+ &:after {
+ content: ''; /* This is necessary for the pseudo element to work. */
+ display: block;
+ margin: 0 auto;
+ width: 70%;
+ padding-top: 0.5rem;
+ border-bottom: 4px solid var(--primary-color);
+ }
+ }
+ }
+ &__content {
+ padding: var(--margins-xs);
+ margin-bottom: 1vh;
+ .module-media-grid-item__image,
+ .module-media-grid-item {
+ height: calc(
+ var(--right-panel-width) / 4
+ ); //.right-panel is var(--right-panel-width) and we want three rows with some space so divide it by 4
+ width: calc(
+ var(--right-panel-width) / 4
+ ); //.right-panel is var(--right-panel-width) and we want three rows with some space so divide it by 4
+ margin: auto;
+ }
+ }
+ }
+ }
+`;
+
const ClosableOverlay = () => {
const rightOverlayMode = useRightOverlayMode();
- switch (rightOverlayMode) {
- case 'disappearing-messages':
+ switch (rightOverlayMode?.type) {
+ case 'disappearing_messages':
return ;
+ case 'message_info':
+ // TODO: copy this
+ // return ;
+ return <>>;
default:
return ;
}
@@ -17,8 +94,15 @@ const ClosableOverlay = () => {
export const RightPanel = () => {
return (
-
+
-
+
);
};
diff --git a/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx b/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx
index cd96706e0..8f6d5cdf6 100644
--- a/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx
+++ b/ts/components/conversation/right-panel/overlay/OverlayRightPanelSettings.tsx
@@ -355,7 +355,7 @@ export const OverlayRightPanelSettings = () => {
iconType={'timer50'}
text={window.i18n('disappearingMessages')}
onClick={() => {
- dispatch(setRightOverlayMode('disappearing-messages'));
+ dispatch(setRightOverlayMode({ type: 'disappearing_messages', params: null }));
}}
/>
diff --git a/ts/state/ducks/section.tsx b/ts/state/ducks/section.tsx
index e68be2d05..0992649ad 100644
--- a/ts/state/ducks/section.tsx
+++ b/ts/state/ducks/section.tsx
@@ -87,8 +87,17 @@ export function resetOverlayMode(): ResetOverlayModeActionType {
};
}
-// TODO possibly more overlays here
-export type RightOverlayMode = 'disappearing-messages';
+type RightPanelDefaultState = { type: 'default'; params: null };
+type RightPanelMessageInfoState = {
+ type: 'message_info';
+ params: { messageId: string; visibleAttachmentIndex: number | undefined };
+};
+type RightPanelDisappearingMessagesState = { type: 'disappearing_messages'; params: null };
+
+export type RightOverlayMode =
+ | RightPanelDefaultState
+ | RightPanelMessageInfoState
+ | RightPanelDisappearingMessagesState;
export function setRightOverlayMode(overlayMode: RightOverlayMode): RightOverlayModeActionType {
return {
@@ -126,7 +135,7 @@ export const initialSectionState: SectionStateType = {
focusedSettingsSection: undefined,
isAppFocused: false,
overlayMode: undefined,
- rightOverlayMode: undefined,
+ rightOverlayMode: { type: 'default', params: null },
};
export type SectionStateType = {