Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add responsivity to conversation view acc-63 #13717

Merged
merged 18 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 76 additions & 16 deletions src/script/components/InputBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ import {TeamState} from '../../team/TeamState';
import {UserState} from '../../user/UserState';
import {SearchRepository} from '../../search/SearchRepository';
import {ContentMessage} from '../../entity/message/ContentMessage';
import InputBarControls from '../../page/message-list/InputBarControls';
import {Conversation} from '../../entity/Conversation';
import {AssetRepository} from '../../assets/AssetRepository';
import {ConversationRepository} from '../../conversation/ConversationRepository';
Expand All @@ -82,7 +81,10 @@ import useScrollSync from '../../hooks/useScrollSync';
import useResizeTarget from '../../hooks/useResizeTarget';
import useDropFiles from '../../hooks/useDropFiles';
import useTextAreaFocus from '../../hooks/useTextAreaFocus';
import {StyledApp, THEME_ID} from '@wireapp/react-ui-kit';
import {StyledApp, THEME_ID, useMatchMedia} from '@wireapp/react-ui-kit';
import ControlButtons from '../../page/message-list/InputBarControls/ControlButtons';
import Icon from 'Components/Icon';
import GiphyButton from '../../page/message-list/InputBarControls/GiphyButton';

const CONFIG = {
...Config.getConfig(),
Expand Down Expand Up @@ -193,6 +195,14 @@ const InputBar = ({

const richTextInput = getRichTextInput(currentMentions, inputValue);

const isScaledDown = useMatchMedia('max-width: 768px');

const config = {
GIPHY_TEXT_LENGTH: 256,
};

const showGiphyButton = inputValue.length > 0 && inputValue.length <= config.GIPHY_TEXT_LENGTH;

const updateSelectionState = (updateOnInit = true) => {
if (!updateOnInit) {
return;
Expand Down Expand Up @@ -861,20 +871,70 @@ const InputBar = ({
suggestions={mentionSuggestions}
onSelectionValidated={addMention}
/>

<InputBarControls
conversation={conversationEntity}
input={inputValue}
isEditing={isEditing}
disablePing={pingDisabled}
disableFilesharing={!isFileSharingSendingEnabled}
onSend={() => onSend(inputValue)}
onSelectFiles={uploadFiles}
onSelectImages={uploadImages}
onCancelEditing={cancelMessageEditing}
onClickGif={onGifClick}
onClickPing={onPingClick}
/>
{isScaledDown ? (
<>
<ul className="controls-right buttons-group" css={{minWidth: '95px'}}>
{showGiphyButton && <GiphyButton onGifClick={onGifClick} />}
<li>
<button
type="button"
className={cx('controls-right-button controls-right-button--send')}
disabled={inputValue.length === 0}
title={t('tooltipConversationSendMessage')}
aria-label={t('tooltipConversationSendMessage')}
onClick={() => onSend(inputValue)}
data-uie-name="do-send-message"
>
<Icon.Send />
</button>
</li>
</ul>
<ul className="controls-right buttons-group" css={{justifyContent: 'center', width: '100%'}}>
<ControlButtons
conversation={conversationEntity}
input={inputValue}
isEditing={isEditing}
isScaledDown={isScaledDown}
disablePing={pingDisabled}
disableFilesharing={!isFileSharingSendingEnabled}
onSelectFiles={uploadFiles}
onSelectImages={uploadImages}
onCancelEditing={cancelMessageEditing}
onGifClick={onGifClick}
onClickPing={onPingClick}
V-Gira marked this conversation as resolved.
Show resolved Hide resolved
/>
</ul>
</>
) : (
<ul className="controls-right buttons-group">
<ControlButtons
conversation={conversationEntity}
input={inputValue}
isEditing={isEditing}
disablePing={pingDisabled}
disableFilesharing={!isFileSharingSendingEnabled}
showGiphyButton={showGiphyButton}
onSelectFiles={uploadFiles}
onSelectImages={uploadImages}
onCancelEditing={cancelMessageEditing}
onGifClick={onGifClick}
onClickPing={onPingClick}
/>
<li>
<button
type="button"
className={cx('controls-right-button controls-right-button--send')}
disabled={inputValue.length === 0}
title={t('tooltipConversationSendMessage')}
aria-label={t('tooltipConversationSendMessage')}
onClick={() => onSend(inputValue)}
data-uie-name="do-send-message"
>
<Icon.Send />
</button>
</li>
</ul>
)}
</>
)}
</>
Expand Down
10 changes: 10 additions & 0 deletions src/script/components/TitleBar/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ import {User} from '../../entity/User';
import {QualifiedId} from '@wireapp/api-client/src/user';
import {amplify} from 'amplify';
import {ContentViewModel} from '../../view_model/ContentViewModel';
import * as uiKit from '@wireapp/react-ui-kit';

jest.mock('@wireapp/react-ui-kit', () => ({
...jest.requireActual('@wireapp/react-ui-kit'),
useMatchMedia: jest.fn(),
}));

const mockedUiKit = uiKit as jest.Mocked<typeof uiKit>;

jest.spyOn(Runtime, 'isSupportingConferenceCalling').mockReturnValue(true);

Expand Down Expand Up @@ -137,6 +145,8 @@ describe('TitleBar', () => {
const panelViewModel = createPanelViewModel();
const conversation = createConversationEntity();

mockedUiKit.useMatchMedia.mockReturnValue(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

challenge for you: write a test that checks that the component renders correctly when the view is scaledDown 😉


const {getByLabelText} = render(
<TitleBar
{...getDefaultProps(callingRepository)}
Expand Down
209 changes: 120 additions & 89 deletions src/script/components/TitleBar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {CallActions} from '../../view_model/CallingViewModel';
import {handleKeyDown} from 'Util/KeyboardUtil';
import {PanelViewModel} from '../../view_model/PanelViewModel';
import {TIME_IN_MILLIS} from 'Util/TimeUtil';
import {IconButton, StyledApp, THEME_ID, useMatchMedia} from '@wireapp/react-ui-kit';

export interface TitleBarProps {
conversation: Conversation;
Expand Down Expand Up @@ -131,6 +132,8 @@ const TitleBar: React.FC<TitleBarProps> = ({
const shortcut = Shortcut.getShortcutTooltip(ShortcutType.PEOPLE);
const peopleTooltip = t('tooltipConversationPeople', shortcut);

const isScaledDown = useMatchMedia('max-width: 768px');

const showDetails = useCallback(
(addParticipants: boolean): void => {
const panelId = addParticipants
Expand Down Expand Up @@ -183,109 +186,137 @@ const TitleBar: React.FC<TitleBarProps> = ({
};

return (
<ul id="conversation-title-bar" className="conversation-title-bar">
<li className="conversation-title-bar-library">
{isActivatedAccount && (
<button
className="conversation-title-bar-icon icon-search"
type="button"
title={t('tooltipConversationSearch')}
aria-label={t('tooltipConversationSearch')}
onClick={onClickCollectionButton}
data-uie-name="do-collections"
<StyledApp themeId={THEME_ID.DEFAULT}>
<ul id="conversation-title-bar" className="conversation-title-bar">
<li className="conversation-title-bar-library">
{isActivatedAccount && !isScaledDown && (
<button
className="conversation-title-bar-icon icon-search"
type="button"
title={t('tooltipConversationSearch')}
aria-label={t('tooltipConversationSearch')}
onClick={onClickCollectionButton}
data-uie-name="do-collections"
>
<span className="visually-hidden">{t('tooltipConversationSearch')}</span>
</button>
)}
</li>

<li className="conversation-title-bar-name">
<div
id="show-participants"
onClick={onClickDetails}
title={peopleTooltip}
aria-label={peopleTooltip}
onKeyDown={e => handleKeyDown(e, onClickDetails)}
data-placement="bottom"
role="button"
tabIndex={0}
data-uie-name="do-participants"
>
<span className="visually-hidden">{t('tooltipConversationSearch')}</span>
</button>
)}
</li>

<li className="conversation-title-bar-name">
<div
id="show-participants"
onClick={onClickDetails}
title={peopleTooltip}
aria-label={peopleTooltip}
onKeyDown={e => handleKeyDown(e, onClickDetails)}
data-placement="bottom"
role="button"
tabIndex={0}
data-uie-name="do-participants"
>
<div className="conversation-title-bar-name-label--wrapper">
{hasLegalHold && (
<LegalHoldDot
dataUieName="status-legal-hold-conversation"
className="conversation-title-bar-legal-hold"
legalHoldModal={legalHoldModal}
conversation={conversation}
/>
)}

{verificationState === ConversationVerificationState.VERIFIED && (
<Icon.Verified
data-uie-name="conversation-title-bar-verified-icon"
className="conversation-title-bar-name--verified"
/>
<div className="conversation-title-bar-name-label--wrapper">
{hasLegalHold && (
<LegalHoldDot
dataUieName="status-legal-hold-conversation"
className="conversation-title-bar-legal-hold"
legalHoldModal={legalHoldModal}
conversation={conversation}
/>
)}

{verificationState === ConversationVerificationState.VERIFIED && (
<Icon.Verified
data-uie-name="conversation-title-bar-verified-icon"
className="conversation-title-bar-name--verified"
/>
)}

<h2 className="conversation-title-bar-name-label" data-uie-name="status-conversation-title-bar-label">
{displayName}
</h2>
</div>

{conversationSubtitle && (
<div className="conversation-title-bar-name--subtitle">{conversationSubtitle}</div>
)}

<h2 className="conversation-title-bar-name-label" data-uie-name="status-conversation-title-bar-label">
{displayName}
</h2>
</div>
</li>

<li className="conversation-title-bar-icons">
{showCallControls && !isScaledDown && (
<div className="buttons-group">
{supportsVideoCall && isVideoCallingEnabled && (
<button
type="button"
className="conversation-title-bar-icon"
title={t('tooltipConversationVideoCall')}
aria-label={t('tooltipConversationVideoCall')}
onClick={() => callActions.startVideo(conversation)}
data-uie-name="do-video-call"
>
<Icon.Camera />
</button>
)}

{conversationSubtitle && <div className="conversation-title-bar-name--subtitle">{conversationSubtitle}</div>}
</div>
</li>

<li className="conversation-title-bar-icons">
{showCallControls && (
<div className="buttons-group">
{supportsVideoCall && isVideoCallingEnabled && (
<button
type="button"
className="conversation-title-bar-icon"
title={t('tooltipConversationVideoCall')}
aria-label={t('tooltipConversationVideoCall')}
onClick={() => callActions.startVideo(conversation)}
data-uie-name="do-video-call"
title={t('tooltipConversationCall')}
aria-label={t('tooltipConversationCall')}
onClick={() => callActions.startAudio(conversation)}
data-uie-name="do-call"
>
<Icon.Camera />
<Icon.Pickup />
</button>
)}

</div>
)}

{isScaledDown ? (
<>
<IconButton
className="icon-search"
css={{marginBottom: 0}}
title={t('tooltipConversationSearch')}
aria-label={t('tooltipConversationSearch')}
onClick={onClickCollectionButton}
data-uie-name="do-collections"
>
<span className="visually-hidden">{t('tooltipConversationSearch')}</span>
</IconButton>
<IconButton
title={t('tooltipConversationCall')}
aria-label={t('tooltipConversationCall')}
css={{marginBottom: 0}}
onClick={() => callActions.startAudio(conversation)}
data-uie-name="do-call"
>
<Icon.Pickup />
</IconButton>
</>
) : (
<button
type="button"
className="conversation-title-bar-icon"
title={t('tooltipConversationCall')}
aria-label={t('tooltipConversationCall')}
onClick={() => callActions.startAudio(conversation)}
data-uie-name="do-call"
title={t('tooltipConversationInfo')}
aria-label={t('tooltipConversationInfo')}
onClick={onClickDetails}
className={cx('conversation-title-bar-icon', {active: isPanelVisible})}
data-uie-name="do-open-info"
>
<Icon.Pickup />
<Icon.Info />
</button>
</div>
)}
</li>

{badgeLabelCopy && (
<li
className="conversation-title-bar-indication-badge"
data-uie-name="status-indication-badge"
dangerouslySetInnerHTML={{__html: badgeLabelCopy}}
/>
)}

<button
type="button"
title={t('tooltipConversationInfo')}
aria-label={t('tooltipConversationInfo')}
onClick={onClickDetails}
className={cx('conversation-title-bar-icon', {active: isPanelVisible})}
data-uie-name="do-open-info"
>
<Icon.Info />
</button>
</li>

{badgeLabelCopy && (
<li
className="conversation-title-bar-indication-badge"
data-uie-name="status-indication-badge"
dangerouslySetInnerHTML={{__html: badgeLabelCopy}}
/>
)}
</ul>
</ul>
</StyledApp>
);
};

Expand Down
3 changes: 0 additions & 3 deletions src/script/page/MainContent/MainContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@ import {ClientState} from '../../client/ClientState';
import {UserState} from '../../user/UserState';
import {StyledApp, THEME_ID} from '@wireapp/react-ui-kit';

// Ko imported components
import '../message-list/InputBarControls';

type LeftSidebarProps = {
contentViewModel: ContentViewModel;
conversationState?: ConversationState;
Expand Down
Loading